Skip to contentSkip to conversation

tegra: Add display driver and LCD support for Seaboard

PATCH Superseded Simon Glass 4 participants 20 messages Oct 8, 2012 – Oct 17, 2012 1 message not in the archive

Subsystems (4)

v5 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v5 cover tegra: Add display driver and LCD support for Seaboard

This series adds support for the Tegra2x's display peripheral. This supports the LCD display on Seaboard and we use this to enable console output in U-Boot on the LCD.

Configuration is via the device tree. Proposed bindings are included in this series, taken from pwm bindings that should be in linux-next, a Tegra video binding that might be accepted in devicetree-discuss and a proposed video mode binding posted to dri-devel.

While I agree EDID is convenient for machines I would prefer to provide a user-friendly way of selecting LCD settings as well, with EDID more as a fallback and auto-detection when available.

To improve performance two optimisations are offered:

1. The LCD frame buffer is cached, with the cache being flushed after each newline sent to putc(), and in a few other situations. This dramatically increases performance (around 10x). This requires a few additions to the ARM cache support.

2. The console supports scrolling in steps of more than 1 line. This speeds up scrolling output considerably, particularly commands like 'printenv' which display a lot of output, and particular when the dcache is off. This requires a new CONFIG and a change to the console_scrollup() function.

As reported by Stephen Warren: there is one problem with this serial. The display works fine for cold boot, or hitting the physical reset button, but when I execute "reset" at the U-Boot prompt, or "reboot" within Linux, the display is messed up; it looks like the LCD isn't able to sync to the timings sent by the display controller or something similar.

Changes in v5:
- Update Tegra PWM binding s/duty cycle/period/
- Make all Tegra LCD fdt nodes disabled by default
- Enable required LCD fdt nodes (which are now disabled by default)
- Fix CONFIG_CONSOLE_SCROLL_LINES commit title
- Fix misleading comments in common/lcd.c

Changes in v4:
- Moved panel information into panel node (was in rgb node)
- Remove LCD frame buffer address property hack
- Add CONFIG_PWM_TEGRA to control inclusion of PWM support
- Add a little more debugging to the PWM driver
- Move code to set up PWM into the PWM commit
- Rebase on top of new tegra common directory structure
- Adjust fdt binding according to Thierry and Stephen's comments
- Remove LCD frame buffer address property hack
- Rebase on top of new tegra common directory structure
- Change LCD panel GPIOs to be entirely optional
- Only indicate that LCD init is complete when all stages complete
- Change order of LCD init so that PWM comes first
- Use system bit values for enum dcache_option instead of arbitrary numbers
- Remove system.h header which is included anyway by most archs
- Use lcd_puts() for echoing user input so lcd cached data is flushed
- Adjust LCD fdt nodes for new binding
- Remove LCD frame buffer address property hack
- Use CONFIG_CONSOLE_SCROLL_LINES instead of CONSOLE_SCROLL_LINES
- Put default CONFIG_CONSOLE_SCROLL_LINES at top of file
- Add CONFIG_BOARD_LATE_INIT to enable LCD
- Use CONFIG_CONSOLE_SCROLL_LINES instead of CONSOLE_SCROLL_LINES
- Enable separate CONFIG_PWM_TEGRA option

Changes in v3:
- Remove LPW1 pin which is not needed by display
- Add new commit for pwm binding and node
- Use displaymode binding for fdt
- Bring in proposed tegra display controller binding
- Add new panel binding to fit with tegra display controller binding
- Rename pwfm driver to pwm
- Use new proposed upstream pwm binding
- Decode fdt node within the pwm driver
- Introduce concept of a pwm channel, rather than separate peripherals
- Separate display driver and LCD driver more in fdt
- Add probe function to read in fdt parameters in display driver
- Move some fdt decode code from LCD driver to SOC display driver
- Rename fdt config structures
- Use new pwm binding from pre-linux-next
- Adjust LCD driver to use new SOC display driver structures
- Add separate call to pwm_init() in board_init()
- Put the LCD cache flush logic back into lcd_puts()
- Handle a cached frame buffer out of normal U-Boot memory
- Use new upstream proposed LCD definitions
- Fix tiny bug in mult-line lcd scrolling

Changes in v2:
- Add new patch to use const in pinmux_config_pingroup/table()
- Use const where possible in funcmux
- Add nvidia prefix to device tree properties
- Update LCD driver to deal with new fdt bindings
- Use a more generic config CONFIG_LCD_ALIGNMENT for lcd alignment
- Put the LCD cache flush logic into lcd_putc() instead of lcd_puts()
- Align tegra display using new CONFIG_LCD_ALIGNMENT feature
- Update seaboard LCD definitions for new fdt binding

Mayuresh Kulkarni (1):
tegra: Enable display/lcd support on Seaboard

Simon Glass (14):
tegra: Use const for pinmux_config_pingroup/table()
tegra: Add display support to funcmux
tegra: fdt: Add pwm binding and node
tegra: fdt: Add LCD definitions for Tegra
tegra: Add support for PWM
tegra: Add LCD driver
tegra: Add LCD support to Nvidia boards
arm: Add control over cachability of memory regions
lcd: Add CONFIG_LCD_ALIGNMENT to select frame buffer alignment
lcd: Add support for flushing LCD fb from dcache after update
tegra: Align LCD frame buffer to section boundary
tegra: Support control of cache settings for LCD
tegra: fdt: Add LCD definitions for Seaboard
lcd: Add CONFIG_CONSOLE_SCROLL_LINES option to speed console

Wei Ni (1):
tegra: Add SOC support for display/lcd

 README                                         |   16 +
 arch/arm/cpu/armv7/cache_v7.c                  |   11 +
 arch/arm/cpu/armv7/tegra20/Makefile            |    2 +
 arch/arm/cpu/armv7/tegra20/display.c           |  409 ++++++++++++++++++
 arch/arm/cpu/armv7/tegra20/pwm.c               |  101 +++++
 arch/arm/cpu/tegra20-common/funcmux.c          |   37 ++
 arch/arm/cpu/tegra20-common/pinmux.c           |    4 +-
 arch/arm/dts/tegra20.dtsi                      |  105 +++++
 arch/arm/include/asm/arch-tegra20/dc.h         |  545 ++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra20/display.h    |  152 +++++++
 arch/arm/include/asm/arch-tegra20/pinmux.h     |    4 +-
 arch/arm/include/asm/arch-tegra20/pwm.h        |   75 ++++
 arch/arm/include/asm/system.h                  |   30 ++
 arch/arm/lib/cache-cp15.c                      |   50 ++-
 board/nvidia/common/board.c                    |   26 ++-
 board/nvidia/dts/tegra20-seaboard.dts          |   33 ++
 common/lcd.c                                   |   89 ++++-
 common/main.c                                  |   12 +-
 doc/device-tree-bindings/pwm/tegra20-pwm.txt   |   18 +
 doc/device-tree-bindings/video/displaymode.txt |   42 ++
 doc/device-tree-bindings/video/tegra20-dc.txt  |   84 ++++
 drivers/video/Makefile                         |    1 +
 drivers/video/tegra.c                          |  372 ++++++++++++++++
 include/configs/seaboard.h                     |   13 +-
 include/configs/tegra20-common.h               |    3 +
 include/fdtdec.h                               |    2 +
 include/lcd.h                                  |   11 +
 lib/fdtdec.c                                   |    2 +
 28 files changed, 2212 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra20/display.c
 create mode 100644 arch/arm/cpu/armv7/tegra20/pwm.c
 create mode 100644 arch/arm/include/asm/arch-tegra20/dc.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/display.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/pwm.h
 create mode 100644 doc/device-tree-bindings/pwm/tegra20-pwm.txt
 create mode 100644 doc/device-tree-bindings/video/displaymode.txt
 create mode 100644 doc/device-tree-bindings/video/tegra20-dc.txt
 create mode 100644 drivers/video/tegra.c
Signature · 1 line
1.7.7.3
#1 lore raw

PATCH v5 1/16 tegra: Use const for pinmux_config_pingroup/table()

These two functions don't actually modify their arguments so add a const keyword.

---
Changes in v2:
- Add new patch to use const in pinmux_config_pingroup/table()

 arch/arm/cpu/tegra20-common/pinmux.c       |    4 ++--
 arch/arm/include/asm/arch-tegra20/pinmux.h |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
arch/arm/cpu/tegra20-common/pinmux.c +2 -2
index 08b8305..a2a0916 100644
@@ -554,7 +554,7 @@ void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
 	writel(reg, muxctl);
 }
 
-void pinmux_config_pingroup(struct pingroup_config *config)
+void pinmux_config_pingroup(const struct pingroup_config *config)
 {
 	enum pmux_pingrp pin = config->pingroup;
 
@@ -563,7 +563,7 @@ void pinmux_config_pingroup(struct pingroup_config *config)
 	pinmux_set_tristate(pin, config->tristate);
 }
 
-void pinmux_config_table(struct pingroup_config *config, int len)
+void pinmux_config_table(const struct pingroup_config *config, int len)
 {
 	int i;
 
arch/arm/include/asm/arch-tegra20/pinmux.h +2 -2
index 03fa7ca..797e158 100644
@@ -339,7 +339,7 @@ void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd);
 void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func);
 
 /* Set the complete configuration for a pin group */
-void pinmux_config_pingroup(struct pingroup_config *config);
+void pinmux_config_pingroup(const struct pingroup_config *config);
 
 void pinmux_set_tristate(enum pmux_pingrp pin, int enable);
 
@@ -349,6 +349,6 @@ void pinmux_set_tristate(enum pmux_pingrp pin, int enable);
  * @param config	List of config items
  * @param len		Number of config items in list
  */
-void pinmux_config_table(struct pingroup_config *config, int len);
+void pinmux_config_table(const struct pingroup_config *config, int len);
 
 #endif	/* PINMUX_H */
Signature · 1 line
1.7.7.3
#2 lore raw

PATCH v5 2/16 tegra: Add display support to funcmux

In reply to Simon Glass

Add support for a default pin mapping for display1.

---
Changes in v3:
- Remove LPW1 pin which is not needed by display

Changes in v2:
- Use const where possible in funcmux

 arch/arm/cpu/tegra20-common/funcmux.c |   37 +++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)
arch/arm/cpu/tegra20-common/funcmux.c +37 -0
index b2129ad..ca20f93 100644
@@ -25,6 +25,30 @@
 #include <asm/arch/funcmux.h>
 #include <asm/arch/pinmux.h>
 
+/*
+ * The PINMUX macro is used to set up pinmux tables.
+ */
+#define PINMUX(grp, mux, pupd, tri)                   \
+	{PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
+
+static const struct pingroup_config disp1_default[] = {
+	PINMUX(LDI,   DISPA,      NORMAL,    NORMAL),
+	PINMUX(LHP0,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LHP1,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LHP2,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LHS,   DISPA,      NORMAL,    NORMAL),
+	PINMUX(LM0,   RSVD4,      NORMAL,    NORMAL),
+	PINMUX(LPP,   DISPA,      NORMAL,    NORMAL),
+	PINMUX(LPW0,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LPW2,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LSC0,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LSPI,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LVP1,  DISPA,      NORMAL,    NORMAL),
+	PINMUX(LVS,   DISPA,      NORMAL,    NORMAL),
+	PINMUX(SLXD,  SPDIF,      NORMAL,    NORMAL),
+};
+
+
 int funcmux_select(enum periph_id id, int config)
 {
 	int bad_config = config != FUNCMUX_DEFAULT;
@@ -240,6 +264,19 @@ int funcmux_select(enum periph_id id, int config)
 			pinmux_tristate_disable(PINGRP_ATC);
 		}
 		break;
+	case PERIPH_ID_DISP1:
+		if (config == FUNCMUX_DEFAULT) {
+			int i;
+
+			for (i = PINGRP_LD0; i <= PINGRP_LD17; i++) {
+				pinmux_set_func(i, PMUX_FUNC_DISPA);
+				pinmux_tristate_disable(i);
+				pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
+			}
+			pinmux_config_table(disp1_default,
+					    ARRAY_SIZE(disp1_default));
+		}
+		break;
 
 	default:
 		debug("%s: invalid periph_id %d", __func__, id);
Signature · 1 line
1.7.7.3

A message that is not in the archive (sent off-list or not yet received): 1349732556-30700-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org

#4 lore raw

PATCH v5 3/16 tegra: fdt: Add pwm binding and node

This binding will apparently soon be in linux-next. Bring it in now since we need to do something, and may as well try to target what Linux will have.

---
Changes in v5:
- Update Tegra PWM binding s/duty cycle/period/

Changes in v3:
- Add new commit for pwm binding and node

 arch/arm/dts/tegra20.dtsi                    |    7 +++++++
 doc/device-tree-bindings/pwm/tegra20-pwm.txt |   18 ++++++++++++++++++
 2 files changed, 25 insertions(+), 0 deletions(-)
 create mode 100644 doc/device-tree-bindings/pwm/tegra20-pwm.txt
arch/arm/dts/tegra20.dtsi +7 -0
index d936b1e..3221bc9 100644
@@ -211,4 +211,11 @@
 		compatible = "nvidia,tegra20-nand";
 		reg = <0x70008000 0x100>;
 	};
+
+	pwm: pwm@7000a000 {
+		compatible = "nvidia,tegra20-pwm";
+		reg = <0x7000a000 0x100>;
+		#pwm-cells = <2>;
+	};
+
 };
doc/device-tree-bindings/pwm/tegra20-pwm.txt new file +18 -0
new file mode 100644
index 0000000..01438ec
@@ -0,0 +1,18 @@
+Tegra SoC PWFM controller
+
+Required properties:
+- compatible: should be one of:
+  - "nvidia,tegra20-pwm"
+  - "nvidia,tegra30-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The
+  first cell specifies the per-chip index of the PWM to use and the second
+  cell is the period in nanoseconds.
+
+Example:
+
+	pwm: pwm@7000a000 {
+		compatible = "nvidia,tegra20-pwm";
+		reg = <0x7000a000 0x100>;
+		#pwm-cells = <2>;
+	};
Signature · 1 line
1.7.7.3
#5 lore raw

PATCH v5 4/16 tegra: fdt: Add LCD definitions for Tegra

In reply to a message not in the archive

Add LCD definitions and also a proposed binding for LCD displays.

The PWM is as per what will likely be committed to linux-next soon.

The displaymode binding comes from a proposal here:

http://lists.freedesktop.org/archives/dri-devel/2012-July/024875.html

The panel binding is new, and fills a need to specify the panel timings and other tegra-specific information. Should a binding appear that allows the pwm to handle this automatically, we can revisit this.

---
Changes in v5:
- Make all Tegra LCD fdt nodes disabled by default

Changes in v4:
- Moved panel information into panel node (was in rgb node)
- Remove LCD frame buffer address property hack

Changes in v3:
- Use displaymode binding for fdt
- Bring in proposed tegra display controller binding
- Add new panel binding to fit with tegra display controller binding

Changes in v2:
- Add nvidia prefix to device tree properties

 arch/arm/dts/tegra20.dtsi                      |   98 ++++++++++++++++++++++++
 doc/device-tree-bindings/video/displaymode.txt |   42 ++++++++++
 doc/device-tree-bindings/video/tegra20-dc.txt  |   84 ++++++++++++++++++++
 3 files changed, 224 insertions(+), 0 deletions(-)
 create mode 100644 doc/device-tree-bindings/video/displaymode.txt
 create mode 100644 doc/device-tree-bindings/video/tegra20-dc.txt
arch/arm/dts/tegra20.dtsi +98 -0
index 3221bc9..636ec2c 100644
@@ -218,4 +218,102 @@
 		#pwm-cells = <2>;
 	};
 
+	host1x {
+		compatible = "nvidia,tegra20-host1x", "simple-bus";
+		reg = <0x50000000 0x00024000>;
+		interrupts = <0 65 0x04   /* mpcore syncpt */
+			      0 67 0x04>; /* mpcore general */
+		status = "disabled";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0x54000000 0x54000000 0x04000000>;
+
+		/* video-encoding/decoding */
+		mpe {
+			reg = <0x54040000 0x00040000>;
+			interrupts = <0 68 0x04>;
+			status = "disabled";
+		};
+
+		/* video input */
+		vi {
+			reg = <0x54080000 0x00040000>;
+			interrupts = <0 69 0x04>;
+			status = "disabled";
+		};
+
+		/* EPP */
+		epp {
+			reg = <0x540c0000 0x00040000>;
+			interrupts = <0 70 0x04>;
+			status = "disabled";
+		};
+
+		/* ISP */
+		isp {
+			reg = <0x54100000 0x00040000>;
+			interrupts = <0 71 0x04>;
+			status = "disabled";
+		};
+
+		/* 2D engine */
+		gr2d {
+			reg = <0x54140000 0x00040000>;
+			interrupts = <0 72 0x04>;
+			status = "disabled";
+		};
+
+		/* 3D engine */
+		gr3d {
+			reg = <0x54180000 0x00040000>;
+			status = "disabled";
+		};
+
+		/* display controllers */
+		dc@54200000 {
+			compatible = "nvidia,tegra20-dc";
+			reg = <0x54200000 0x00040000>;
+			interrupts = <0 73 0x04>;
+			status = "disabled";
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		dc@54240000 {
+			compatible = "nvidia,tegra20-dc";
+			reg = <0x54240000 0x00040000>;
+			interrupts = <0 74 0x04>;
+			status = "disabled";
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		/* outputs */
+		hdmi {
+			compatible = "nvidia,tegra20-hdmi";
+			reg = <0x54280000 0x00040000>;
+			interrupts = <0 75 0x04>;
+			status = "disabled";
+		};
+
+		tvo {
+			compatible = "nvidia,tegra20-tvo";
+			reg = <0x542c0000 0x00040000>;
+			interrupts = <0 76 0x04>;
+			status = "disabled";
+		};
+
+		dsi {
+			compatible = "nvidia,tegra20-dsi";
+			reg = <0x54300000 0x00040000>;
+			status = "disabled";
+		};
+	};
+
 };
doc/device-tree-bindings/video/displaymode.txt new file +42 -0

42 lines not on this page · raw message

doc/device-tree-bindings/video/tegra20-dc.txt new file +84 -0

84 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#6 lore raw

PATCH v5 14/16 tegra: fdt: Add LCD definitions for Seaboard

In reply to a message not in the archive

The Seaboard has a 1366x768 16bpp LCD. The backlight is controlled by one of the PWMs.

---
Changes in v5:
- Enable required LCD fdt nodes (which are now disabled by default)

Changes in v4:
- Adjust LCD fdt nodes for new binding
- Remove LCD frame buffer address property hack

Changes in v3:
- Use new upstream proposed LCD definitions

Changes in v2:
- Update seaboard LCD definitions for new fdt binding

 board/nvidia/dts/tegra20-seaboard.dts |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)
board/nvidia/dts/tegra20-seaboard.dts +33 -0
index 25a63a0..02d7c68 100644
@@ -163,4 +163,37 @@
 			compatible = "hynix,hy27uf4g2b", "nand-flash";
 		};
 	};
+
+	host1x {
+		status = "okay";
+		dc@54200000 {
+			status = "okay";
+			rgb {
+				status = "okay";
+				nvidia,panel = <&lcd_panel>;
+			};
+		};
+	};
+
+	lcd_panel: panel {
+		/* Seaboard has 1366x768 */
+		clock = <70600000>;
+		xres = <1366>;
+		yres = <768>;
+		left-margin = <58>;
+		right-margin = <58>;
+		hsync-len = <58>;
+		lower-margin = <4>;
+		upper-margin = <4>;
+		vsync-len = <4>;
+		hsync-active-high;
+		nvidia,bits-per-pixel = <16>;
+		nvidia,pwm = <&pwm 2 0>;
+		nvidia,backlight-enable-gpios = <&gpio 28 0>;	/* PD4 */
+		nvidia,lvds-shutdown-gpios = <&gpio 10 0>;	/* PB2 */
+		nvidia,backlight-vdd-gpios = <&gpio 176 0>;	/* PW0 */
+		nvidia,panel-vdd-gpios = <&gpio 22 0>;		/* PC6 */
+		nvidia,panel-timings = <4 203 17 15>;
+	};
+
 };
Signature · 1 line
1.7.7.3
#7 lore raw

PATCH v5 5/16 tegra: Add support for PWM

In reply to Simon Glass

The pulse width/frequency modulation peripheral supports generating a repeating pulse. It is useful for controlling LCD brightness.

---
Changes in v4:
- Add CONFIG_PWM_TEGRA to control inclusion of PWM support
- Add a little more debugging to the PWM driver
- Move code to set up PWM into the PWM commit

Changes in v3:
- Rename pwfm driver to pwm
- Use new proposed upstream pwm binding
- Decode fdt node within the pwm driver
- Introduce concept of a pwm channel, rather than separate peripherals

 arch/arm/cpu/armv7/tegra20/Makefile     |    1 +
 arch/arm/cpu/armv7/tegra20/pwm.c        |  101 +++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra20/pwm.h |   75 +++++++++++++++++++++++
 board/nvidia/common/board.c             |    5 ++
 include/fdtdec.h                        |    1 +
 lib/fdtdec.c                            |    1 +
 6 files changed, 184 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra20/pwm.c
 create mode 100644 arch/arm/include/asm/arch-tegra20/pwm.h
arch/arm/cpu/armv7/tegra20/Makefile +1 -0
index 09a0314..77cb4d1 100644
@@ -28,6 +28,7 @@ include $(TOPDIR)/config.mk
 LIB	=  $(obj)lib$(SOC).o
 
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
+COBJS-$(CONFIG_PWM_TEGRA) += pwm.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
arch/arm/cpu/armv7/tegra20/pwm.c new file +101 -0

101 lines not on this page · raw message

arch/arm/include/asm/arch-tegra20/pwm.h new file +75 -0

75 lines not on this page · raw message

board/nvidia/common/board.c +5 -0
index 8821fdf..7a7d55c 100644
@@ -29,6 +29,7 @@
 #include <asm/arch/emc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/pmu.h>
+#include <asm/arch/pwm.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch/usb.h>
 #include <asm/arch-tegra/board.h>
@@ -105,6 +106,10 @@ int board_init(void)
 	pin_mux_spi();
 	spi_init();
 #endif
+#ifdef CONFIG_PWM_TEGRA
+	if (pwm_init(gd->fdt_blob))
+		debug("%s: Failed to init pwm\n", __func__);
+#endif
 	/* boot param addr */
 	gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100);
 
include/fdtdec.h +1 -0
index 0b14075..cdc87eb 100644
@@ -66,6 +66,7 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
 	COMPAT_NVIDIA_TEGRA20_KBC,	/* Tegra20 Keyboard */
 	COMPAT_NVIDIA_TEGRA20_NAND,	/* Tegra2 NAND controller */
+	COMPAT_NVIDIA_TEGRA20_PWM,	/* Tegra 2 PWM controller */
 
 	COMPAT_COUNT,
 };
lib/fdtdec.c +1 -0
index 4c23f45..947f7c0 100644
@@ -43,6 +43,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
 	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),
 	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
+	COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
1.7.7.3
#8 lore raw

PATCH v5 6/16 tegra: Add SOC support for display/lcd

In reply to Simon Glass

From: Wei Ni <[email protected]>

Add support for the LCD peripheral at the Tegra2 SOC level. A separate LCD driver will use this functionality to configure the display.

Mayuresh Kulkarni:
- changes to remove bitfields and clean up for submission

Simon Glass:
- simplify code, move clock control into here, clean-up

---
Changes in v4:
- Rebase on top of new tegra common directory structure
- Adjust fdt binding according to Thierry and Stephen's comments
- Remove LCD frame buffer address property hack

Changes in v3:
- Separate display driver and LCD driver more in fdt
- Add probe function to read in fdt parameters in display driver

 arch/arm/cpu/armv7/tegra20/Makefile         |    1 +
 arch/arm/cpu/armv7/tegra20/display.c        |  409 ++++++++++++++++++++
 arch/arm/include/asm/arch-tegra20/dc.h      |  545 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra20/display.h |  152 ++++++++
 include/fdtdec.h                            |    1 +
 lib/fdtdec.c                                |    1 +
 6 files changed, 1109 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra20/display.c
 create mode 100644 arch/arm/include/asm/arch-tegra20/dc.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/display.h
arch/arm/cpu/armv7/tegra20/Makefile +1 -0
index 77cb4d1..54ed8c4 100644
@@ -29,6 +29,7 @@ LIB	=  $(obj)lib$(SOC).o
 
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
 COBJS-$(CONFIG_PWM_TEGRA) += pwm.o
+COBJS-$(CONFIG_VIDEO_TEGRA) += display.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
arch/arm/cpu/armv7/tegra20/display.c new file +409 -0

409 lines not on this page · raw message

arch/arm/include/asm/arch-tegra20/dc.h new file +545 -0

545 lines not on this page · raw message

arch/arm/include/asm/arch-tegra20/display.h new file +152 -0

152 lines not on this page · raw message

include/fdtdec.h +1 -0
index cdc87eb..64e5cff 100644
@@ -67,6 +67,7 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_KBC,	/* Tegra20 Keyboard */
 	COMPAT_NVIDIA_TEGRA20_NAND,	/* Tegra2 NAND controller */
 	COMPAT_NVIDIA_TEGRA20_PWM,	/* Tegra 2 PWM controller */
+	COMPAT_NVIDIA_TEGRA20_DC,	/* Tegra 2 Display controller */
 
 	COMPAT_COUNT,
 };
lib/fdtdec.c +1 -0
index 947f7c0..23e0205 100644
@@ -44,6 +44,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),
 	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
 	COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
+	COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
1.7.7.3
#9 lore raw

PATCH v5 7/16 tegra: Add LCD driver

In reply to Simon Glass

This driver supports driving a single LCD and providing a U-Boot console on it.

---
Changes in v4:
- Rebase on top of new tegra common directory structure
- Change LCD panel GPIOs to be entirely optional
- Only indicate that LCD init is complete when all stages complete

Changes in v3:
- Move some fdt decode code from LCD driver to SOC display driver
- Rename fdt config structures
- Use new pwm binding from pre-linux-next
- Adjust LCD driver to use new SOC display driver structures

Changes in v2:
- Update LCD driver to deal with new fdt bindings

 drivers/video/Makefile |    1 +
 drivers/video/tegra.c  |  361 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 362 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/tegra.c
drivers/video/Makefile +1 -0
index ebb6da8..78a7668 100644
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
 COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o
 COBJS-$(CONFIG_VIDEO_SM501) += sm501.o
 COBJS-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
+COBJS-$(CONFIG_VIDEO_TEGRA) += tegra.o
 COBJS-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 
 COBJS	:= $(sort $(COBJS-y))
drivers/video/tegra.c new file +361 -0

361 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#10 lore raw

PATCH v5 8/16 tegra: Add LCD support to Nvidia boards

In reply to Simon Glass

Add calls to the LCD driver from Nvidia board code.

---
Changes in v4:
- Change order of LCD init so that PWM comes first

Changes in v3:
- Add separate call to pwm_init() in board_init()

 board/nvidia/common/board.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)
board/nvidia/common/board.c +20 -1
index 7a7d55c..17aafb6 100644
@@ -26,6 +26,7 @@
 #include <linux/compiler.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/display.h>
 #include <asm/arch/emc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/pmu.h>
@@ -110,6 +111,9 @@ int board_init(void)
 	if (pwm_init(gd->fdt_blob))
 		debug("%s: Failed to init pwm\n", __func__);
 #endif
+#ifdef CONFIG_LCD
+	tegra_lcd_check_next_stage(gd->fdt_blob, 0);
+#endif
 	/* boot param addr */
 	gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100);
 
@@ -135,6 +139,9 @@ int board_init(void)
 	pin_mux_usb();
 	board_usb_init(gd->fdt_blob);
 #endif
+#ifdef CONFIG_LCD
+	tegra_lcd_check_next_stage(gd->fdt_blob, 0);
+#endif
 
 #ifdef CONFIG_TEGRA_LP0
 	/* save Sdram params to PMC 2, 4, and 24 for WB0 */
@@ -165,6 +172,18 @@ int board_early_init_f(void)
 #else
 	gpio_config_uart();
 #endif
-	return 0;
+#ifdef CONFIG_LCD
+	tegra_lcd_early_init(gd->fdt_blob);
+#endif
+return 0;
 }
 #endif	/* EARLY_INIT */
+
+int board_late_init(void)
+{
+#ifdef CONFIG_LCD
+	/* Make sure we finish initing the LCD */
+	tegra_lcd_check_next_stage(gd->fdt_blob, 1);
+#endif
+	return 0;
+}
Signature · 1 line
1.7.7.3
#11 lore raw

PATCH v5 9/16 arm: Add control over cachability of memory regions

In reply to Simon Glass

Add support for adjusting the cachability of an L1 section by updating the MMU. The mmu_set_region_dcache() function allows drivers to make these changes after the MMU is set up.

It is implemented only for ARMv7 at present.

This is needed for LCD support, where we want to make the LCD frame buffer write-through (or off) rather than write-back.

---
Changes in v4:
- Use system bit values for enum dcache_option instead of arbitrary numbers

 arch/arm/cpu/armv7/cache_v7.c |   11 +++++++++
 arch/arm/include/asm/system.h |   30 ++++++++++++++++++++++++
 arch/arm/lib/cache-cp15.c     |   50 ++++++++++++++++++++++++++++++++---------
 3 files changed, 80 insertions(+), 11 deletions(-)
arch/arm/cpu/armv7/cache_v7.c +11 -0
index 1b4e808..5f6d039 100644
@@ -297,6 +297,12 @@ void arm_init_before_mmu(void)
 	v7_inval_tlb();
 }
 
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+	flush_dcache_range(start, stop);
+	v7_inval_tlb();
+}
+
 /*
  * Flush range from all levels of d-cache/unified-cache used:
  * Affects the range [start, start + size - 1]
@@ -329,6 +335,11 @@ void arm_init_before_mmu(void)
 void  flush_cache(unsigned long start, unsigned long size)
 {
 }
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+}
+
 #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
 
 #ifndef CONFIG_SYS_ICACHE_OFF
arch/arm/include/asm/system.h +30 -0
index 2b28a26..9a05211 100644
@@ -75,6 +75,36 @@ static inline void set_cr(unsigned int val)
 	isb();
 }
 
+/* options available for data cache on each page */
+enum dcache_option {
+	DCACHE_OFF = 0x12,
+	DCACHE_WRITETHROUGH = 0x1a,
+	DCACHE_WRITEBACK = 0x1e,
+};
+
+/* Size of an MMU section */
+enum {
+	MMU_SECTION_SHIFT	= 20,
+	MMU_SECTION_SIZE	= 1 << MMU_SECTION_SHIFT,
+};
+
+/**
+ * Change the cache settings for a region.
+ *
+ * \param start		start address of memory region to change
+ * \param size		size of memory region to change
+ * \param option	dcache option to select
+ */
+void mmu_set_region_dcache(u32 start, int size, enum dcache_option option);
+
+/**
+ * Register an update to the page tables, and flush the TLB
+ *
+ * \param start		start address of update in page table
+ * \param stop		stop address of update in page table
+ */
+void mmu_page_table_flush(unsigned long start, unsigned long stop);
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
arch/arm/lib/cache-cp15.c +39 -11

88 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#12 lore raw

PATCH v5 9/16 arm: Add control over cachability of memory regions

Hi,

Quoted 9 lines

Add support for adjusting the cachability of an L1 section by updating the MMU. The mmu_set_region_dcache() function allows drivers to make these changes after the MMU is set up.

It is implemented only for ARMv7 at present.

This is needed for LCD support, where we want to make the LCD frame buffer write-through (or off) rather than write-back.

This is a much needed support. I was looking for a way to change the permissions to avoid speculative aborts for non executable regions. This should help.

Quoted 98 lines

---
Changes in v4:
- Use system bit values for enum dcache_option instead of arbitrary numbers

  arch/arm/cpu/armv7/cache_v7.c |   11 +++++++++
  arch/arm/include/asm/system.h |   30 ++++++++++++++++++++++++
  arch/arm/lib/cache-cp15.c     |   50 ++++++++++++++++++++++++++++++++---------
  3 files changed, 80 insertions(+), 11 deletions(-)
arch/arm/cpu/armv7/cache_v7.c +11 -0
index 1b4e808..5f6d039 100644
@@ -297,6 +297,12 @@ void arm_init_before_mmu(void)
  	v7_inval_tlb();
  }
 
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+	flush_dcache_range(start, stop);
+	v7_inval_tlb();
+}
+
  /*
   * Flush range from all levels of d-cache/unified-cache used:
   * Affects the range [start, start + size - 1]
@@ -329,6 +335,11 @@ void arm_init_before_mmu(void)
  void  flush_cache(unsigned long start, unsigned long size)
  {
  }
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+}
+
  #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
 
  #ifndef CONFIG_SYS_ICACHE_OFF
arch/arm/include/asm/system.h +30 -0
index 2b28a26..9a05211 100644
@@ -75,6 +75,36 @@ static inline void set_cr(unsigned int val)
  	isb();
  }
 
+/* options available for data cache on each page */
+enum dcache_option {
+	DCACHE_OFF = 0x12,
+	DCACHE_WRITETHROUGH = 0x1a,
+	DCACHE_WRITEBACK = 0x1e,
+};
+
+/* Size of an MMU section */
+enum {
+	MMU_SECTION_SHIFT	= 20,
+	MMU_SECTION_SIZE	= 1 << MMU_SECTION_SHIFT,
+};
+
+/**
+ * Change the cache settings for a region.
+ *
+ * \param start		start address of memory region to change
+ * \param size		size of memory region to change
+ * \param option	dcache option to select
+ */
+void mmu_set_region_dcache(u32 start, int size, enum dcache_option option);
+
+/**
+ * Register an update to the page tables, and flush the TLB
+ *
+ * \param start		start address of update in page table
+ * \param stop		stop address of update in page table
+ */
+void mmu_page_table_flush(unsigned long start, unsigned long stop);
+
  #endif /* __ASSEMBLY__ */
 
  #define arch_align_stack(x) (x)
arch/arm/lib/cache-cp15.c +0 -6
index 939de10..c9bee42 100644
@@ -26,12 +26,6 @@
 
  #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
 
-#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
-#define CACHE_SETUP	0x1a
-#else
-#define CACHE_SETUP	0x1e
-#endif
-
  DECLARE_GLOBAL_DATA_PTR;
 
  void __arm_init_before_mmu(void)

arch/arm/lib/cache-cp15.c static void cp_delay (void) · line 52

Quoted 10 lines
arch/arm/lib/cache-cp15.c +4 -1
@@ -50,9 +44,40 @@ static void cp_delay (void)
  	asm volatile("" : : : "memory");
  }
 
-static inline void dram_bank_mmu_setup(int bank)
+void set_section_dcache(int section, enum dcache_option option)
  {
  	u32 *page_table = (u32 *)gd->tlb_addr;
+	u32 value;
+
+	value = (section << MMU_SECTION_SHIFT) | (3 << 10);

Nit.. How about avoiding this magic value (3 << 10).

Quoted 15 lines
arch/arm/lib/cache-cp15.c +15 -0
+	value |= option;
+	page_table[section] = value;
+}
+
+void __mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+	debug("%s: Warning: not implemented\n", __func__);
+}
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+	__attribute__((weak, alias("__mmu_page_table_flush")));
+
+void mmu_set_region_dcache(u32 start, int size, enum dcache_option option)
+{
+	u32 *page_table = (u32 *)gd->tlb_addr;

arch/arm/lib/cache-cp15.c static void cp_delay (void) · line 77

Quoted 10 lines
arch/arm/lib/cache-cp15.c +10 -0
+	u32 upto, end;
+
+	end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
+	start = start >> MMU_SECTION_SHIFT;
+	debug("mmu_set_region_dcache start=%x, size=%x, option=%d\n",
+	      start, size, option);
+	for (upto = start; upto < end; upto++)
+		set_section_dcache(upto, option);
+	mmu_page_table_flush((u32)&page_table[start], (u32)&page_table[end]);
+}

Should this be page_table[end + 1] instead, to ensure that the last entry is also flushed ?

#13 lore raw

PATCH v5 9/16 arm: Add control over cachability of memory regions

In reply to Simon Glass

Hi Simon,

No comment on the patch itself except for one general question:

Quoted 3 lines · Simon Glass

Add support for adjusting the cachability of an L1 section by updating the MMU. The mmu_set_region_dcache() function allows drivers to make these changes after the MMU is set up.

Can you just reformulate this a bit? "L1" is not necessary about cache (there can be for instance TCM, frequently (if not correctly) called L1 RAM where I work, for the obvious reason that they are accessed at the same level/layer as the L1 cache. Also, off, writethrough and copyback are "cache behaviors" in ARM parlance, not "cachability". Therefore I would prefer something like

"Add support for adjusting the L1 cache behavior by updating the MMU configuration. The mmu_set_region_dcache_behavior() function allows drivers to make these changes after the MMU is set up."

(note the suggestion includes slightly renaming the function)

Thanks in advance for considering this suggestion.

Amicalement,

Signature · 1 line
Albert.
#14 lore raw

PATCH v5 9/16 arm: Add control over cachability of memory regions

Hi Albert,

Quoted 18 lines · Albert ARIBAUD

Hi Simon,

No comment on the patch itself except for one general question:

Quoted 3 lines · Simon Glass

Add support for adjusting the cachability of an L1 section by updating the MMU. The mmu_set_region_dcache() function allows drivers to make these changes after the MMU is set up.

Can you just reformulate this a bit? "L1" is not necessary about cache (there can be for instance TCM, frequently (if not correctly) called L1 RAM where I work, for the obvious reason that they are accessed at the same level/layer as the L1 cache. Also, off, writethrough and copyback are "cache behaviors" in ARM parlance, not "cachability". Therefore I would prefer something like

Quoted 7 lines

"Add support for adjusting the L1 cache behavior by updating the MMU configuration. The mmu_set_region_dcache_behavior() function allows drivers to make these changes after the MMU is set up."

(note the suggestion includes slightly renaming the function)

Thanks in advance for considering this suggestion.

Yes I will do that and send an updated patch. I will also rebase on top of master, since the T30 changes are in there now.

Regards,
Simon

Quoted 4 lines

Amicalement,
--
Albert.

#15 lore raw

PATCH v5 10/16 lcd: Add CONFIG_LCD_ALIGNMENT to select frame buffer alignment

In reply to Simon Glass

The normal alignment is PAGE_SIZE, but if this is defined, we can support other alignments.

The motivation for this change is to make the display section-aligned on ARM so that we can easily turn off data caching for the frame buffer region without resorting to level 2 page tables.

---
Changes in v4:
- Remove system.h header which is included anyway by most archs

Changes in v2:
- Use a more generic config CONFIG_LCD_ALIGNMENT for lcd alignment

 README        |   10 ++++++++++
 common/lcd.c  |   21 ++++++++++++++++-----
 include/lcd.h |    3 +++
 3 files changed, 29 insertions(+), 5 deletions(-)
README +10 -0
index 0d17e7d..42b3172 100644
@@ -1440,6 +1440,16 @@ The following options need to be configured:
 		Normally display is black on white background; define
 		CONFIG_SYS_WHITE_ON_BLACK to get it inverted.
 
+
+		CONFIG_LCD_ALIGNMENT
+
+		Normally the LCD is page-aligned (tyically 4KB). If this is
+		defined then the LCD will be aligned to this value instead.
+		For ARM it is sometimes useful to use MMU_SECTION_SIZE
+		here, since it is cheaper to change data cache settings on
+		a per-section basis.
+
+
 - Splash Screen Support: CONFIG_SPLASH_SCREEN
 
 		If this option is set, the environment is checked for
common/lcd.c +16 -5
index b6be800..37b0393 100644
@@ -72,6 +72,10 @@
 # endif
 #endif
 
+#ifndef CONFIG_LCD_ALIGNMENT
+#define CONFIG_LCD_ALIGNMENT PAGE_SIZE
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong lcd_setmem (ulong addr);
@@ -326,6 +330,12 @@ static void test_pattern(void)
 /* ** GENERIC Initialization Routines					*/
 /************************************************************************/
 
+int lcd_get_size(int *line_length)
+{
+	*line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
+	return *line_length * panel_info.vl_row;
+}
+
 int drv_lcd_init (void)
 {
 	struct stdio_dev lcddev;
@@ -333,7 +343,7 @@ int drv_lcd_init (void)
 
 	lcd_base = (void *)(gd->fb_base);
 
-	lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
+	lcd_get_size(&lcd_line_length);
 
 	lcd_init(lcd_base);		/* LCD initialization */
 
@@ -445,15 +455,16 @@ static int lcd_init(void *lcdbase)
 ulong lcd_setmem(ulong addr)
 {
 	ulong size;
-	int line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
+	int line_length;
 
 	debug("LCD panel info: %d x %d, %d bit/pix\n", panel_info.vl_col,
 		panel_info.vl_row, NBITS(panel_info.vl_bpix));
 
-	size = line_length * panel_info.vl_row;
+	size = lcd_get_size(&line_length);
 
-	/* Round up to nearest full page */
-	size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+	/* Round up to nearest full page, or MMU section if defined */
+	size = ALIGN(size, CONFIG_LCD_ALIGNMENT);
+	addr = ALIGN(addr - CONFIG_LCD_ALIGNMENT + 1, CONFIG_LCD_ALIGNMENT);
 
 	/* Allocate pages for the frame buffer. */
 	addr -= size;
include/lcd.h +3 -0
index 42070d7..6a600ee 100644
@@ -297,6 +297,9 @@ int	lcd_display_bitmap(ulong bmp_image, int x, int y);
 /* Allow boards to customize the information displayed */
 void lcd_show_board_info(void);
 
+/* Return the size of the LCD frame buffer, and the line length */
+int lcd_get_size(int *line_length);
+
 /************************************************************************/
 /* ** BITMAP DISPLAY SUPPORT						*/
 /************************************************************************/
Signature · 1 line
1.7.7.3
#16 lore raw

PATCH v5 11/16 lcd: Add support for flushing LCD fb from dcache after update

In reply to Simon Glass

This provides an option for the LCD to flush the dcache after each update (puts, scroll or clear).

---
Changes in v4:
- Use lcd_puts() for echoing user input so lcd cached data is flushed

Changes in v3:
- Put the LCD cache flush logic back into lcd_puts()

Changes in v2:
- Put the LCD cache flush logic into lcd_putc() instead of lcd_puts()

 common/lcd.c  |   46 +++++++++++++++++++++++++++++++++++++++-------
 common/main.c |   12 ++++++++++--
 include/lcd.h |    8 ++++++++
 3 files changed, 57 insertions(+), 9 deletions(-)
common/lcd.c +39 -7
index 37b0393..74fa3f9 100644
@@ -94,6 +94,9 @@ static void lcd_setbgcolor(int color);
 
 char lcd_is_enabled = 0;
 
+static char lcd_flush_dcache;	/* 1 to flush dcache after each lcd update */
+
+
 #ifdef	NOT_USED_SO_FAR
 static void lcd_getcolreg(ushort regno,
 				ushort *red, ushort *green, ushort *blue);
@@ -102,6 +105,28 @@ static int lcd_getfgcolor(void);
 
 /************************************************************************/
 
+/* Flush LCD activity to the caches */
+void lcd_sync(void)
+{
+	/*
+	 * flush_dcache_range() is declared in common.h but it seems that some
+	 * architectures do not actually implement it. Is there a way to find
+	 * out whether it exists? For now, ARM is safe.
+	 */
+#ifdef CONFIG_ARM
+	int line_length;
+
+	if (lcd_flush_dcache)
+		flush_dcache_range((u32)lcd_base,
+			(u32)(lcd_base + lcd_get_size(&line_length)));
+#endif
+}
+
+void lcd_set_flush_dcache(int flush)
+{
+	lcd_flush_dcache = (flush != 0);
+}
+
 /*----------------------------------------------------------------------*/
 
 static void console_scrollup(void)
@@ -111,6 +136,7 @@ static void console_scrollup(void)
 
 	/* Clear the last one */
 	memset(CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
+	lcd_sync();
 }
 
 /*----------------------------------------------------------------------*/
@@ -140,6 +166,8 @@ static inline void console_newline(void)
 		/* Scroll everything up */
 		console_scrollup();
 		--console_row;
+	} else {
+		lcd_sync();
 	}
 }
 
@@ -195,6 +223,7 @@ void lcd_puts(const char *s)
 	while (*s) {
 		lcd_putc(*s++);
 	}
+	lcd_sync();
 }
 
 /*----------------------------------------------------------------------*/
@@ -362,13 +391,6 @@ int drv_lcd_init (void)
 }
 
 /*----------------------------------------------------------------------*/
-static
-int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
-{
-	lcd_clear();
-	return 0;
-}
-
 void lcd_clear(void)
 {
 #if LCD_BPP == LCD_MONOCHROME
@@ -410,6 +432,14 @@ void lcd_clear(void)
 
 	console_col = 0;
 	console_row = 0;
+	lcd_sync();
+}
+
+static int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc,
+			char *const argv[])
+{
+	lcd_clear();
+	return 0;
 }
 
 U_BOOT_CMD(
@@ -621,6 +651,7 @@ void bitmap_plot(int x, int y)
 	}
 
 	WATCHDOG_RESET();
+	lcd_sync();
 }
 #else
 static inline void bitmap_plot(int x, int y) {}
@@ -842,6 +873,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
 		break;
 	};
 
+	lcd_sync();
 	return 0;
 }
 #endif
common/main.c +10 -2
index 81984ac..d3356e1 100644
@@ -1040,8 +1040,16 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout)
 					puts (tab_seq+(col&07));
 					col += 8 - (col&07);
 				} else {
-					++col;		/* echo input		*/
-					putc (c);
+					char buf[2];
+
+					/*
+					 * Echo input using puts() to force am
+					 * LCD flush if we are using an LCD
+					 */
+					++col;
+					buf[0] = c;
+					buf[1] = '\0';
+					puts(buf);
 				}
 				*p++ = c;
 				++n;
include/lcd.h +8 -0
index 6a600ee..8f84741 100644
@@ -57,6 +57,14 @@ extern void lcd_initcolregs (void);
 extern struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp);
 extern int bmp_display(ulong addr, int x, int y);
 
+/**
+ * Set whether we need to flush the dcache when changing the LCD image. This
+ * defaults to off.
+ *
+ * @param flush		non-zero to flush cache after update, 0 to skip
+ */
+void lcd_set_flush_dcache(int flush);
+
 #if defined CONFIG_MPC823
 /*
  * LCD controller stucture for MPC823 CPU
Signature · 1 line
1.7.7.3
#17 lore raw

PATCH v5 12/16 tegra: Align LCD frame buffer to section boundary

In reply to Simon Glass

For tegra we want to enable the cache for the LCD. This is easier if we can avoid using L2 page tages, so align the LCD to a section boundary.

---
Changes in v2:
- Align tegra display using new CONFIG_LCD_ALIGNMENT feature

 include/configs/tegra20-common.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
include/configs/tegra20-common.h +3 -0
index fa14a1c..a96233a 100644
@@ -45,6 +45,9 @@
 
 #include <asm/arch/tegra.h>		/* get chip and board defs */
 
+/* Align LCD to 1MB boundary */
+#define CONFIG_LCD_ALIGNMENT	MMU_SECTION_SIZE
+
 /*
  * Display CPU and Board information
  */
Signature · 1 line
1.7.7.3
#18 lore raw

PATCH v5 13/16 tegra: Support control of cache settings for LCD

In reply to Simon Glass

Add support for selecting the required cache mode for the LCD:
off, write-through or write-back.

---
Changes in v3:
- Handle a cached frame buffer out of normal U-Boot memory

 drivers/video/tegra.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/video/tegra.c +11 -0
index 9df2bd3..ff2b70e 100644
@@ -145,6 +145,7 @@ static void update_panel_size(struct fdt_disp_config *config)
 void lcd_ctrl_init(void *lcdbase)
 {
 	int line_length, size;
+	int type = DCACHE_OFF;
 
 	assert(disp_config);
 
@@ -160,6 +161,16 @@ void lcd_ctrl_init(void *lcdbase)
 		update_panel_size(disp_config);
 	size = lcd_get_size(&line_length);
 
+	/* Set up the LCD caching as requested */
+	if (config.cache_type & FDT_LCD_CACHE_WRITE_THROUGH)
+		type = DCACHE_WRITETHROUGH;
+	else if (config.cache_type & FDT_LCD_CACHE_WRITE_BACK)
+		type = DCACHE_WRITEBACK;
+	mmu_set_region_dcache(disp_config->frame_buffer, size, type);
+
+	/* Enable flushing after LCD writes if requested */
+	lcd_set_flush_dcache(config.cache_type & FDT_LCD_CACHE_FLUSH);
+
 	debug("LCD frame buffer at %p\n", lcd_base);
 }
 
Signature · 1 line
1.7.7.3
#19 lore raw

PATCH v5 15/16 lcd: Add CONFIG_CONSOLE_SCROLL_LINES option to speed console

In reply to Simon Glass

When the cursor position gets to the end of the LCD console we normally scroll by one line. This adds an option to increase that value.

Console scrolling is often slow, and if a large amount of output is being sent, increasing this option to 10 or so will speed things up considerably.

---
Changes in v5:
- Fix CONFIG_CONSOLE_SCROLL_LINES commit title
- Fix misleading comments in common/lcd.c

Changes in v4:
- Use CONFIG_CONSOLE_SCROLL_LINES instead of CONSOLE_SCROLL_LINES
- Put default CONFIG_CONSOLE_SCROLL_LINES at top of file

Changes in v3:
- Fix tiny bug in mult-line lcd scrolling

 README       |    6 ++++++
 common/lcd.c |   22 +++++++++++++++++-----
 2 files changed, 23 insertions(+), 5 deletions(-)
README +6 -0
index 42b3172..255d073 100644
@@ -1449,6 +1449,12 @@ The following options need to be configured:
 		here, since it is cheaper to change data cache settings on
 		a per-section basis.
 
+		CONFIG_CONSOLE_SCROLL_LINES
+
+		When the console need to be scrolled, this is the number of
+		lines to scroll by. It defaults to 1. Increasing this makes
+		the console jump but can help speed up operation when scrolling
+		is slow.
 
 - Splash Screen Support: CONFIG_SPLASH_SCREEN
 
common/lcd.c +17 -5
index 74fa3f9..3d53651 100644
@@ -76,6 +76,11 @@
 #define CONFIG_LCD_ALIGNMENT PAGE_SIZE
 #endif
 
+/* By default we scroll by a single line */
+#ifndef CONFIG_CONSOLE_SCROLL_LINES
+#define CONFIG_CONSOLE_SCROLL_LINES 1
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong lcd_setmem (ulong addr);
@@ -131,12 +136,20 @@ void lcd_set_flush_dcache(int flush)
 
 static void console_scrollup(void)
 {
-	/* Copy up rows ignoring the first one */
-	memcpy(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE);
+	const int rows = CONFIG_CONSOLE_SCROLL_LINES;
+
+	/* Copy up rows ignoring those that will be overwritten */
+	memcpy(CONSOLE_ROW_FIRST,
+	       lcd_console_address + CONSOLE_ROW_SIZE * rows,
+	       CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
+
+	/* Clear the last rows */
+	memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
+		COLOR_MASK(lcd_color_bg),
+	       CONSOLE_ROW_SIZE * rows);
 
-	/* Clear the last one */
-	memset(CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
 	lcd_sync();
+	console_row -= rows;
 }
 
 /*----------------------------------------------------------------------*/
@@ -165,7 +178,6 @@ static inline void console_newline(void)
 	if (console_row >= CONSOLE_ROWS) {
 		/* Scroll everything up */
 		console_scrollup();
-		--console_row;
 	} else {
 		lcd_sync();
 	}
Signature · 1 line
1.7.7.3
#20 lore raw

PATCH v5 16/16 tegra: Enable display/lcd support on Seaboard

In reply to Simon Glass

From: Mayuresh Kulkarni <[email protected]>

Enable the Seaboard's 16-bit LCD and use it as the console.

---
Changes in v4:
- Add CONFIG_BOARD_LATE_INIT to enable LCD
- Use CONFIG_CONSOLE_SCROLL_LINES instead of CONSOLE_SCROLL_LINES
- Enable separate CONFIG_PWM_TEGRA option

 include/configs/seaboard.h |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)
include/configs/seaboard.h +11 -2
index de19e38..19c5bf3 100644
@@ -55,6 +55,7 @@
 #define CONFIG_MACH_TYPE		MACH_TYPE_SEABOARD
 
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT		/* Make sure LCD init is complete */
 
 /* I2C */
 #define CONFIG_TEGRA_I2C
@@ -101,8 +102,16 @@
 
 #undef TEGRA_DEVICE_SETTINGS
 #define TEGRA_DEVICE_SETTINGS	"stdin=serial,tegra-kbc\0" \
-				"stdout=serial\0" \
-				"stderr=serial\0"
+				"stdout=serial,lcd\0" \
+				"stderr=serial,lcd\0"
+
+/* LCD support */
+#define CONFIG_LCD
+#define CONFIG_PWM_TEGRA
+#define CONFIG_VIDEO_TEGRA
+#define LCD_BPP				LCD_COLOR16
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES	10
 
 #include "tegra-common-post.h"
 
Signature · 1 line
1.7.7.3