* [PATCH 01/10] Add more useful generic macros
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 02/10] ARM Chumby: Fix memory index Juergen Beisert
` (8 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
Stolen from the Linux kernel.
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
include/common.h | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/include/common.h b/include/common.h
index 1bea10c..35ad7b9 100644
--- a/include/common.h
+++ b/include/common.h
@@ -231,4 +231,14 @@ extern const char version_string[];
} \
)
+#define abs(x) ({ \
+ long __x = (x); \
+ (__x < 0) ? -__x : __x; \
+ })
+
+#define abs64(x) ({ \
+ s64 __x = (x); \
+ (__x < 0) ? -__x : __x; \
+ })
+
#endif /* __COMMON_H_ */
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 02/10] ARM Chumby: Fix memory index
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
2010-12-20 15:05 ` [PATCH 01/10] Add more useful generic macros Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 03/10] ARM Chumby: Fix unit of the clocks after the change to Hz Juergen Beisert
` (7 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/boards/chumby_falconwing/falconwing.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c
index 952a384..e0706f8 100644
--- a/arch/arm/boards/chumby_falconwing/falconwing.c
+++ b/arch/arm/boards/chumby_falconwing/falconwing.c
@@ -35,6 +35,7 @@ static struct memory_platform_data ram_pdata = {
};
static struct device_d sdram_dev = {
+ .id = -1,
.name = "mem",
.map_base = IMX_MEMORY_BASE,
.size = 64 * 1024 * 1024,
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 03/10] ARM Chumby: Fix unit of the clocks after the change to Hz
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
2010-12-20 15:05 ` [PATCH 01/10] Add more useful generic macros Juergen Beisert
2010-12-20 15:05 ` [PATCH 02/10] ARM Chumby: Fix memory index Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 04/10] ARM Chumby: Just fix some typos Juergen Beisert
` (6 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
With the change to Hz as the main clock unit on the STM architecture the
Chumby must also use this unit.
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/boards/chumby_falconwing/falconwing.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c
index e0706f8..10fbba8 100644
--- a/arch/arm/boards/chumby_falconwing/falconwing.c
+++ b/arch/arm/boards/chumby_falconwing/falconwing.c
@@ -266,9 +266,9 @@ static int falconwing_devices_init(void)
imx_gpio_mode(pad_setup[i]);
register_device(&sdram_dev);
- imx_set_ioclk(480U * 1000U); /* enable IOCLK to run at the PLL frequency */
+ imx_set_ioclk(480000000); /* enable IOCLK to run at the PLL frequency */
/* run the SSP unit clock at 100,000 kHz */
- imx_set_sspclk(0, 100U * 1000U, 1);
+ imx_set_sspclk(0, 100000000, 1);
register_device(&mci_dev);
armlinux_add_dram(&sdram_dev);
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 04/10] ARM Chumby: Just fix some typos
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (2 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 03/10] ARM Chumby: Fix unit of the clocks after the change to Hz Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 05/10] Fix default framebuffer 'enable' set Juergen Beisert
` (5 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/boards/chumby_falconwing/falconwing.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c
index 10fbba8..93ce7e2 100644
--- a/arch/arm/boards/chumby_falconwing/falconwing.c
+++ b/arch/arm/boards/chumby_falconwing/falconwing.c
@@ -225,8 +225,8 @@ static const uint32_t pad_setup[] = {
* Try to register an environment storage on the attached MCI card
* @return 0 on success
*
- * We relay on the existance of a useable SD card, already attached to
- * our system, to get someting like a persistant memory for our environment.
+ * We rely on the existence of a usable SD card, already attached to
+ * our system, to get something like a persistent memory for our environment.
* If this SD card is also the boot media, we can use the second partition
* for our environment purpose (if present!).
*/
@@ -253,7 +253,7 @@ static int register_persistant_environment(void)
return -ENODEV;
}
- /* use the full partition as our persistant environment storage */
+ /* use the full partition as our persistent environment storage */
return devfs_add_partition("disk0.1", 0, cdev->size, DEVFS_PARTITION_FIXED, "env0");
}
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 05/10] Fix default framebuffer 'enable' set
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (3 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 04/10] ARM Chumby: Just fix some typos Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 06/10] Add the feature to change the video mode at runtime Juergen Beisert
` (4 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
To setup the default 'enable' setting the "dev_set_param(dev, "enable", "0");"
does not work as expected. After the call the parameter is still "<NULL>".
This is due to any change of the setting is rejected, if the same setting
is already active.
This patch also let the default setting be successfull, but only calls the
graphics backend if a change happens.
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
drivers/video/fb.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index ab2c5eb..bef4147 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -39,14 +39,13 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param,
enable = simple_strtoul(val, NULL, 0);
- if (info->enabled == !!enable)
- return 0;
-
if (enable) {
- info->fbops->fb_enable(info);
+ if (!info->enabled)
+ info->fbops->fb_enable(info);
new = "1";
} else {
- info->fbops->fb_disable(info);
+ if (info->enabled)
+ info->fbops->fb_disable(info);
new = "0";
}
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 06/10] Add the feature to change the video mode at runtime
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (4 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 05/10] Fix default framebuffer 'enable' set Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 07/10] ARM STM/i.MX: Add a pixel clock calculation routine for i.MX23/i.MX28 Juergen Beisert
` (3 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
This patch add the possibility to change the video mode at barebox's runtime
if the graphics driver in use supports it.
Signed-off-by: <jbe@pengutronix.de>
---
drivers/video/fb.c | 35 +++++++++++++++++++++++++++++++++++
include/fb.h | 3 +++
2 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index bef4147..aad0e1f 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -56,6 +56,35 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param,
return 0;
}
+static int fb_setup_mode(struct device_d *dev, struct param_d *param,
+ const char *val)
+{
+ struct fb_info *info = dev->priv;
+ int mode, ret;
+
+ if (info->enabled != 0)
+ return -EPERM;
+
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
+ for (mode = 0; mode < info->num_modes; mode++) {
+ if (!strcmp(info->mode_list[mode].name, val))
+ break;
+ }
+ if (mode >= info->num_modes)
+ return -EINVAL;
+
+ info->mode = &info->mode_list[mode];
+
+ ret = info->fbops->fb_activate_var(info);
+
+ if (ret == 0)
+ dev_param_set_generic(dev, param, val);
+
+ return ret;
+}
+
static struct file_operations fb_ops = {
.read = mem_read,
.write = mem_write,
@@ -87,6 +116,12 @@ int register_framebuffer(struct fb_info *info)
dev_add_param(dev, "enable", fb_enable_set, NULL, 0);
dev_set_param(dev, "enable", "0");
+ if (info->num_modes && (info->mode_list != NULL) &&
+ (info->fbops->fb_activate_var != NULL)) {
+ dev_add_param(dev, "mode_name", fb_setup_mode, NULL, 0);
+ dev_set_param(dev, "mode_name", info->mode_list[0].name);
+ }
+
devfs_create(&info->cdev);
return 0;
diff --git a/include/fb.h b/include/fb.h
index 379f931..41deb8c 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -73,10 +73,13 @@ struct fb_ops {
unsigned blue, unsigned transp, struct fb_info *info);
void (*fb_enable)(struct fb_info *info);
void (*fb_disable)(struct fb_info *info);
+ int (*fb_activate_var)(struct fb_info *info);
};
struct fb_info {
struct fb_videomode *mode;
+ struct fb_videomode *mode_list;
+ unsigned num_modes;
struct fb_ops *fbops;
struct device_d dev; /* This is this fb device */
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 07/10] ARM STM/i.MX: Add a pixel clock calculation routine for i.MX23/i.MX28
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (5 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 06/10] Add the feature to change the video mode at runtime Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 08/10] ARM STM/i.MX: Add video driver " Juergen Beisert
` (2 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
In order to support video graphics output on i.MX23/i.MX28 based platforms,
a calculation routine for the pixel clock is required.
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/mach-stm/Makefile | 1 +
arch/arm/mach-stm/imx_lcd_clk.c | 149 ++++++++++++++++++++++++++
arch/arm/mach-stm/include/mach/clock-imx23.h | 2 +
arch/arm/mach-stm/include/mach/clock-imx28.h | 2 +
4 files changed, 154 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-stm/imx_lcd_clk.c
diff --git a/arch/arm/mach-stm/Makefile b/arch/arm/mach-stm/Makefile
index 3c7ce09..0ff8fd1 100644
--- a/arch/arm/mach-stm/Makefile
+++ b/arch/arm/mach-stm/Makefile
@@ -1,3 +1,4 @@
obj-y += imx.o iomux-imx.o reset-imx.o
+obj-$(CONFIG_DRIVER_VIDEO_STM) += imx_lcd_clk.o
obj-$(CONFIG_ARCH_IMX23) += speed-imx23.o clocksource-imx23.o
obj-$(CONFIG_ARCH_IMX28) += speed-imx28.o clocksource-imx28.o
diff --git a/arch/arm/mach-stm/imx_lcd_clk.c b/arch/arm/mach-stm/imx_lcd_clk.c
new file mode 100644
index 0000000..8938664
--- /dev/null
+++ b/arch/arm/mach-stm/imx_lcd_clk.c
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright 2010 Juergen Beisert - Pengutronix <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mach/imx-regs.h>
+#include <mach/clock.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_ARCH_IMX23
+
+# define HW_CLKCTRL_DIS_LCDIF 0x060
+# define CLKCTRL_DIS_LCDIF_GATE (1 << 31)
+# define CLKCTRL_DIS_LCDIF_BUSY (1 << 29)
+# define MASK_DIS_LCDIF_DIV 0xfff
+# define SET_DIS_LCDIF_DIV(x) ((x) & MASK_DIS_LCDIF_DIV)
+# define GET_DIS_LCDIF_DIV(x) ((x) & MASK_DIS_LCDIF_DIV)
+
+# define HW_CLKCTRL_FRAC 0xf0
+# define MASK_PIXFRAC 0x3f
+# define GET_PIXFRAC(x) (((x) >> 16) & MASK_PIXFRAC)
+# define SET_PIXFRAC(x) (((x) & MASK_PIXFRAC) << 16)
+# define CLKCTRL_FRAC_CLKGATEPIX (1 << 23)
+
+# define HW_CLKCTRL_CLKSEQ 0x110
+# define CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF (1 << 1)
+
+#endif
+
+#ifdef CONFIG_ARCH_IMX28
+
+# define HW_CLKCTRL_DIS_LCDIF 0x120
+# define CLKCTRL_DIS_LCDIF_GATE (1 << 31)
+# define CLKCTRL_DIS_LCDIF_BUSY (1 << 29)
+# define MASK_DIS_LCDIF_DIV 0x1fff
+# define SET_DIS_LCDIF_DIV(x) ((x) & MASK_DIS_LCDIF_DIV)
+# define GET_DIS_LCDIF_DIV(x) ((x) & MASK_DIS_LCDIF_DIV)
+
+/* note: On i.MX28 this is called 'FRAC1' */
+# define HW_CLKCTRL_FRAC 0x1c0
+# define MASK_PIXFRAC 0x3f
+# define GET_PIXFRAC(x) ((x) & MASK_PIXFRAC)
+# define SET_PIXFRAC(x) ((x) & MASK_PIXFRAC)
+# define CLKCTRL_FRAC_CLKGATEPIX (1 << 7)
+
+# define HW_CLKCTRL_CLKSEQ 0x1d0
+# define CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF (1 << 14)
+
+#endif
+
+unsigned imx_get_lcdifclk(void)
+{
+ unsigned rate = (imx_get_mpllclk() / 1000) * 18U;
+ unsigned div;
+
+ div = GET_PIXFRAC(readl(IMX_CCM_BASE + HW_CLKCTRL_FRAC));
+ if (div != 0U) {
+ rate /= div;
+ div = GET_DIS_LCDIF_DIV(readl(IMX_CCM_BASE +
+ HW_CLKCTRL_DIS_LCDIF));
+ if (div != 0U)
+ rate /= div;
+ else
+ pr_debug("LCDIF clock has divisor 0!\n");
+ } else
+ pr_debug("LCDIF clock has frac divisor 0!\n");
+
+ return rate * 1000;
+}
+
+/*
+ * The source of the pixel clock can be the external 24 MHz crystal or the
+ * internal PLL running at 480 MHz. In order to support at least VGA sized
+ * displays/resolutions this routine forces the PLL as the clock source.
+ */
+unsigned imx_set_lcdifclk(unsigned nc)
+{
+ unsigned frac, best_frac = 0, div, best_div = 0, result;
+ int delta, best_delta = 0xffffff;
+ unsigned i, parent_rate = imx_get_mpllclk() / 1000;
+ uint32_t reg;
+
+#define SH_DIV(NOM, DEN, LSH) ((((NOM) / (DEN)) << (LSH)) + \
+ DIV_ROUND_CLOSEST(((NOM) % (DEN)) << (LSH), DEN))
+#define SHIFT 4
+
+ nc /= 1000;
+ nc <<= SHIFT;
+
+ for (frac = 18; frac <= 35; ++frac) {
+ for (div = 1; div <= 255; ++div) {
+ result = DIV_ROUND_CLOSEST(parent_rate *
+ SH_DIV(18U, frac, SHIFT), div);
+ delta = nc - result;
+ if (abs(delta) < abs(best_delta)) {
+ best_delta = delta;
+ best_frac = frac;
+ best_div = div;
+ }
+ }
+ }
+
+ if (best_delta == 0xffffff) {
+ pr_debug("Unable to match the pixelclock\n");
+ return 0;
+ }
+
+ pr_debug("Programming PFD=%u,DIV=%u ref_pix=%u MHz PIXCLK=%u kHz\n",
+ best_frac, best_div, 480 * 18 / best_frac,
+ 480000 * 18 / best_frac / best_div);
+
+ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_FRAC) & ~MASK_PIXFRAC;
+ reg |= SET_PIXFRAC(best_frac);
+ writel(reg, IMX_CCM_BASE + HW_CLKCTRL_FRAC);
+ writel(reg & ~CLKCTRL_FRAC_CLKGATEPIX, IMX_CCM_BASE + HW_CLKCTRL_FRAC);
+
+ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_DIS_LCDIF) & ~MASK_DIS_LCDIF_DIV;
+ reg &= ~CLKCTRL_DIS_LCDIF_GATE;
+ reg |= SET_DIS_LCDIF_DIV(best_div);
+ writel(reg, IMX_CCM_BASE + HW_CLKCTRL_DIS_LCDIF);
+
+ /* Wait for divider update */
+ for (i = 0; i < 10000; i++) {
+ if (!(readl(IMX_CCM_BASE + HW_CLKCTRL_DIS_LCDIF) &
+ CLKCTRL_DIS_LCDIF_BUSY))
+ break;
+ }
+
+ if (i >= 10000) {
+ pr_debug("Setting LCD clock failed\n");
+ return 0;
+ }
+
+ writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF,
+ IMX_CCM_BASE + HW_CLKCTRL_CLKSEQ + BIT_CLR);
+
+ return imx_get_lcdifclk();
+}
diff --git a/arch/arm/mach-stm/include/mach/clock-imx23.h b/arch/arm/mach-stm/include/mach/clock-imx23.h
index bb499f2..723f343 100644
--- a/arch/arm/mach-stm/include/mach/clock-imx23.h
+++ b/arch/arm/mach-stm/include/mach/clock-imx23.h
@@ -22,5 +22,7 @@ unsigned imx_get_xclk(void);
unsigned imx_get_sspclk(unsigned);
unsigned imx_set_sspclk(unsigned, unsigned, int);
unsigned imx_set_ioclk(unsigned);
+unsigned imx_set_lcdifclk(unsigned);
+unsigned imx_get_lcdifclk(void);
#endif /* MACH_CLOCK_IMX23_H */
diff --git a/arch/arm/mach-stm/include/mach/clock-imx28.h b/arch/arm/mach-stm/include/mach/clock-imx28.h
index afc9fb6..45fb043 100644
--- a/arch/arm/mach-stm/include/mach/clock-imx28.h
+++ b/arch/arm/mach-stm/include/mach/clock-imx28.h
@@ -22,6 +22,8 @@ unsigned imx_get_xclk(void);
unsigned imx_get_sspclk(unsigned);
unsigned imx_set_sspclk(unsigned, unsigned, int);
unsigned imx_set_ioclk(unsigned, unsigned);
+unsigned imx_set_lcdifclk(unsigned);
+unsigned imx_get_lcdifclk(void);
unsigned imx_get_fecclk(void);
void imx_enable_enetclk(void);
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 08/10] ARM STM/i.MX: Add video driver for i.MX23/i.MX28
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (6 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 07/10] ARM STM/i.MX: Add a pixel clock calculation routine for i.MX23/i.MX28 Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-29 14:55 ` Gregory CLEMENT
2010-12-20 15:05 ` [PATCH 09/10] ARM KARO-TX28-STK5: Add a user for video graphics support on i.MX28 Juergen Beisert
2010-12-20 15:05 ` [PATCH 10/10] ARM Chumby-Falconwing: Add a user for video graphics support on i.MX23 Juergen Beisert
9 siblings, 1 reply; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/mach-stm/include/mach/fb.h | 43 +++
arch/arm/mach-stm/include/mach/imx23-regs.h | 1 +
drivers/video/Kconfig | 7 +
drivers/video/Makefile | 1 +
drivers/video/stm.c | 540 +++++++++++++++++++++++++++
5 files changed, 592 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-stm/include/mach/fb.h
create mode 100644 drivers/video/stm.c
diff --git a/arch/arm/mach-stm/include/mach/fb.h b/arch/arm/mach-stm/include/mach/fb.h
new file mode 100644
index 0000000..65e3be2
--- /dev/null
+++ b/arch/arm/mach-stm/include/mach/fb.h
@@ -0,0 +1,43 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_FB_H
+# define __MACH_FB_H
+
+#include <fb.h>
+
+#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
+#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
+#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
+
+/** LC display uses active high data enable signal */
+#define FB_SYNC_DE_HIGH_ACT (1 << 27)
+/** LC display will latch its data at clock's rising edge */
+#define FB_SYNC_CLK_INVERT (1 << 28)
+/** output RGB digital data inverted */
+#define FB_SYNC_DATA_INVERT (1 << 29)
+/** Stop clock if no data is sent (required for passive displays) */
+#define FB_SYNC_CLK_IDLE_DIS (1 << 30)
+/** swap RGB to BGR */
+#define FB_SYNC_SWAP_RGB (1 << 31)
+
+struct imx_fb_videomode {
+ struct fb_videomode *mode_list;
+ unsigned mode_cnt;
+
+ unsigned dotclk_delay; /**< refer manual HW_LCDIF_VDCTRL4 register */
+ unsigned ld_intf_width; /**< refer STMLCDIF_* macros */
+};
+
+#endif /* __MACH_FB_H */
+
diff --git a/arch/arm/mach-stm/include/mach/imx23-regs.h b/arch/arm/mach-stm/include/mach/imx23-regs.h
index 89ca453..caac19b 100644
--- a/arch/arm/mach-stm/include/mach/imx23-regs.h
+++ b/arch/arm/mach-stm/include/mach/imx23-regs.h
@@ -36,6 +36,7 @@
#define IMX_CCM_BASE 0x80040000
#define IMX_I2C1_BASE 0x80058000
#define IMX_SSP1_BASE 0x80010000
+#define IMX_FB_BASE 0x80030000
#define IMX_SSP2_BASE 0x80034000
#endif /* __ASM_ARCH_MX23_REGS_H */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 7a89a3f..c69308e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -20,4 +20,11 @@ config DRIVER_VIDEO_IMX_IPU
Add support for the IPU framebuffer device found on
i.MX31 and i.MX35 CPUs.
+config DRIVER_VIDEO_STM
+ bool "i.MX23/28 framebuffer driver"
+ depends on ARCH_STM
+ help
+ Say 'Y' here to enable framebuffer and splash screen support for
+ i.MX23 and i.MX28 based systems.
+
endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 179f0c4..a217a0b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_VIDEO) += fb.o
+obj-$(CONFIG_DRIVER_VIDEO_STM) += stm.o
obj-$(CONFIG_DRIVER_VIDEO_IMX) += imx.o
obj-$(CONFIG_DRIVER_VIDEO_IMX_IPU) += imx-ipu-fb.o
diff --git a/drivers/video/stm.c b/drivers/video/stm.c
new file mode 100644
index 0000000..f0abe4c
--- /dev/null
+++ b/drivers/video/stm.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix <jbe@pengutronix.de>
+ *
+ * This is based on code from:
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <malloc.h>
+#include <errno.h>
+#include <xfuncs.h>
+#include <asm/io.h>
+#include <mach/imx-regs.h>
+#include <mach/clock.h>
+#include <mach/fb.h>
+
+#define HW_LCDIF_CTRL 0x00
+# define CTRL_SFTRST (1 << 31)
+# define CTRL_CLKGATE (1 << 30)
+# define CTRL_BYPASS_COUNT (1 << 19)
+# define CTRL_VSYNC_MODE (1 << 18)
+# define CTRL_DOTCLK_MODE (1 << 17)
+# define CTRL_DATA_SELECT (1 << 16)
+# define SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
+# define SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
+# define GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
+# define CTRL_MASTER (1 << 5)
+# define CTRL_DF16 (1 << 3)
+# define CTRL_DF18 (1 << 2)
+# define CTRL_DF24 (1 << 1)
+# define CTRL_RUN (1 << 0)
+
+#define HW_LCDIF_CTRL1 0x10
+# define CTRL1_FIFO_CLEAR (1 << 21)
+# define SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
+# define GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
+
+#ifdef CONFIG_ARCH_IMX28
+# define HW_LCDIF_CTRL2 0x20
+# define HW_LCDIF_TRANSFER_COUNT 0x30
+#endif
+#ifdef CONFIG_ARCH_IMX23
+# define HW_LCDIF_TRANSFER_COUNT 0x20
+#endif
+# define SET_VCOUNT(x) (((x) & 0xffff) << 16)
+# define SET_HCOUNT(x) ((x) & 0xffff)
+
+#ifdef CONFIG_ARCH_IMX28
+# define HW_LCDIF_CUR_BUF 0x40
+# define HW_LCDIF_NEXT_BUF 0x50
+#endif
+#ifdef CONFIG_ARCH_IMX23
+# define HW_LCDIF_CUR_BUF 0x30
+# define HW_LCDIF_NEXT_BUF 0x40
+#endif
+
+#define HW_LCDIF_TIMING 0x60
+# define SET_CMD_HOLD(x) (((x) & 0xff) << 24)
+# define SET_CMD_SETUP(x) (((x) & 0xff) << 16)
+# define SET_DATA_HOLD(x) (((x) & 0xff) << 8)
+# define SET_DATA_SETUP(x) ((x) & 0xff)
+
+#define HW_LCDIF_VDCTRL0 0x70
+# define VDCTRL0_ENABLE_PRESENT (1 << 28)
+# define VDCTRL0_VSYNC_POL (1 << 27) /* 0 = low active, 1 = high active */
+# define VDCTRL0_HSYNC_POL (1 << 26) /* 0 = low active, 1 = high active */
+# define VDCTRL0_DOTCLK_POL (1 << 25) /* 0 = output@falling, capturing@rising edge */
+# define VDCTRL0_ENABLE_POL (1 << 24) /* 0 = low active, 1 = high active */
+# define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
+# define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
+# define VDCTRL0_HALF_LINE (1 << 19)
+# define VDCTRL0_HALF_LINE_MODE (1 << 18)
+# define SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+
+#define HW_LCDIF_VDCTRL1 0x80
+
+#define HW_LCDIF_VDCTRL2 0x90
+#ifdef CONFIG_ARCH_IMX28
+# define SET_HSYNC_PULSE_WIDTH(x) (((x) & 0x3fff) << 18)
+#endif
+#ifdef CONFIG_ARCH_IMX23
+# define SET_HSYNC_PULSE_WIDTH(x) (((x) & 0xff) << 24)
+#endif
+# define SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
+
+#define HW_LCDIF_VDCTRL3 0xa0
+# define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
+# define VDCTRL3_VSYNC_ONLY (1 << 28)
+# define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
+# define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
+
+#define HW_LCDIF_VDCTRL4 0xb0
+#ifdef CONFIG_ARCH_IMX28
+# define SET_DOTCLK_DLY(x) (((x) & 0x7) << 29)
+#endif
+# define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
+# define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
+
+#define HW_LCDIF_DVICTRL0 0xc0
+#define HW_LCDIF_DVICTRL1 0xd0
+#define HW_LCDIF_DVICTRL2 0xe0
+#define HW_LCDIF_DVICTRL3 0xf0
+#define HW_LCDIF_DVICTRL4 0x100
+
+#ifdef CONFIG_ARCH_IMX28
+# define HW_LCDIF_DATA 0x180
+#endif
+#ifdef CONFIG_ARCH_IMX23
+# define HW_LCDIF_DATA 0x1b0
+#endif
+
+#ifdef CONFIG_ARCH_IMX28
+# define HW_LCDIF_DEBUG0 0x1d0
+#endif
+#ifdef CONFIG_ARCH_IMX23
+# define HW_LCDIF_DEBUG0 0x1f0
+#endif
+# define DEBUG_HSYNC (1 < 26)
+# define DEBUG_VSYNC (1 < 25)
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define TRANSP 3
+
+struct imxfb_info {
+ void __iomem *base;
+ unsigned memory_size;
+ struct fb_info info;
+ struct device_d *hw_dev;
+ struct imx_fb_videomode *pdata;
+};
+
+/* the RGB565 true colour mode */
+static const struct fb_bitfield def_rgb565[] = {
+ [RED] = {
+ .offset = 11,
+ .length = 5,
+ },
+ [GREEN] = {
+ .offset = 5,
+ .length = 6,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 5,
+ },
+ [TRANSP] = { /* no support for transparency */
+ .length = 0,
+ }
+};
+
+/* the RGB666 true colour mode */
+static const struct fb_bitfield def_rgb666[] = {
+ [RED] = {
+ .offset = 16,
+ .length = 6,
+ },
+ [GREEN] = {
+ .offset = 8,
+ .length = 6,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 6,
+ },
+ [TRANSP] = { /* no support for transparency */
+ .length = 0,
+ }
+};
+
+/* the RGB888 true colour mode */
+static const struct fb_bitfield def_rgb888[] = {
+ [RED] = {
+ .offset = 16,
+ .length = 8,
+ },
+ [GREEN] = {
+ .offset = 8,
+ .length = 8,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 8,
+ },
+ [TRANSP] = { /* no support for transparency */
+ .length = 0,
+ }
+};
+
+static inline unsigned calc_line_length(unsigned ppl, unsigned bpp)
+{
+ if (bpp == 24)
+ bpp = 32;
+ return (ppl * bpp) >> 3;
+}
+
+static int stmfb_memory_mmgt(struct fb_info *fb_info, unsigned size)
+{
+ struct imxfb_info *fbi = fb_info->priv;
+
+ if (fbi->memory_size != 0) {
+ free(fb_info->screen_base);
+ fb_info->screen_base = NULL;
+ fbi->memory_size = 0;
+ }
+
+ if (fbi->memory_size == 0) {
+ fb_info->screen_base = xzalloc(size);
+ fbi->memory_size = size;
+ }
+
+ return 0;
+}
+
+static void stmfb_enable_controller(struct fb_info *fb_info)
+{
+ struct imxfb_info *fbi = fb_info->priv;
+ uint32_t reg, last_reg;
+ unsigned loop, edges;
+
+ /*
+ * Sometimes some data is still present in the FIFO. This leads into
+ * a correct but shifted picture. Clearing the FIFO helps
+ */
+ writel(CTRL1_FIFO_CLEAR, fbi->base + HW_LCDIF_CTRL1 + BIT_SET);
+
+ /* if it was disabled, re-enable the mode again */
+ reg = readl(fbi->base + HW_LCDIF_CTRL);
+ reg |= CTRL_DOTCLK_MODE;
+ writel(reg, fbi->base + HW_LCDIF_CTRL);
+
+ /* enable the SYNC signals first, then the DMA engine */
+ reg = readl(fbi->base + HW_LCDIF_VDCTRL4);
+ reg |= VDCTRL4_SYNC_SIGNALS_ON;
+ writel(reg, fbi->base + HW_LCDIF_VDCTRL4);
+
+ /*
+ * Give the attached LC display or monitor a chance to sync into
+ * our signals.
+ * Wait for at least 2 VSYNCs = four VSYNC edges
+ */
+ edges = 4;
+
+ while (edges != 0) {
+ loop = 800;
+ last_reg = readl(fbi->base + HW_LCDIF_DEBUG0) & DEBUG_VSYNC;
+ do {
+ reg = readl(fbi->base + HW_LCDIF_DEBUG0) & DEBUG_VSYNC;
+ if (reg != last_reg)
+ break;
+ last_reg = reg;
+ loop--;
+ } while (loop != 0);
+ edges--;
+ }
+
+ /* stop FIFO reset */
+ writel(CTRL1_FIFO_CLEAR, fbi->base + HW_LCDIF_CTRL1 + BIT_CLR);
+ /* start the engine right now */
+ writel(CTRL_RUN, fbi->base + HW_LCDIF_CTRL + BIT_SET);
+}
+
+static void stmfb_disable_controller(struct fb_info *fb_info)
+{
+ struct imxfb_info *fbi = fb_info->priv;
+ unsigned loop;
+ uint32_t reg;
+
+ /*
+ * Even if we disable the controller here, it will still continue
+ * until its FIFOs are running out of data
+ */
+ reg = readl(fbi->base + HW_LCDIF_CTRL);
+ reg &= ~CTRL_DOTCLK_MODE;
+ writel(reg, fbi->base + HW_LCDIF_CTRL);
+
+ loop = 1000;
+ while (loop) {
+ reg = readl(fbi->base + HW_LCDIF_CTRL);
+ if (!(reg & CTRL_RUN))
+ break;
+ loop--;
+ }
+
+ reg = readl(fbi->base + HW_LCDIF_VDCTRL4);
+ reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
+ writel(reg, fbi->base + HW_LCDIF_VDCTRL4);
+}
+
+static int stmfb_activate_var(struct fb_info *fb_info)
+{
+ struct imxfb_info *fbi = fb_info->priv;
+ struct imx_fb_videomode *pdata = fbi->pdata;
+ struct fb_videomode *mode = fb_info->mode;
+ uint32_t reg;
+ int ret;
+ unsigned size;
+
+ /*
+ * we need at least this amount of memory for the framebuffer
+ */
+ size = calc_line_length(mode->xres, fb_info->bits_per_pixel) *
+ mode->yres;
+
+ ret = stmfb_memory_mmgt(fb_info, size);
+ if (ret != 0) {
+ dev_err(fbi->hw_dev, "Cannot allocate framebuffer memory\n");
+ return ret;
+ }
+
+ /** @todo ensure HCLK is active at this point of time! */
+
+ size = imx_set_lcdifclk(PICOS2KHZ(mode->pixclock) * 1000);
+ if (size == 0) {
+ dev_dbg(fbi->hw_dev, "Unable to set a valid pixel clock\n");
+ return -EINVAL;
+ }
+
+ /*
+ * bring the controller out of reset and
+ * configure it into DOTCLOCK mode
+ */
+ reg = CTRL_BYPASS_COUNT | /* always in DOTCLOCK mode */
+ CTRL_DOTCLK_MODE;
+ writel(reg, fbi->base + HW_LCDIF_CTRL);
+
+ /* master mode only */
+ reg |= CTRL_MASTER;
+
+ /*
+ * Configure videomode and interface mode
+ */
+ reg |= SET_BUS_WIDTH(pdata->ld_intf_width);
+ switch (fb_info->bits_per_pixel) {
+ case 8:
+ reg |= SET_WORD_LENGTH(1);
+ /** @todo refer manual page 2046 for 8 bpp modes */
+ dev_dbg(fbi->hw_dev, "8 bpp mode not supported yet\n");
+ break;
+ case 16:
+ pr_debug("Setting up an RGB565 mode\n");
+ reg |= SET_WORD_LENGTH(0);
+ reg &= ~CTRL_DF16; /* we assume RGB565 */
+ writel(SET_BYTE_PACKAGING(0xf), fbi->base + HW_LCDIF_CTRL1);
+ fb_info->red = def_rgb565[RED];
+ fb_info->green = def_rgb565[GREEN];
+ fb_info->blue = def_rgb565[BLUE];
+ fb_info->transp = def_rgb565[TRANSP];
+ break;
+ case 24:
+ case 32:
+ pr_debug("Setting up an RGB888/666 mode\n");
+ reg |= SET_WORD_LENGTH(3);
+ switch (pdata->ld_intf_width) {
+ case STMLCDIF_8BIT:
+ dev_dbg(fbi->hw_dev,
+ "Unsupported LCD bus width mapping\n");
+ break;
+ case STMLCDIF_16BIT:
+ case STMLCDIF_18BIT:
+ /* 24 bit to 18 bit mapping
+ * which means: ignore the upper 2 bits in
+ * each colour component
+ */
+ reg |= CTRL_DF24;
+ fb_info->red = def_rgb666[RED];
+ fb_info->green = def_rgb666[GREEN];
+ fb_info->blue = def_rgb666[BLUE];
+ fb_info->transp = def_rgb666[TRANSP];
+ break;
+ case STMLCDIF_24BIT:
+ /* real 24 bit */
+ fb_info->red = def_rgb888[RED];
+ fb_info->green = def_rgb888[GREEN];
+ fb_info->blue = def_rgb888[BLUE];
+ fb_info->transp = def_rgb888[TRANSP];
+ break;
+ }
+ /* do not use packed pixels = one pixel per word instead */
+ writel(SET_BYTE_PACKAGING(0x7), fbi->base + HW_LCDIF_CTRL1);
+ break;
+ default:
+ dev_dbg(fbi->hw_dev, "Unhandled colour depth of %u\n",
+ fb_info->bits_per_pixel);
+ return -EINVAL;
+ }
+ writel(reg, fbi->base + HW_LCDIF_CTRL);
+ pr_debug("Setting up CTRL to %08X\n", reg);
+
+ writel(SET_VCOUNT(mode->yres) |
+ SET_HCOUNT(mode->xres), fbi->base + HW_LCDIF_TRANSFER_COUNT);
+
+ reg = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
+ VDCTRL0_VSYNC_PERIOD_UNIT |
+ VDCTRL0_VSYNC_PULSE_WIDTH_UNIT;
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+ reg |= VDCTRL0_HSYNC_POL;
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ reg |= VDCTRL0_VSYNC_POL;
+ if (mode->sync & FB_SYNC_DE_HIGH_ACT)
+ reg |= VDCTRL0_ENABLE_POL;
+ if (mode->sync & FB_SYNC_CLK_INVERT)
+ reg |= VDCTRL0_DOTCLK_POL;
+
+ reg |= SET_VSYNC_PULSE_WIDTH(mode->vsync_len);
+ writel(reg, fbi->base + HW_LCDIF_VDCTRL0);
+ pr_debug("Setting up VDCTRL0 to %08X\n", reg);
+
+ /* frame length in lines */
+ writel(mode->upper_margin + mode->vsync_len + mode->lower_margin +
+ mode->yres,
+ fbi->base + HW_LCDIF_VDCTRL1);
+
+ /* line length in units of clocks or pixels */
+ writel(SET_HSYNC_PULSE_WIDTH(mode->hsync_len) |
+ SET_HSYNC_PERIOD(mode->left_margin + mode->hsync_len +
+ mode->right_margin + mode->xres),
+ fbi->base + HW_LCDIF_VDCTRL2);
+
+ writel(SET_HOR_WAIT_CNT(mode->left_margin + mode->hsync_len) |
+ SET_VERT_WAIT_CNT(mode->upper_margin + mode->vsync_len),
+ fbi->base + HW_LCDIF_VDCTRL3);
+
+ writel(
+#ifdef CONFIG_ARCH_IMX28
+ SET_DOTCLK_DLY(pdata->dotclk_delay) |
+#endif
+ SET_DOTCLK_H_VALID_DATA_CNT(mode->xres),
+ fbi->base + HW_LCDIF_VDCTRL4);
+
+ writel((uint32_t)fb_info->screen_base, fbi->base + HW_LCDIF_CUR_BUF);
+ writel((uint32_t)fb_info->screen_base, fbi->base + HW_LCDIF_NEXT_BUF);
+
+ return 0;
+}
+
+static void stmfb_info(struct device_d *hw_dev)
+{
+ struct imx_fb_videomode *pdata = hw_dev->platform_data;
+ unsigned u;
+
+ printf(" Supported video modes:\n");
+ for (u = 0; u < pdata->mode_cnt; u++)
+ printf(" - '%s': %u x %u\n", pdata->mode_list[u].name,
+ pdata->mode_list[u].xres, pdata->mode_list[u].yres);
+}
+
+/*
+ * There is only one video hardware instance available.
+ * It makes no sense to dynamically allocate this data
+ */
+static struct fb_ops imxfb_ops = {
+ .fb_activate_var = stmfb_activate_var,
+ .fb_enable = stmfb_enable_controller,
+ .fb_disable = stmfb_disable_controller,
+};
+
+static struct imxfb_info fbi = {
+ .info = {
+ .fbops = &imxfb_ops,
+ },
+};
+
+static int stmfb_probe(struct device_d *hw_dev)
+{
+ struct imx_fb_videomode *pdata = hw_dev->platform_data;
+ int ret;
+
+ /* just init */
+ fbi.info.priv = &fbi;
+
+ /* add runtime hardware info */
+ fbi.hw_dev = hw_dev;
+ fbi.base = (void *)hw_dev->map_base;
+ fbi.pdata = pdata;
+
+ /* add runtime video info */
+ fbi.info.mode_list = pdata->mode_list;
+ fbi.info.num_modes = pdata->mode_cnt;
+ fbi.info.mode = &fbi.info.mode_list[0];
+ fbi.info.xres = fbi.info.mode->xres;
+ fbi.info.yres = fbi.info.mode->yres;
+ fbi.info.bits_per_pixel = 16;
+
+ ret = register_framebuffer(&fbi.info);
+ if (ret != 0) {
+ dev_err(hw_dev, "Failed to register framebuffer\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct driver_d stmfb_driver = {
+ .name = "stmfb",
+ .probe = stmfb_probe,
+ .info = stmfb_info,
+};
+
+static int stmfb_init(void)
+{
+ return register_driver(&stmfb_driver);
+}
+
+device_initcall(stmfb_init);
+
+/**
+ * @file
+ * @brief LCDIF driver for i.MX23 and i.MX28
+ *
+ * The LCDIF support four modes of operation
+ * - MPU interface (to drive smart displays) -> not supported yet
+ * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
+ * - Dotclock interface (to drive LC displays with RGB data and sync signals)
+ * - DVI (to drive ITU-R BT656) -> not supported yet
+ *
+ * This driver depends on a correct setup of the pins used for this purpose
+ * (platform specific).
+ *
+ * For the developer: Don't forget to set the data bus width to the display
+ * in the imx_fb_videomode structure. You will else end up with ugly colours.
+ * If you fight against jitter you can vary the clock delay. This is a feature
+ * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
+ * the required value in the imx_fb_videomode structure.
+ */
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 08/10] ARM STM/i.MX: Add video driver for i.MX23/i.MX28
2010-12-20 15:05 ` [PATCH 08/10] ARM STM/i.MX: Add video driver " Juergen Beisert
@ 2010-12-29 14:55 ` Gregory CLEMENT
0 siblings, 0 replies; 12+ messages in thread
From: Gregory CLEMENT @ 2010-12-29 14:55 UTC (permalink / raw)
To: Juergen Beisert, gregory.clement; +Cc: barebox
Hi,
I apply this patch for my project and use it with an imx23 base board.
I have a few comments and I think that I found a bug.
I you are interested I can send you patches related to my comments.
2010/12/20 Juergen Beisert <jbe@pengutronix.de>:
> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> ---
> arch/arm/mach-stm/include/mach/fb.h | 43 +++
> arch/arm/mach-stm/include/mach/imx23-regs.h | 1 +
> drivers/video/Kconfig | 7 +
> drivers/video/Makefile | 1 +
> drivers/video/stm.c | 540 +++++++++++++++++++++++++++
> 5 files changed, 592 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-stm/include/mach/fb.h
> create mode 100644 drivers/video/stm.c
>
> diff --git a/arch/arm/mach-stm/include/mach/fb.h b/arch/arm/mach-stm/include/mach/fb.h
> new file mode 100644
> index 0000000..65e3be2
> --- /dev/null
> +++ b/arch/arm/mach-stm/include/mach/fb.h
> @@ -0,0 +1,43 @@
> +/*
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_FB_H
> +# define __MACH_FB_H
> +
> +#include <fb.h>
> +
> +#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
> +#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
> +#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
> +#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
> +
> +/** LC display uses active high data enable signal */
> +#define FB_SYNC_DE_HIGH_ACT (1 << 27)
> +/** LC display will latch its data at clock's rising edge */
> +#define FB_SYNC_CLK_INVERT (1 << 28)
> +/** output RGB digital data inverted */
> +#define FB_SYNC_DATA_INVERT (1 << 29)
> +/** Stop clock if no data is sent (required for passive displays) */
> +#define FB_SYNC_CLK_IDLE_DIS (1 << 30)
> +/** swap RGB to BGR */
> +#define FB_SYNC_SWAP_RGB (1 << 31)
> +
> +struct imx_fb_videomode {
> + struct fb_videomode *mode_list;
> + unsigned mode_cnt;
> +
> + unsigned dotclk_delay; /**< refer manual HW_LCDIF_VDCTRL4 register */
> + unsigned ld_intf_width; /**< refer STMLCDIF_* macros */
> +};
Should it be acceptable to add new field in this structure ?
For example for my need I added a data_mode flag which is used to configure
command mode polarity (bit 16 in HW_LCDIF_CTRL register)
> +
> +#endif /* __MACH_FB_H */
> +
> diff --git a/arch/arm/mach-stm/include/mach/imx23-regs.h b/arch/arm/mach-stm/include/mach/imx23-regs.h
> index 89ca453..caac19b 100644
> --- a/arch/arm/mach-stm/include/mach/imx23-regs.h
> +++ b/arch/arm/mach-stm/include/mach/imx23-regs.h
> @@ -36,6 +36,7 @@
> #define IMX_CCM_BASE 0x80040000
> #define IMX_I2C1_BASE 0x80058000
> #define IMX_SSP1_BASE 0x80010000
> +#define IMX_FB_BASE 0x80030000
> #define IMX_SSP2_BASE 0x80034000
>
> #endif /* __ASM_ARCH_MX23_REGS_H */
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 7a89a3f..c69308e 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -20,4 +20,11 @@ config DRIVER_VIDEO_IMX_IPU
> Add support for the IPU framebuffer device found on
> i.MX31 and i.MX35 CPUs.
>
> +config DRIVER_VIDEO_STM
> + bool "i.MX23/28 framebuffer driver"
> + depends on ARCH_STM
> + help
> + Say 'Y' here to enable framebuffer and splash screen support for
> + i.MX23 and i.MX28 based systems.
> +
> endif
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index 179f0c4..a217a0b 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -1,4 +1,5 @@
> obj-$(CONFIG_VIDEO) += fb.o
>
> +obj-$(CONFIG_DRIVER_VIDEO_STM) += stm.o
> obj-$(CONFIG_DRIVER_VIDEO_IMX) += imx.o
> obj-$(CONFIG_DRIVER_VIDEO_IMX_IPU) += imx-ipu-fb.o
> diff --git a/drivers/video/stm.c b/drivers/video/stm.c
> new file mode 100644
> index 0000000..f0abe4c
> --- /dev/null
> +++ b/drivers/video/stm.c
> @@ -0,0 +1,540 @@
> +/*
> + * Copyright (C) 2010 Juergen Beisert, Pengutronix <jbe@pengutronix.de>
> + *
> + * This is based on code from:
> + * Author: Vitaly Wool <vital@embeddedalley.com>
> + *
> + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +#include <common.h>
> +#include <init.h>
> +#include <driver.h>
> +#include <malloc.h>
> +#include <errno.h>
> +#include <xfuncs.h>
> +#include <asm/io.h>
> +#include <mach/imx-regs.h>
> +#include <mach/clock.h>
> +#include <mach/fb.h>
> +
> +#define HW_LCDIF_CTRL 0x00
> +# define CTRL_SFTRST (1 << 31)
> +# define CTRL_CLKGATE (1 << 30)
> +# define CTRL_BYPASS_COUNT (1 << 19)
> +# define CTRL_VSYNC_MODE (1 << 18)
> +# define CTRL_DOTCLK_MODE (1 << 17)
> +# define CTRL_DATA_SELECT (1 << 16)
> +# define SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
> +# define SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
> +# define GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
> +# define CTRL_MASTER (1 << 5)
> +# define CTRL_DF16 (1 << 3)
> +# define CTRL_DF18 (1 << 2)
> +# define CTRL_DF24 (1 << 1)
> +# define CTRL_RUN (1 << 0)
> +
> +#define HW_LCDIF_CTRL1 0x10
> +# define CTRL1_FIFO_CLEAR (1 << 21)
> +# define SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
> +# define GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
> +
> +#ifdef CONFIG_ARCH_IMX28
> +# define HW_LCDIF_CTRL2 0x20
> +# define HW_LCDIF_TRANSFER_COUNT 0x30
> +#endif
> +#ifdef CONFIG_ARCH_IMX23
> +# define HW_LCDIF_TRANSFER_COUNT 0x20
> +#endif
> +# define SET_VCOUNT(x) (((x) & 0xffff) << 16)
> +# define SET_HCOUNT(x) ((x) & 0xffff)
> +
> +#ifdef CONFIG_ARCH_IMX28
> +# define HW_LCDIF_CUR_BUF 0x40
> +# define HW_LCDIF_NEXT_BUF 0x50
> +#endif
> +#ifdef CONFIG_ARCH_IMX23
> +# define HW_LCDIF_CUR_BUF 0x30
> +# define HW_LCDIF_NEXT_BUF 0x40
> +#endif
> +
> +#define HW_LCDIF_TIMING 0x60
> +# define SET_CMD_HOLD(x) (((x) & 0xff) << 24)
> +# define SET_CMD_SETUP(x) (((x) & 0xff) << 16)
> +# define SET_DATA_HOLD(x) (((x) & 0xff) << 8)
> +# define SET_DATA_SETUP(x) ((x) & 0xff)
> +
> +#define HW_LCDIF_VDCTRL0 0x70
> +# define VDCTRL0_ENABLE_PRESENT (1 << 28)
> +# define VDCTRL0_VSYNC_POL (1 << 27) /* 0 = low active, 1 = high active */
> +# define VDCTRL0_HSYNC_POL (1 << 26) /* 0 = low active, 1 = high active */
> +# define VDCTRL0_DOTCLK_POL (1 << 25) /* 0 = output@falling, capturing@rising edge */
> +# define VDCTRL0_ENABLE_POL (1 << 24) /* 0 = low active, 1 = high active */
> +# define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
> +# define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
> +# define VDCTRL0_HALF_LINE (1 << 19)
> +# define VDCTRL0_HALF_LINE_MODE (1 << 18)
> +# define SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
> +
> +#define HW_LCDIF_VDCTRL1 0x80
> +
> +#define HW_LCDIF_VDCTRL2 0x90
> +#ifdef CONFIG_ARCH_IMX28
> +# define SET_HSYNC_PULSE_WIDTH(x) (((x) & 0x3fff) << 18)
> +#endif
> +#ifdef CONFIG_ARCH_IMX23
> +# define SET_HSYNC_PULSE_WIDTH(x) (((x) & 0xff) << 24)
> +#endif
> +# define SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
> +
> +#define HW_LCDIF_VDCTRL3 0xa0
> +# define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
> +# define VDCTRL3_VSYNC_ONLY (1 << 28)
> +# define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
> +# define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
> +
> +#define HW_LCDIF_VDCTRL4 0xb0
> +#ifdef CONFIG_ARCH_IMX28
> +# define SET_DOTCLK_DLY(x) (((x) & 0x7) << 29)
> +#endif
> +# define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
> +# define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
> +
> +#define HW_LCDIF_DVICTRL0 0xc0
> +#define HW_LCDIF_DVICTRL1 0xd0
> +#define HW_LCDIF_DVICTRL2 0xe0
> +#define HW_LCDIF_DVICTRL3 0xf0
> +#define HW_LCDIF_DVICTRL4 0x100
> +
> +#ifdef CONFIG_ARCH_IMX28
> +# define HW_LCDIF_DATA 0x180
> +#endif
> +#ifdef CONFIG_ARCH_IMX23
> +# define HW_LCDIF_DATA 0x1b0
> +#endif
> +
> +#ifdef CONFIG_ARCH_IMX28
> +# define HW_LCDIF_DEBUG0 0x1d0
> +#endif
> +#ifdef CONFIG_ARCH_IMX23
> +# define HW_LCDIF_DEBUG0 0x1f0
> +#endif
> +# define DEBUG_HSYNC (1 < 26)
> +# define DEBUG_VSYNC (1 < 25)
> +
> +#define RED 0
> +#define GREEN 1
> +#define BLUE 2
> +#define TRANSP 3
> +
> +struct imxfb_info {
> + void __iomem *base;
> + unsigned memory_size;
> + struct fb_info info;
> + struct device_d *hw_dev;
> + struct imx_fb_videomode *pdata;
> +};
> +
> +/* the RGB565 true colour mode */
> +static const struct fb_bitfield def_rgb565[] = {
> + [RED] = {
> + .offset = 11,
> + .length = 5,
> + },
> + [GREEN] = {
> + .offset = 5,
> + .length = 6,
> + },
> + [BLUE] = {
> + .offset = 0,
> + .length = 5,
> + },
> + [TRANSP] = { /* no support for transparency */
> + .length = 0,
> + }
> +};
> +
> +/* the RGB666 true colour mode */
> +static const struct fb_bitfield def_rgb666[] = {
> + [RED] = {
> + .offset = 16,
> + .length = 6,
> + },
> + [GREEN] = {
> + .offset = 8,
> + .length = 6,
> + },
> + [BLUE] = {
> + .offset = 0,
> + .length = 6,
> + },
> + [TRANSP] = { /* no support for transparency */
> + .length = 0,
> + }
> +};
> +
> +/* the RGB888 true colour mode */
> +static const struct fb_bitfield def_rgb888[] = {
> + [RED] = {
> + .offset = 16,
> + .length = 8,
> + },
> + [GREEN] = {
> + .offset = 8,
> + .length = 8,
> + },
> + [BLUE] = {
> + .offset = 0,
> + .length = 8,
> + },
> + [TRANSP] = { /* no support for transparency */
> + .length = 0,
> + }
> +};
> +
> +static inline unsigned calc_line_length(unsigned ppl, unsigned bpp)
> +{
> + if (bpp == 24)
> + bpp = 32;
> + return (ppl * bpp) >> 3;
> +}
> +
> +static int stmfb_memory_mmgt(struct fb_info *fb_info, unsigned size)
> +{
> + struct imxfb_info *fbi = fb_info->priv;
> +
> + if (fbi->memory_size != 0) {
> + free(fb_info->screen_base);
> + fb_info->screen_base = NULL;
> + fbi->memory_size = 0;
> + }
> +
> + if (fbi->memory_size == 0) {
> + fb_info->screen_base = xzalloc(size);
> + fbi->memory_size = size;
> + }
> +
> + return 0;
> +}
> +
> +static void stmfb_enable_controller(struct fb_info *fb_info)
> +{
> + struct imxfb_info *fbi = fb_info->priv;
> + uint32_t reg, last_reg;
> + unsigned loop, edges;
> +
> + /*
> + * Sometimes some data is still present in the FIFO. This leads into
> + * a correct but shifted picture. Clearing the FIFO helps
> + */
> + writel(CTRL1_FIFO_CLEAR, fbi->base + HW_LCDIF_CTRL1 + BIT_SET);
> +
> + /* if it was disabled, re-enable the mode again */
> + reg = readl(fbi->base + HW_LCDIF_CTRL);
> + reg |= CTRL_DOTCLK_MODE;
> + writel(reg, fbi->base + HW_LCDIF_CTRL);
> +
> + /* enable the SYNC signals first, then the DMA engine */
> + reg = readl(fbi->base + HW_LCDIF_VDCTRL4);
> + reg |= VDCTRL4_SYNC_SIGNALS_ON;
> + writel(reg, fbi->base + HW_LCDIF_VDCTRL4);
> +
> + /*
> + * Give the attached LC display or monitor a chance to sync into
> + * our signals.
> + * Wait for at least 2 VSYNCs = four VSYNC edges
> + */
> + edges = 4;
> +
> + while (edges != 0) {
> + loop = 800;
> + last_reg = readl(fbi->base + HW_LCDIF_DEBUG0) & DEBUG_VSYNC;
> + do {
> + reg = readl(fbi->base + HW_LCDIF_DEBUG0) & DEBUG_VSYNC;
> + if (reg != last_reg)
> + break;
> + last_reg = reg;
> + loop--;
> + } while (loop != 0);
> + edges--;
> + }
> +
> + /* stop FIFO reset */
> + writel(CTRL1_FIFO_CLEAR, fbi->base + HW_LCDIF_CTRL1 + BIT_CLR);
> + /* start the engine right now */
> + writel(CTRL_RUN, fbi->base + HW_LCDIF_CTRL + BIT_SET);
> +}
> +
> +static void stmfb_disable_controller(struct fb_info *fb_info)
> +{
> + struct imxfb_info *fbi = fb_info->priv;
> + unsigned loop;
> + uint32_t reg;
> +
> + /*
> + * Even if we disable the controller here, it will still continue
> + * until its FIFOs are running out of data
> + */
> + reg = readl(fbi->base + HW_LCDIF_CTRL);
> + reg &= ~CTRL_DOTCLK_MODE;
> + writel(reg, fbi->base + HW_LCDIF_CTRL);
> +
> + loop = 1000;
> + while (loop) {
> + reg = readl(fbi->base + HW_LCDIF_CTRL);
> + if (!(reg & CTRL_RUN))
> + break;
> + loop--;
> + }
> +
> + reg = readl(fbi->base + HW_LCDIF_VDCTRL4);
> + reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
> + writel(reg, fbi->base + HW_LCDIF_VDCTRL4);
> +}
> +
> +static int stmfb_activate_var(struct fb_info *fb_info)
> +{
> + struct imxfb_info *fbi = fb_info->priv;
> + struct imx_fb_videomode *pdata = fbi->pdata;
> + struct fb_videomode *mode = fb_info->mode;
> + uint32_t reg;
> + int ret;
> + unsigned size;
> +
> + /*
> + * we need at least this amount of memory for the framebuffer
> + */
> + size = calc_line_length(mode->xres, fb_info->bits_per_pixel) *
> + mode->yres;
> +
> + ret = stmfb_memory_mmgt(fb_info, size);
> + if (ret != 0) {
> + dev_err(fbi->hw_dev, "Cannot allocate framebuffer memory\n");
> + return ret;
> + }
> +
> + /** @todo ensure HCLK is active at this point of time! */
> +
> + size = imx_set_lcdifclk(PICOS2KHZ(mode->pixclock) * 1000);
> + if (size == 0) {
> + dev_dbg(fbi->hw_dev, "Unable to set a valid pixel clock\n");
> + return -EINVAL;
> + }
> +
> + /*
> + * bring the controller out of reset and
> + * configure it into DOTCLOCK mode
> + */
> + reg = CTRL_BYPASS_COUNT | /* always in DOTCLOCK mode */
> + CTRL_DOTCLK_MODE;
> + writel(reg, fbi->base + HW_LCDIF_CTRL);
> +
> + /* master mode only */
> + reg |= CTRL_MASTER;
> +
> + /*
> + * Configure videomode and interface mode
> + */
> + reg |= SET_BUS_WIDTH(pdata->ld_intf_width);
> + switch (fb_info->bits_per_pixel) {
> + case 8:
> + reg |= SET_WORD_LENGTH(1);
> + /** @todo refer manual page 2046 for 8 bpp modes */
> + dev_dbg(fbi->hw_dev, "8 bpp mode not supported yet\n");
> + break;
> + case 16:
> + pr_debug("Setting up an RGB565 mode\n");
> + reg |= SET_WORD_LENGTH(0);
> + reg &= ~CTRL_DF16; /* we assume RGB565 */
> + writel(SET_BYTE_PACKAGING(0xf), fbi->base + HW_LCDIF_CTRL1);
> + fb_info->red = def_rgb565[RED];
> + fb_info->green = def_rgb565[GREEN];
> + fb_info->blue = def_rgb565[BLUE];
> + fb_info->transp = def_rgb565[TRANSP];
> + break;
> + case 24:
> + case 32:
> + pr_debug("Setting up an RGB888/666 mode\n");
> + reg |= SET_WORD_LENGTH(3);
> + switch (pdata->ld_intf_width) {
> + case STMLCDIF_8BIT:
> + dev_dbg(fbi->hw_dev,
> + "Unsupported LCD bus width mapping\n");
> + break;
> + case STMLCDIF_16BIT:
> + case STMLCDIF_18BIT:
> + /* 24 bit to 18 bit mapping
> + * which means: ignore the upper 2 bits in
> + * each colour component
> + */
> + reg |= CTRL_DF24;
> + fb_info->red = def_rgb666[RED];
> + fb_info->green = def_rgb666[GREEN];
> + fb_info->blue = def_rgb666[BLUE];
> + fb_info->transp = def_rgb666[TRANSP];
> + break;
> + case STMLCDIF_24BIT:
> + /* real 24 bit */
> + fb_info->red = def_rgb888[RED];
> + fb_info->green = def_rgb888[GREEN];
> + fb_info->blue = def_rgb888[BLUE];
> + fb_info->transp = def_rgb888[TRANSP];
> + break;
> + }
> + /* do not use packed pixels = one pixel per word instead */
> + writel(SET_BYTE_PACKAGING(0x7), fbi->base + HW_LCDIF_CTRL1);
> + break;
> + default:
> + dev_dbg(fbi->hw_dev, "Unhandled colour depth of %u\n",
> + fb_info->bits_per_pixel);
> + return -EINVAL;
> + }
> + writel(reg, fbi->base + HW_LCDIF_CTRL);
> + pr_debug("Setting up CTRL to %08X\n", reg);
> +
> + writel(SET_VCOUNT(mode->yres) |
> + SET_HCOUNT(mode->xres), fbi->base + HW_LCDIF_TRANSFER_COUNT);
> +
> + reg = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
> + VDCTRL0_VSYNC_PERIOD_UNIT |
> + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT;
> + if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
> + reg |= VDCTRL0_HSYNC_POL;
> + if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
> + reg |= VDCTRL0_VSYNC_POL;
> + if (mode->sync & FB_SYNC_DE_HIGH_ACT)
> + reg |= VDCTRL0_ENABLE_POL;
> + if (mode->sync & FB_SYNC_CLK_INVERT)
> + reg |= VDCTRL0_DOTCLK_POL;
> +
> + reg |= SET_VSYNC_PULSE_WIDTH(mode->vsync_len);
> + writel(reg, fbi->base + HW_LCDIF_VDCTRL0);
> + pr_debug("Setting up VDCTRL0 to %08X\n", reg);
> +
> + /* frame length in lines */
> + writel(mode->upper_margin + mode->vsync_len + mode->lower_margin +
> + mode->yres,
> + fbi->base + HW_LCDIF_VDCTRL1);
> +
> + /* line length in units of clocks or pixels */
> + writel(SET_HSYNC_PULSE_WIDTH(mode->hsync_len) |
> + SET_HSYNC_PERIOD(mode->left_margin + mode->hsync_len +
> + mode->right_margin + mode->xres),
> + fbi->base + HW_LCDIF_VDCTRL2);
> +
> + writel(SET_HOR_WAIT_CNT(mode->left_margin + mode->hsync_len) |
> + SET_VERT_WAIT_CNT(mode->upper_margin + mode->vsync_len),
> + fbi->base + HW_LCDIF_VDCTRL3);
> +
> + writel(
> +#ifdef CONFIG_ARCH_IMX28
> + SET_DOTCLK_DLY(pdata->dotclk_delay) |
> +#endif
> + SET_DOTCLK_H_VALID_DATA_CNT(mode->xres),
> + fbi->base + HW_LCDIF_VDCTRL4);
> +
> + writel((uint32_t)fb_info->screen_base, fbi->base + HW_LCDIF_CUR_BUF);
> + writel((uint32_t)fb_info->screen_base, fbi->base + HW_LCDIF_NEXT_BUF);
> +
> + return 0;
> +}
> +
> +static void stmfb_info(struct device_d *hw_dev)
> +{
> + struct imx_fb_videomode *pdata = hw_dev->platform_data;
> + unsigned u;
> +
> + printf(" Supported video modes:\n");
> + for (u = 0; u < pdata->mode_cnt; u++)
> + printf(" - '%s': %u x %u\n", pdata->mode_list[u].name,
> + pdata->mode_list[u].xres, pdata->mode_list[u].yres);
> +}
> +
> +/*
> + * There is only one video hardware instance available.
> + * It makes no sense to dynamically allocate this data
> + */
> +static struct fb_ops imxfb_ops = {
> + .fb_activate_var = stmfb_activate_var,
> + .fb_enable = stmfb_enable_controller,
> + .fb_disable = stmfb_disable_controller,
> +};
> +
> +static struct imxfb_info fbi = {
> + .info = {
> + .fbops = &imxfb_ops,
> + },
> +};
> +
> +static int stmfb_probe(struct device_d *hw_dev)
> +{
> + struct imx_fb_videomode *pdata = hw_dev->platform_data;
> + int ret;
> +
> + /* just init */
> + fbi.info.priv = &fbi;
> +
> + /* add runtime hardware info */
> + fbi.hw_dev = hw_dev;
> + fbi.base = (void *)hw_dev->map_base;
> + fbi.pdata = pdata;
> +
> + /* add runtime video info */
> + fbi.info.mode_list = pdata->mode_list;
> + fbi.info.num_modes = pdata->mode_cnt;
> + fbi.info.mode = &fbi.info.mode_list[0];
> + fbi.info.xres = fbi.info.mode->xres;
> + fbi.info.yres = fbi.info.mode->yres;
> + fbi.info.bits_per_pixel = 16;
Could we consider to pass .bits_per_pixel through platform _data?
Is there any reason to hardcode this value?
> +
> + ret = register_framebuffer(&fbi.info);
At this point you register the framebuffer but screen_base is not set yet.
So when we want to access framebuffer from mmap we get a pointer to 0x0
instead of getting the pointer to the frambeffer address..
I moved stmfb_memory_mmgt from stmfb_activate_var to be able to
display a picture with bmp command. It worked for me because I have only
one screen available, but if you want to keep the capability to change screen on
the fly, then we will need to update map_base in fb driver.
> + if (ret != 0) {
> + dev_err(hw_dev, "Failed to register framebuffer\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static struct driver_d stmfb_driver = {
> + .name = "stmfb",
> + .probe = stmfb_probe,
> + .info = stmfb_info,
> +};
> +
> +static int stmfb_init(void)
> +{
> + return register_driver(&stmfb_driver);
> +}
> +
> +device_initcall(stmfb_init);
> +
> +/**
> + * @file
> + * @brief LCDIF driver for i.MX23 and i.MX28
> + *
> + * The LCDIF support four modes of operation
> + * - MPU interface (to drive smart displays) -> not supported yet
> + * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
> + * - Dotclock interface (to drive LC displays with RGB data and sync signals)
> + * - DVI (to drive ITU-R BT656) -> not supported yet
> + *
> + * This driver depends on a correct setup of the pins used for this purpose
> + * (platform specific).
> + *
> + * For the developer: Don't forget to set the data bus width to the display
> + * in the imx_fb_videomode structure. You will else end up with ugly colours.
> + * If you fight against jitter you can vary the clock delay. This is a feature
> + * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
> + * the required value in the imx_fb_videomode structure.
> + */
> --
> 1.7.2.3
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 09/10] ARM KARO-TX28-STK5: Add a user for video graphics support on i.MX28
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (7 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 08/10] ARM STM/i.MX: Add video driver " Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
2010-12-20 15:05 ` [PATCH 10/10] ARM Chumby-Falconwing: Add a user for video graphics support on i.MX23 Juergen Beisert
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/boards/karo-tx28/tx28-stk5.c | 148 +++++++++++++++++++++++++++++++++
arch/arm/configs/tx28stk5_defconfig | 4 +
2 files changed, 152 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boards/karo-tx28/tx28-stk5.c b/arch/arm/boards/karo-tx28/tx28-stk5.c
index a032e6a..6de41f7 100644
--- a/arch/arm/boards/karo-tx28/tx28-stk5.c
+++ b/arch/arm/boards/karo-tx28/tx28-stk5.c
@@ -23,6 +23,7 @@
#include <mach/imx-regs.h>
#include <mach/clock.h>
#include <mach/mci.h>
+#include <mach/fb.h>
static struct stm_mci_platform_data mci_pdata = {
.caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz,
@@ -48,6 +49,152 @@ static struct device_d fec_dev = {
.platform_data = &fec_info,
};
+/*
+ * The TX28 EVK comes with a VGA connector. We can support many video modes
+ *
+ * Note: The VGA connector is driven from the LCD lines via an ADV7125. This
+ * DA converter needs an high active DE signal to show a video signal.
+ */
+static struct fb_videomode tx28evk_vmodes[] = {
+ {
+ /*
+ * Modeline "640x480" x 59.9 (to be used with the VGA connector)
+ * Clock: 25.18 MHz
+ * Line: 640 656 752 800 (31.5 kHz)
+ * Frame: 480 490 492 525
+ * Syncs: -hsync -vsync
+ */
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25180),
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 33,
+ .vsync_len = 2,
+ .lower_margin = 10,
+ .sync = FB_SYNC_DE_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ }, {
+ /*
+ * Emerging ETV570 640 x 480 display (directly connected)
+ * Clock: 25.175 MHz
+ * Syncs: low active, DE high active
+ * Display area: 115.2 mm x 86.4 mm
+ */
+ .name = "ETV570",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 114,
+ .hsync_len = 30,
+ .right_margin = 16,
+ .upper_margin = 32,
+ .vsync_len = 3,
+ .lower_margin = 10,
+ .sync = FB_SYNC_DE_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ /*
+ * This display is connected:
+ * display side -> CPU side
+ * ----------------------------
+ * RESET# pin -> GPIO126 (3/30) LCD_RESET -> L = display reset
+ * PWRCTRL pin -> GPIO63 (1/31) LCD_ENABLE - > H=on, L=off
+ * LEDCTRL pin -> GPIO112 (2/16) PWM0 -> 2.5 V = LEDs off
+ * -> 0 V = LEDs on
+ *
+ * Note: Backlight is on, only if PWRCTRL=H _and_ LEDCTRL=0
+ */
+ }, {
+ /*
+ * Modeline "800x600" x 60.3
+ * Clock: 40.00 MHz
+ * Line: 800 840 968 1056 (37.9 kHz)
+ * Frame: 600 601 605 628
+ * Syncs: +hsync +vsync
+ */
+ .name = "SVGA",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = KHZ2PICOS(40000),
+ .left_margin = 88,
+ .hsync_len = 128,
+ .right_margin = 40,
+ .upper_margin = 23,
+ .vsync_len = 4,
+ .lower_margin = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
+ FB_SYNC_DE_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ }, {
+ /*
+ * Modeline "1024x768" x 60.0
+ * Clock: 65.00 MHz
+ * Line: 1024 1048 1184 1344 (48.4 kHz)
+ * Frame: 768 771 777 806
+ * Syncs: -hsync -vsync
+ */
+ .name = "XGA",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = KHZ2PICOS(65000),
+ .left_margin = 160,
+ .hsync_len = 136,
+ .right_margin = 24,
+ .upper_margin = 29,
+ .vsync_len = 6,
+ .lower_margin = 3,
+ .sync = FB_SYNC_DE_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ }, {
+ /*
+ * Modeline "1280x1024" x 60.0
+ * Clock: 108.00 MHz
+ * Line: 1280 1328 1440 1688 (64.0 kHz)
+ * Frame: 1024 1025 1028 1066
+ * Syncs: +hsync +vsync
+ */
+ .name = "SXGA",
+ .refresh = 60,
+ .xres = 1280,
+ .yres = 1024,
+ .pixclock = KHZ2PICOS(108000),
+ .left_margin = 248,
+ .hsync_len = 112,
+ .right_margin = 48,
+ .upper_margin = 38,
+ .vsync_len = 3,
+ .lower_margin = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
+ FB_SYNC_DE_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ },
+};
+
+static struct imx_fb_videomode imxfb_mode = {
+ .mode_list = tx28evk_vmodes,
+ .mode_cnt = ARRAY_SIZE(tx28evk_vmodes),
+ .dotclk_delay = 0, /* no adaption required */
+ .ld_intf_width = STMLCDIF_24BIT, /* full 24 bit */
+};
+
+static struct device_d ldcif_dev = {
+ .name = "stmfb",
+ .map_base = IMX_FB_BASE,
+ .size = 4096,
+ .platform_data = &imxfb_mode,
+};
+
static const uint32_t tx28_starterkit_pad_setup[] = {
/*
* Part II of phy's initialization
@@ -205,6 +352,7 @@ void base_board_init(void)
imx_set_sspclk(0, 100000000, 1);
register_device(&mci_socket);
+ register_device(&ldcif_dev);
imx_enable_enetclk();
register_device(&fec_dev);
diff --git a/arch/arm/configs/tx28stk5_defconfig b/arch/arm/configs/tx28stk5_defconfig
index 7246553..d6b81c6 100644
--- a/arch/arm/configs/tx28stk5_defconfig
+++ b/arch/arm/configs/tx28stk5_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARCH_STM=y
CONFIG_ARCH_IMX28=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_MALLOC_SIZE=0x800000
CONFIG_BROKEN=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -30,12 +31,15 @@ CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_BMP=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_TFTP=y
CONFIG_NET_RESOLV=y
CONFIG_DRIVER_NET_FEC_IMX=y
# CONFIG_SPI is not set
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_STM=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_STM378X=y
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 10/10] ARM Chumby-Falconwing: Add a user for video graphics support on i.MX23
2010-12-20 15:04 [PATCH] Add support for runtime selection of video mode in barebox Juergen Beisert
` (8 preceding siblings ...)
2010-12-20 15:05 ` [PATCH 09/10] ARM KARO-TX28-STK5: Add a user for video graphics support on i.MX28 Juergen Beisert
@ 2010-12-20 15:05 ` Juergen Beisert
9 siblings, 0 replies; 12+ messages in thread
From: Juergen Beisert @ 2010-12-20 15:05 UTC (permalink / raw)
To: barebox
[-- Attachment #1: Type: text/plain, Size: 4039 bytes --]
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
arch/arm/boards/chumby_falconwing/falconwing.c | 88 +++++++++++++++++------
arch/arm/configs/chumbyone_defconfig | 3 +
2 files changed, 68 insertions(+), 23 deletions(-)
diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c
index 93ce7e2..f5ed133 100644
--- a/arch/arm/boards/chumby_falconwing/falconwing.c
+++ b/arch/arm/boards/chumby_falconwing/falconwing.c
@@ -28,6 +28,7 @@
#include <mach/imx-regs.h>
#include <mach/clock.h>
#include <mach/mci.h>
+#include <mach/fb.h>
static struct memory_platform_data ram_pdata = {
.name = "ram0",
@@ -53,6 +54,45 @@ static struct device_d mci_dev = {
.platform_data = &mci_pdata,
};
+static struct fb_videomode falconwing_vmode = {
+ /*
+ * Nanovision NMA35QV65-B2-K01 (directly connected)
+ * Clock: 6.25 MHz
+ * Syncs: high active, DE low active
+ * Display area: 70.08 mm x 52.56 mm
+ */
+ .name = "NMA35",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6250), /* max. 10 MHz */
+ /* line lenght should be 64 �s */
+ .left_margin = 28,
+ .hsync_len = 24,
+ .right_margin = 28,
+ /* frame rate should be 60 Hz */
+ .upper_margin = 8,
+ .vsync_len = 4,
+ .lower_margin = 8,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_fb_videomode fb_mode = {
+ .mode_list = &falconwing_vmode,
+ .mode_cnt = 1,
+ /* the NMA35 is a 24 bit display, but only 18 bits are connected */
+ .ld_intf_width = STMLCDIF_18BIT,
+};
+
+static struct device_d ldcif_dev = {
+ .name = "stmfb",
+ .map_base = IMX_FB_BASE,
+ .size = 4096,
+ .platform_data = &fb_mode,
+};
+
static const uint32_t pad_setup[] = {
/* may be not required as already done by the bootlet code */
#if 0
@@ -113,33 +153,34 @@ static const uint32_t pad_setup[] = {
PWM0_DUART_RX | STRENGTH(S4MA), /* strength is TBD */
/* lcd */
- LCD_VSYNC, /* kernel tries with 12 mA for all LCD related pins */
- LCD_HSYNC,
- LCD_ENABE,
- LCD_DOTCLOCK,
- LCD_D17,
- LCD_D16,
- LCD_D15,
- LCD_D14,
- LCD_D13,
- LCD_D12,
- LCD_D11,
- LCD_D10,
- LCD_D9,
- LCD_D8,
- LCD_D7,
- LCD_D6,
- LCD_D5,
- LCD_D4,
- LCD_D3,
- LCD_D2,
- LCD_D1,
- LCD_D0,
+ LCD_VSYNC | STRENGTH(S12MA),
+ LCD_HSYNC | STRENGTH(S12MA),
+ LCD_ENABE | STRENGTH(S12MA),
+ LCD_DOTCLOCK | STRENGTH(S12MA),
+ LCD_D17 | STRENGTH(S12MA),
+ LCD_D16 | STRENGTH(S12MA),
+ LCD_D15 | STRENGTH(S12MA),
+ LCD_D14 | STRENGTH(S12MA),
+ LCD_D13 | STRENGTH(S12MA),
+ LCD_D12 | STRENGTH(S12MA),
+ LCD_D11 | STRENGTH(S12MA),
+ LCD_D10 | STRENGTH(S12MA),
+ LCD_D9 | STRENGTH(S12MA),
+ LCD_D8 | STRENGTH(S12MA),
+ LCD_D7 | STRENGTH(S12MA),
+ LCD_D6 | STRENGTH(S12MA),
+ LCD_D5 | STRENGTH(S12MA),
+ LCD_D4 | STRENGTH(S12MA),
+ LCD_D3 | STRENGTH(S12MA),
+ LCD_D2 | STRENGTH(S12MA),
+ LCD_D1 | STRENGTH(S12MA),
+ LCD_D0 | STRENGTH(S12MA),
/* LCD usage currently unknown */
LCD_CS, /* used as SPI SS */
LCD_RS, /* used as SPI CLK */
- LCD_RESET,
+ /* keep the display in reset state */
+ LCD_RESET_GPIO | STRENGTH(S4MA) | GPIO_OUT | GPIO_VALUE(0),
LCD_WR, /* used as SPI MOSI */
/* I2C to the MMA7455L, KXTE9, AT24C08 (DCID), AT24C128B (ID EEPROM) and QN8005B */
@@ -270,6 +311,7 @@ static int falconwing_devices_init(void)
/* run the SSP unit clock at 100,000 kHz */
imx_set_sspclk(0, 100000000, 1);
register_device(&mci_dev);
+ register_device(&ldcif_dev);
armlinux_add_dram(&sdram_dev);
armlinux_set_bootparams((void*)(sdram_dev.map_base + 0x100));
diff --git a/arch/arm/configs/chumbyone_defconfig b/arch/arm/configs/chumbyone_defconfig
index 595b6a9..6e6623a 100644
--- a/arch/arm/configs/chumbyone_defconfig
+++ b/arch/arm/configs/chumbyone_defconfig
@@ -23,7 +23,10 @@ CONFIG_CMD_MTEST_ALTERNATIVE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_BMP=y
# CONFIG_SPI is not set
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_STM=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_STM378X=y
--
1.7.2.3
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread