All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard
@ 2016-01-14 15:57 Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 01/37] stdio: Correct a build error with driver model Simon Glass
                   ` (37 more replies)
  0 siblings, 38 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

This series adds display drivers for rockchip and enables them on jerry,
firefly-rk3288 (HDMI only) and rock2 (HDMI only). It builds on the recent
keyboard series.

Driver are provided for video displays (EDP and HDMI) and the VOP (video
output processor).

This series also adds several new uclasses:
- PWM (Pulse-width modulation)
- Panel (used for LCD panels)
- Display (renamed from DisplayPort - a generic display with power, etc.)
- Backlight (used for LCD backlights)

Since most of this implementation is device-tree-controlled it is fairly
easy to enable HDMI on the other RK3288 devices. This series adds this for
Firefly-RK3288. It also includes Radxa Rock 2 as a separate board since a
device tree file is now available in Linux. HDMI is enabled on that board
also.

There remain quite a few things still to do for core rockchip support. Here
are a few noticed while preparing this series:

- Clocks / caches are not working correctly. The 'dhry' command shows
approximately 60 DMIPS when supposedly running at 1.8GHz. Turning the cache
on or off makes no difference. The platform should run at over 2000 DMIPS by
my estimate. This problem is common on ARM platforms. For example I found:

beaver (Tegra) 818 DMIPS
pit (Exynos) 276 DMIPS
snow (Exynos) 521 DMIPS

- HDMI EDID-reading does not work on Jerry, perhaps because the clocks are
not running as they should. It seems to work fine on other boards.

This series is available at u-boot-dm/rkd-working


Simon Glass (37):
  stdio: Correct a build error with driver model
  gpio: Warn about invalid GPIOs used with the 'gpio' command
  video: Name consoles by their number
  video: Add a function to control cache flushing
  video: bridge: Allow GPIOs to be optional
  dm: pwm: Add a PWM uclass
  pwm: rockchip: Add a PWM driver for Rockchip SoCs
  dm: backlight: Add a backlight uclass
  dm: backlight: Add a driver for a PWM backlight
  dm: panel: Add a panel uclass
  video: panel: Add a simple panel driver
  dm: video: Repurpose the 'displayport' uclass to 'display'
  rockchip: Rename the CRU_MODE_CON fields
  rockchip: clk: Add support for clocks needed by the displays
  rockchip: video: Add a display driver for rockchip HDMI
  rockchip: video: Add a display driver for rockchip eDP
  rockchip: video: Add a video-output driver
  rockchip: Don't skip low-level init
  rockchip: Add a simple 'clock' command
  rockchip: Add a script to parse datasheets
  rockchip: config: Enable the 'gpio' command
  rockchip: sdram: Tidy up a few comments
  rockchip: sdram: Use syscon_get_first_range() where possible
  rockchip: Tidy up the register-access macros
  rockchip: spl: Drop MMC support code when not needed
  rockchip: jerry: Fix the SDRAM timing
  rockchip: rk3288: clock: Fix various minor errors
  rockchip: rk3288: pinctrl: Fix HDMI pinctrl
  rockchip: spl: Support full-speed CPU in SPL
  rockchip: jerry: Add support for timing SPI flash speed
  rockchip: jerry: Enable EDP and HDMI video output
  rockchip: firefly-rk3288: Enable HDMI output
  rockchip: dts: Sync up SPDIF node with Linux
  rockchip: rock2: Bring in device tree files from Linux
  rockchip: rock2: dts: Make changes for U-Boot
  rockchip: Add support for Raxda Rock 2
  rockchip: Update the README

 arch/arm/dts/Makefile                            |    1 +
 arch/arm/dts/rk3288-jerry.dts                    |    5 +
 arch/arm/dts/rk3288-rock2-som.dtsi               |  278 ++++++
 arch/arm/dts/rk3288-rock2-square.dts             |  201 ++++
 arch/arm/dts/rk3288-veyron.dtsi                  |    4 +-
 arch/arm/dts/rk3288.dtsi                         |   22 +
 arch/arm/include/asm/arch-rockchip/clock.h       |    5 +
 arch/arm/include/asm/arch-rockchip/cru_rk3288.h  |   70 +-
 arch/arm/include/asm/arch-rockchip/edp_rk3288.h  |  636 +++++++++++++
 arch/arm/include/asm/arch-rockchip/hardware.h    |    7 +-
 arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h |  456 +++++++++
 arch/arm/include/asm/arch-rockchip/pwm.h         |   41 +
 arch/arm/include/asm/arch-rockchip/vop_rk3288.h  |  349 +++++++
 arch/arm/mach-rockchip/board.c                   |   28 +
 arch/arm/mach-rockchip/rk3288-board-spl.c        |   10 +-
 arch/arm/mach-rockchip/rk3288/Kconfig            |   19 +
 arch/arm/mach-rockchip/rk3288/sdram_rk3288.c     |   57 +-
 board/radxa/rock2/Kconfig                        |   15 +
 board/radxa/rock2/MAINTAINERS                    |    6 +
 board/radxa/rock2/Makefile                       |    7 +
 board/radxa/rock2/rock2.c                        |    7 +
 common/cmd_gpio.c                                |    4 +-
 common/stdio.c                                   |    3 +
 configs/chromebook_jerry_defconfig               |    7 +
 configs/firefly-rk3288_defconfig                 |    7 +
 configs/nyan-big_defconfig                       |    2 +-
 configs/rock2_defconfig                          |   53 ++
 doc/README.rockchip                              |   53 +-
 drivers/Kconfig                                  |    2 +
 drivers/clk/clk_rk3288.c                         |  290 +++++-
 drivers/pinctrl/rockchip/pinctrl_rk3288.c        |    2 +
 drivers/pwm/Kconfig                              |   19 +
 drivers/pwm/Makefile                             |    2 +
 drivers/pwm/pwm-uclass.c                         |   36 +
 drivers/pwm/rk_pwm.c                             |  103 +++
 drivers/video/Kconfig                            |   23 +-
 drivers/video/Makefile                           |    8 +-
 drivers/video/backlight-uclass.c                 |   25 +
 drivers/video/bridge/video-bridge-uclass.c       |   11 +-
 drivers/video/display-uclass.c                   |   52 ++
 drivers/video/dp-uclass.c                        |   34 -
 drivers/video/panel-uclass.c                     |   25 +
 drivers/video/pwm_backlight.c                    |  134 +++
 drivers/video/rockchip/Makefile                  |    8 +
 drivers/video/rockchip/rk_edp.c                  | 1081 ++++++++++++++++++++++
 drivers/video/rockchip/rk_hdmi.c                 |  929 +++++++++++++++++++
 drivers/video/rockchip/rk_vop.c                  |  346 +++++++
 drivers/video/simple_panel.c                     |   99 ++
 drivers/video/tegra124/display.c                 |   18 +-
 drivers/video/tegra124/dp.c                      |    9 +-
 drivers/video/vidconsole-uclass.c                |    7 +-
 drivers/video/video-uclass.c                     |    7 +
 include/backlight.h                              |   31 +
 include/configs/chromebook_jerry.h               |   14 +-
 include/configs/firefly-rk3288.h                 |    9 +-
 include/configs/rk3288_common.h                  |    2 +-
 include/configs/rock2.h                          |   31 +
 include/configs/sandbox.h                        |    8 +-
 include/{displayport.h => display.h}             |   33 +-
 include/dm/uclass-id.h                           |    5 +-
 include/edid.h                                   |    1 +
 include/panel.h                                  |   31 +
 include/pwm.h                                    |   53 ++
 include/video.h                                  |    8 +
 tools/rkmux.py                                   |  218 +++++
 65 files changed, 5864 insertions(+), 203 deletions(-)
 create mode 100644 arch/arm/dts/rk3288-rock2-som.dtsi
 create mode 100644 arch/arm/dts/rk3288-rock2-square.dts
 create mode 100644 arch/arm/include/asm/arch-rockchip/edp_rk3288.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/pwm.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/vop_rk3288.h
 create mode 100644 board/radxa/rock2/Kconfig
 create mode 100644 board/radxa/rock2/MAINTAINERS
 create mode 100644 board/radxa/rock2/Makefile
 create mode 100644 board/radxa/rock2/rock2.c
 create mode 100644 configs/rock2_defconfig
 create mode 100644 drivers/pwm/Kconfig
 create mode 100644 drivers/pwm/pwm-uclass.c
 create mode 100644 drivers/pwm/rk_pwm.c
 create mode 100644 drivers/video/backlight-uclass.c
 create mode 100644 drivers/video/display-uclass.c
 delete mode 100644 drivers/video/dp-uclass.c
 create mode 100644 drivers/video/panel-uclass.c
 create mode 100644 drivers/video/pwm_backlight.c
 create mode 100644 drivers/video/rockchip/Makefile
 create mode 100644 drivers/video/rockchip/rk_edp.c
 create mode 100644 drivers/video/rockchip/rk_hdmi.c
 create mode 100644 drivers/video/rockchip/rk_vop.c
 create mode 100644 drivers/video/simple_panel.c
 create mode 100644 include/backlight.h
 create mode 100644 include/configs/rock2.h
 rename include/{displayport.h => display.h} (59%)
 create mode 100644 include/panel.h
 create mode 100755 tools/rkmux.py

-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 01/37] stdio: Correct a build error with driver model
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 02/37] gpio: Warn about invalid GPIOs used with the 'gpio' command Simon Glass
                   ` (36 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

When driver model is used for video but not for the keyboard, a compiler
warnings is produced. Fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/stdio.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/stdio.c b/common/stdio.c
index 7252bab..f99cfe7 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -283,6 +283,9 @@ int stdio_add_devices(void)
 #endif
 #ifdef CONFIG_DM_VIDEO
 	struct udevice *vdev;
+# ifndef CONFIG_DM_KEYBOARD
+	int ret;
+# endif
 
 	for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
 	     vdev;
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 02/37] gpio: Warn about invalid GPIOs used with the 'gpio' command
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 01/37] stdio: Correct a build error with driver model Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 03/37] video: Name consoles by their number Simon Glass
                   ` (35 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

At present there is no indication that an invalid GPIO is used except that
the GPIO status is not displayed. Make the error more explicit to avoid
confusion.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/cmd_gpio.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/common/cmd_gpio.c b/common/cmd_gpio.c
index bb0f63a..2b78b16 100644
--- a/common/cmd_gpio.c
+++ b/common/cmd_gpio.c
@@ -174,8 +174,10 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 * GPIO compatibility layer.
 	 */
 	ret = gpio_lookup_name(str_gpio, NULL, NULL, &gpio);
-	if (ret)
+	if (ret) {
+		printf("GPIO: '%s' not found\n", str_gpio);
 		return cmd_process_error(cmdtp, ret);
+	}
 #else
 	/* turn the gpio name into a gpio number */
 	gpio = name_to_gpio(str_gpio);
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 03/37] video: Name consoles by their number
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 01/37] stdio: Correct a build error with driver model Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 02/37] gpio: Warn about invalid GPIOs used with the 'gpio' command Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 04/37] video: Add a function to control cache flushing Simon Glass
                   ` (34 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

We must use the console name in the 'stdout' variable to select the one
we want. At present the name is formed from the driver name with a suffix
indicating the rotation value.

It seems better to name them sequentially since this can be controlled by
driver order. So adjust the code to use 'vidconsole' for the first,
'vidconsole1' for the second, etc.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/vidconsole-uclass.c | 7 ++++++-
 include/configs/sandbox.h         | 8 ++++----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index ea10189..706a189 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -161,7 +161,12 @@ static int vidconsole_post_probe(struct udevice *dev)
 	struct stdio_dev *sdev = &priv->sdev;
 	int ret;
 
-	strlcpy(sdev->name, dev->name, sizeof(sdev->name));
+	if (dev->seq) {
+		snprintf(sdev->name, sizeof(sdev->name), "vidconsole%d",
+			 dev->seq);
+	} else {
+		strcpy(sdev->name, "vidconsole");
+	}
 	sdev->flags = DEV_FLAGS_OUTPUT;
 	sdev->putc = vidconsole_putc;
 	sdev->puts = vidconsole_puts;
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 6498981..4bffd8d 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -169,12 +169,12 @@
 #define CONFIG_KEYBOARD
 
 #define SANDBOX_SERIAL_SETTINGS		"stdin=serial,cros-ec-keyb,usbkbd\0" \
-					"stdout=serial,lcd.vidconsole\0" \
-					"stderr=serial,lcd.vidconsole\0"
+					"stdout=serial,vidconsole\0" \
+					"stderr=serial,vidconsole\0"
 #else
 #define SANDBOX_SERIAL_SETTINGS		"stdin=serial\0" \
-					"stdout=serial,lcd.vidconsole\0" \
-					"stderr=serial,lcd.vidconsole\0"
+					"stdout=serial,vidconsole\0" \
+					"stderr=serial,vidconsole\0"
 #endif
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 04/37] video: Add a function to control cache flushing
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (2 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 03/37] video: Name consoles by their number Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 05/37] video: bridge: Allow GPIOs to be optional Simon Glass
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Allow the cache-flushing function of a video device to be controlled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/video-uclass.c | 7 +++++++
 include/video.h              | 8 ++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 63d0d9d..24d537e 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -42,6 +42,13 @@
  */
 DECLARE_GLOBAL_DATA_PTR;
 
+void video_set_flush_dcache(struct udevice *dev, bool flush)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	priv->flush_dcache = flush;
+}
+
 static ulong alloc_fb(struct udevice *dev, ulong *addrp)
 {
 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
diff --git a/include/video.h b/include/video.h
index 5fd426e..5b147ba 100644
--- a/include/video.h
+++ b/include/video.h
@@ -159,6 +159,14 @@ int video_get_xsize(struct udevice *dev);
  */
 int video_get_ysize(struct udevice *dev);
 
+/**
+ * Set whether we need to flush the dcache when changing the image. This
+ * defaults to off.
+ *
+ * @param flush		non-zero to flush cache after update, 0 to skip
+ */
+void video_set_flush_dcache(struct udevice *dev, bool flush);
+
 #endif /* CONFIG_DM_VIDEO */
 
 #ifndef CONFIG_DM_VIDEO
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 05/37] video: bridge: Allow GPIOs to be optional
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (3 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 04/37] video: Add a function to control cache flushing Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 06/37] dm: pwm: Add a PWM uclass Simon Glass
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Some video bridges will not have GPIOs to control reset, etc. Allow these
to be optional.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/bridge/video-bridge-uclass.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c
index 6c5990f..07270ba 100644
--- a/drivers/video/bridge/video-bridge-uclass.c
+++ b/drivers/video/bridge/video-bridge-uclass.c
@@ -55,7 +55,8 @@ static int video_bridge_pre_probe(struct udevice *dev)
 				   &uc_priv->sleep, GPIOD_IS_OUT);
 	if (ret) {
 		debug("%s: Could not decode sleep-gpios (%d)\n", __func__, ret);
-		return ret;
+		if (ret != -ENOENT)
+			return ret;
 	}
 	/*
 	 * Drop this for now as we do not have driver model pinctrl support
@@ -70,7 +71,8 @@ static int video_bridge_pre_probe(struct udevice *dev)
 				   GPIOD_IS_OUT);
 	if (ret) {
 		debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
-		return ret;
+		if (ret != -ENOENT)
+			return ret;
 	}
 	/*
 	 * Drop this for now as we do not have driver model pinctrl support
@@ -83,9 +85,10 @@ static int video_bridge_pre_probe(struct udevice *dev)
 	 */
 	ret = gpio_request_by_name(dev, "hotplug-gpios", 0, &uc_priv->hotplug,
 				   GPIOD_IS_IN);
-	if (ret && ret != -ENOENT) {
+	if (ret) {
 		debug("%s: Could not decode hotplug (%d)\n", __func__, ret);
-		return ret;
+		if (ret != -ENOENT)
+			return ret;
 	}
 
 	return 0;
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 06/37] dm: pwm: Add a PWM uclass
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (4 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 05/37] video: bridge: Allow GPIOs to be optional Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 07/37] pwm: rockchip: Add a PWM driver for Rockchip SoCs Simon Glass
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Add a uclass that supports Pulse Width Modulation (PWM) devices. It
provides methods to enable/disable and configure the device.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/Kconfig          |  2 ++
 drivers/pwm/Kconfig      | 10 +++++++++
 drivers/pwm/Makefile     |  1 +
 drivers/pwm/pwm-uclass.c | 36 ++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |  1 +
 include/pwm.h            | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 103 insertions(+)
 create mode 100644 drivers/pwm/Kconfig
 create mode 100644 drivers/pwm/pwm-uclass.c

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c481e93..70993fd 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -46,6 +46,8 @@ source "drivers/pinctrl/Kconfig"
 
 source "drivers/power/Kconfig"
 
+source "drivers/pwm/Kconfig"
+
 source "drivers/ram/Kconfig"
 
 source "drivers/remoteproc/Kconfig"
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
new file mode 100644
index 0000000..bd47159
--- /dev/null
+++ b/drivers/pwm/Kconfig
@@ -0,0 +1,10 @@
+config DM_PWM
+	bool "Enable support for pulse-width modulation devices (PWM)"
+	depends on DM
+	help
+	  A pulse-width modulator emits a pulse of varying width and provides
+	  control over the duty cycle (high and low time) of the signal. This
+	  is often used to control a voltage level. The more time the PWM
+	  spends in the 'high' state, the higher the voltage. The PWM's
+	  frequency/period can be controlled along with the proportion of that
+	  time that the signal is high.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index c0c4883..d1b15e5 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -10,4 +10,5 @@
 
 #ccflags-y += -DDEBUG
 
+obj-$(CONFIG_DM_PWM) += pwm-uclass.o
 obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o
diff --git a/drivers/pwm/pwm-uclass.c b/drivers/pwm/pwm-uclass.c
new file mode 100644
index 0000000..c2200af
--- /dev/null
+++ b/drivers/pwm/pwm-uclass.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pwm.h>
+
+int pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
+		   uint duty_ns)
+{
+	struct pwm_ops *ops = pwm_get_ops(dev);
+
+	if (!ops->set_config)
+		return -ENOSYS;
+
+	return ops->set_config(dev, channel, period_ns, duty_ns);
+}
+
+int pwm_set_enable(struct udevice *dev, uint channel, bool enable)
+{
+	struct pwm_ops *ops = pwm_get_ops(dev);
+
+	if (!ops->set_enable)
+		return -ENOSYS;
+
+	return ops->set_enable(dev, channel, enable);
+}
+
+UCLASS_DRIVER(pwm) = {
+	.id		= UCLASS_PWM,
+	.name		= "pwm",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index b5f43ae..8f0381d 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -51,6 +51,7 @@ enum uclass_id {
 	UCLASS_PINCTRL,		/* Pinctrl (pin muxing/configuration) device */
 	UCLASS_PINCONFIG,	/* Pin configuration node device */
 	UCLASS_PMIC,		/* PMIC I/O device */
+	UCLASS_PWM,		/* Pulse-width modulator */
 	UCLASS_PWRSEQ,		/* Power sequence device */
 	UCLASS_REGULATOR,	/* Regulator device */
 	UCLASS_RESET,		/* Reset device */
diff --git a/include/pwm.h b/include/pwm.h
index f24f220..851915e 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -1,6 +1,7 @@
 /*
  * header file for pwm driver.
  *
+ * Copyright 2016 Google Inc.
  * Copyright (c) 2011 samsung electronics
  * Donghwa Lee <dh09.lee@samsung.com>
  *
@@ -10,9 +11,61 @@
 #ifndef _pwm_h_
 #define _pwm_h_
 
+/* struct pwm_ops: Operations for the PWM uclass */
+struct pwm_ops {
+	/**
+	 * set_config() - Set the PWM configuration
+	 *
+	 * @dev:	PWM device to update
+	 * @channel:	PWM channel to update
+	 * @period_ns:	PWM period in nanoseconds
+	 * @duty_ns:	PWM duty period in nanoseconds
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_config)(struct udevice *dev, uint channel, uint period_ns,
+			  uint duty_ns);
+
+	/**
+	 * set_enable() - Enable or disable the PWM
+	 *
+	 * @dev:	PWM device to update
+	 * @channel:	PWM channel to update
+	 * @enable:	true to enable, false to disable
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_enable)(struct udevice *dev, uint channel, bool enable);
+};
+
+#define pwm_get_ops(dev)	((struct pwm_ops *)(dev)->driver->ops)
+
+/**
+ * pwm_set_config() - Set the PWM configuration
+ *
+ * @dev:	PWM device to update
+ * @channel:	PWM channel to update
+ * @period_ns:	PWM period in nanoseconds
+ * @duty_ns:	PWM duty period in nanoseconds
+ * @return 0 if OK, -ve on error
+ */
+int pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
+		   uint duty_ns);
+
+/**
+ * pwm_set_enable() - Enable or disable the PWM
+ *
+ * @dev:	PWM device to update
+ * @channel:	PWM channel to update
+ * @enable:	true to enable, false to disable
+ * @return 0 if OK, -ve on error
+ */
+int pwm_set_enable(struct udevice *dev, uint channel, bool enable);
+
+/* Legacy interface */
+#ifndef CONFIG_DM_PWM
 int	pwm_init		(int pwm_id, int div, int invert);
 int	pwm_config		(int pwm_id, int duty_ns, int period_ns);
 int	pwm_enable		(int pwm_id);
 void	pwm_disable		(int pwm_id);
+#endif
 
 #endif /* _pwm_h_ */
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 07/37] pwm: rockchip: Add a PWM driver for Rockchip SoCs
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (5 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 06/37] dm: pwm: Add a PWM uclass Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 08/37] dm: backlight: Add a backlight uclass Simon Glass
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Add a simple driver which implements the standard PWM uclass interface.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/arch-rockchip/pwm.h |  41 ++++++++++++
 drivers/pwm/Kconfig                      |   9 +++
 drivers/pwm/Makefile                     |   1 +
 drivers/pwm/rk_pwm.c                     | 103 +++++++++++++++++++++++++++++++
 4 files changed, 154 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/pwm.h
 create mode 100644 drivers/pwm/rk_pwm.c

diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h b/arch/arm/include/asm/arch-rockchip/pwm.h
new file mode 100644
index 0000000..08ff945
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/pwm.h
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2016 Google, Inc
+ * (C) Copyright 2008-2014 Rockchip Electronics
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_PWM_H
+#define _ASM_ARCH_PWM_H
+
+struct rk3288_pwm {
+	u32 cnt;
+	u32 period_hpr;
+	u32 duty_lpr;
+	u32 ctrl;
+};
+check_member(rk3288_pwm, ctrl, 0xc);
+
+#define RK_PWM_DISABLE                  (0 << 0)
+#define RK_PWM_ENABLE                   (1 << 0)
+
+#define PWM_ONE_SHOT                    (0 << 1)
+#define PWM_CONTINUOUS                  (1 << 1)
+#define RK_PWM_CAPTURE                  (1 << 2)
+
+#define PWM_DUTY_POSTIVE                (1 << 3)
+#define PWM_DUTY_NEGATIVE               (0 << 3)
+
+#define PWM_INACTIVE_POSTIVE            (1 << 4)
+#define PWM_INACTIVE_NEGATIVE           (0 << 4)
+
+#define PWM_OUTPUT_LEFT                 (0 << 5)
+#define PWM_OUTPUT_CENTER               (1 << 5)
+
+#define PWM_LP_ENABLE                   (1 << 8)
+#define PWM_LP_DISABLE                  (0 << 8)
+
+#define PWM_SEL_SCALE_CLK		(1 << 9)
+#define PWM_SEL_SRC_CLK			(0 << 9)
+
+#endif
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index bd47159..cd8f357 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -8,3 +8,12 @@ config DM_PWM
 	  spends in the 'high' state, the higher the voltage. The PWM's
 	  frequency/period can be controlled along with the proportion of that
 	  time that the signal is high.
+
+config PWM_ROCKCHIP
+	bool "Enable support for the Rockchip PWM"
+	depends on DM_PWM
+	help
+	  This PWM is found on RK3288 and other Rockchip SoCs. It supports a
+	  programmable period and duty cycle. A 32-bit counter is used.
+	  Various options provided in the hardware (such as capture mode and
+	  continuous/single-shot) are not supported by the driver.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index d1b15e5..b6d8c16 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -11,4 +11,5 @@
 #ccflags-y += -DDEBUG
 
 obj-$(CONFIG_DM_PWM) += pwm-uclass.o
+obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o
 obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o
diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c
new file mode 100644
index 0000000..2d289a4
--- /dev/null
+++ b/drivers/pwm/rk_pwm.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <dm.h>
+#include <pwm.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3288.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/pwm.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk_pwm_priv {
+	struct rk3288_pwm *regs;
+	struct rk3288_grf *grf;
+};
+
+static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
+			     uint duty_ns)
+{
+	struct rk_pwm_priv *priv = dev_get_priv(dev);
+	struct rk3288_pwm *regs = priv->regs;
+	unsigned long period, duty;
+
+	debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
+	writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE |
+		PWM_CONTINUOUS | PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE |
+		RK_PWM_DISABLE,
+		&regs->ctrl);
+
+	period = lldiv((uint64_t)(PD_BUS_PCLK_HZ / 1000) * period_ns, 1000000);
+	duty = lldiv((uint64_t)(PD_BUS_PCLK_HZ / 1000) * duty_ns, 1000000);
+
+	writel(period, &regs->period_hpr);
+	writel(duty, &regs->duty_lpr);
+	debug("%s: period=%lu, duty=%lu\n", __func__, period, duty);
+
+	return 0;
+}
+
+static int rk_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
+{
+	struct rk_pwm_priv *priv = dev_get_priv(dev);
+	struct rk3288_pwm *regs = priv->regs;
+
+	debug("%s: Enable '%s'\n", __func__, dev->name);
+	clrsetbits_le32(&regs->ctrl, RK_PWM_ENABLE, enable ? RK_PWM_ENABLE : 0);
+
+	return 0;
+}
+
+static int rk_pwm_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk_pwm_priv *priv = dev_get_priv(dev);
+	struct regmap *map;
+
+	priv->regs = (struct rk3288_pwm *)dev_get_addr(dev);
+	map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_GRF);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+	priv->grf = regmap_get_range(map, 0);
+
+	return 0;
+}
+
+static int rk_pwm_probe(struct udevice *dev)
+{
+	struct rk_pwm_priv *priv = dev_get_priv(dev);
+
+	rk_setreg(&priv->grf->soc_con2, 1 << 0);
+
+	return 0;
+}
+
+static const struct pwm_ops rk_pwm_ops = {
+	.set_config	= rk_pwm_set_config,
+	.set_enable	= rk_pwm_set_enable,
+};
+
+static const struct udevice_id rk_pwm_ids[] = {
+	{ .compatible = "rockchip,rk3288-pwm" },
+	{ }
+};
+
+U_BOOT_DRIVER(rk_pwm) = {
+	.name	= "rk_pwm",
+	.id	= UCLASS_PWM,
+	.of_match = rk_pwm_ids,
+	.ops	= &rk_pwm_ops,
+	.ofdata_to_platdata	= rk_pwm_ofdata_to_platdata,
+	.probe		= rk_pwm_probe,
+	.priv_auto_alloc_size	= sizeof(struct rk_pwm_priv),
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 08/37] dm: backlight: Add a backlight uclass
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (6 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 07/37] pwm: rockchip: Add a PWM driver for Rockchip SoCs Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 09/37] dm: backlight: Add a driver for a PWM backlight Simon Glass
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

LCD panels normally have a backlight which can be controlled to illuminate
the LCD contents. Add a uclass to support this. Initially it only has a
method to enable the backlight.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Makefile           |  1 +
 drivers/video/backlight-uclass.c | 25 +++++++++++++++++++++++++
 include/backlight.h              | 31 +++++++++++++++++++++++++++++++
 include/dm/uclass-id.h           |  1 +
 4 files changed, 58 insertions(+)
 create mode 100644 drivers/video/backlight-uclass.c
 create mode 100644 include/backlight.h

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ee04629..fa90721 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -7,6 +7,7 @@
 
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
+obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
 obj-$(CONFIG_DM_VIDEO) += video_bmp.o
 obj-$(CONFIG_VIDEO_ROTATION) += console_rotate.o
diff --git a/drivers/video/backlight-uclass.c b/drivers/video/backlight-uclass.c
new file mode 100644
index 0000000..0238289
--- /dev/null
+++ b/drivers/video/backlight-uclass.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <backlight.h>
+
+int backlight_enable(struct udevice *dev)
+{
+	const struct backlight_ops *ops = backlight_get_ops(dev);
+
+	if (!ops->enable)
+		return -ENOSYS;
+
+	return ops->enable(dev);
+}
+
+UCLASS_DRIVER(backlight) = {
+	.id		= UCLASS_PANEL_BACKLIGHT,
+	.name		= "backlight",
+};
diff --git a/include/backlight.h b/include/backlight.h
new file mode 100644
index 0000000..90e1d98
--- /dev/null
+++ b/include/backlight.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _BACKLIGHT_H
+#define _BACKLIGHT_H
+
+struct backlight_ops {
+	/**
+	 * enable() - Enable a backlight
+	 *
+	 * @dev:	Backlight device to enable
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*enable)(struct udevice *dev);
+};
+
+#define backlight_get_ops(dev)	((struct backlight_ops *)(dev)->driver->ops)
+
+/**
+ * backlight_enable() - Enable a backlight
+ *
+ * @dev:	Backlight device to enable
+ * @return 0 if OK, -ve on error
+ */
+int backlight_enable(struct udevice *dev);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8f0381d..5421981 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -45,6 +45,7 @@ enum uclass_id {
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
 	UCLASS_MTD,		/* Memory Technology Device (MTD) device */
+	UCLASS_PANEL_BACKLIGHT,	/* Backlight controller for panel */
 	UCLASS_PCH,		/* x86 platform controller hub */
 	UCLASS_PCI,		/* PCI bus */
 	UCLASS_PCI_GENERIC,	/* Generic PCI bus device */
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 09/37] dm: backlight: Add a driver for a PWM backlight
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (7 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 08/37] dm: backlight: Add a backlight uclass Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 10/37] dm: panel: Add a panel uclass Simon Glass
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Many backlights need to use a PWM to control the brightness. Add a driver
for this. It understands the standard device tree binding.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Makefile        |   3 +
 drivers/video/pwm_backlight.c | 134 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+)
 create mode 100644 drivers/video/pwm_backlight.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index fa90721..6d89532 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -10,6 +10,9 @@ obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
 obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
 obj-$(CONFIG_DM_VIDEO) += video_bmp.o
+ifdef CONFIG_DM_VIDEO
+obj-$(CONFIG_DM_PWM) += pwm_backlight.o
+endif
 obj-$(CONFIG_VIDEO_ROTATION) += console_rotate.o
 endif
 
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c
new file mode 100644
index 0000000..de6277f
--- /dev/null
+++ b/drivers/video/pwm_backlight.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <backlight.h>
+#include <pwm.h>
+#include <asm/gpio.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pwm_backlight_priv {
+	struct udevice *reg;
+	struct gpio_desc enable;
+	struct udevice *pwm;
+	uint channel;
+	uint period_ns;
+	uint default_level;
+	uint min_level;
+	uint max_level;
+};
+
+static int pwm_backlight_enable(struct udevice *dev)
+{
+	struct pwm_backlight_priv *priv = dev_get_priv(dev);
+	uint duty_cycle;
+	int ret;
+
+	debug("%s: Enable '%s', regulator '%s'\n", __func__, dev->name,
+	      priv->reg->name);
+	ret = regulator_set_enable(priv->reg, true);
+	if (ret) {
+		debug("%s: Cannot enable regulator for PWM '%s'\n", __func__,
+		      dev->name);
+		return ret;
+	}
+	mdelay(120);
+
+	duty_cycle = priv->period_ns * (priv->default_level - priv->min_level) /
+		(priv->max_level - priv->min_level + 1);
+	ret = pwm_set_config(priv->pwm, priv->channel, priv->period_ns,
+			     duty_cycle);
+	if (ret)
+		return ret;
+	ret = pwm_set_enable(priv->pwm, priv->channel, true);
+	if (ret)
+		return ret;
+	mdelay(10);
+	dm_gpio_set_value(&priv->enable, 1);
+
+	return 0;
+}
+
+static int pwm_backlight_ofdata_to_platdata(struct udevice *dev)
+{
+	struct pwm_backlight_priv *priv = dev_get_priv(dev);
+	struct fdtdec_phandle_args args;
+	const void *blob = gd->fdt_blob;
+	int node = dev->of_offset;
+	int index, ret, count, len;
+	const u32 *cell;
+
+	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+					   "power-supply", &priv->reg);
+	if (ret) {
+		debug("%s: Cannot get power supply: ret=%d\n", __func__, ret);
+		return ret;
+	}
+	ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
+				   GPIOD_IS_OUT);
+	if (ret) {
+		debug("%s: Warning: cannot get enable GPIO: ret=%d\n",
+		      __func__, ret);
+		if (ret != -ENOENT)
+			return ret;
+	}
+	ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells",
+					     0, 0, &args);
+	if (ret) {
+		debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm);
+	if (ret) {
+		debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
+		return ret;
+	}
+	priv->channel = args.args[0];
+	priv->period_ns = args.args[1];
+
+	index = fdtdec_get_int(blob, node, "default-brightness-level", 255);
+	cell = fdt_getprop(blob, node, "brightness-levels", &len);
+	count = len / sizeof(u32);
+	if (cell && count > index) {
+		priv->default_level = fdt32_to_cpu(cell[index]);
+		priv->max_level = fdt32_to_cpu(cell[count - 1]);
+	} else {
+		priv->default_level = index;
+		priv->max_level = 255;
+	}
+
+
+	return 0;
+}
+
+static int pwm_backlight_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct backlight_ops pwm_backlight_ops = {
+	.enable	= pwm_backlight_enable,
+};
+
+static const struct udevice_id pwm_backlight_ids[] = {
+	{ .compatible = "pwm-backlight" },
+	{ }
+};
+
+U_BOOT_DRIVER(pwm_backlight) = {
+	.name	= "pwm_backlight",
+	.id	= UCLASS_PANEL_BACKLIGHT,
+	.of_match = pwm_backlight_ids,
+	.ops	= &pwm_backlight_ops,
+	.ofdata_to_platdata	= pwm_backlight_ofdata_to_platdata,
+	.probe		= pwm_backlight_probe,
+	.priv_auto_alloc_size	= sizeof(struct pwm_backlight_priv),
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 10/37] dm: panel: Add a panel uclass
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (8 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 09/37] dm: backlight: Add a driver for a PWM backlight Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 11/37] video: panel: Add a simple panel driver Simon Glass
                   ` (27 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

LCD panels can usefully be modelled as their own uclass. They can be probed
(which powers them up ready for use). If they have a backlight, this can be
enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Makefile       |  1 +
 drivers/video/panel-uclass.c | 25 +++++++++++++++++++++++++
 include/dm/uclass-id.h       |  1 +
 include/panel.h              | 31 +++++++++++++++++++++++++++++++
 4 files changed, 58 insertions(+)
 create mode 100644 drivers/video/panel-uclass.c
 create mode 100644 include/panel.h

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 6d89532..d29280c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -8,6 +8,7 @@
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
 obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o
+obj-$(CONFIG_DM_VIDEO) += panel-uclass.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
 obj-$(CONFIG_DM_VIDEO) += video_bmp.o
 ifdef CONFIG_DM_VIDEO
diff --git a/drivers/video/panel-uclass.c b/drivers/video/panel-uclass.c
new file mode 100644
index 0000000..3f4c41b
--- /dev/null
+++ b/drivers/video/panel-uclass.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <panel.h>
+
+int panel_enable_backlight(struct udevice *dev)
+{
+	struct panel_ops *ops = panel_get_ops(dev);
+
+	if (!ops->enable_backlight)
+		return -ENOSYS;
+
+	return ops->enable_backlight(dev);
+}
+
+UCLASS_DRIVER(panel) = {
+	.id		= UCLASS_PANEL,
+	.name		= "panel",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 5421981..8308c23 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -45,6 +45,7 @@ enum uclass_id {
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
 	UCLASS_MTD,		/* Memory Technology Device (MTD) device */
+	UCLASS_PANEL,		/* Display panel, such as an LCD */
 	UCLASS_PANEL_BACKLIGHT,	/* Backlight controller for panel */
 	UCLASS_PCH,		/* x86 platform controller hub */
 	UCLASS_PCI,		/* PCI bus */
diff --git a/include/panel.h b/include/panel.h
new file mode 100644
index 0000000..57fccf2
--- /dev/null
+++ b/include/panel.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _PANEL_H
+#define _PANEL_H
+
+struct panel_ops {
+	/**
+	 * enable_backlight() - Enable the panel backlight
+	 *
+	 * @dev:	Panel device containing the backlight to enable
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*enable_backlight)(struct udevice *dev);
+};
+
+#define panel_get_ops(dev)	((struct panel_ops *)(dev)->driver->ops)
+
+/**
+ * panel_enable_backlight() - Enable the panel backlight
+ *
+ * @dev:	Panel device containing the backlight to enable
+ * @return 0 if OK, -ve on error
+ */
+int panel_enable_backlight(struct udevice *dev);
+
+#endif
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 11/37] video: panel: Add a simple panel driver
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (9 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 10/37] dm: panel: Add a panel uclass Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 12/37] dm: video: Repurpose the 'displayport' uclass to 'display' Simon Glass
                   ` (26 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Most panels are very simple - they just have a power supply and a backlight.
Add a driver which supports this and implements the enable_backlight()
method.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/Makefile       |  2 +-
 drivers/video/simple_panel.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/simple_panel.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index d29280c..6658e96 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -8,7 +8,7 @@
 ifdef CONFIG_DM
 obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
 obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o
-obj-$(CONFIG_DM_VIDEO) += panel-uclass.o
+obj-$(CONFIG_DM_VIDEO) += panel-uclass.o simple_panel.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
 obj-$(CONFIG_DM_VIDEO) += video_bmp.o
 ifdef CONFIG_DM_VIDEO
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c
new file mode 100644
index 0000000..b161517
--- /dev/null
+++ b/drivers/video/simple_panel.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <asm/gpio.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct simple_panel_priv {
+	struct udevice *reg;
+	struct udevice *backlight;
+	struct gpio_desc enable;
+};
+
+static int simple_panel_enable_backlight(struct udevice *dev)
+{
+	struct simple_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	dm_gpio_set_value(&priv->enable, 1);
+	ret = backlight_enable(priv->backlight);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int simple_panel_ofdata_to_platdata(struct udevice *dev)
+{
+	struct simple_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+					   "power-supply", &priv->reg);
+	if (ret) {
+		debug("%s: Warning: cnnot get power supply: ret=%d\n",
+		      __func__, ret);
+		if (ret != -ENOENT)
+			return ret;
+	}
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+					   "backlight", &priv->backlight);
+	if (ret) {
+		debug("%s: Cannot get backlight: ret=%d\n", __func__, ret);
+		return ret;
+	}
+	ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
+				   GPIOD_IS_OUT);
+	if (ret) {
+		debug("%s: Warning: cannot get enable GPIO: ret=%d\n",
+		      __func__, ret);
+		if (ret != -ENOENT)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int simple_panel_probe(struct udevice *dev)
+{
+	struct simple_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (priv->reg) {
+		debug("%s: Enable regulator '%s'\n", __func__, priv->reg->name);
+		ret = regulator_set_enable(priv->reg, true);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct panel_ops simple_panel_ops = {
+	.enable_backlight	= simple_panel_enable_backlight,
+};
+
+static const struct udevice_id simple_panel_ids[] = {
+	{ .compatible = "simple-panel" },
+	{ }
+};
+
+U_BOOT_DRIVER(simple_panel) = {
+	.name	= "simple_panel",
+	.id	= UCLASS_PANEL,
+	.of_match = simple_panel_ids,
+	.ops	= &simple_panel_ops,
+	.ofdata_to_platdata	= simple_panel_ofdata_to_platdata,
+	.probe		= simple_panel_probe,
+	.priv_auto_alloc_size	= sizeof(struct simple_panel_priv),
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 12/37] dm: video: Repurpose the 'displayport' uclass to 'display'
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (10 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 11/37] video: panel: Add a simple panel driver Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 13/37] rockchip: Rename the CRU_MODE_CON fields Simon Glass
                   ` (25 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

The current DisplayPort uclass is too specific. The operations it provides
are shared with other types of output devices, such as HDMI and LVDS LCD
displays.

Generalise the uclass so that it can be used with these devices as well.
Adjust the uclass to handle the EDID reading and conversion to
display_timing internally.

Also update nyan-big which is affected by this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 configs/nyan-big_defconfig           |  2 +-
 drivers/video/Kconfig                | 13 +++++----
 drivers/video/Makefile               |  2 +-
 drivers/video/display-uclass.c       | 52 ++++++++++++++++++++++++++++++++++++
 drivers/video/dp-uclass.c            | 34 -----------------------
 drivers/video/tegra124/display.c     | 18 ++++---------
 drivers/video/tegra124/dp.c          |  9 ++++---
 include/{displayport.h => display.h} | 33 ++++++++++++++---------
 include/dm/uclass-id.h               |  2 +-
 include/edid.h                       |  1 +
 10 files changed, 95 insertions(+), 71 deletions(-)
 create mode 100644 drivers/video/display-uclass.c
 delete mode 100644 drivers/video/dp-uclass.c
 rename include/{displayport.h => display.h} (59%)

diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig
index 7fc1bde..03348a6 100644
--- a/configs/nyan-big_defconfig
+++ b/configs/nyan-big_defconfig
@@ -25,7 +25,7 @@ CONFIG_TEGRA114_SPI=y
 CONFIG_TPM_TIS_INFINEON=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
-CONFIG_DISPLAY_PORT=y
+CONFIG_DISPLAY=y
 CONFIG_VIDEO_TEGRA124=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_TPM=y
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index b90850b..1790fdd 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -293,12 +293,15 @@ config VIDEO_LCD_SPI_MISO
 	option takes a string in the format understood by 'name_to_gpio'
 	function, e.g. PH1 for pin 1 of port H.
 
-config DISPLAY_PORT
-	bool "Enable DisplayPort support"
+config DISPLAY
+	bool "Enable Display support"
+	depends on DM
+	default y
 	help
-	   eDP (Embedded DisplayPort) is a standard widely used in laptops
-	   to drive LCD panels. This framework provides support for enabling
-	   these displays where supported by the video hardware.
+	   This supports drivers that provide a display, such as eDP (Embedded
+	   DisplayPort) and HDMI (High Definition Multimedia Interface).
+	   The devices provide a simple interface to start up the display,
+	   read display information and enable it.
 
 config VIDEO_SANDBOX_SDL
 	bool "Enable sandbox video console using SDL"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 6658e96..c135e22 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -6,7 +6,7 @@
 #
 
 ifdef CONFIG_DM
-obj-$(CONFIG_DISPLAY_PORT) += dp-uclass.o
+obj-$(CONFIG_DISPLAY) += display-uclass.o
 obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o
 obj-$(CONFIG_DM_VIDEO) += panel-uclass.o simple_panel.o
 obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o console_normal.o
diff --git a/drivers/video/display-uclass.c b/drivers/video/display-uclass.c
new file mode 100644
index 0000000..31522ea
--- /dev/null
+++ b/drivers/video/display-uclass.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <display.h>
+#include <edid.h>
+#include <errno.h>
+
+int display_read_edid(struct udevice *dev, u8 *buf, int buf_size)
+{
+	struct dm_display_ops *ops = display_get_ops(dev);
+
+	if (!ops || !ops->read_edid)
+		return -ENOSYS;
+	return ops->read_edid(dev, buf, buf_size);
+}
+
+int display_enable(struct udevice *dev, int panel_bpp,
+			const struct display_timing *timing)
+{
+	struct dm_display_ops *ops = display_get_ops(dev);
+
+	if (!ops || !ops->enable)
+		return -ENOSYS;
+	return ops->enable(dev, panel_bpp, timing);
+}
+
+int display_read_timing(struct udevice *dev, struct display_timing *timing)
+{
+	struct dm_display_ops *ops = display_get_ops(dev);
+	int panel_bits_per_colour;
+	u8 buf[EDID_EXT_SIZE];
+	int ret;
+
+	if (!ops || !ops->read_edid)
+		return -ENOSYS;
+	ret = ops->read_edid(dev, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	return edid_get_timing(buf, ret, timing, &panel_bits_per_colour);
+}
+
+UCLASS_DRIVER(display) = {
+	.id		= UCLASS_DISPLAY,
+	.name		= "display",
+	.per_device_platdata_auto_alloc_size	= sizeof(struct display_plat),
+};
diff --git a/drivers/video/dp-uclass.c b/drivers/video/dp-uclass.c
deleted file mode 100644
index 17f5de9..0000000
--- a/drivers/video/dp-uclass.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * SPDX-License-Identifier:     GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <displayport.h>
-#include <errno.h>
-
-int display_port_read_edid(struct udevice *dev, u8 *buf, int buf_size)
-{
-	struct dm_display_port_ops *ops = display_port_get_ops(dev);
-
-	if (!ops || !ops->read_edid)
-		return -ENOSYS;
-	return ops->read_edid(dev, buf, buf_size);
-}
-
-int display_port_enable(struct udevice *dev, int panel_bpp,
-			const struct display_timing *timing)
-{
-	struct dm_display_port_ops *ops = display_port_get_ops(dev);
-
-	if (!ops || !ops->enable)
-		return -ENOSYS;
-	return ops->enable(dev, panel_bpp, timing);
-}
-
-UCLASS_DRIVER(display_port) = {
-	.id		= UCLASS_DISPLAY_PORT,
-	.name		= "display_port",
-};
diff --git a/drivers/video/tegra124/display.c b/drivers/video/tegra124/display.c
index 7179dbf..610ffa9 100644
--- a/drivers/video/tegra124/display.c
+++ b/drivers/video/tegra124/display.c
@@ -10,7 +10,7 @@
 #include <dm.h>
 #include <edid.h>
 #include <errno.h>
-#include <displayport.h>
+#include <display.h>
 #include <edid.h>
 #include <fdtdec.h>
 #include <lcd.h>
@@ -324,20 +324,12 @@ static int display_update_config_from_edid(struct udevice *dp_dev,
 					   int *panel_bppp,
 					   struct display_timing *timing)
 {
-	u8 buf[EDID_SIZE];
-	int bpc, ret;
+	int ret;
 
-	ret = display_port_read_edid(dp_dev, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-	ret = edid_get_timing(buf, ret, timing, &bpc);
+	ret = display_read_timing(dp_dev, timing);
 	if (ret)
 		return ret;
 
-	/* Use this information if valid */
-	if (bpc != -1)
-		*panel_bppp = bpc * 3;
-
 	return 0;
 }
 
@@ -398,7 +390,7 @@ int display_init(void *lcdbase, int fb_bits_per_pixel,
 	int node;
 	int ret;
 
-	ret = uclass_get_device(UCLASS_DISPLAY_PORT, 0, &dp_dev);
+	ret = uclass_get_device(UCLASS_DISPLAY, 0, &dp_dev);
 	if (ret)
 		return ret;
 
@@ -450,7 +442,7 @@ int display_init(void *lcdbase, int fb_bits_per_pixel,
 	}
 
 	/* Enable dp */
-	ret = display_port_enable(dp_dev, panel_bpp, timing);
+	ret = display_enable(dp_dev, panel_bpp, timing);
 	if (ret)
 		return ret;
 
diff --git a/drivers/video/tegra124/dp.c b/drivers/video/tegra124/dp.c
index 1bf9202..bb1805a 100644
--- a/drivers/video/tegra124/dp.c
+++ b/drivers/video/tegra124/dp.c
@@ -6,16 +6,17 @@
  */
 
 #include <common.h>
-#include <displayport.h>
+#include <display.h>
 #include <dm.h>
 #include <div64.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/dc.h>
-#include "displayport.h"
+#include "display.h"
 #include "edid.h"
 #include "sor.h"
+#include "displayport.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -1573,7 +1574,7 @@ static int tegra_dp_read_edid(struct udevice *dev, u8 *buf, int buf_size)
 				     buf_size, &aux_stat);
 }
 
-static const struct dm_display_port_ops dp_tegra_ops = {
+static const struct dm_display_ops dp_tegra_ops = {
 	.read_edid = tegra_dp_read_edid,
 	.enable = tegra_dp_enable,
 };
@@ -1596,7 +1597,7 @@ static const struct udevice_id tegra_dp_ids[] = {
 
 U_BOOT_DRIVER(dp_tegra) = {
 	.name	= "dpaux_tegra",
-	.id	= UCLASS_DISPLAY_PORT,
+	.id	= UCLASS_DISPLAY,
 	.of_match = tegra_dp_ids,
 	.ofdata_to_platdata = tegra_dp_ofdata_to_platdata,
 	.probe	= dp_tegra_probe,
diff --git a/include/displayport.h b/include/display.h
similarity index 59%
rename from include/displayport.h
rename to include/display.h
index f7c7e25..c180e76 100644
--- a/include/displayport.h
+++ b/include/display.h
@@ -4,21 +4,31 @@
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
-#ifndef _DISPLAYPORT_H
-#define _DISPLAYPORT_H
+#ifndef _DISPLAY_H
+#define _DISPLAY_H
 
 struct udevice;
 struct display_timing;
 
 /**
- * display_port_read_edid() - Read information from EDID
+ * Display uclass platform data for each device
+ *
+ * @source_id:	ID for the source of the display data, typically a video
+ * controller
+ * @src_dev:	Source device providing the video
+ */
+struct display_plat {
+	int source_id;
+	struct udevice *src_dev;
+};
+
+/**
+ * display_read_timing() - Read timing information from EDID
  *
  * @dev:	Device to read from
- * @buf:	Buffer to read into (should be EDID_SIZE bytes)
- * @buf_size:	Buffer size (should be EDID_SIZE)
- * @return number of bytes read, <=0 for error
+ * @return 0 if OK, -ve on error
  */
-int display_port_read_edid(struct udevice *dev, u8 *buf, int buf_size);
+int display_read_timing(struct udevice *dev, struct display_timing *timing);
 
 /**
  * display_port_enable() - Enable a display port device
@@ -28,10 +38,10 @@ int display_port_read_edid(struct udevice *dev, u8 *buf, int buf_size);
  * @timing:	Display timings
  * @return 0 if OK, -ve on error
  */
-int display_port_enable(struct udevice *dev, int panel_bpp,
-			const struct display_timing *timing);
+int display_enable(struct udevice *dev, int panel_bpp,
+		   const struct display_timing *timing);
 
-struct dm_display_port_ops {
+struct dm_display_ops {
 	/**
 	 * read_edid() - Read information from EDID
 	 *
@@ -54,7 +64,6 @@ struct dm_display_port_ops {
 		      const struct display_timing *timing);
 };
 
-#define display_port_get_ops(dev)	\
-	((struct dm_display_port_ops *)(dev)->driver->ops)
+#define display_get_ops(dev)	((struct dm_display_ops *)(dev)->driver->ops)
 
 #endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8308c23..8391e38 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -29,7 +29,7 @@ enum uclass_id {
 	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
 	UCLASS_CPU,		/* CPU, typically part of an SoC */
 	UCLASS_CROS_EC,		/* Chrome OS EC */
-	UCLASS_DISPLAY_PORT,	/* Display port video */
+	UCLASS_DISPLAY,		/* Display (e.g. DisplayPort, HDMI) */
 	UCLASS_RAM,		/* RAM controller */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
diff --git a/include/edid.h b/include/edid.h
index 88b4b7d..8b022fa 100644
--- a/include/edid.h
+++ b/include/edid.h
@@ -17,6 +17,7 @@
 
 /* Size of the EDID data */
 #define EDID_SIZE	128
+#define EDID_EXT_SIZE	256
 
 #define GET_BIT(_x, _pos) \
 	(((_x) >> (_pos)) & 1)
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 13/37] rockchip: Rename the CRU_MODE_CON fields
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (11 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 12/37] dm: video: Repurpose the 'displayport' uclass to 'display' Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 14/37] rockchip: clk: Add support for clocks needed by the displays Simon Glass
                   ` (24 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

These should match the datasheet naming. Adjust them.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/arch-rockchip/cru_rk3288.h | 58 ++++++++++++-------------
 drivers/clk/clk_rk3288.c                        | 39 ++++-------------
 2 files changed, 38 insertions(+), 59 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
index 7ebcc40..b0dea70 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
@@ -131,35 +131,35 @@ enum {
 
 /* CRU_MODE_CON */
 enum {
-	NPLL_WORK_SHIFT		= 0xe,
-	NPLL_WORK_MASK		= 3,
-	NPLL_WORK_SLOW		= 0,
-	NPLL_WORK_NORMAL,
-	NPLL_WORK_DEEP,
-
-	GPLL_WORK_SHIFT		= 0xc,
-	GPLL_WORK_MASK		= 3,
-	GPLL_WORK_SLOW		= 0,
-	GPLL_WORK_NORMAL,
-	GPLL_WORK_DEEP,
-
-	CPLL_WORK_SHIFT		= 8,
-	CPLL_WORK_MASK		= 3,
-	CPLL_WORK_SLOW		= 0,
-	CPLL_WORK_NORMAL,
-	CPLL_WORK_DEEP,
-
-	DPLL_WORK_SHIFT		= 4,
-	DPLL_WORK_MASK		= 3,
-	DPLL_WORK_SLOW		= 0,
-	DPLL_WORK_NORMAL,
-	DPLL_WORK_DEEP,
-
-	APLL_WORK_SHIFT		= 0,
-	APLL_WORK_MASK		= 3,
-	APLL_WORK_SLOW		= 0,
-	APLL_WORK_NORMAL,
-	APLL_WORK_DEEP,
+	NPLL_MODE_SHIFT		= 0xe,
+	NPLL_MODE_MASK		= 3,
+	NPLL_MODE_SLOW		= 0,
+	NPLL_MODE_NORMAL,
+	NPLL_MODE_DEEP,
+
+	GPLL_MODE_SHIFT		= 0xc,
+	GPLL_MODE_MASK		= 3,
+	GPLL_MODE_SLOW		= 0,
+	GPLL_MODE_NORMAL,
+	GPLL_MODE_DEEP,
+
+	CPLL_MODE_SHIFT		= 8,
+	CPLL_MODE_MASK		= 3,
+	CPLL_MODE_SLOW		= 0,
+	CPLL_MODE_NORMAL,
+	CPLL_MODE_DEEP,
+
+	DPLL_MODE_SHIFT		= 4,
+	DPLL_MODE_MASK		= 3,
+	DPLL_MODE_SLOW		= 0,
+	DPLL_MODE_NORMAL,
+	DPLL_MODE_DEEP,
+
+	APLL_MODE_SHIFT		= 0,
+	APLL_MODE_MASK		= 3,
+	APLL_MODE_SLOW		= 0,
+	APLL_MODE_NORMAL,
+	APLL_MODE_DEEP,
 };
 
 /* CRU_APLL_CON0 */
diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
index f25a124..d3c14dd 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/clk_rk3288.c
@@ -97,27 +97,6 @@ enum {
 	PERI_ACLK_DIV_SHIFT	= 0,
 	PERI_ACLK_DIV_MASK	= 0x1f,
 
-	/* CLKSEL37 */
-	DPLL_MODE_MASK		= 0x3,
-	DPLL_MODE_SHIFT		= 4,
-	DPLL_MODE_SLOW		= 0,
-	DPLL_MODE_NORM,
-
-	CPLL_MODE_MASK		= 3,
-	CPLL_MODE_SHIFT		= 8,
-	CPLL_MODE_SLOW		= 0,
-	CPLL_MODE_NORM,
-
-	GPLL_MODE_MASK		= 3,
-	GPLL_MODE_SHIFT		= 12,
-	GPLL_MODE_SLOW		= 0,
-	GPLL_MODE_NORM,
-
-	NPLL_MODE_MASK		= 3,
-	NPLL_MODE_SHIFT		= 14,
-	NPLL_MODE_SLOW		= 0,
-	NPLL_MODE_NORM,
-
 	SOCSTS_DPLL_LOCK	= 1 << 5,
 	SOCSTS_APLL_LOCK	= 1 << 6,
 	SOCSTS_CPLL_LOCK	= 1 << 7,
@@ -251,7 +230,7 @@ static int rkclk_configure_ddr(struct rk3288_cru *cru, struct rk3288_grf *grf,
 
 	/* PLL enter normal-mode */
 	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
-		     DPLL_MODE_NORM << DPLL_MODE_SHIFT);
+		     DPLL_MODE_NORMAL << DPLL_MODE_SHIFT);
 
 	return 0;
 }
@@ -331,8 +310,8 @@ static void rkclk_init(struct rk3288_cru *cru, struct rk3288_grf *grf)
 	rk_clrsetreg(&cru->cru_mode_con,
 		     GPLL_MODE_MASK << GPLL_MODE_SHIFT |
 		     CPLL_MODE_MASK << CPLL_MODE_SHIFT,
-		     GPLL_MODE_NORM << GPLL_MODE_SHIFT |
-		     GPLL_MODE_NORM << CPLL_MODE_SHIFT);
+		     GPLL_MODE_NORMAL << GPLL_MODE_SHIFT |
+		     CPLL_MODE_NORMAL << CPLL_MODE_SHIFT);
 }
 #endif
 
@@ -345,17 +324,17 @@ static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru,
 	int pll_id = rk_pll_id(clk_id);
 	struct rk3288_pll *pll = &cru->pll[pll_id];
 	static u8 clk_shift[CLK_COUNT] = {
-		0xff, APLL_WORK_SHIFT, DPLL_WORK_SHIFT, CPLL_WORK_SHIFT,
-		GPLL_WORK_SHIFT, NPLL_WORK_SHIFT
+		0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
+		GPLL_MODE_SHIFT, NPLL_MODE_SHIFT
 	};
 	uint shift;
 
 	con = readl(&cru->cru_mode_con);
 	shift = clk_shift[clk_id];
-	switch ((con >> shift) & APLL_WORK_MASK) {
-	case APLL_WORK_SLOW:
+	switch ((con >> shift) & APLL_MODE_MASK) {
+	case APLL_MODE_SLOW:
 		return OSC_HZ;
-	case APLL_WORK_NORMAL:
+	case APLL_MODE_NORMAL:
 		/* normal mode */
 		con = readl(&pll->con0);
 		no = ((con >> CLKOD_SHIFT) & CLKOD_MASK) + 1;
@@ -364,7 +343,7 @@ static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru,
 		nf = ((con >> CLKF_SHIFT) & CLKF_MASK) + 1;
 
 		return (24 * nf / (nr * no)) * 1000000;
-	case APLL_WORK_DEEP:
+	case APLL_MODE_DEEP:
 	default:
 		return 32768;
 	}
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 14/37] rockchip: clk: Add support for clocks needed by the displays
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (12 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 13/37] rockchip: Rename the CRU_MODE_CON fields Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 15/37] rockchip: video: Add a display driver for rockchip HDMI Simon Glass
                   ` (23 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

The displays need to use NPLL and also select some new peripheral clocks.
Add support for these to the clock driver.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/clk/clk_rk3288.c | 174 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 170 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
index d3c14dd..42d2f85 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/clk_rk3288.c
@@ -235,6 +235,124 @@ static int rkclk_configure_ddr(struct rk3288_cru *cru, struct rk3288_grf *grf,
 	return 0;
 }
 
+#ifndef CONFIG_SPL_BUILD
+#define VCO_MAX_KHZ	2200000
+#define VCO_MIN_KHZ	440000
+#define FREF_MAX_KHZ	2200000
+#define FREF_MIN_KHZ	269
+
+static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div)
+{
+	uint ref_khz = OSC_HZ / 1000, nr, nf = 0;
+	uint fref_khz;
+	uint diff_khz, best_diff_khz;
+	const uint max_nr = 1 << 6, max_nf = 1 << 12, max_no = 1 << 4;
+	uint vco_khz;
+	uint no = 1;
+	uint freq_khz = freq_hz / 1000;
+
+	if (!freq_hz) {
+		printf("%s: the frequency can not be 0 Hz\n", __func__);
+		return -EINVAL;
+	}
+
+	no = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
+	if (ext_div) {
+		*ext_div = DIV_ROUND_UP(no, max_no);
+		no = DIV_ROUND_UP(no, *ext_div);
+	}
+
+	/* only even divisors (and 1) are supported */
+	if (no > 1)
+		no = DIV_ROUND_UP(no, 2) * 2;
+
+	vco_khz = freq_khz * no;
+	if (ext_div)
+		vco_khz *= *ext_div;
+
+	if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ || no > max_no) {
+		printf("%s: Cannot find out a supported VCO for Frequency (%luHz).\n",
+		       __func__, freq_hz);
+		return -1;
+	}
+
+	div->no = no;
+
+	best_diff_khz = vco_khz;
+	for (nr = 1; nr < max_nr && best_diff_khz; nr++) {
+		fref_khz = ref_khz / nr;
+		if (fref_khz < FREF_MIN_KHZ)
+			break;
+		if (fref_khz > FREF_MAX_KHZ)
+			continue;
+
+		nf = vco_khz / fref_khz;
+		if (nf >= max_nf)
+			continue;
+		diff_khz = vco_khz - nf * fref_khz;
+		if (nf + 1 < max_nf && diff_khz > fref_khz / 2) {
+			nf++;
+			diff_khz = fref_khz - diff_khz;
+		}
+
+		if (diff_khz >= best_diff_khz)
+			continue;
+
+		best_diff_khz = diff_khz;
+		div->nr = nr;
+		div->nf = nf;
+	}
+
+	if (best_diff_khz > 4 * 1000) {
+		printf("%s: Failed to match output frequency %lu, difference is %u Hz, exceed 4MHZ\n",
+		       __func__, freq_hz, best_diff_khz * 1000);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rockchip_vop_set_clk(struct rk3288_cru *cru, struct rk3288_grf *grf,
+				int periph, unsigned int rate_hz)
+{
+	struct pll_div npll_config = {0};
+	u32 lcdc_div;
+	int ret;
+
+	ret = pll_para_config(rate_hz, &npll_config, &lcdc_div);
+	if (ret)
+		return ret;
+
+	rk_clrsetreg(&cru->cru_mode_con, NPLL_MODE_MASK << NPLL_MODE_SHIFT,
+		     NPLL_MODE_SLOW << NPLL_MODE_SHIFT);
+	rkclk_set_pll(cru, CLK_NEW, &npll_config);
+
+	/* waiting for pll lock */
+	while (1) {
+		if (readl(&grf->soc_status[1]) & SOCSTS_NPLL_LOCK)
+			break;
+		udelay(1);
+	}
+
+	rk_clrsetreg(&cru->cru_mode_con, NPLL_MODE_MASK << NPLL_MODE_SHIFT,
+		     NPLL_MODE_NORMAL << NPLL_MODE_SHIFT);
+
+	/* vop dclk source clk: npll,dclk_div: 1 */
+	switch (periph) {
+	case DCLK_VOP0:
+		rk_clrsetreg(&cru->cru_clksel_con[27], 0xff << 8 | 3 << 0,
+			     (lcdc_div - 1) << 8 | 2 << 0);
+		break;
+	case DCLK_VOP1:
+		rk_clrsetreg(&cru->cru_clksel_con[29], 0xff << 8 | 3 << 6,
+			     (lcdc_div - 1) << 8 | 2 << 6);
+		break;
+	}
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SPL_BUILD
 static void rkclk_init(struct rk3288_cru *cru, struct rk3288_grf *grf)
 {
@@ -559,6 +677,7 @@ ulong rk3288_get_periph_rate(struct udevice *dev, int periph)
 ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
 {
 	struct rk3288_clk_priv *priv = dev_get_priv(dev);
+	struct rk3288_cru *cru = priv->cru;
 	struct udevice *gclk;
 	ulong new_rate, gclk_rate;
 	int ret;
@@ -571,15 +690,62 @@ ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
 	case HCLK_EMMC:
 	case HCLK_SDMMC:
 	case HCLK_SDIO0:
-		new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate, periph,
-						rate);
+		new_rate = rockchip_mmc_set_clk(cru, gclk_rate, periph, rate);
 		break;
 	case SCLK_SPI0:
 	case SCLK_SPI1:
 	case SCLK_SPI2:
-		new_rate = rockchip_spi_set_clk(priv->cru, gclk_rate, periph,
-						rate);
+		new_rate = rockchip_spi_set_clk(cru, gclk_rate, periph, rate);
 		break;
+#ifndef CONFIG_SPL_BUILD
+	case DCLK_VOP0:
+	case DCLK_VOP1:
+		new_rate = rockchip_vop_set_clk(cru, priv->grf, periph, rate);
+		break;
+	case SCLK_EDP_24M:
+		/* clk_edp_24M source: 24M */
+		rk_setreg(&cru->cru_clksel_con[28], 1 << 15);
+
+		/* rst edp */
+		rk_setreg(&cru->cru_clksel_con[6], 1 << 15);
+		udelay(1);
+		rk_clrreg(&cru->cru_clksel_con[6], 1 << 15);
+		new_rate = rate;
+		break;
+	case ACLK_VOP0:
+	case ACLK_VOP1: {
+		u32 div;
+
+		/* vop aclk source clk: cpll */
+		div = CPLL_HZ / rate;
+		assert((div - 1 < 64) && (div * rate == CPLL_HZ));
+
+		switch (periph) {
+		case ACLK_VOP0:
+			rk_clrsetreg(&cru->cru_clksel_con[31],
+				     3 << 6 | 0x1f << 0,
+				     0 << 6 | (div - 1) << 0);
+			break;
+		case ACLK_VOP1:
+			rk_clrsetreg(&cru->cru_clksel_con[31],
+				     3 << 14 | 0x1f << 8,
+				     0 << 14 | (div - 1) << 8);
+			break;
+		}
+		new_rate = rate;
+		break;
+	}
+	case PCLK_HDMI_CTRL:
+		/* enable pclk hdmi ctrl */
+		rk_clrreg(&cru->cru_clkgate_con[16], 1 << 9);
+
+		/* software reset hdmi */
+		rk_setreg(&cru->cru_clkgate_con[7], 1 << 9);
+		udelay(1);
+		rk_clrreg(&cru->cru_clkgate_con[7], 1 << 9);
+		new_rate = rate;
+		break;
+#endif
 	default:
 		return -ENOENT;
 	}
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 15/37] rockchip: video: Add a display driver for rockchip HDMI
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (13 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 14/37] rockchip: clk: Add support for clocks needed by the displays Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:57 ` [U-Boot] [PATCH 16/37] rockchip: video: Add a display driver for rockchip eDP Simon Glass
                   ` (22 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Some Rockchip SoCs support HDMI output. Add a display driver for this so
that these displays can be used on supported boards.

Unfortunately this driver is not fully functional. It cannot reliably read
EDID information over HDMI. This seems to be due to the clocks being
incorrect - the I2C bus speed appears to be up to 100x slower than the
clock settings indicate. The root cause may be in the clock logic.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h | 456 +++++++++++
 drivers/video/Kconfig                            |  10 +
 drivers/video/Makefile                           |   1 +
 drivers/video/rockchip/Makefile                  |   8 +
 drivers/video/rockchip/rk_hdmi.c                 | 929 +++++++++++++++++++++++
 5 files changed, 1404 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h
 create mode 100644 drivers/video/rockchip/Makefile
 create mode 100644 drivers/video/rockchip/rk_hdmi.c

diff --git a/arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h b/arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h
new file mode 100644
index 0000000..0b51d40
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/hdmi_rk3288.h
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_HDMI_H
+#define _ASM_ARCH_HDMI_H
+
+
+#define HDMI_EDID_BLOCK_SIZE            128
+
+struct rk3288_hdmi {
+	u32 reserved0[0x100];
+	u32 ih_fc_stat0;
+	u32 ih_fc_stat1;
+	u32 ih_fc_stat2;
+	u32 ih_as_stat0;
+	u32 ih_phy_stat0;
+	u32 ih_i2cm_stat0;
+	u32 ih_cec_stat0;
+	u32 ih_vp_stat0;
+	u32 ih_i2cmphy_stat0;
+	u32 ih_ahbdmaaud_stat0;
+	u32 reserved1[0x17f-0x109];
+	u32 ih_mute_fc_stat0;
+	u32 ih_mute_fc_stat1;
+	u32 ih_mute_fc_stat2;
+	u32 ih_mute_as_stat0;
+	u32 ih_mute_phy_stat0;
+	u32 ih_mute_i2cm_stat0;
+	u32 ih_mute_cec_stat0;
+	u32 ih_mute_vp_stat0;
+	u32 ih_mute_i2cmphy_stat0;
+	u32 ih_mute_ahbdmaaud_stat0;
+	u32 reserved2[0x1fe - 0x189];
+	u32 ih_mute;
+	u32 tx_invid0;
+	u32 tx_instuffing;
+	u32 tx_gydata0;
+	u32 tx_gydata1;
+	u32 tx_rcrdata0;
+	u32 tx_rcrdata1;
+	u32 tx_bcbdata0;
+	u32 tx_bcbdata1;
+	u32 reserved3[0x7ff-0x207];
+	u32 vp_status;
+	u32 vp_pr_cd;
+	u32 vp_stuff;
+	u32 vp_remap;
+	u32 vp_conf;
+	u32 vp_stat;
+	u32 vp_int;
+	u32 vp_mask;
+	u32 vp_pol;
+	u32 reserved4[0xfff-0x808];
+	u32 fc_invidconf;
+	u32 fc_inhactv0;
+	u32 fc_inhactv1;
+	u32 fc_inhblank0;
+	u32 fc_inhblank1;
+	u32 fc_invactv0;
+	u32 fc_invactv1;
+	u32 fc_invblank;
+	u32 fc_hsyncindelay0;
+	u32 fc_hsyncindelay1;
+	u32 fc_hsyncinwidth0;
+	u32 fc_hsyncinwidth1;
+	u32 fc_vsyncindelay;
+	u32 fc_vsyncinwidth;
+	u32 fc_infreq0;
+	u32 fc_infreq1;
+	u32 fc_infreq2;
+	u32 fc_ctrldur;
+	u32 fc_exctrldur;
+	u32 fc_exctrlspac;
+	u32 fc_ch0pream;
+	u32 fc_ch1pream;
+	u32 fc_ch2pream;
+	u32 fc_aviconf3;
+	u32 fc_gcp;
+	u32 fc_aviconf0;
+	u32 fc_aviconf1;
+	u32 fc_aviconf2;
+	u32 fc_avivid;
+	u32 fc_avietb0;
+	u32 fc_avietb1;
+	u32 fc_avisbb0;
+	u32 fc_avisbb1;
+	u32 fc_avielb0;
+	u32 fc_avielb1;
+	u32 fc_avisrb0;
+	u32 fc_avisrb1;
+	u32 fc_audiconf0;
+	u32 fc_audiconf1;
+	u32 fc_audiconf2;
+	u32 fc_audiconf3;
+	u32 fc_vsdieeeid0;
+	u32 fc_vsdsize;
+	u32 reserved7[0x2fff-0x102a];
+	u32 phy_conf0;
+	u32 phy_tst0;
+	u32 phy_tst1;
+	u32 phy_tst2;
+	u32 phy_stat0;
+	u32 phy_int0;
+	u32 phy_mask0;
+	u32 phy_pol0;
+	u32 reserved8[0x301f-0x3007];
+	u32 phy_i2cm_slave_addr;
+	u32 phy_i2cm_address_addr;
+	u32 phy_i2cm_datao_1_addr;
+	u32 phy_i2cm_datao_0_addr;
+	u32 phy_i2cm_datai_1_addr;
+	u32 phy_i2cm_datai_0_addr;
+	u32 phy_i2cm_operation_addr;
+	u32 phy_i2cm_int_addr;
+	u32 phy_i2cm_ctlint_addr;
+	u32 phy_i2cm_div_addr;
+	u32 phy_i2cm_softrstz_addr;
+	u32 phy_i2cm_ss_scl_hcnt_1_addr;
+	u32 phy_i2cm_ss_scl_hcnt_0_addr;
+	u32 phy_i2cm_ss_scl_lcnt_1_addr;
+	u32 phy_i2cm_ss_scl_lcnt_0_addr;
+	u32 phy_i2cm_fs_scl_hcnt_1_addr;
+	u32 phy_i2cm_fs_scl_hcnt_0_addr;
+	u32 phy_i2cm_fs_scl_lcnt_1_addr;
+	u32 phy_i2cm_fs_scl_lcnt_0_addr;
+	u32 reserved9[0x30ff-0x3032];
+	u32 aud_conf0;
+	u32 aud_conf1;
+	u32 aud_int;
+	u32 aud_conf2;
+	u32 aud_int1;
+	u32 reserved32[0x31ff-0x3104];
+	u32 aud_n1;
+	u32 aud_n2;
+	u32 aud_n3;
+	u32 aud_cts1;
+	u32 aud_cts2;
+	u32 aud_cts3;
+	u32 aud_inputclkfs;
+	u32 reserved12[0x3fff-0x3206];
+	u32 mc_sfrdiv;
+	u32 mc_clkdis;
+	u32 mc_swrstz;
+	u32 mc_opctrl;
+	u32 mc_flowctrl;
+	u32 mc_phyrstz;
+	u32 mc_lockonclock;
+	u32 mc_heacphy_rst;
+	u32 reserved13[0x40ff-0x4007];
+	u32 csc_cfg;
+	u32 csc_scale;
+	struct {
+		u32 msb;
+		u32 lsb;
+	} csc_coef[3][4];
+	u32 reserved17[0x7dff-0x4119];
+	u32 i2cm_slave;
+	u32 i2c_address;
+	u32 i2cm_datao;
+	u32 i2cm_datai;
+	u32 i2cm_operation;
+	u32 i2cm_int;
+	u32 i2cm_ctlint;
+	u32 i2cm_div;
+	u32 i2cm_segaddr;
+	u32 i2cm_softrstz;
+	u32 i2cm_segptr;
+	u32 i2cm_ss_scl_hcnt_1_addr;
+	u32 i2cm_ss_scl_hcnt_0_addr;
+	u32 i2cm_ss_scl_lcnt_1_addr;
+	u32 i2cm_ss_scl_lcnt_0_addr;
+	u32 i2cm_fs_scl_hcnt_1_addr;
+	u32 i2cm_fs_scl_hcnt_0_addr;
+	u32 i2cm_fs_scl_lcnt_1_addr;
+	u32 i2cm_fs_scl_lcnt_0_addr;
+	u32 reserved18[0x7e1f-0x7e12];
+	u32 i2cm_buf0;
+};
+check_member(rk3288_hdmi, i2cm_buf0, 0x1f880);
+
+enum {
+	/* HDMI PHY registers define */
+	PHY_OPMODE_PLLCFG = 0x06,
+	PHY_CKCALCTRL = 0x05,
+	PHY_CKSYMTXCTRL = 0x09,
+	PHY_VLEVCTRL = 0x0e,
+	PHY_PLLCURRCTRL = 0x10,
+	PHY_PLLPHBYCTRL = 0x13,
+	PHY_PLLGMPCTRL = 0x15,
+	PHY_PLLCLKBISTPHASE = 0x17,
+	PHY_TXTERM = 0x19,
+
+	/* ih_phy_stat0 field values */
+	HDMI_IH_PHY_STAT0_HPD = 0x1,
+
+	/* ih_mute field values */
+	HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
+	HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
+
+	/* tx_invid0 field values */
+	HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
+	HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1f,
+	HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
+
+	/* tx_instuffing field values */
+	HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
+	HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
+	HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
+
+	/* vp_pr_cd field values */
+	HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xf0,
+	HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
+	HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0f,
+	HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
+
+	/* vp_stuff field values */
+	HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
+	HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
+	HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
+	HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
+	HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
+	HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
+	HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
+	HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
+
+	/* vp_conf field values */
+	HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
+	HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
+	HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
+	HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
+	HDMI_VP_CONF_PR_EN_MASK = 0x10,
+	HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
+	HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
+	HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
+	HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
+	HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
+	HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
+	HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
+
+	/* vp_remap field values */
+	HDMI_VP_REMAP_YCC422_16BIT = 0x0,
+
+	/* fc_invidconf field values */
+	HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80,
+	HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80,
+	HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00,
+	HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
+	HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
+	HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+	HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
+	HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
+	HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+	HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
+	HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
+	HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
+	HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
+	HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
+	HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
+	HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
+	HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
+	HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
+	HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
+	HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
+	HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
+
+
+	/* fc_aviconf0-fc_aviconf3 field values */
+	HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
+	HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
+	HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
+	HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
+	HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
+	HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
+	HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
+	HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0c,
+	HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
+	HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
+	HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
+	HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0c,
+	HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
+	HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
+	HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
+	HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
+
+	HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0f,
+	HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
+	HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
+	HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0a,
+	HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0b,
+	HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
+	HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
+	HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
+	HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
+	HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xc0,
+	HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
+	HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
+	HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
+	HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xc0,
+
+	HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
+	HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
+	HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
+	HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
+	HDMI_FC_AVICONF2_SCALING_HORIZ_vert = 0x03,
+	HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0c,
+	HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
+	HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
+	HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
+	HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
+	HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
+	HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
+	HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
+	HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
+	HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
+	HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
+	HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
+	HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
+
+	HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
+	HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
+	HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
+	HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
+	HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
+	HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0c,
+	HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
+	HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
+
+	/* fc_gcp field values*/
+	HDMI_FC_GCP_SET_AVMUTE = 0x02,
+	HDMI_FC_GCP_CLEAR_AVMUTE = 0x01,
+
+	/* phy_conf0 field values */
+	HDMI_PHY_CONF0_PDZ_MASK = 0x80,
+	HDMI_PHY_CONF0_PDZ_OFFSET = 7,
+	HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
+	HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
+	HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20,
+	HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5,
+	HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
+	HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
+	HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
+	HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
+	HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
+	HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
+	HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
+	HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
+
+	/* phy_tst0 field values */
+	HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
+	HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
+
+	/* phy_stat0 field values */
+	HDMI_PHY_HPD = 0x02,
+	HDMI_PHY_TX_PHY_LOCK = 0x01,
+
+	/* phy_i2cm_slave_addr field values */
+	HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
+
+	/* phy_i2cm_operation_addr field values */
+	HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
+
+	/* hdmi_phy_i2cm_int_addr */
+	HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
+
+	/* hdmi_phy_i2cm_ctlint_addr */
+	HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
+	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
+
+	/* aud_conf0 field values */
+	HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST = 0x80,
+	HDMI_AUD_CONF0_I2S_SELECT = 0x20,
+	HDMI_AUD_CONF0_I2S_IN_EN_0 = 0x01,
+	HDMI_AUD_CONF0_I2S_IN_EN_1 = 0x02,
+	HDMI_AUD_CONF0_I2S_IN_EN_2 = 0x04,
+	HDMI_AUD_CONF0_I2S_IN_EN_3 = 0x08,
+
+	/* aud_conf0 field values */
+	HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE = 0x0,
+	HDMI_AUD_CONF1_I2S_WIDTH_16BIT = 0x10,
+
+	/* aud_n3 field values */
+	HDMI_AUD_N3_NCTS_ATOMIC_WRITE = 0x80,
+	HDMI_AUD_N3_AUDN19_16_MASK = 0x0f,
+
+	/* aud_cts3 field values */
+	HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
+	HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
+	HDMI_AUD_CTS3_N_SHIFT_1 = 0,
+	HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
+	HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
+	HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
+	HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
+	HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
+	HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
+	HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
+
+	/* aud_inputclkfs filed values */
+	HDMI_AUD_INPUTCLKFS_128 = 0x0,
+
+	/* mc_clkdis field values */
+	HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
+	HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
+	HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
+
+	/* mc_swrstz field values */
+	HDMI_MC_SWRSTZ_II2SSWRST_REQ = 0x08,
+	HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
+
+	/* mc_flowctrl field values */
+	HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
+	HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
+
+	/* mc_phyrstz field values */
+	HDMI_MC_PHYRSTZ_ASSERT = 0x0,
+	HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
+
+	/* mc_heacphy_rst field values */
+	HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
+
+	/* csc_cfg field values */
+	HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
+
+	/* csc_scale field values */
+	HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xf0,
+	HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
+	HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
+	HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
+	HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
+	HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
+
+	/* i2cm filed values */
+	HDMI_I2CM_SLAVE_DDC_ADDR = 0x50,
+	HDMI_I2CM_SEGADDR_DDC = 0x30,
+	HDMI_I2CM_OPT_RD8_EXT = 0x8,
+	HDMI_I2CM_OPT_RD8 = 0x4,
+	HDMI_I2CM_DIV_FAST_STD_MODE = 0x8,
+	HDMI_I2CM_DIV_FAST_MODE = 0x8,
+	HDMI_I2CM_DIV_STD_MODE = 0x0,
+	HDMI_I2CM_SOFTRSTZ = 0x1,
+};
+
+/*
+struct display_timing;
+struct rk3288_grf;
+
+int rk_hdmi_init(struct rk3288_grf *grf, u32 vop_id);
+int rk_hdmi_enable(const struct display_timing *edid);
+int rk_hdmi_get_edid(struct rk3288_grf *grf, struct display_timing *edid);
+*/
+
+#endif
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 1790fdd..c23ab00 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -303,6 +303,16 @@ config DISPLAY
 	   The devices provide a simple interface to start up the display,
 	   read display information and enable it.
 
+config VIDEO_ROCKCHIP
+	bool "Enable Rockchip video support"
+	depends on DM_VIDEO
+	help
+	   Rockchip SoCs provide video output capabilities for High-Definition
+	   Multimedia Interface (HDMI), Low-voltage Differential Signalling
+	   (LVDS), embedded DisplayPort (eDP) and Display Serial Interface
+	   (DSI). This driver supports the on-chip video output device, and
+	   targets the Rockchip RK3288.
+
 config VIDEO_SANDBOX_SDL
 	bool "Enable sandbox video console using SDL"
 	depends on SANDBOX
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index c135e22..0910510 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -62,5 +62,6 @@ obj-$(CONFIG_LG4573) += lg4573.o
 obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 
 obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
+obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/
 
 obj-y += bridge/
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
new file mode 100644
index 0000000..361fcb5
--- /dev/null
+++ b/drivers/video/rockchip/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += rk_hdmi.o
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
new file mode 100644
index 0000000..66b238a
--- /dev/null
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -0,0 +1,929 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <edid.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/hdmi_rk3288.h>
+#include <power/regulator.h>
+
+struct tmds_n_cts {
+	u32 tmds;
+	u32 cts;
+	u32 n;
+};
+
+struct rk_hdmi_priv {
+	struct rk3288_hdmi *regs;
+	struct rk3288_grf *grf;
+};
+
+static const struct tmds_n_cts n_cts_table[] = {
+	{
+		.tmds = 25175, .n = 6144, .cts = 25175,
+	}, {
+		.tmds = 25200, .n = 6144, .cts = 25200,
+	}, {
+		.tmds = 27000, .n = 6144, .cts = 27000,
+	}, {
+		.tmds = 27027, .n = 6144, .cts = 27027,
+	}, {
+		.tmds = 40000, .n = 6144, .cts = 40000,
+	}, {
+		.tmds = 54000, .n = 6144, .cts = 54000,
+	}, {
+		.tmds = 54054, .n = 6144, .cts = 54054,
+	}, {
+		.tmds = 65000, .n = 6144, .cts = 65000,
+	}, {
+		.tmds = 74176, .n = 11648, .cts = 140625,
+	}, {
+		.tmds = 74250, .n = 6144, .cts = 74250,
+	}, {
+		.tmds = 83500, .n = 6144, .cts = 83500,
+	}, {
+		.tmds = 106500, .n = 6144, .cts = 106500,
+	}, {
+		.tmds = 108000, .n = 6144, .cts = 108000,
+	}, {
+		.tmds = 148352, .n = 5824, .cts = 140625,
+	}, {
+		.tmds = 148500, .n = 6144, .cts = 148500,
+	}, {
+		.tmds = 297000, .n = 5120, .cts = 247500,
+	}
+};
+
+struct hdmi_mpll_config {
+	u64 mpixelclock;
+	/* Mode of Operation and PLL Dividers Control Register */
+	u32 cpce;
+	/* PLL Gmp Control Register */
+	u32 gmp;
+	/* PLL Current COntrol Register */
+	u32 curr;
+};
+
+struct hdmi_phy_config {
+	u64 mpixelclock;
+	u32 sym_ctr;    /* clock symbol and transmitter control */
+	u32 term;       /* transmission termination value */
+	u32 vlev_ctr;   /* voltage level control */
+};
+
+static const struct hdmi_phy_config rockchip_phy_config[] = {
+	{
+		.mpixelclock = 74250,
+		.sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272,
+	}, {
+		.mpixelclock = 148500,
+		.sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d,
+	}, {
+		.mpixelclock = 297000,
+		.sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d,
+	}, {
+		.mpixelclock = ~0ul,
+		.sym_ctr = 0x0000, .term = 0x0000, .vlev_ctr = 0x0000,
+	}
+};
+
+static const struct hdmi_mpll_config rockchip_mpll_cfg[] = {
+	{
+		.mpixelclock = 40000,
+		.cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018,
+	}, {
+		.mpixelclock = 65000,
+		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
+	}, {
+		.mpixelclock = 66000,
+		.cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
+	}, {
+		.mpixelclock = 83500,
+		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
+	}, {
+		.mpixelclock = 146250,
+		.cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038,
+	}, {
+		.mpixelclock = 148500,
+		.cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
+	}, {
+		.mpixelclock = ~0ul,
+		.cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
+	}
+};
+
+static const u32 csc_coeff_default[3][4] = {
+	{ 0x2000, 0x0000, 0x0000, 0x0000 },
+	{ 0x0000, 0x2000, 0x0000, 0x0000 },
+	{ 0x0000, 0x0000, 0x2000, 0x0000 }
+};
+
+static void hdmi_set_clock_regenerator(struct rk3288_hdmi *regs, u32 n, u32 cts)
+{
+	u8 cts3;
+	u8 n3;
+
+	/* first set ncts_atomic_write (if present) */
+	n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
+	writel(n3, &regs->aud_n3);
+
+	/* set cts_manual (if present) */
+	cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
+
+	cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
+	cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
+
+	/* write cts values; cts3 must be written first */
+	writel(cts3, &regs->aud_cts3);
+	writel((cts >> 8) & 0xff, &regs->aud_cts2);
+	writel(cts & 0xff, &regs->aud_cts1);
+
+	/* write n values; n1 must be written last */
+	n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
+	writel(n3, &regs->aud_n3);
+	writel((n >> 8) & 0xff, &regs->aud_n2);
+	writel(n & 0xff, &regs->aud_n1);
+
+	writel(HDMI_AUD_INPUTCLKFS_128, &regs->aud_inputclkfs);
+}
+
+static int hdmi_lookup_n_cts(u32 pixel_clk)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
+		if (pixel_clk <= n_cts_table[i].tmds)
+			break;
+
+	if (i >= ARRAY_SIZE(n_cts_table))
+		return -1;
+
+	return i;
+}
+
+static void hdmi_audio_set_samplerate(struct rk3288_hdmi *regs, u32 pixel_clk)
+{
+	u32 clk_n, clk_cts;
+	int index;
+
+	index = hdmi_lookup_n_cts(pixel_clk);
+	if (index == -1) {
+		debug("audio not supported for pixel clk %d\n", pixel_clk);
+		return;
+	}
+
+	clk_n = n_cts_table[index].n;
+	clk_cts = n_cts_table[index].cts;
+	hdmi_set_clock_regenerator(regs, clk_n, clk_cts);
+}
+
+/*
+ * this submodule is responsible for the video data synchronization.
+ * for example, for rgb 4:4:4 input, the data map is defined as
+ *			pin{47~40} <==> r[7:0]
+ *			pin{31~24} <==> g[7:0]
+ *			pin{15~8}  <==> b[7:0]
+ */
+static void hdmi_video_sample(struct rk3288_hdmi *regs)
+{
+	u32 color_format = 0x01;
+	u8 val;
+
+	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
+	      ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
+	      HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
+
+	writel(val, &regs->tx_invid0);
+
+	/* enable tx stuffing: when de is inactive, fix the output data to 0 */
+	val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
+	      HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
+	      HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
+	writel(val, &regs->tx_instuffing);
+	writel(0x0, &regs->tx_gydata0);
+	writel(0x0, &regs->tx_gydata1);
+	writel(0x0, &regs->tx_rcrdata0);
+	writel(0x0, &regs->tx_rcrdata1);
+	writel(0x0, &regs->tx_bcbdata0);
+	writel(0x0, &regs->tx_bcbdata1);
+}
+
+static void hdmi_update_csc_coeffs(struct rk3288_hdmi *regs)
+{
+	u32 i, j;
+	u32 csc_scale = 1;
+
+	/* the csc registers are sequential, alternating msb then lsb */
+	for (i = 0; i < ARRAY_SIZE(csc_coeff_default); i++) {
+		for (j = 0; j < ARRAY_SIZE(csc_coeff_default[0]); j++) {
+			u32 coeff = csc_coeff_default[i][j];
+			writel(coeff >> 8, &regs->csc_coef[i][j].msb);
+			writel(coeff && 0xff, &regs->csc_coef[i][j].lsb);
+		}
+	}
+
+	clrsetbits_le32(&regs->csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+			csc_scale);
+}
+
+static void hdmi_video_csc(struct rk3288_hdmi *regs)
+{
+	u32 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
+	u32 interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
+
+	/* configure the csc registers */
+	writel(interpolation, &regs->csc_cfg);
+	clrsetbits_le32(&regs->csc_scale,
+			HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, color_depth);
+
+	hdmi_update_csc_coeffs(regs);
+}
+
+static void hdmi_video_packetize(struct rk3288_hdmi *regs)
+{
+	u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+	u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
+	u32 color_depth = 0;
+	u8 val, vp_conf;
+
+	/* set the packetizer registers */
+	val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
+		HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
+		((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
+		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
+	writel(val, &regs->vp_pr_cd);
+
+	clrsetbits_le32(&regs->vp_stuff, HDMI_VP_STUFF_PR_STUFFING_MASK,
+			HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
+
+	/* data from pixel repeater block */
+	vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+		  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
+
+	clrsetbits_le32(&regs->vp_conf, HDMI_VP_CONF_PR_EN_MASK |
+			HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
+
+	clrsetbits_le32(&regs->vp_stuff, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
+			1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
+
+	writel(remap_size, &regs->vp_remap);
+
+	vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+		  HDMI_VP_CONF_PP_EN_DISABLE |
+		  HDMI_VP_CONF_YCC422_EN_DISABLE;
+
+	clrsetbits_le32(&regs->vp_conf, HDMI_VP_CONF_BYPASS_EN_MASK |
+			HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
+			vp_conf);
+
+	clrsetbits_le32(&regs->vp_stuff, HDMI_VP_STUFF_PP_STUFFING_MASK |
+			HDMI_VP_STUFF_YCC422_STUFFING_MASK,
+			HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+			HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
+
+	clrsetbits_le32(&regs->vp_conf, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+			output_select);
+}
+
+static inline void hdmi_phy_test_clear(struct rk3288_hdmi *regs, u8 bit)
+{
+	clrsetbits_le32(&regs->phy_tst0, HDMI_PHY_TST0_TSTCLR_MASK,
+			bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
+}
+
+static int hdmi_phy_wait_i2c_done(struct rk3288_hdmi *regs, u32 msec)
+{
+	ulong start;
+	u32 val;
+
+	start = get_timer(0);
+	do {
+		val = readl(&regs->ih_i2cmphy_stat0);
+		if (val & 0x3) {
+			writel(val, &regs->ih_i2cmphy_stat0);
+			return 0;
+		}
+
+		udelay(100);
+	} while (get_timer(start) < msec);
+
+	return 1;
+}
+
+static void hdmi_phy_i2c_write(struct rk3288_hdmi *regs, uint data, uint addr)
+{
+	writel(0xff, &regs->ih_i2cmphy_stat0);
+	writel(addr, &regs->phy_i2cm_address_addr);
+	writel((u8)(data >> 8), &regs->phy_i2cm_datao_1_addr);
+	writel((u8)(data >> 0), &regs->phy_i2cm_datao_0_addr);
+	writel(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
+	       &regs->phy_i2cm_operation_addr);
+
+	hdmi_phy_wait_i2c_done(regs, 1000);
+}
+
+static void hdmi_phy_enable_power(struct rk3288_hdmi *regs, uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_PDZ_MASK,
+			enable << HDMI_PHY_CONF0_PDZ_OFFSET);
+}
+
+static void hdmi_phy_enable_tmds(struct rk3288_hdmi *regs, uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_ENTMDS_MASK,
+			enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
+}
+
+static void hdmi_phy_enable_spare(struct rk3288_hdmi *regs, uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_SPARECTRL_MASK,
+			enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
+}
+
+static void hdmi_phy_gen2_pddq(struct rk3288_hdmi *regs, uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
+			enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
+}
+
+static void hdmi_phy_gen2_txpwron(struct rk3288_hdmi *regs, uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0,
+			HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
+			enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
+}
+
+static void hdmi_phy_sel_data_en_pol(struct rk3288_hdmi *regs, uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0,
+			HDMI_PHY_CONF0_SELDATAENPOL_MASK,
+			enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
+}
+
+static void hdmi_phy_sel_interface_control(struct rk3288_hdmi *regs,
+					   uint enable)
+{
+	clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_SELDIPIF_MASK,
+			enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
+}
+
+static int hdmi_phy_configure(struct rk3288_hdmi *regs, u32 mpixelclock)
+{
+	ulong start;
+	u8 i, val;
+
+	writel(HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
+	       &regs->mc_flowctrl);
+
+	/* gen2 tx power off */
+	hdmi_phy_gen2_txpwron(regs, 0);
+
+	/* gen2 pddq */
+	hdmi_phy_gen2_pddq(regs, 1);
+
+	/* phy reset */
+	writel(HDMI_MC_PHYRSTZ_DEASSERT, &regs->mc_phyrstz);
+	writel(HDMI_MC_PHYRSTZ_ASSERT, &regs->mc_phyrstz);
+	writel(HDMI_MC_HEACPHY_RST_ASSERT, &regs->mc_heacphy_rst);
+
+	hdmi_phy_test_clear(regs, 1);
+	writel(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, &regs->phy_i2cm_slave_addr);
+	hdmi_phy_test_clear(regs, 0);
+
+	/* pll/mpll cfg - always match on final entry */
+	for (i = 0; rockchip_mpll_cfg[i].mpixelclock != (~0ul); i++)
+		if (mpixelclock <= rockchip_mpll_cfg[i].mpixelclock)
+			break;
+
+	hdmi_phy_i2c_write(regs, rockchip_mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
+	hdmi_phy_i2c_write(regs, rockchip_mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
+	hdmi_phy_i2c_write(regs, rockchip_mpll_cfg[i].curr, PHY_PLLCURRCTRL);
+
+	hdmi_phy_i2c_write(regs, 0x0000, PHY_PLLPHBYCTRL);
+	hdmi_phy_i2c_write(regs, 0x0006, PHY_PLLCLKBISTPHASE);
+
+	for (i = 0; rockchip_phy_config[i].mpixelclock != (~0ul); i++)
+		if (mpixelclock <= rockchip_phy_config[i].mpixelclock)
+			break;
+
+	/*
+	 * resistance term 133ohm cfg
+	 * preemp cgf 0.00
+	 * tx/ck lvl 10
+	 */
+	hdmi_phy_i2c_write(regs, rockchip_phy_config[i].term, PHY_TXTERM);
+	hdmi_phy_i2c_write(regs, rockchip_phy_config[i].sym_ctr,
+			   PHY_CKSYMTXCTRL);
+	hdmi_phy_i2c_write(regs, rockchip_phy_config[i].vlev_ctr, PHY_VLEVCTRL);
+
+	/* remove clk term */
+	hdmi_phy_i2c_write(regs, 0x8000, PHY_CKCALCTRL);
+
+	hdmi_phy_enable_power(regs, 1);
+
+	/* toggle tmds enable */
+	hdmi_phy_enable_tmds(regs, 0);
+	hdmi_phy_enable_tmds(regs, 1);
+
+	/* gen2 tx power on */
+	hdmi_phy_gen2_txpwron(regs, 1);
+	hdmi_phy_gen2_pddq(regs, 0);
+
+	hdmi_phy_enable_spare(regs, 1);
+
+	/* wait for phy pll lock */
+	start = get_timer(0);
+	do {
+		val = readl(&regs->phy_stat0);
+		if (!(val & HDMI_PHY_TX_PHY_LOCK))
+			return 0;
+
+		udelay(100);
+	} while (get_timer(start) < 5);
+
+	return -1;
+}
+
+static int hdmi_phy_init(struct rk3288_hdmi *regs, uint mpixelclock)
+{
+	int i, ret;
+
+	/* hdmi phy spec says to do the phy initialization sequence twice */
+	for (i = 0; i < 2; i++) {
+		hdmi_phy_sel_data_en_pol(regs, 1);
+		hdmi_phy_sel_interface_control(regs, 0);
+		hdmi_phy_enable_tmds(regs, 0);
+		hdmi_phy_enable_power(regs, 0);
+
+		/* enable csc */
+		ret = hdmi_phy_configure(regs, mpixelclock);
+		if (ret) {
+			debug("hdmi phy config failure %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void hdmi_av_composer(struct rk3288_hdmi *regs,
+			     const struct display_timing *edid)
+{
+	u8 mdataenablepolarity = 1;
+	u8 inv_val;
+	uint hbl;
+	uint vbl;
+
+	hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
+			edid->hsync_len.typ;
+	vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
+			edid->vsync_len.typ;
+
+	/* set up hdmi_fc_invidconf */
+	inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
+
+	inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
+		   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
+		   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
+
+	inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
+		   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
+		   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
+
+	inv_val |= (mdataenablepolarity ?
+		   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
+		   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
+
+	/*
+	 * TODO(sjg at chromium.org>: Need to check for HDMI / DVI
+	 * inv_val |= (edid->hdmi_monitor_detected ?
+	 *	   HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
+	 *	   HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
+	 */
+	inv_val |= HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE;
+
+	inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
+
+	inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
+
+	writel(inv_val, &regs->fc_invidconf);
+
+	/* set up horizontal active pixel width */
+	writel(edid->hactive.typ >> 8, &regs->fc_inhactv1);
+	writel(edid->hactive.typ, &regs->fc_inhactv0);
+
+	/* set up vertical active lines */
+	writel(edid->vactive.typ >> 8, &regs->fc_invactv1);
+	writel(edid->vactive.typ, &regs->fc_invactv0);
+
+	/* set up horizontal blanking pixel region width */
+	writel(hbl >> 8, &regs->fc_inhblank1);
+	writel(hbl, &regs->fc_inhblank0);
+
+	/* set up vertical blanking pixel region width */
+	writel(vbl, &regs->fc_invblank);
+
+	/* set up hsync active edge delay width (in pixel clks) */
+	writel(edid->hfront_porch.typ >> 8, &regs->fc_hsyncindelay1);
+	writel(edid->hfront_porch.typ, &regs->fc_hsyncindelay0);
+
+	/* set up vsync active edge delay (in lines) */
+	writel(edid->vfront_porch.typ, &regs->fc_vsyncindelay);
+
+	/* set up hsync active pulse width (in pixel clks) */
+	writel(edid->hsync_len.typ >> 8, &regs->fc_hsyncinwidth1);
+	writel(edid->hsync_len.typ, &regs->fc_hsyncinwidth0);
+
+	/* set up vsync active edge delay (in lines) */
+	writel(edid->vsync_len.typ, &regs->fc_vsyncinwidth);
+}
+
+/* hdmi initialization step b.4 */
+static void hdmi_enable_video_path(struct rk3288_hdmi *regs)
+{
+	u8 clkdis;
+
+	/* control period minimum duration */
+	writel(12, &regs->fc_ctrldur);
+	writel(32, &regs->fc_exctrldur);
+	writel(1, &regs->fc_exctrlspac);
+
+	/* set to fill tmds data channels */
+	writel(0x0b, &regs->fc_ch0pream);
+	writel(0x16, &regs->fc_ch1pream);
+	writel(0x21, &regs->fc_ch2pream);
+
+	/* enable pixel clock and tmds data path */
+	clkdis = 0x7f;
+	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+	writel(clkdis, &regs->mc_clkdis);
+
+	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+	writel(clkdis, &regs->mc_clkdis);
+
+	clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
+	writel(clkdis, &regs->mc_clkdis);
+}
+
+/* workaround to clear the overflow condition */
+static void hdmi_clear_overflow(struct rk3288_hdmi *regs)
+{
+	u8 val, count;
+
+	/* tmds software reset */
+	writel((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &regs->mc_swrstz);
+
+	val = readl(&regs->fc_invidconf);
+
+	for (count = 0; count < 4; count++)
+		writel(val, &regs->fc_invidconf);
+}
+
+static void hdmi_audio_set_format(struct rk3288_hdmi *regs)
+{
+	writel(HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
+	       &regs->aud_conf0);
+
+
+	writel(HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
+	       HDMI_AUD_CONF1_I2S_WIDTH_16BIT, &regs->aud_conf1);
+
+	writel(0x00, &regs->aud_conf2);
+}
+
+static void hdmi_audio_fifo_reset(struct rk3288_hdmi *regs)
+{
+	writel((u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, &regs->mc_swrstz);
+	writel(HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, &regs->aud_conf0);
+
+	writel(0x00, &regs->aud_int);
+	writel(0x00, &regs->aud_int1);
+}
+
+static void hdmi_init_interrupt(struct rk3288_hdmi *regs)
+{
+	u8 ih_mute;
+
+	/*
+	 * boot up defaults are:
+	 * hdmi_ih_mute   = 0x03 (disabled)
+	 * hdmi_ih_mute_* = 0x00 (enabled)
+	 *
+	 * disable top level interrupt bits in hdmi block
+	 */
+	ih_mute = readl(&regs->ih_mute) |
+		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+	writel(ih_mute, &regs->ih_mute);
+
+	/* enable i2c master done irq */
+	writel(~0x04, &regs->i2cm_int);
+
+	/* enable i2c client nack % arbitration error irq */
+	writel(~0x44, &regs->i2cm_ctlint);
+
+	/* enable phy i2cm done irq */
+	writel(HDMI_PHY_I2CM_INT_ADDR_DONE_POL, &regs->phy_i2cm_int_addr);
+
+	/* enable phy i2cm nack & arbitration error irq */
+	writel(HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
+		HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
+		&regs->phy_i2cm_ctlint_addr);
+
+	/* enable cable hot plug irq */
+	writel((u8)~HDMI_PHY_HPD, &regs->phy_mask0);
+
+	/* clear hotplug interrupts */
+	writel(HDMI_IH_PHY_STAT0_HPD, &regs->ih_phy_stat0);
+}
+
+static u8 hdmi_get_plug_in_status(struct rk3288_hdmi *regs)
+{
+	u8 val = readl(&regs->phy_stat0) & HDMI_PHY_HPD;
+
+	return !!(val);
+}
+
+static int hdmi_wait_for_hpd(struct rk3288_hdmi *regs)
+{
+	ulong start;
+
+	start = get_timer(0);
+	do {
+		if (hdmi_get_plug_in_status(regs))
+			return 0;
+		udelay(100);
+	} while (get_timer(start) < 30000);
+
+	return -1;
+}
+
+static int hdmi_ddc_wait_i2c_done(struct rk3288_hdmi *regs, int msec)
+{
+	u32 val;
+	ulong start;
+
+	start = get_timer(0);
+	do {
+		val = readl(&regs->ih_i2cm_stat0);
+		if (val & 0x2) {
+			writel(val, &regs->ih_i2cm_stat0);
+			return 0;
+		}
+
+		udelay(100);
+	} while (get_timer(start) < msec);
+
+	return 1;
+}
+
+static void hdmi_ddc_reset(struct rk3288_hdmi *regs)
+{
+	clrbits_le32(&regs->i2cm_softrstz, HDMI_I2CM_SOFTRSTZ);
+}
+
+static int hdmi_read_edid(struct rk3288_hdmi *regs, int block, u8 *buff)
+{
+	int shift = (block % 2) * 0x80;
+	int edid_read_err = 0;
+	u32 trytime = 5;
+	u32 n, j, val;
+
+	/* set ddc i2c clk which devided from ddc_clk to 100khz */
+	writel(0x7a, &regs->i2cm_ss_scl_hcnt_0_addr);
+	writel(0x8d, &regs->i2cm_ss_scl_lcnt_0_addr);
+
+	/*
+	 * TODO(sjg at chromium.org): The above values don't work - these ones
+	 * work better, but generate lots of errors in the data.
+	 */
+	writel(0x0d, &regs->i2cm_ss_scl_hcnt_0_addr);
+	writel(0x0d, &regs->i2cm_ss_scl_lcnt_0_addr);
+	clrsetbits_le32(&regs->i2cm_div, HDMI_I2CM_DIV_FAST_STD_MODE,
+			HDMI_I2CM_DIV_STD_MODE);
+
+	writel(HDMI_I2CM_SLAVE_DDC_ADDR, &regs->i2cm_slave);
+	writel(HDMI_I2CM_SEGADDR_DDC, &regs->i2cm_segaddr);
+	writel(block >> 1, &regs->i2cm_segptr);
+
+	while (trytime--) {
+		edid_read_err = 0;
+
+		for (n = 0; n < HDMI_EDID_BLOCK_SIZE / 8; n++) {
+			writel(shift + 8 * n, &regs->i2c_address);
+
+			if (block == 0)
+				clrsetbits_le32(&regs->i2cm_operation,
+						HDMI_I2CM_OPT_RD8,
+						HDMI_I2CM_OPT_RD8);
+			else
+				clrsetbits_le32(&regs->i2cm_operation,
+						HDMI_I2CM_OPT_RD8_EXT,
+						HDMI_I2CM_OPT_RD8_EXT);
+
+			if (hdmi_ddc_wait_i2c_done(regs, 10)) {
+				hdmi_ddc_reset(regs);
+				edid_read_err = 1;
+				break;
+			}
+
+			for (j = 0; j < 8; j++) {
+				val = readl(&regs->i2cm_buf0 + j);
+				buff[8 * n + j] = val;
+			}
+		}
+
+		if (!edid_read_err)
+			break;
+	}
+
+	return edid_read_err;
+}
+
+static u8 pre_buf[] = {
+	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+	0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
+	0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
+	0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
+	0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
+	0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
+	0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
+	0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+	0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
+	0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
+	0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
+	0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+	0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
+	0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
+	0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
+	0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
+	0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
+	0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
+	0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
+	0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
+	0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
+	0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
+	0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
+	0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
+	0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
+	0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
+	0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
+	0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
+	0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
+};
+
+static int rk_hdmi_read_edid(struct udevice *dev, u8 *buf, int buf_size)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	u32 edid_size = HDMI_EDID_BLOCK_SIZE;
+	int ret;
+
+	if (0) {
+		edid_size = sizeof(pre_buf);
+		memcpy(buf, pre_buf, edid_size);
+	} else {
+		ret = hdmi_read_edid(priv->regs, 0, buf);
+		if (ret) {
+			debug("failed to read edid.\n");
+			return -1;
+		}
+
+		if (buf[0x7e] != 0) {
+			hdmi_read_edid(priv->regs, 1,
+				       buf + HDMI_EDID_BLOCK_SIZE);
+			edid_size += HDMI_EDID_BLOCK_SIZE;
+		}
+	}
+
+	return edid_size;
+}
+
+static int rk_hdmi_enable(struct udevice *dev, int panel_bpp,
+			  const struct display_timing *edid)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	struct rk3288_hdmi *regs = priv->regs;
+	int ret;
+
+	debug("hdmi, mode info : clock %d hdis %d vdis %d\n",
+	      edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
+
+	hdmi_av_composer(regs, edid);
+
+	ret = hdmi_phy_init(regs, edid->pixelclock.typ);
+	if (ret)
+		return ret;
+
+	hdmi_enable_video_path(regs);
+
+	hdmi_audio_fifo_reset(regs);
+	hdmi_audio_set_format(regs);
+	hdmi_audio_set_samplerate(regs, edid->pixelclock.typ);
+
+	hdmi_video_packetize(regs);
+	hdmi_video_csc(regs);
+	hdmi_video_sample(regs);
+
+	hdmi_clear_overflow(regs);
+
+	return 0;
+}
+
+static int rk_hdmi_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+
+	priv->regs = (struct rk3288_hdmi *)dev_get_addr(dev);
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+
+	return 0;
+}
+
+static int rk_hdmi_probe(struct udevice *dev)
+{
+	struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	struct udevice *reg, *clk;
+	int periph;
+	int ret;
+	int vop_id = uc_plat->source_id;
+
+	ret = clk_get_by_index(dev, 0, &clk, &periph);
+	if (!ret)
+		ret = clk_set_periph_rate(clk, periph, 0);
+	if (ret) {
+		debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	/*
+	 * Configure the maximum clock to permit whatever resolution the
+	 * monitor wants
+	 */
+	ret = clk_get_by_index(uc_plat->src_dev, 0, &clk, &periph);
+	if (!ret)
+		ret = clk_set_periph_rate(clk, periph, 384000000);
+	if (ret < 0) {
+		debug("%s: Failed to set clock in source device '%s': ret=%d\n",
+		      __func__, uc_plat->src_dev->name, ret);
+		return ret;
+	}
+
+	ret = regulator_get_by_platname("vcc50_hdmi", &reg);
+	if (!ret)
+		ret = regulator_set_enable(reg, true);
+	if (ret)
+		debug("%s: Cannot set regulator vcc50_hdmi\n", __func__);
+
+	/* hdmi source select hdmi controller */
+	rk_setreg(&priv->grf->soc_con6, 1 << 15);
+
+	/* hdmi data from vop id */
+	rk_setreg(&priv->grf->soc_con6, (vop_id == 1) ? (1 << 4) : (1 << 4));
+
+	ret = hdmi_wait_for_hpd(priv->regs);
+	if (ret < 0) {
+		debug("hdmi can not get hpd signal\n");
+		return -1;
+	}
+
+	hdmi_init_interrupt(priv->regs);
+
+	return 0;
+}
+
+static const struct dm_display_ops rk_hdmi_ops = {
+	.read_edid = rk_hdmi_read_edid,
+	.enable = rk_hdmi_enable,
+};
+
+static const struct udevice_id rk_hdmi_ids[] = {
+	{ .compatible = "rockchip,rk3288-dw-hdmi" },
+	{ }
+};
+
+U_BOOT_DRIVER(hdmi_rockchip) = {
+	.name	= "hdmi_rockchip",
+	.id	= UCLASS_DISPLAY,
+	.of_match = rk_hdmi_ids,
+	.ops	= &rk_hdmi_ops,
+	.ofdata_to_platdata	= rk_hdmi_ofdata_to_platdata,
+	.probe	= rk_hdmi_probe,
+	.priv_auto_alloc_size	 = sizeof(struct rk_hdmi_priv),
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 16/37] rockchip: video: Add a display driver for rockchip eDP
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (14 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 15/37] rockchip: video: Add a display driver for rockchip HDMI Simon Glass
@ 2016-01-14 15:57 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 17/37] rockchip: video: Add a video-output driver Simon Glass
                   ` (21 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:57 UTC (permalink / raw)
  To: u-boot

Some Rockchip SoCs support embedded DisplayPort output. Add a display driver
for this so that these displays can be used on supported boards.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/arch-rockchip/edp_rk3288.h |  636 +++++++++++++
 drivers/video/rockchip/Makefile                 |    2 +-
 drivers/video/rockchip/rk_edp.c                 | 1081 +++++++++++++++++++++++
 3 files changed, 1718 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-rockchip/edp_rk3288.h
 create mode 100644 drivers/video/rockchip/rk_edp.c

diff --git a/arch/arm/include/asm/arch-rockchip/edp_rk3288.h b/arch/arm/include/asm/arch-rockchip/edp_rk3288.h
new file mode 100644
index 0000000..a9e2761
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/edp_rk3288.h
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_EDP_H
+#define _ASM_ARCH_EDP_H
+
+struct rk3288_edp {
+	u8	res0[0x10];
+	u32	dp_tx_version;
+	u8	res1[0x4];
+	u32	func_en_1;
+	u32	func_en_2;
+	u32	video_ctl_1;
+	u32	video_ctl_2;
+	u32	video_ctl_3;
+	u32	video_ctl_4;
+	u8	res2[0xc];
+	u32	video_ctl_8;
+	u8	res3[0x4];
+	u32	video_ctl_10;
+	u32	total_line_l;
+	u32	total_line_h;
+	u32	active_line_l;
+	u32	active_line_h;
+	u32	v_f_porch;
+	u32	vsync;
+	u32	v_b_porch;
+	u32	total_pixel_l;
+	u32	total_pixel_h;
+	u32	active_pixel_l;
+	u32	active_pixel_h;
+	u32	h_f_porch_l;
+	u32	h_f_porch_h;
+	u32	hsync_l;
+	u32	hysnc_h;
+	u32	h_b_porch_l;
+	u32	h_b_porch_h;
+	u32	vid_status;
+	u32	total_line_sta_l;
+	u32	total_line_sta_h;
+	u32	active_line_sta_l;
+	u32	active_line_sta_h;
+	u32	v_f_porch_sta;
+	u32	vsync_sta;
+	u32	v_b_porch_sta;
+	u32	total_pixel_sta_l;
+	u32	total_pixel_sta_h;
+	u32	active_pixel_sta_l;
+	u32	active_pixel_sta_h;
+	u32	h_f_porch_sta_l;
+	u32	h_f_porch_sta_h;
+	u32	hsync_sta_l;
+	u32	hsync_sta_h;
+	u32	h_b_porch_sta_l;
+	u32	h_b_porch__sta_h;
+	u8      res4[0x28];
+	u32	pll_reg_1;
+	u8	res5[4];
+	u32	ssc_reg;
+	u8	res6[0xc];
+	u32	tx_common;
+	u32	tx_common2;
+	u8	res7[0x4];
+	u32	dp_aux;
+	u32	dp_bias;
+	u32	dp_test;
+	u32	dp_pd;
+	u32	dp_reserv1;
+	u32	dp_reserv2;
+	u8	res8[0x224];
+	u32	lane_map;
+	u8	res9[0x14];
+	u32	analog_ctl_2;
+	u8	res10[0x48];
+	u32	int_state;
+	u32	common_int_sta_1;
+	u32	common_int_sta_2;
+	u32	common_int_sta_3;
+	u32	common_int_sta_4;
+	u32	spdif_biphase_int_sta;
+	u8	res11[0x4];
+	u32	dp_int_sta;
+	u32	common_int_mask_1;
+	u32	common_int_mask_2;
+	u32	common_int_mask_3;
+	u32	common_int_mask_4;
+	u8	res12[0x08];
+	u32	int_sta_mask;
+	u32	int_ctl;
+	u8	res13[0x200];
+	u32	sys_ctl_1;
+	u32	sys_ctl_2;
+	u32	sys_ctl_3;
+	u32	sys_ctl_4;
+	u32	dp_vid_ctl;
+	u8	res14[0x4];
+	u32	dp_aud_ctl;
+	u8	res15[0x24];
+	u32	pkt_send_ctl;
+	u8	res16[0x4];
+	u32	dp_hdcp_ctl;
+	u8	res17[0x34];
+	u32	link_bw_set;
+	u32	lane_count_set;
+	u32	dp_training_ptn_set;
+	u32	ln_link_trn_ctl[4];
+	u8	res18[0x4];
+	u32	dp_hw_link_training;
+	u8	res19[0x1c];
+	u32	dp_debug_ctl;
+	u32	hpd_deglitch_l;
+	u32	hpd_deglitch_h;
+	u8	res20[0x14];
+	u32	dp_link_debug_ctl;
+	u8	res21[0x1c];
+	u32	m_vid_0;
+	u32	m_vid_1;
+	u32	m_vid_2;
+	u32	n_vid_0;
+	u32	n_vid_1;
+	u32	n_vid_2;
+	u32	m_vid_mon;
+	u8	res22[0x14];
+	u32	dp_video_fifo_thrd;
+	u8	res23[0x8];
+	u32	dp_audio_margin;
+	u8	res24[0x20];
+	u32	dp_m_cal_ctl;
+	u32	m_vid_gen_filter_th;
+	u8	res25[0x10];
+	u32	m_aud_gen_filter_th;
+	u8	res26[0x4];
+	u32	aux_ch_sta;
+	u32	aux_err_num;
+	u32	aux_ch_defer_dtl;
+	u32	aux_rx_comm;
+	u32	buf_data_ctl;
+	u32	aux_ch_ctl_1;
+	u32	aux_addr_7_0;
+	u32	aux_addr_15_8;
+	u32	aux_addr_19_16;
+	u32	aux_ch_ctl_2;
+	u8	res27[0x18];
+	u32	buf_data[16];
+	u32	soc_general_ctl;
+	u8	res29[0x1e0];
+	u32	pll_reg_2;
+	u32	pll_reg_3;
+	u32	pll_reg_4;
+	u8	res30[0x10];
+	u32	pll_reg_5;
+};
+check_member(rk3288_edp, pll_reg_5, 0xa00);
+
+/* func_en_1 */
+#define VID_CAP_FUNC_EN_N			(0x1 << 6)
+#define VID_FIFO_FUNC_EN_N			(0x1 << 5)
+#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
+#define AUD_FUNC_EN_N				(0x1 << 3)
+#define HDCP_FUNC_EN_N				(0x1 << 2)
+#define SW_FUNC_EN_N				(0x1 << 0)
+
+/* func_en_2 */
+#define SSC_FUNC_EN_N				(0x1 << 7)
+#define AUX_FUNC_EN_N				(0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
+
+/* video_ctl_1 */
+#define VIDEO_EN				(0x1 << 7)
+#define VIDEO_MUTE				(0x1 << 6)
+
+/* video_ctl_2 */
+#define IN_D_RANGE_MASK				(0x1 << 7)
+#define IN_D_RANGE_SHIFT			(7)
+#define IN_D_RANGE_CEA				(0x1 << 7)
+#define IN_D_RANGE_VESA				(0x0 << 7)
+#define IN_BPC_MASK				(0x7 << 4)
+#define IN_BPC_SHIFT				(4)
+#define IN_BPC_12_BITS				(0x3 << 4)
+#define IN_BPC_10_BITS				(0x2 << 4)
+#define IN_BPC_8_BITS				(0x1 << 4)
+#define IN_BPC_6_BITS				(0x0 << 4)
+#define IN_COLOR_F_MASK				(0x3 << 0)
+#define IN_COLOR_F_SHIFT			(0)
+#define IN_COLOR_F_YCBCR444			(0x2 << 0)
+#define IN_COLOR_F_YCBCR422			(0x1 << 0)
+#define IN_COLOR_F_RGB				(0x0 << 0)
+
+/* video_ctl_3 */
+#define IN_YC_COEFFI_MASK			(0x1 << 7)
+#define IN_YC_COEFFI_SHIFT			(7)
+#define IN_YC_COEFFI_ITU709			(0x1 << 7)
+#define IN_YC_COEFFI_ITU601			(0x0 << 7)
+#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
+#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
+
+/* video_ctl_4 */
+#define BIST_EN					(0x1 << 3)
+#define BIST_WH_64				(0x1 << 2)
+#define BIST_WH_32				(0x0 << 2)
+#define BIST_TYPE_COLR_BAR			(0x0 << 0)
+#define BIST_TYPE_GRAY_BAR			(0x1 << 0)
+#define BIST_TYPE_MOBILE_BAR			(0x2 << 0)
+
+/* video_ctl_8 */
+#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
+#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
+
+/* video_ctl_10 */
+#define F_SEL					(0x1 << 4)
+#define INTERACE_SCAN_CFG			(0x1 << 2)
+#define INTERACD_SCAN_CFG_OFFSET		2
+#define VSYNC_POLARITY_CFG			(0x1 << 1)
+#define VSYNC_POLARITY_CFG_OFFSET		1
+#define HSYNC_POLARITY_CFG			(0x1 << 0)
+#define HSYNC_POLARITY_CFG_OFFSET		0
+
+/* dp_pd */
+#define PD_INC_BG				(0x1 << 7)
+#define PD_EXP_BG				(0x1 << 6)
+#define PD_AUX					(0x1 << 5)
+#define PD_PLL					(0x1 << 4)
+#define PD_CH3					(0x1 << 3)
+#define PD_CH2					(0x1 << 2)
+#define PD_CH1					(0x1 << 1)
+#define PD_CH0					(0x1 << 0)
+
+/* pll_reg_1 */
+#define REF_CLK_24M				(0x1 << 1)
+#define REF_CLK_27M				(0x0 << 1)
+
+/* line_map */
+#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
+#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
+#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
+#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
+#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
+#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
+#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
+#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
+#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
+#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
+#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
+#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
+#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
+#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
+#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
+#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
+
+/* analog_ctl_2 */
+#define SEL_24M					(0x1 << 3)
+
+/* common_int_sta_1 */
+#define VSYNC_DET				(0x1 << 7)
+#define PLL_LOCK_CHG				(0x1 << 6)
+#define SPDIF_ERR				(0x1 << 5)
+#define SPDIF_UNSTBL				(0x1 << 4)
+#define VID_FORMAT_CHG				(0x1 << 3)
+#define AUD_CLK_CHG				(0x1 << 2)
+#define VID_CLK_CHG				(0x1 << 1)
+#define SW_INT					(0x1 << 0)
+
+/* common_int_sta_2 */
+#define ENC_EN_CHG				(0x1 << 6)
+#define HW_BKSV_RDY				(0x1 << 3)
+#define HW_SHA_DONE				(0x1 << 2)
+#define HW_AUTH_STATE_CHG			(0x1 << 1)
+#define HW_AUTH_DONE				(0x1 << 0)
+
+/* common_int_sta_3 */
+#define AFIFO_UNDER				(0x1 << 7)
+#define AFIFO_OVER				(0x1 << 6)
+#define R0_CHK_FLAG				(0x1 << 5)
+
+/* common_int_sta_4 */
+#define PSR_ACTIVE				(0x1 << 7)
+#define PSR_INACTIVE				(0x1 << 6)
+#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
+#define HOTPLUG_CHG				(0x1 << 2)
+#define HPD_LOST				(0x1 << 1)
+#define PLUG					(0x1 << 0)
+
+/* dp_int_sta */
+#define INT_HPD					(0x1 << 6)
+#define HW_LT_DONE				(0x1 << 5)
+#define SINK_LOST				(0x1 << 3)
+#define LINK_LOST				(0x1 << 2)
+#define RPLY_RECEIV				(0x1 << 1)
+#define AUX_ERR					(0x1 << 0)
+
+/* int_ctl */
+#define SOFT_INT_CTRL				(0x1 << 2)
+#define INT_POL					(0x1 << 0)
+
+/* sys_ctl_1 */
+#define DET_STA					(0x1 << 2)
+#define FORCE_DET				(0x1 << 1)
+#define DET_CTRL				(0x1 << 0)
+
+/* sys_ctl_2 */
+#define CHA_CRI(x)				(((x) & 0xf) << 4)
+#define CHA_STA					(0x1 << 2)
+#define FORCE_CHA				(0x1 << 1)
+#define CHA_CTRL				(0x1 << 0)
+
+/* sys_ctl_3 */
+#define HPD_STATUS				(0x1 << 6)
+#define F_HPD					(0x1 << 5)
+#define HPD_CTRL				(0x1 << 4)
+#define HDCP_RDY				(0x1 << 3)
+#define STRM_VALID				(0x1 << 2)
+#define F_VALID					(0x1 << 1)
+#define VALID_CTRL				(0x1 << 0)
+
+/* sys_ctl_4 */
+#define FIX_M_AUD				(0x1 << 4)
+#define ENHANCED				(0x1 << 3)
+#define FIX_M_VID				(0x1 << 2)
+#define M_VID_UPDATE_CTRL			(0x3 << 0)
+
+/* pll_reg_2 */
+#define LDO_OUTPUT_V_SEL_145			(2 << 6)
+#define KVCO_DEFALUT				(1 << 4)
+#define CHG_PUMP_CUR_SEL_5US			(1 << 2)
+#define V2L_CUR_SEL_1MA				(1 << 0)
+
+/* pll_reg_3 */
+#define LOCK_DET_CNT_SEL_256			(2 << 5)
+#define LOOP_FILTER_RESET			(0 << 4)
+#define PALL_SSC_RESET				(0 << 3)
+#define LOCK_DET_BYPASS				(0 << 2)
+#define PLL_LOCK_DET_MODE			(0 << 1)
+#define PLL_LOCK_DET_FORCE			(0 << 0)
+
+/* pll_reg_5 */
+#define REGULATOR_V_SEL_950MV			(2 << 4)
+#define STANDBY_CUR_SEL				(0 << 3)
+#define CHG_PUMP_INOUT_CTRL_1200MV		(1 << 1)
+#define CHG_PUMP_INPUT_CTRL_OP			(0 << 0)
+
+/* ssc_reg */
+#define SSC_OFFSET				(0 << 6)
+#define SSC_MODE				(1 << 4)
+#define SSC_DEPTH				(9 << 0)
+
+/* tx_common */
+#define TX_SWING_PRE_EMP_MODE			(1 << 7)
+#define PRE_DRIVER_PW_CTRL1			(0 << 5)
+#define LP_MODE_CLK_REGULATOR			(0 << 4)
+#define RESISTOR_MSB_CTRL			(0 << 3)
+#define RESISTOR_CTRL				(7 << 0)
+
+/* dp_aux */
+#define DP_AUX_COMMON_MODE			(0 << 4)
+#define DP_AUX_EN				(0 << 3)
+#define AUX_TERM_50OHM				(3 << 0)
+
+/* dp_bias */
+#define DP_BG_OUT_SEL				(4 << 4)
+#define DP_DB_CUR_CTRL				(0 << 3)
+#define DP_BG_SEL				(1 << 2)
+#define DP_RESISTOR_TUNE_BG			(2 << 0)
+
+/* dp_reserv2 */
+#define CH1_CH3_SWING_EMP_CTRL			(5 << 4)
+#define CH0_CH2_SWING_EMP_CTRL			(5 << 0)
+
+/* dp_training_ptn_set */
+#define SCRAMBLING_DISABLE			(0x1 << 5)
+#define SCRAMBLING_ENABLE			(0x0 << 5)
+#define LINK_QUAL_PATTERN_SET_MASK		(0x7 << 2)
+#define LINK_QUAL_PATTERN_SET_HBR2		(0x5 << 2)
+#define LINK_QUAL_PATTERN_SET_80BIT		(0x4 << 2)
+#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
+#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
+#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
+#define SW_TRAINING_PATTERN_SET_DISABLE		(0x0 << 0)
+
+/* dp_hw_link_training_ctl */
+#define HW_LT_ERR_CODE_MASK			0x70
+#define HW_LT_ERR_CODE_SHIFT			4
+#define HW_LT_EN				(0x1 << 0)
+
+/* dp_debug_ctl */
+#define PLL_LOCK				(0x1 << 4)
+#define F_PLL_LOCK				(0x1 << 3)
+#define PLL_LOCK_CTRL				(0x1 << 2)
+#define POLL_EN					(0x1 << 1)
+#define PN_INV					(0x1 << 0)
+
+/* aux_ch_sta */
+#define AUX_BUSY				(0x1 << 4)
+#define AUX_STATUS_MASK				(0xf << 0)
+
+/* aux_ch_defer_ctl */
+#define DEFER_CTRL_EN				(0x1 << 7)
+#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
+
+/* aux_rx_comm */
+#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
+#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
+
+/* buffer_data_ctl */
+#define BUF_CLR					(0x1 << 7)
+#define BUF_HAVE_DATA				(0x1 << 4)
+#define BUF_DATA_COUNT(x)			(((x) & 0xf) << 0)
+
+/* aux_ch_ctl_1 */
+#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
+#define AUX_TX_COMM_MASK			(0xf << 0)
+#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
+#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
+#define AUX_TX_COMM_MOT				(0x1 << 2)
+#define AUX_TX_COMM_WRITE			(0x0 << 0)
+#define AUX_TX_COMM_READ			(0x1 << 0)
+
+/* aux_ch_ctl_2 */
+#define PD_AUX_IDLE				(0x1 << 3)
+#define ADDR_ONLY				(0x1 << 1)
+#define AUX_EN					(0x1 << 0)
+
+/* tx_sw_reset */
+#define RST_DP_TX				(0x1 << 0)
+
+/* analog_ctl_1 */
+#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
+
+/* analog_ctl_3 */
+#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
+#define VCO_BIT_600_MICRO			(0x5 << 0)
+
+/* pll_filter_ctl_1 */
+#define PD_RING_OSC				(0x1 << 6)
+#define AUX_TERMINAL_CTRL_37_5_OHM		(0x0 << 4)
+#define AUX_TERMINAL_CTRL_45_OHM		(0x1 << 4)
+#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
+#define AUX_TERMINAL_CTRL_65_OHM		(0x3 << 4)
+#define TX_CUR1_2X				(0x1 << 2)
+#define TX_CUR_16_MA				(0x3 << 0)
+
+/* Definition for DPCD Register */
+#define DPCD_DPCD_REV				(0x0000)
+#define DPCD_MAX_LINK_RATE			(0x0001)
+#define DPCD_MAX_LANE_COUNT			(0x0002)
+#define DP_MAX_LANE_COUNT_MASK			0x1f
+#define DP_TPS3_SUPPORTED			(1 << 6)
+#define DP_ENHANCED_FRAME_CAP			(1 << 7)
+
+#define DPCD_LINK_BW_SET			(0x0100)
+#define DPCD_LANE_COUNT_SET			(0x0101)
+
+#define DPCD_TRAINING_PATTERN_SET		(0x0102)
+#define DP_TRAINING_PATTERN_DISABLE		0
+#define DP_TRAINING_PATTERN_1			1
+#define DP_TRAINING_PATTERN_2			2
+#define DP_TRAINING_PATTERN_3			3
+#define DP_TRAINING_PATTERN_MASK		0x3
+
+#define DPCD_TRAINING_LANE0_SET			(0x0103)
+#define DP_TRAIN_VOLTAGE_SWING_MASK		0x3
+#define DP_TRAIN_VOLTAGE_SWING_SHIFT		0
+#define DP_TRAIN_MAX_SWING_REACHED		(1 << 2)
+#define DP_TRAIN_VOLTAGE_SWING_400		(0 << 0)
+#define DP_TRAIN_VOLTAGE_SWING_600		(1 << 0)
+#define DP_TRAIN_VOLTAGE_SWING_800		(2 << 0)
+#define DP_TRAIN_VOLTAGE_SWING_1200		(3 << 0)
+
+#define DP_TRAIN_PRE_EMPHASIS_MASK		(3 << 3)
+#define DP_TRAIN_PRE_EMPHASIS_0			(0 << 3)
+#define DP_TRAIN_PRE_EMPHASIS_3_5		(1 << 3)
+#define DP_TRAIN_PRE_EMPHASIS_6			(2 << 3)
+#define DP_TRAIN_PRE_EMPHASIS_9_5		(3 << 3)
+
+#define DP_TRAIN_PRE_EMPHASIS_SHIFT		3
+#define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED	(1 << 5)
+
+#define DPCD_LANE0_1_STATUS			(0x0202)
+#define DPCD_LANE2_3_STATUS			(0x0203)
+#define DP_LANE_CR_DONE				(1 << 0)
+#define DP_LANE_CHANNEL_EQ_DONE			(1 << 1)
+#define DP_LANE_SYMBOL_LOCKED			(1 << 2)
+#define DP_CHANNEL_EQ_BITS			(DP_LANE_CR_DONE |\
+						DP_LANE_CHANNEL_EQ_DONE |\
+						DP_LANE_SYMBOL_LOCKED)
+
+#define DPCD_LANE_ALIGN_STATUS_UPDATED		(0x0204)
+#define DP_INTERLANE_ALIGN_DONE			(1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED	(1 << 6)
+#define DP_LINK_STATUS_UPDATED			(1 << 7)
+
+#define DPCD_ADJUST_REQUEST_LANE0_1		(0x0206)
+#define DPCD_ADJUST_REQUEST_LANE2_3		(0x0207)
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK	0x03
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT	0
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK	0x0c
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT	2
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK	0x30
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT	4
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK	0xc0
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT	6
+
+#define DPCD_TEST_REQUEST			(0x0218)
+#define DPCD_TEST_RESPONSE			(0x0260)
+#define DPCD_TEST_EDID_CHECKSUM			(0x0261)
+#define DPCD_LINK_POWER_STATE			(0x0600)
+#define DP_SET_POWER_D0				0x1
+#define DP_SET_POWER_D3				0x2
+#define DP_SET_POWER_MASK			0x3
+
+#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
+#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
+#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
+
+#define STREAM_ON_TIMEOUT 100
+#define PLL_LOCK_TIMEOUT 10
+#define DP_INIT_TRIES 10
+
+#define EDID_ADDR				0x50
+#define EDID_LENGTH				0x80
+#define EDID_HEADER				0x00
+#define EDID_EXTENSION_FLAG			0x7e
+
+
+enum dpcd_request {
+	DPCD_READ,
+	DPCD_WRITE,
+};
+
+enum dp_irq_type {
+	DP_IRQ_TYPE_HP_CABLE_IN,
+	DP_IRQ_TYPE_HP_CABLE_OUT,
+	DP_IRQ_TYPE_HP_CHANGE,
+	DP_IRQ_TYPE_UNKNOWN,
+};
+
+enum color_coefficient {
+	COLOR_YCBCR601,
+	COLOR_YCBCR709
+};
+
+enum dynamic_range {
+	VESA,
+	CEA
+};
+
+enum clock_recovery_m_value_type {
+	CALCULATED_M,
+	REGISTER_M
+};
+
+enum video_timing_recognition_type {
+	VIDEO_TIMING_FROM_CAPTURE,
+	VIDEO_TIMING_FROM_REGISTER
+};
+
+enum pattern_set {
+	PRBS7,
+	D10_2,
+	TRAINING_PTN1,
+	TRAINING_PTN2,
+	DP_NONE
+};
+
+enum color_space {
+	CS_RGB,
+	CS_YCBCR422,
+	CS_YCBCR444
+};
+
+enum color_depth {
+	COLOR_6,
+	COLOR_8,
+	COLOR_10,
+	COLOR_12
+};
+
+enum link_rate_type {
+	LINK_RATE_1_62GBPS = 0x06,
+	LINK_RATE_2_70GBPS = 0x0a
+};
+
+enum link_lane_count_type {
+	LANE_CNT1 = 1,
+	LANE_CNT2 = 2,
+	LANE_CNT4 = 4
+};
+
+enum link_training_state {
+	LT_START,
+	LT_CLK_RECOVERY,
+	LT_EQ_TRAINING,
+	FINISHED,
+	FAILED
+};
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum analog_power_block {
+	AUX_BLOCK,
+	CH0_BLOCK,
+	CH1_BLOCK,
+	CH2_BLOCK,
+	CH3_BLOCK,
+	ANALOG_TOTAL,
+	POWER_ALL
+};
+
+struct link_train {
+	unsigned char revision;
+	u8 link_rate;
+	u8 lane_count;
+};
+
+#endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 361fcb5..5566719 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += rk_hdmi.o
+obj-y += rk_edp.o rk_hdmi.o
diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c
new file mode 100644
index 0000000..0ed4467
--- /dev/null
+++ b/drivers/video/rockchip/rk_edp.c
@@ -0,0 +1,1081 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <edid.h>
+#include <panel.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/edp_rk3288.h>
+#include <asm/arch/grf_rk3288.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+#define DP_LINK_STATUS_SIZE 6
+
+static const char * const voltage_names[] = {
+	"0.4V", "0.6V", "0.8V", "1.2V"
+};
+static const char * const pre_emph_names[] = {
+	"0dB", "3.5dB", "6dB", "9.5dB"
+};
+
+#define DP_VOLTAGE_MAX         DP_TRAIN_VOLTAGE_SWING_1200
+#define DP_PRE_EMPHASIS_MAX    DP_TRAIN_PRE_EMPHASIS_9_5
+
+struct rk_edp_priv {
+	struct rk3288_edp *regs;
+	struct rk3288_grf *grf;
+	struct udevice *panel;
+	struct link_train link_train;
+	u8 train_set[4];
+};
+
+static void rk_edp_init_refclk(struct rk3288_edp *regs)
+{
+	writel(SEL_24M, &regs->analog_ctl_2);
+	writel(REF_CLK_24M, &regs->pll_reg_1);
+
+	writel(LDO_OUTPUT_V_SEL_145 | KVCO_DEFALUT | CHG_PUMP_CUR_SEL_5US |
+	       V2L_CUR_SEL_1MA, &regs->pll_reg_2);
+
+	writel(LOCK_DET_CNT_SEL_256 | LOOP_FILTER_RESET | PALL_SSC_RESET |
+	       LOCK_DET_BYPASS | PLL_LOCK_DET_MODE | PLL_LOCK_DET_FORCE,
+	       &regs->pll_reg_3);
+
+	writel(REGULATOR_V_SEL_950MV | STANDBY_CUR_SEL |
+	       CHG_PUMP_INOUT_CTRL_1200MV | CHG_PUMP_INPUT_CTRL_OP,
+	       &regs->pll_reg_5);
+
+	writel(SSC_OFFSET | SSC_MODE | SSC_DEPTH, &regs->ssc_reg);
+
+	writel(TX_SWING_PRE_EMP_MODE | PRE_DRIVER_PW_CTRL1 |
+	       LP_MODE_CLK_REGULATOR | RESISTOR_MSB_CTRL | RESISTOR_CTRL,
+	       &regs->tx_common);
+
+	writel(DP_AUX_COMMON_MODE | DP_AUX_EN | AUX_TERM_50OHM,
+	       &regs->dp_aux);
+
+	writel(DP_BG_OUT_SEL | DP_DB_CUR_CTRL | DP_BG_SEL | DP_RESISTOR_TUNE_BG,
+	       &regs->dp_bias);
+
+	writel(CH1_CH3_SWING_EMP_CTRL | CH0_CH2_SWING_EMP_CTRL,
+	       &regs->dp_reserv2);
+}
+
+static void rk_edp_init_interrupt(struct rk3288_edp *regs)
+{
+	/* Set interrupt pin assertion polarity as high */
+	writel(INT_POL, &regs->int_ctl);
+
+	/* Clear pending registers */
+	writel(0xff, &regs->common_int_sta_1);
+	writel(0x4f, &regs->common_int_sta_2);
+	writel(0xff, &regs->common_int_sta_3);
+	writel(0x27, &regs->common_int_sta_4);
+	writel(0x7f, &regs->dp_int_sta);
+
+	/* 0:mask,1: unmask */
+	writel(0x00, &regs->common_int_mask_1);
+	writel(0x00, &regs->common_int_mask_2);
+	writel(0x00, &regs->common_int_mask_3);
+	writel(0x00, &regs->common_int_mask_4);
+	writel(0x00, &regs->int_sta_mask);
+}
+
+static void rk_edp_enable_sw_function(struct rk3288_edp *regs)
+{
+	clrbits_le32(&regs->func_en_1, SW_FUNC_EN_N);
+}
+
+static bool rk_edp_get_pll_locked(struct rk3288_edp *regs)
+{
+	u32 val;
+
+	val = readl(&regs->dp_debug_ctl);
+
+	return val & PLL_LOCK;
+}
+
+static int rk_edp_init_analog_func(struct rk3288_edp *regs)
+{
+	ulong start;
+
+	writel(0x00, &regs->dp_pd);
+	writel(PLL_LOCK_CHG, &regs->common_int_sta_1);
+
+	clrbits_le32(&regs->dp_debug_ctl, F_PLL_LOCK | PLL_LOCK_CTRL);
+
+	start = get_timer(0);
+	while (!rk_edp_get_pll_locked(regs)) {
+		if (get_timer(start) > PLL_LOCK_TIMEOUT) {
+			printf("%s: PLL is not locked\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* Enable Serdes FIFO function and Link symbol clock domain module */
+	clrbits_le32(&regs->func_en_2, SERDES_FIFO_FUNC_EN_N |
+				       LS_CLK_DOMAIN_FUNC_EN_N | AUX_FUNC_EN_N |
+				       SSC_FUNC_EN_N);
+
+	return 0;
+}
+
+static void rk_edp_init_aux(struct rk3288_edp *regs)
+{
+	/* Clear inerrupts related to AUX channel */
+	writel(AUX_FUNC_EN_N, &regs->dp_int_sta);
+
+	/* Disable AUX channel module */
+	setbits_le32(&regs->func_en_2, AUX_FUNC_EN_N);
+
+	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
+	writel(DEFER_CTRL_EN | DEFER_COUNT(1), &regs->aux_ch_defer_dtl);
+
+	/* Enable AUX channel module */
+	clrbits_le32(&regs->func_en_2, AUX_FUNC_EN_N);
+}
+
+static int rk_edp_aux_enable(struct rk3288_edp *regs)
+{
+	ulong start;
+
+	setbits_le32(&regs->aux_ch_ctl_2, AUX_EN);
+	start = get_timer(0);
+	do {
+		if (!(readl(&regs->aux_ch_ctl_2) & AUX_EN))
+			return 0;
+	} while (get_timer(start) < 20);
+
+	return -ETIMEDOUT;
+}
+
+static int rk_edp_is_aux_reply(struct rk3288_edp *regs)
+{
+	ulong start;
+
+	start = get_timer(0);
+	while (!(readl(&regs->dp_int_sta) & RPLY_RECEIV)) {
+		if (get_timer(start) > 10)
+			return -ETIMEDOUT;
+	}
+
+	writel(RPLY_RECEIV, &regs->dp_int_sta);
+
+	return 0;
+}
+
+static int rk_edp_start_aux_transaction(struct rk3288_edp *regs)
+{
+	int val, ret;
+
+	/* Enable AUX CH operation */
+	ret = rk_edp_aux_enable(regs);
+	if (ret) {
+		debug("AUX CH enable timeout!\n");
+		return ret;
+	}
+
+	/* Is AUX CH command reply received? */
+	if (rk_edp_is_aux_reply(regs)) {
+		debug("AUX CH command reply failed!\n");
+		return ret;
+	}
+
+	/* Clear interrupt source for AUX CH access error */
+	val = readl(&regs->dp_int_sta);
+	if (val & AUX_ERR) {
+		writel(AUX_ERR, &regs->dp_int_sta);
+		return -EIO;
+	}
+
+	/* Check AUX CH error access status */
+	val = readl(&regs->dp_int_sta);
+	if (val & AUX_STATUS_MASK) {
+		debug("AUX CH error happens: %d\n\n", val & AUX_STATUS_MASK);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int rk_edp_dpcd_transfer(struct rk3288_edp *regs,
+				unsigned int val_addr, u8 *in_data,
+				unsigned int length,
+				enum dpcd_request request)
+{
+	int val;
+	int i, try_times;
+	u8 *data;
+	int ret = 0;
+	u32 len = 0;
+
+	while (length) {
+		len = min(length, 16U);
+		for (try_times = 0; try_times < 10; try_times++) {
+			data = in_data;
+			/* Clear AUX CH data buffer */
+			writel(BUF_CLR, &regs->buf_data_ctl);
+
+			/* Select DPCD device address */
+			writel(AUX_ADDR_7_0(val_addr), &regs->aux_addr_7_0);
+			writel(AUX_ADDR_15_8(val_addr), &regs->aux_addr_15_8);
+			writel(AUX_ADDR_19_16(val_addr), &regs->aux_addr_19_16);
+
+			/*
+			 * Set DisplayPort transaction and read 1 byte
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			if (request == DPCD_WRITE) {
+				val = AUX_LENGTH(len) |
+					AUX_TX_COMM_DP_TRANSACTION |
+					AUX_TX_COMM_WRITE;
+				for (i = 0; i < len; i++)
+					writel(*data++, &regs->buf_data[i]);
+			} else
+				val = AUX_LENGTH(len) |
+					AUX_TX_COMM_DP_TRANSACTION |
+					AUX_TX_COMM_READ;
+
+			writel(val, &regs->aux_ch_ctl_1);
+
+			/* Start AUX transaction */
+			ret = rk_edp_start_aux_transaction(regs);
+			if (ret == 0)
+				break;
+			else
+				printf("read dpcd Aux Transaction fail!\n");
+		}
+
+		if (ret)
+			return ret;
+
+		if (request == DPCD_READ) {
+			for (i = 0; i < len; i++)
+				*data++ = (u8)readl(&regs->buf_data[i]);
+		}
+
+		length -= len;
+		val_addr += len;
+		in_data += len;
+	}
+
+	return 0;
+}
+
+static int rk_edp_dpcd_read(struct rk3288_edp *regs, u32 addr, u8 *values,
+			    size_t size)
+{
+	return rk_edp_dpcd_transfer(regs, addr, values, size, DPCD_READ);
+}
+
+static int rk_edp_dpcd_write(struct rk3288_edp *regs, u32 addr, u8 *values,
+			     size_t size)
+{
+	return rk_edp_dpcd_transfer(regs, addr, values, size, DPCD_WRITE);
+}
+
+
+static int rk_edp_link_power_up(struct rk_edp_priv *edp)
+{
+	u8 value;
+	int ret;
+
+	/* DP_SET_POWER register is only available on DPCD v1.1 and later */
+	if (edp->link_train.revision < 0x11)
+		return 0;
+
+	ret = rk_edp_dpcd_read(edp->regs, DPCD_LINK_POWER_STATE, &value, 1);
+	if (ret)
+		return ret;
+
+	value &= ~DP_SET_POWER_MASK;
+	value |= DP_SET_POWER_D0;
+
+	ret = rk_edp_dpcd_write(edp->regs, DPCD_LINK_POWER_STATE, &value, 1);
+	if (ret)
+		return ret;
+
+	/*
+	 * According to the DP 1.1 specification, a "Sink Device must exit the
+	 * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
+	 * Control Field" (register 0x600).
+	 */
+	mdelay(1);
+
+	return 0;
+}
+
+static int rk_edp_link_configure(struct rk_edp_priv *edp)
+{
+	u8 values[2];
+
+	values[0] = edp->link_train.link_rate;
+	values[1] = edp->link_train.lane_count;
+
+	return rk_edp_dpcd_write(edp->regs, DPCD_LINK_BW_SET, values,
+				 sizeof(values));
+}
+
+static void rk_edp_set_link_training(struct rk_edp_priv *edp,
+				     const u8 *training_values)
+{
+	int i;
+
+	for (i = 0; i < edp->link_train.lane_count; i++)
+		writel(training_values[i], &edp->regs->ln_link_trn_ctl[i]);
+}
+
+static u8 edp_link_status(const u8 *link_status, int r)
+{
+	return link_status[r - DPCD_LANE0_1_STATUS];
+}
+
+static int rk_edp_dpcd_read_link_status(struct rk_edp_priv *edp,
+					u8 *link_status)
+{
+	return rk_edp_dpcd_read(edp->regs, DPCD_LANE0_1_STATUS, link_status,
+				DP_LINK_STATUS_SIZE);
+}
+
+static u8 edp_get_lane_status(const u8 *link_status, int lane)
+{
+	int i = DPCD_LANE0_1_STATUS + (lane >> 1);
+	int s = (lane & 1) * 4;
+	u8 l = edp_link_status(link_status, i);
+
+	return (l >> s) & 0xf;
+}
+
+static int rk_edp_clock_recovery(const u8 *link_status, int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = edp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_LANE_CR_DONE) == 0)
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static int rk_edp_channel_eq(const u8 *link_status, int lane_count)
+{
+	u8 lane_align;
+	u8 lane_status;
+	int lane;
+
+	lane_align = edp_link_status(link_status,
+				    DPCD_LANE_ALIGN_STATUS_UPDATED);
+	if (!(lane_align & DP_INTERLANE_ALIGN_DONE))
+		return -EIO;
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = edp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static uint rk_edp_get_adjust_request_voltage(const u8 *link_status, int lane)
+{
+	int i = DPCD_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int s = ((lane & 1) ?
+		 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+		 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+	u8 l = edp_link_status(link_status, i);
+
+	return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static uint rk_edp_get_adjust_request_pre_emphasis(const u8 *link_status,
+						   int lane)
+{
+	int i = DPCD_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int s = ((lane & 1) ?
+		 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+		 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+	u8 l = edp_link_status(link_status, i);
+
+	return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+static void edp_get_adjust_train(const u8 *link_status, int lane_count,
+				 u8 train_set[])
+{
+	uint v = 0;
+	uint p = 0;
+	int lane;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		uint this_v, this_p;
+
+		this_v = rk_edp_get_adjust_request_voltage(link_status, lane);
+		this_p = rk_edp_get_adjust_request_pre_emphasis(link_status,
+								lane);
+
+		debug("requested signal parameters: lane %d voltage %s pre_emph %s\n",
+		      lane,
+		      voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
+		      pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
+
+		if (this_v > v)
+			v = this_v;
+		if (this_p > p)
+			p = this_p;
+	}
+
+	if (v >= DP_VOLTAGE_MAX)
+		v |= DP_TRAIN_MAX_SWING_REACHED;
+
+	if (p >= DP_PRE_EMPHASIS_MAX)
+		p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+	debug("using signal parameters: voltage %s pre_emph %s\n",
+	      voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK)
+			>> DP_TRAIN_VOLTAGE_SWING_SHIFT],
+	      pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK)
+			>> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
+
+	for (lane = 0; lane < 4; lane++)
+		train_set[lane] = v | p;
+}
+
+static int rk_edp_link_train_cr(struct rk_edp_priv *edp)
+{
+	struct rk3288_edp *regs = edp->regs;
+	int clock_recovery;
+	uint voltage, tries = 0;
+	u8 status[DP_LINK_STATUS_SIZE];
+	int i, ret;
+	u8 value;
+
+	value = DP_TRAINING_PATTERN_1;
+	writel(value, &regs->dp_training_ptn_set);
+	ret = rk_edp_dpcd_write(regs, DPCD_TRAINING_PATTERN_SET, &value, 1);
+	if (ret)
+		return ret;
+	memset(edp->train_set, '\0', sizeof(edp->train_set));
+
+	/* clock recovery loop */
+	clock_recovery = 0;
+	tries = 0;
+	voltage = 0xff;
+
+	while (1) {
+		rk_edp_set_link_training(edp, edp->train_set);
+		ret = rk_edp_dpcd_write(regs, DPCD_TRAINING_LANE0_SET,
+					edp->train_set,
+					edp->link_train.lane_count);
+		if (ret)
+			return ret;
+
+		mdelay(1);
+
+		ret = rk_edp_dpcd_read_link_status(edp, status);
+		if (ret) {
+			printf("displayport link status failed, ret=%d\n", ret);
+			break;
+		}
+
+		clock_recovery = rk_edp_clock_recovery(status,
+						edp->link_train.lane_count);
+		if (!clock_recovery)
+			break;
+
+		for (i = 0; i < edp->link_train.lane_count; i++) {
+			if ((edp->train_set[i] &
+				DP_TRAIN_MAX_SWING_REACHED) == 0)
+				break;
+		}
+		if (i == edp->link_train.lane_count) {
+			printf("clock recovery reached max voltage\n");
+			break;
+		}
+
+		if ((edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) ==
+				voltage) {
+			if (++tries == MAX_CR_LOOP) {
+				printf("clock recovery tried 5 times\n");
+				break;
+			}
+		} else {
+			tries = 0;
+		}
+
+		voltage = edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+		/* Compute new train_set as requested by sink */
+		edp_get_adjust_train(status, edp->link_train.lane_count,
+				     edp->train_set);
+	}
+	if (clock_recovery) {
+		printf("clock recovery failed: %d\n", clock_recovery);
+		return clock_recovery;
+	} else {
+		debug("clock recovery at voltage %d pre-emphasis %d\n",
+		      edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
+		      (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >>
+				DP_TRAIN_PRE_EMPHASIS_SHIFT);
+		return 0;
+	}
+}
+
+static int rk_edp_link_train_ce(struct rk_edp_priv *edp)
+{
+	struct rk3288_edp *regs = edp->regs;
+	int channel_eq;
+	u8 value;
+	int tries;
+	u8 status[DP_LINK_STATUS_SIZE];
+	int ret;
+
+	value = DP_TRAINING_PATTERN_2;
+	writel(value, &regs->dp_training_ptn_set);
+	ret = rk_edp_dpcd_write(regs, DPCD_TRAINING_PATTERN_SET, &value, 1);
+	if (ret)
+		return ret;
+
+	/* channel equalization loop */
+	channel_eq = 0;
+	for (tries = 0; tries < 5; tries++) {
+		rk_edp_set_link_training(edp, edp->train_set);
+		udelay(400);
+
+		if (rk_edp_dpcd_read_link_status(edp, status) < 0) {
+			printf("displayport link status failed\n");
+			return -1;
+		}
+
+		channel_eq = rk_edp_channel_eq(status,
+					       edp->link_train.lane_count);
+		if (!channel_eq)
+			break;
+		edp_get_adjust_train(status, edp->link_train.lane_count,
+				     edp->train_set);
+	}
+
+	if (channel_eq) {
+		printf("channel eq failed, ret=%d\n", channel_eq);
+		return channel_eq;
+	}
+
+	debug("channel eq at voltage %d pre-emphasis %d\n",
+	      edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
+	      (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
+			>> DP_TRAIN_PRE_EMPHASIS_SHIFT);
+
+	return 0;
+}
+
+static int rk_edp_init_training(struct rk_edp_priv *edp)
+{
+	u8 values[3];
+	int ret;
+
+	ret = rk_edp_dpcd_read(edp->regs, DPCD_DPCD_REV, values,
+			       sizeof(values));
+	if (ret < 0)
+		return ret;
+
+	edp->link_train.revision = values[0];
+	edp->link_train.link_rate = values[1];
+	edp->link_train.lane_count = values[2] & DP_MAX_LANE_COUNT_MASK;
+
+	debug("max link rate:%d.%dGps max number of lanes:%d\n",
+	      edp->link_train.link_rate * 27 / 100,
+	      edp->link_train.link_rate * 27 % 100,
+	      edp->link_train.lane_count);
+
+	if ((edp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
+	    (edp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
+		debug("Rx Max Link Rate is abnormal :%x\n",
+		      edp->link_train.link_rate);
+		return -EPERM;
+	}
+
+	if (edp->link_train.lane_count == 0) {
+		debug("Rx Max Lane count is abnormal :%x\n",
+		      edp->link_train.lane_count);
+		return -EPERM;
+	}
+
+	ret = rk_edp_link_power_up(edp);
+	if (ret)
+		return ret;
+
+	return rk_edp_link_configure(edp);
+}
+
+static int rk_edp_hw_link_training(struct rk_edp_priv *edp)
+{
+	ulong start;
+	u32 val;
+	int ret;
+
+	/* Set link rate and count as you want to establish */
+	writel(edp->link_train.link_rate, &edp->regs->link_bw_set);
+	writel(edp->link_train.lane_count, &edp->regs->lane_count_set);
+
+	ret = rk_edp_link_train_cr(edp);
+	if (ret)
+		return ret;
+	ret = rk_edp_link_train_ce(edp);
+	if (ret)
+		return ret;
+
+	writel(HW_LT_EN, &edp->regs->dp_hw_link_training);
+	start = get_timer(0);
+	do {
+		val = readl(&edp->regs->dp_hw_link_training);
+		if (!(val & HW_LT_EN))
+			break;
+	} while (get_timer(start) < 10);
+
+	if (val & HW_LT_ERR_CODE_MASK) {
+		printf("edp hw link training error: %d\n",
+		       val >> HW_LT_ERR_CODE_SHIFT);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int rk_edp_select_i2c_device(struct rk3288_edp *regs,
+				    unsigned int device_addr,
+				    unsigned int val_addr)
+{
+	int ret;
+
+	/* Set EDID device address */
+	writel(device_addr, &regs->aux_addr_7_0);
+	writel(0x0, &regs->aux_addr_15_8);
+	writel(0x0, &regs->aux_addr_19_16);
+
+	/* Set offset from base address of EDID device */
+	writel(val_addr, &regs->buf_data[0]);
+
+	/*
+	 * Set I2C transaction and write address
+	 * If bit 3 is 1, DisplayPort transaction.
+	 * If Bit 3 is 0, I2C transaction.
+	 */
+	writel(AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
+	       AUX_TX_COMM_WRITE, &regs->aux_ch_ctl_1);
+
+	/* Start AUX transaction */
+	ret = rk_edp_start_aux_transaction(regs);
+	if (ret != 0) {
+		debug("select_i2c_device Aux Transaction fail!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rk_edp_i2c_read(struct rk3288_edp *regs, unsigned int device_addr,
+			   unsigned int val_addr, unsigned int count, u8 edid[])
+{
+	u32 val;
+	unsigned int i, j;
+	unsigned int cur_data_idx;
+	unsigned int defer = 0;
+	int ret = 0;
+
+	for (i = 0; i < count; i += 16) {
+		for (j = 0; j < 10; j++) { /* try 10 times */
+			/* Clear AUX CH data buffer */
+			writel(BUF_CLR, &regs->buf_data_ctl);
+
+			/* Set normal AUX CH command */
+			clrbits_le32(&regs->aux_ch_ctl_2, ADDR_ONLY);
+
+			/*
+			 * If Rx sends defer, Tx sends only reads
+			 * request without sending addres
+			 */
+			if (!defer) {
+				ret = rk_edp_select_i2c_device(regs,
+							       device_addr,
+							       val_addr + i);
+			} else {
+				defer = 0;
+			}
+
+			/*
+			 * Set I2C transaction and write data
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			writel(AUX_LENGTH(16) | AUX_TX_COMM_I2C_TRANSACTION |
+			       AUX_TX_COMM_READ, &regs->aux_ch_ctl_1);
+
+			/* Start AUX transaction */
+			ret = rk_edp_start_aux_transaction(regs);
+			if (ret == 0) {
+				break;
+			} else {
+				debug("Aux Transaction fail!\n");
+				continue;
+			}
+
+			/* Check if Rx sends defer */
+			val = readl(&regs->aux_rx_comm);
+			if (val == AUX_RX_COMM_AUX_DEFER ||
+			    val == AUX_RX_COMM_I2C_DEFER) {
+				debug("Defer: %d\n\n", val);
+				defer = 1;
+			}
+		}
+
+		if (ret)
+			return ret;
+
+		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
+			val = readl(&regs->buf_data[cur_data_idx]);
+			edid[i + cur_data_idx] = (u8)val;
+		}
+	}
+
+	return 0;
+}
+
+static int rk_edp_set_link_train(struct rk_edp_priv *edp)
+{
+	int ret;
+
+	ret = rk_edp_init_training(edp);
+	if (ret) {
+		printf("DP LT init failed!\n");
+		return ret;
+	}
+
+	ret = rk_edp_hw_link_training(edp);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void rk_edp_init_video(struct rk3288_edp *regs)
+{
+	writel(VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG,
+	       &regs->common_int_sta_1);
+	writel(CHA_CRI(4) | CHA_CTRL, &regs->sys_ctl_2);
+	writel(VID_HRES_TH(2) | VID_VRES_TH(0), &regs->video_ctl_8);
+}
+
+static void rk_edp_config_video_slave_mode(struct rk3288_edp *regs)
+{
+	clrbits_le32(&regs->func_en_1, VID_FIFO_FUNC_EN_N | VID_CAP_FUNC_EN_N);
+}
+
+static void rk_edp_set_video_cr_mn(struct rk3288_edp *regs,
+				   enum clock_recovery_m_value_type type,
+				   u32 m_value,
+				   u32 n_value)
+{
+	if (type == REGISTER_M) {
+		setbits_le32(&regs->sys_ctl_4, FIX_M_VID);
+		writel(m_value & 0xff, &regs->m_vid_0);
+		writel((m_value >> 8) & 0xff, &regs->m_vid_1);
+		writel((m_value >> 16) & 0xff, &regs->m_vid_2);
+
+		writel(n_value & 0xf, &regs->n_vid_0);
+		writel((n_value >> 8) & 0xff, &regs->n_vid_1);
+		writel((n_value >> 16) & 0xff, &regs->n_vid_2);
+	} else {
+		clrbits_le32(&regs->sys_ctl_4, FIX_M_VID);
+
+		writel(0x00, &regs->n_vid_0);
+		writel(0x80, &regs->n_vid_1);
+		writel(0x00, &regs->n_vid_2);
+	}
+}
+
+static int rk_edp_is_video_stream_clock_on(struct rk3288_edp *regs)
+{
+	ulong start;
+	u32 val;
+
+	start = get_timer(0);
+	do {
+		val = readl(&regs->sys_ctl_1);
+
+		/* must write value to update DET_STA bit status */
+		writel(val, &regs->sys_ctl_1);
+		val = readl(&regs->sys_ctl_1);
+		if (!(val & DET_STA))
+			continue;
+
+		val = readl(&regs->sys_ctl_2);
+
+		/* must write value to update CHA_STA bit status */
+		writel(val, &regs->sys_ctl_2);
+		val = readl(&regs->sys_ctl_2);
+		if (!(val & CHA_STA))
+			return 0;
+
+	} while (get_timer(start) < 100);
+
+	return -ETIMEDOUT;
+}
+
+static int rk_edp_is_video_stream_on(struct rk_edp_priv *edp)
+{
+	ulong start;
+	u32 val;
+
+	start = get_timer(0);
+	do {
+		val = readl(&edp->regs->sys_ctl_3);
+
+		/* must write value to update STRM_VALID bit status */
+		writel(val, &edp->regs->sys_ctl_3);
+
+		val = readl(&edp->regs->sys_ctl_3);
+		if (!(val & STRM_VALID))
+			return 0;
+	} while (get_timer(start) < 100);
+
+	return -ETIMEDOUT;
+}
+
+static int rk_edp_config_video(struct rk_edp_priv *edp)
+{
+	int ret;
+
+	rk_edp_config_video_slave_mode(edp->regs);
+
+	if (!rk_edp_get_pll_locked(edp->regs)) {
+		debug("PLL is not locked yet.\n");
+		return -ETIMEDOUT;
+	}
+
+	ret = rk_edp_is_video_stream_clock_on(edp->regs);
+	if (ret)
+		return ret;
+
+	/* Set to use the register calculated M/N video */
+	rk_edp_set_video_cr_mn(edp->regs, CALCULATED_M, 0, 0);
+
+	/* For video bist, Video timing must be generated by register */
+	clrbits_le32(&edp->regs->video_ctl_10, F_SEL);
+
+	/* Disable video mute */
+	clrbits_le32(&edp->regs->video_ctl_1, VIDEO_MUTE);
+
+	/* Enable video at next frame */
+	setbits_le32(&edp->regs->video_ctl_1, VIDEO_EN);
+
+	return rk_edp_is_video_stream_on(edp);
+}
+
+static void rockchip_edp_force_hpd(struct rk_edp_priv *edp)
+{
+	setbits_le32(&edp->regs->sys_ctl_3, F_HPD | HPD_CTRL);
+}
+
+static int rockchip_edp_get_plug_in_status(struct rk_edp_priv *edp)
+{
+	u32 val;
+
+	val = readl(&edp->regs->sys_ctl_3);
+	if (val & HPD_STATUS)
+		return 1;
+
+	return 0;
+}
+
+/*
+ * support edp HPD function
+ * some hardware version do not support edp hdp,
+ * we use 200ms to try to get the hpd single now,
+ * if we can not get edp hpd single, it will delay 200ms,
+ * also meet the edp power timing request, to compatible
+ * all of the hardware version
+ */
+static void rockchip_edp_wait_hpd(struct rk_edp_priv *edp)
+{
+	ulong start;
+
+	start = get_timer(0);
+	do {
+		if (rockchip_edp_get_plug_in_status(edp))
+			return;
+		udelay(100);
+	} while (get_timer(start) < 200);
+
+	debug("do not get hpd single, force hpd\n");
+	rockchip_edp_force_hpd(edp);
+}
+
+static int rk_edp_enable(struct udevice *dev, int panel_bpp,
+			 const struct display_timing *edid)
+{
+	struct rk_edp_priv *priv = dev_get_priv(dev);
+	int ret = 0;
+
+	ret = rk_edp_set_link_train(priv);
+	if (ret) {
+		printf("link train failed!\n");
+		return ret;
+	}
+
+	rk_edp_init_video(priv->regs);
+	ret = rk_edp_config_video(priv);
+	if (ret) {
+		printf("config video failed\n");
+		return ret;
+	}
+	ret = panel_enable_backlight(priv->panel);
+	if (ret) {
+		debug("%s: backlight error: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rk_edp_read_edid(struct udevice *dev, u8 *buf, int buf_size)
+{
+	struct rk_edp_priv *priv = dev_get_priv(dev);
+	u32 edid_size = EDID_LENGTH;
+	int ret;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		ret = rk_edp_i2c_read(priv->regs, EDID_ADDR, EDID_HEADER,
+				      EDID_LENGTH, &buf[EDID_HEADER]);
+		if (ret) {
+			debug("EDID read failed\n");
+			continue;
+		}
+
+		/*
+		 * check if the EDID has an extension flag, and read additional
+		 * EDID data if needed
+		 */
+		if (buf[EDID_EXTENSION_FLAG]) {
+			edid_size += EDID_LENGTH;
+			ret = rk_edp_i2c_read(priv->regs, EDID_ADDR,
+					      EDID_LENGTH, EDID_LENGTH,
+					      &buf[EDID_LENGTH]);
+			if (ret) {
+				debug("EDID Read failed!\n");
+				continue;
+			}
+		}
+		goto done;
+	}
+
+	/* After 3 attempts, give up */
+	return ret;
+
+done:
+	return edid_size;
+}
+
+static int rk_edp_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk_edp_priv *priv = dev_get_priv(dev);
+
+	priv->regs = (struct rk3288_edp *)dev_get_addr(dev);
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+
+	return 0;
+}
+
+int rk_edp_probe(struct udevice *dev)
+{
+	struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
+	struct rk_edp_priv *priv = dev_get_priv(dev);
+	struct rk3288_edp *regs = priv->regs;
+	struct udevice *clk;
+	int periph;
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "rockchip,panel",
+					   &priv->panel);
+	if (ret) {
+		debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__,
+		      dev->name, ret);
+		return ret;
+	}
+
+	int vop_id = uc_plat->source_id;
+	debug("%s, uc_plat=%p, vop_id=%u\n", __func__, uc_plat, vop_id);
+
+	ret = clk_get_by_index(dev, 1, &clk, &periph);
+	if (!ret)
+		ret = clk_set_periph_rate(clk, periph, 0);
+	if (ret) {
+		debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = clk_get_by_index(uc_plat->src_dev, 0, &clk, &periph);
+	if (!ret)
+		ret = clk_set_periph_rate(clk, periph, 192000000);
+	if (ret < 0) {
+		debug("%s: Failed to set clock in source device '%s': ret=%d\n",
+		      __func__, uc_plat->src_dev->name, ret);
+		return ret;
+	}
+
+	/* grf_edp_ref_clk_sel: from internal 24MHz or 27MHz clock */
+	rk_setreg(&priv->grf->soc_con12, 1 << 4);
+
+	/* select epd signal from vop0 or vop1 */
+	rk_setreg(&priv->grf->soc_con6, (vop_id == 1) ? (1 << 5) : (1 << 5));
+
+	rockchip_edp_wait_hpd(priv);
+
+	rk_edp_init_refclk(regs);
+	rk_edp_init_interrupt(regs);
+	rk_edp_enable_sw_function(regs);
+	ret = rk_edp_init_analog_func(regs);
+	if (ret)
+		return ret;
+	rk_edp_init_aux(regs);
+
+	return 0;
+}
+
+static const struct dm_display_ops dp_rockchip_ops = {
+	.read_edid = rk_edp_read_edid,
+	.enable = rk_edp_enable,
+};
+
+static const struct udevice_id rockchip_dp_ids[] = {
+	{ .compatible = "rockchip,rk3288-edp" },
+	{ }
+};
+
+U_BOOT_DRIVER(dp_rockchip) = {
+	.name	= "edp_rockchip",
+	.id	= UCLASS_DISPLAY,
+	.of_match = rockchip_dp_ids,
+	.ops	= &dp_rockchip_ops,
+	.ofdata_to_platdata	= rk_edp_ofdata_to_platdata,
+	.probe	= rk_edp_probe,
+	.priv_auto_alloc_size	= sizeof(struct rk_edp_priv),
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 17/37] rockchip: video: Add a video-output driver
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (15 preceding siblings ...)
  2016-01-14 15:57 ` [U-Boot] [PATCH 16/37] rockchip: video: Add a display driver for rockchip eDP Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 18/37] rockchip: Don't skip low-level init Simon Glass
                   ` (20 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Some rockchip SoCs include video output (VOP). Add a driver to support this.
It can output via a display driver (UCLASS_DISPLAY) and currently HDMI and
eDP are supported.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/arch-rockchip/vop_rk3288.h | 349 ++++++++++++++++++++++++
 drivers/video/rockchip/Makefile                 |   2 +-
 drivers/video/rockchip/rk_vop.c                 | 346 +++++++++++++++++++++++
 3 files changed, 696 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-rockchip/vop_rk3288.h
 create mode 100644 drivers/video/rockchip/rk_vop.c

diff --git a/arch/arm/include/asm/arch-rockchip/vop_rk3288.h b/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
new file mode 100644
index 0000000..0104ba3
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_VOP_RK3288_H
+#define _ASM_ARCH_VOP_RK3288_H
+
+struct rk3288_vop {
+	u32 reg_cfg_done;
+	u32 version_info;
+	u32 sys_ctrl;
+	u32 sys_ctrl1;
+	u32 dsp_ctrl0;
+	u32 dsp_ctrl1;
+	u32 dsp_bg;
+	u32 mcu_ctrl;
+	u32 intr_ctrl0;
+	u32 intr_ctrl1;
+	u32 intr_reserved0;
+	u32 intr_reserved1;
+
+	u32 win0_ctrl0;
+	u32 win0_ctrl1;
+	u32 win0_color_key;
+	u32 win0_vir;
+	u32 win0_yrgb_mst;
+	u32 win0_cbr_mst;
+	u32 win0_act_info;
+	u32 win0_dsp_info;
+	u32 win0_dsp_st;
+	u32 win0_scl_factor_yrgb;
+	u32 win0_scl_factor_cbr;
+	u32 win0_scl_offset;
+	u32 win0_src_alpha_ctrl;
+	u32 win0_dst_alpha_ctrl;
+	u32 win0_fading_ctrl;
+	u32 win0_reserved0;
+
+	u32 win1_ctrl0;
+	u32 win1_ctrl1;
+	u32 win1_color_key;
+	u32 win1_vir;
+	u32 win1_yrgb_mst;
+	u32 win1_cbr_mst;
+	u32 win1_act_info;
+	u32 win1_dsp_info;
+	u32 win1_dsp_st;
+	u32 win1_scl_factor_yrgb;
+	u32 win1_scl_factor_cbr;
+	u32 win1_scl_offset;
+	u32 win1_src_alpha_ctrl;
+	u32 win1_dst_alpha_ctrl;
+	u32 win1_fading_ctrl;
+	u32 win1_reservd0;
+	u32 reserved2[48];
+	u32 post_dsp_hact_info;
+	u32 post_dsp_vact_info;
+	u32 post_scl_factor_yrgb;
+	u32 post_reserved;
+	u32 post_scl_ctrl;
+	u32 post_dsp_vact_info_f1;
+	u32 dsp_htotal_hs_end;
+	u32 dsp_hact_st_end;
+	u32 dsp_vtotal_vs_end;
+	u32 dsp_vact_st_end;
+	u32 dsp_vs_st_end_f1;
+	u32 dsp_vact_st_end_f1;
+};
+check_member(rk3288_vop, dsp_vact_st_end_f1, 0x19c);
+
+enum rockchip_fb_data_format_t {
+	ARGB8888 = 0,
+	RGB888 = 1,
+	RGB565 = 2,
+};
+
+enum {
+	LB_YUV_3840X5 = 0x0,
+	LB_YUV_2560X8 = 0x1,
+	LB_RGB_3840X2 = 0x2,
+	LB_RGB_2560X4 = 0x3,
+	LB_RGB_1920X5 = 0x4,
+	LB_RGB_1280X8 = 0x5
+};
+
+enum vop_modes {
+	VOP_MODE_EDP = 0,
+	VOP_MODE_HDMI,
+	VOP_MODE_NONE,
+	VOP_MODE_AUTO_DETECT,
+	VOP_MODE_UNKNOWN,
+};
+
+/* VOP_VERSION_INFO */
+#define M_FPGA_VERSION (0xffff << 16)
+#define M_RTL_VERSION  (0xffff)
+
+/* VOP_SYS_CTRL */
+#define M_AUTO_GATING_EN (1 << 23)
+#define M_STANDBY_EN     (1 << 22)
+#define M_DMA_STOP       (1 << 21)
+#define M_MMU_EN         (1 << 20)
+#define M_DAM_BURST_LENGTH (0x3 << 18)
+#define M_MIPI_OUT_EN	   (1 << 15)
+#define M_EDP_OUT_EN       (1 << 14)
+#define M_HDMI_OUT_EN      (1 << 13)
+#define M_RGB_OUT_EN       (1 << 12)
+#define M_ALL_OUT_EN		\
+		(M_MIPI_OUT_EN | M_EDP_OUT_EN | M_HDMI_OUT_EN | M_RGB_OUT_EN)
+#define M_EDPI_WMS_FS      (1 << 10)
+#define M_EDPI_WMS_MODE    (1 << 9)
+#define M_EDPI_HALT_EN     (1 << 8)
+#define M_DOUB_CH_OVERLAP_NUM (0xf << 4)
+#define M_DOUB_CHANNEL_EN     (1 << 3)
+#define M_DIRECT_PATH_LAYER_SEL (0x3 << 1)
+#define M_DIRECT_PATH_EN       (1)
+
+#define V_AUTO_GATING_EN(x) (((x) & 1) << 23)
+#define V_STANDBY_EN(x)     (((x) & 1) << 22)
+#define V_DMA_STOP(x)       (((x) & 1) << 21)
+#define V_MMU_EN(x)         (((x) & 1) << 20)
+#define V_DMA_BURST_LENGTH(x) (((x) & 3) << 18)
+#define V_MIPI_OUT_EN(x)      (((x) & 1) << 15)
+#define V_EDP_OUT_EN(x)       (((x) & 1) << 14)
+#define V_HDMI_OUT_EN(x)      (((x) & 1) << 13)
+#define V_RGB_OUT_EN(x)       (((x) & 1) << 12)
+#define V_EDPI_WMS_FS(x)      (((x) & 1) << 10)
+#define V_EDPI_WMS_MODE(x)    (((x) & 1) << 9)
+#define V_EDPI_HALT_EN(x)     (((x)&1)<<8)
+#define V_DOUB_CH_OVERLAP_NUM(x) (((x) & 0xf) << 4)
+#define V_DOUB_CHANNEL_EN(x)     (((x) & 1) << 3)
+#define V_DIRECT_PATH_LAYER_SEL(x) (((x) & 3) << 1)
+#define V_DIRECT_PATH_EN(x)       ((x) & 1)
+
+/* VOP_SYS_CTRL1 */
+#define M_AXI_OUTSTANDING_MAX_NUM (0x1f << 13)
+#define M_AXI_MAX_OUTSTANDING_EN  (1 << 12)
+#define M_NOC_WIN_QOS             (3 << 10)
+#define M_NOC_QOS_EN              (1 << 9)
+#define M_NOC_HURRY_THRESHOLD     (0x3f << 3)
+#define M_NOC_HURRY_VALUE         (0x3 << 1)
+#define M_NOC_HURRY_EN            (1)
+
+#define V_AXI_OUTSTANDING_MAX_NUM(x) (((x) & 0x1f) << 13)
+#define V_AXI_MAX_OUTSTANDING_EN(x)  (((x) & 1) << 12)
+#define V_NOC_WIN_QOS(x)             (((x) & 3) << 10)
+#define V_NOC_QOS_EN(x)              (((x) & 1) << 9)
+#define V_NOC_HURRY_THRESHOLD(x)     (((x) & 0x3f) << 3)
+#define V_NOC_HURRY_VALUE(x)         (((x) & 3) << 1)
+#define V_NOC_HURRY_EN(x)            ((x) & 1)
+
+/* VOP_DSP_CTRL0 */
+#define M_DSP_Y_MIR_EN              (1 << 23)
+#define M_DSP_X_MIR_EN              (1 << 22)
+#define M_DSP_YUV_CLIP              (1 << 21)
+#define M_DSP_CCIR656_AVG           (1 << 20)
+#define M_DSP_BLACK_EN              (1 << 19)
+#define M_DSP_BLANK_EN              (1 << 18)
+#define M_DSP_OUT_ZERO              (1 << 17)
+#define M_DSP_DUMMY_SWAP            (1 << 16)
+#define M_DSP_DELTA_SWAP            (1 << 15)
+#define M_DSP_RG_SWAP               (1 << 14)
+#define M_DSP_RB_SWAP               (1 << 13)
+#define M_DSP_BG_SWAP               (1 << 12)
+#define M_DSP_FIELD_POL             (1 << 11)
+#define M_DSP_INTERLACE             (1 << 10)
+#define M_DSP_DDR_PHASE             (1 << 9)
+#define M_DSP_DCLK_DDR              (1 << 8)
+#define M_DSP_DCLK_POL              (1 << 7)
+#define M_DSP_DEN_POL               (1 << 6)
+#define M_DSP_VSYNC_POL             (1 << 5)
+#define M_DSP_HSYNC_POL             (1 << 4)
+#define M_DSP_OUT_MODE              (0xf)
+
+#define V_DSP_Y_MIR_EN(x)              (((x) & 1) << 23)
+#define V_DSP_X_MIR_EN(x)              (((x) & 1) << 22)
+#define V_DSP_YUV_CLIP(x)              (((x) & 1) << 21)
+#define V_DSP_CCIR656_AVG(x)           (((x) & 1) << 20)
+#define V_DSP_BLACK_EN(x)              (((x) & 1) << 19)
+#define V_DSP_BLANK_EN(x)              (((x) & 1) << 18)
+#define V_DSP_OUT_ZERO(x)              (((x) & 1) << 17)
+#define V_DSP_DUMMY_SWAP(x)            (((x) & 1) << 16)
+#define V_DSP_DELTA_SWAP(x)            (((x) & 1) << 15)
+#define V_DSP_RG_SWAP(x)               (((x) & 1) << 14)
+#define V_DSP_RB_SWAP(x)               (((x) & 1) << 13)
+#define V_DSP_BG_SWAP(x)               (((x) & 1) << 12)
+#define V_DSP_FIELD_POL(x)             (((x) & 1) << 11)
+#define V_DSP_INTERLACE(x)             (((x) & 1) << 10)
+#define V_DSP_DDR_PHASE(x)             (((x) & 1) << 9)
+#define V_DSP_DCLK_DDR(x)              (((x) & 1) << 8)
+#define V_DSP_DCLK_POL(x)              (((x) & 1) << 7)
+#define V_DSP_DEN_POL(x)               (((x) & 1) << 6)
+#define V_DSP_VSYNC_POL(x)             (((x) & 1) << 5)
+#define V_DSP_HSYNC_POL(x)             (((x) & 1) << 4)
+#define V_DSP_OUT_MODE(x)              ((x) & 0xf)
+
+/* VOP_DSP_CTRL1 */
+#define M_DSP_LAYER3_SEL               (3 << 14)
+#define M_DSP_LAYER2_SEL               (3 << 12)
+#define M_DSP_LAYER1_SEL               (3 << 10)
+#define M_DSP_LAYER0_SEL               (3 << 8)
+#define M_DITHER_UP_EN                 (1 << 6)
+#define M_DITHER_DOWN_SEL              (1 << 4)
+#define M_DITHER_DOWN_MODE             (1 << 3)
+#define M_DITHER_DOWN_EN               (1 << 2)
+#define M_PRE_DITHER_DOWN_EN           (1 << 1)
+#define M_DSP_LUT_EN                   (1)
+
+#define V_DSP_LAYER3_SEL(x)                (((x) & 3) << 14)
+#define V_DSP_LAYER2_SEL(x)                (((x) & 3) << 12)
+#define V_DSP_LAYER1_SEL(x)                (((x) & 3) << 10)
+#define V_DSP_LAYER0_SEL(x)                (((x) & 3) << 8)
+#define V_DITHER_UP_EN(x)                  (((x) & 1) << 6)
+#define V_DITHER_DOWN_SEL(x)               (((x) & 1) << 4)
+#define V_DITHER_DOWN_MODE(x)              (((x) & 1) << 3)
+#define V_DITHER_DOWN_EN(x)                (((x) & 1) << 2)
+#define V_PRE_DITHER_DOWN_EN(x)            (((x) & 1) << 1)
+#define V_DSP_LUT_EN(x)                    ((x)&1)
+
+/* VOP_DSP_BG */
+#define M_DSP_BG_RED     (0x3f << 20)
+#define M_DSP_BG_GREEN   (0x3f << 10)
+#define M_DSP_BG_BLUE    (0x3f << 0)
+
+#define V_DSP_BG_RED(x)     (((x) & 0x3f) << 20)
+#define V_DSP_BG_GREEN(x)   (((x) & 0x3f) << 10)
+#define V_DSP_BG_BLUE(x)    (((x) & 0x3f) << 0)
+
+/* VOP_WIN0_CTRL0 */
+#define M_WIN0_YUV_CLIP     (1 << 20)
+#define M_WIN0_CBR_DEFLICK  (1 << 19)
+#define M_WIN0_YRGB_DEFLICK  (1 << 18)
+#define M_WIN0_PPAS_ZERO_EN  (1 << 16)
+#define M_WIN0_UV_SWAP       (1 << 15)
+#define M_WIN0_MID_SWAP      (1 << 14)
+#define M_WIN0_ALPHA_SWAP    (1 << 13)
+#define M_WIN0_RB_SWAP       (1 << 12)
+#define M_WIN0_CSC_MODE      (3 << 10)
+#define M_WIN0_NO_OUTSTANDING (1 << 9)
+#define M_WIN0_INTERLACE_READ  (1 << 8)
+#define M_WIN0_LB_MODE         (7 << 5)
+#define M_WIN0_FMT_10          (1 << 4)
+#define M_WIN0_DATA_FMT        (7 << 1)
+#define M_WIN0_EN              (1 << 0)
+
+#define V_WIN0_YUV_CLIP(x)       (((x) & 1) << 20)
+#define V_WIN0_CBR_DEFLICK(x)    (((x) & 1) << 19)
+#define V_WIN0_YRGB_DEFLICK(x)   (((x) & 1) << 18)
+#define V_WIN0_PPAS_ZERO_EN(x)   (((x) & 1) << 16)
+#define V_WIN0_UV_SWAP(x)        (((x) & 1) << 15)
+#define V_WIN0_MID_SWAP(x)       (((x) & 1) << 14)
+#define V_WIN0_ALPHA_SWAP(x)     (((x) & 1) << 13)
+#define V_WIN0_RB_SWAP(x)        (((x) & 1) << 12)
+#define V_WIN0_CSC_MODE(x)       (((x) & 3) << 10)
+#define V_WIN0_NO_OUTSTANDING(x) (((x) & 1) << 9)
+#define V_WIN0_INTERLACE_READ(x)  (((x) & 1) << 8)
+#define V_WIN0_LB_MODE(x)         (((x) & 7) << 5)
+#define V_WIN0_FMT_10(x)          (((x) & 1) << 4)
+#define V_WIN0_DATA_FMT(x)        (((x) & 7) << 1)
+#define V_WIN0_EN(x)              ((x) & 1)
+
+/* VOP_WIN0_CTRL1 */
+#define M_WIN0_CBR_VSD_MODE        (1 << 31)
+#define M_WIN0_CBR_VSU_MODE        (1 << 30)
+#define M_WIN0_CBR_HSD_MODE        (3 << 28)
+#define M_WIN0_CBR_VER_SCL_MODE    (3 << 26)
+#define M_WIN0_CBR_HOR_SCL_MODE    (3 << 24)
+#define M_WIN0_YRGB_VSD_MODE       (1 << 23)
+#define M_WIN0_YRGB_VSU_MODE       (1 << 22)
+#define M_WIN0_YRGB_HSD_MODE       (3 << 20)
+#define M_WIN0_YRGB_VER_SCL_MODE   (3 << 18)
+#define M_WIN0_YRGB_HOR_SCL_MODE   (3 << 16)
+#define M_WIN0_LINE_LOAD_MODE      (1 << 15)
+#define M_WIN0_CBR_AXI_GATHER_NUM  (7 << 12)
+#define M_WIN0_YRGB_AXI_GATHER_NUM (0xf << 8)
+#define M_WIN0_VSD_CBR_GT2         (1 << 7)
+#define M_WIN0_VSD_CBR_GT4         (1 << 6)
+#define M_WIN0_VSD_YRGB_GT2        (1 << 5)
+#define M_WIN0_VSD_YRGB_GT4        (1 << 4)
+#define M_WIN0_BIC_COE_SEL         (3 << 2)
+#define M_WIN0_CBR_AXI_GATHER_EN   (1 << 1)
+#define M_WIN0_YRGB_AXI_GATHER_EN  (1)
+
+#define V_WIN0_CBR_VSD_MODE(x)        (((x) & 1) << 31)
+#define V_WIN0_CBR_VSU_MODE(x)        (((x) & 1) << 30)
+#define V_WIN0_CBR_HSD_MODE(x)        (((x) & 3) << 28)
+#define V_WIN0_CBR_VER_SCL_MODE(x)    (((x) & 3) << 26)
+#define V_WIN0_CBR_HOR_SCL_MODE(x)    (((x) & 3) << 24)
+#define V_WIN0_YRGB_VSD_MODE(x)       (((x) & 1) << 23)
+#define V_WIN0_YRGB_VSU_MODE(x)       (((x) & 1) << 22)
+#define V_WIN0_YRGB_HSD_MODE(x)       (((x) & 3) << 20)
+#define V_WIN0_YRGB_VER_SCL_MODE(x)   (((x) & 3) << 18)
+#define V_WIN0_YRGB_HOR_SCL_MODE(x)   (((x) & 3) << 16)
+#define V_WIN0_LINE_LOAD_MODE(x)      (((x) & 1) << 15)
+#define V_WIN0_CBR_AXI_GATHER_NUM(x)  (((x) & 7) << 12)
+#define V_WIN0_YRGB_AXI_GATHER_NUM(x) (((x) & 0xf) << 8)
+#define V_WIN0_VSD_CBR_GT2(x)         (((x) & 1) << 7)
+#define V_WIN0_VSD_CBR_GT4(x)         (((x) & 1) << 6)
+#define V_WIN0_VSD_YRGB_GT2(x)        (((x) & 1) << 5)
+#define V_WIN0_VSD_YRGB_GT4(x)        (((x) & 1) << 4)
+#define V_WIN0_BIC_COE_SEL(x)         (((x) & 3) << 2)
+#define V_WIN0_CBR_AXI_GATHER_EN(x)   (((x) & 1) << 1)
+#define V_WIN0_YRGB_AXI_GATHER_EN(x)  ((x) & 1)
+
+/*VOP_WIN0_COLOR_KEY*/
+#define M_WIN0_KEY_EN                 (1 << 31)
+#define M_WIN0_KEY_COLOR              (0x3fffffff)
+
+#define V_WIN0_KEY_EN(x)              (((x) & 1) << 31)
+#define V_WIN0_KEY_COLOR(x)           ((x) & 0x3fffffff)
+
+/* VOP_WIN0_VIR */
+#define V_ARGB888_VIRWIDTH(x)	(((x) & 0x3fff) << 0)
+#define V_RGB888_VIRWIDTH(x)	(((((x * 3) >> 2)+((x) % 3)) & 0x3fff) << 0)
+#define V_RGB565_VIRWIDTH(x)	(((x / 2) & 0x3fff) << 0)
+#define YUV_VIRWIDTH(x)		(((x / 4) & 0x3fff) << 0)
+
+/* VOP_WIN0_ACT_INFO */
+#define V_ACT_HEIGHT(x)         (((x) & 0x1fff) << 16)
+#define V_ACT_WIDTH(x)          ((x) & 0x1fff)
+
+/* VOP_WIN0_DSP_INFO */
+#define V_DSP_HEIGHT(x)         (((x) & 0xfff) << 16)
+#define V_DSP_WIDTH(x)          ((x) & 0xfff)
+
+/* VOP_WIN0_DSP_ST */
+#define V_DSP_YST(x)            (((x) & 0x1fff) << 16)
+#define V_DSP_XST(x)            ((x) & 0x1fff)
+
+/* VOP_WIN0_SCL_OFFSET */
+#define V_WIN0_VS_OFFSET_CBR(x)     (((x) & 0xff) << 24)
+#define V_WIN0_VS_OFFSET_YRGB(x)    (((x) & 0xff) << 16)
+#define V_WIN0_HS_OFFSET_CBR(x)     (((x) & 0xff) << 8)
+#define V_WIN0_HS_OFFSET_YRGB(x)    ((x) & 0xff)
+
+#define V_HSYNC(x)		(((x)&0x1fff)<<0)   /* hsync pulse width */
+#define V_HORPRD(x)		(((x)&0x1fff)<<16)   /* horizontal period */
+#define V_VSYNC(x)		(((x)&0x1fff)<<0)
+#define V_VERPRD(x)		(((x)&0x1fff)<<16)
+
+#define V_HEAP(x)		(((x)&0x1fff)<<0)/* horizontal active end */
+#define V_HASP(x)		(((x)&0x1fff)<<16)/* horizontal active start */
+#define V_VAEP(x)		(((x)&0x1fff)<<0)
+#define V_VASP(x)		(((x)&0x1fff)<<16)
+
+#endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 5566719..0e9a8ac 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += rk_edp.o rk_hdmi.o
+obj-y += rk_edp.o rk_hdmi.o rk_vop.o
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
new file mode 100644
index 0000000..adbc68f
--- /dev/null
+++ b/drivers/video/rockchip/rk_vop.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <edid.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <video.h>
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3288.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/edp_rk3288.h>
+#include <asm/arch/hdmi_rk3288.h>
+#include <asm/arch/vop_rk3288.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk_vop_priv {
+	struct rk3288_vop *regs;
+	struct rk3288_grf *grf;
+};
+
+void rkvop_enable(struct rk3288_vop *regs, ulong fbbase,
+		  int fb_bits_per_pixel, const struct display_timing *edid)
+{
+	u32 lb_mode;
+	u32 rgb_mode;
+	u32 hactive = edid->hactive.typ;
+	u32 vactive = edid->vactive.typ;
+
+	writel(V_ACT_WIDTH(hactive - 1) | V_ACT_HEIGHT(vactive - 1),
+	       &regs->win0_act_info);
+
+	writel(V_DSP_XST(edid->hsync_len.typ + edid->hback_porch.typ) |
+	       V_DSP_YST(edid->vsync_len.typ + edid->vback_porch.typ),
+	       &regs->win0_dsp_st);
+
+	writel(V_DSP_WIDTH(hactive - 1) |
+		V_DSP_HEIGHT(vactive - 1),
+		&regs->win0_dsp_info);
+
+	clrsetbits_le32(&regs->win0_color_key, M_WIN0_KEY_EN | M_WIN0_KEY_COLOR,
+			V_WIN0_KEY_EN(0) | V_WIN0_KEY_COLOR(0));
+
+	switch (fb_bits_per_pixel) {
+	case 16:
+		rgb_mode = RGB565;
+		writel(V_RGB565_VIRWIDTH(hactive), &regs->win0_vir);
+		break;
+	case 24:
+		rgb_mode = RGB888;
+		writel(V_RGB888_VIRWIDTH(hactive), &regs->win0_vir);
+		break;
+	case 32:
+	default:
+		rgb_mode = ARGB8888;
+		writel(V_ARGB888_VIRWIDTH(hactive), &regs->win0_vir);
+		break;
+	}
+
+	if (hactive > 2560)
+		lb_mode = LB_RGB_3840X2;
+	else if (hactive > 1920)
+		lb_mode = LB_RGB_2560X4;
+	else if (hactive > 1280)
+		lb_mode = LB_RGB_1920X5;
+	else
+		lb_mode = LB_RGB_1280X8;
+
+	clrsetbits_le32(&regs->win0_ctrl0,
+			M_WIN0_LB_MODE | M_WIN0_DATA_FMT | M_WIN0_EN,
+			V_WIN0_LB_MODE(lb_mode) | V_WIN0_DATA_FMT(rgb_mode) |
+			V_WIN0_EN(1));
+
+	writel(fbbase, &regs->win0_yrgb_mst);
+	writel(0x01, &regs->reg_cfg_done); /* enable reg config */
+}
+
+void rkvop_mode_set(struct rk3288_vop *regs,
+		    const struct display_timing *edid, enum vop_modes mode)
+{
+	u32 hactive = edid->hactive.typ;
+	u32 vactive = edid->vactive.typ;
+	u32 hsync_len = edid->hsync_len.typ;
+	u32 hback_porch = edid->hback_porch.typ;
+	u32 vsync_len = edid->vsync_len.typ;
+	u32 vback_porch = edid->vback_porch.typ;
+	u32 hfront_porch = edid->hfront_porch.typ;
+	u32 vfront_porch = edid->vfront_porch.typ;
+	uint flags;
+
+	switch (mode) {
+	case VOP_MODE_HDMI:
+		clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN,
+				V_HDMI_OUT_EN(1));
+		break;
+	case VOP_MODE_EDP:
+	default:
+		clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN,
+				V_EDP_OUT_EN(1));
+		break;
+	}
+
+	flags = V_DSP_OUT_MODE(15) |
+		V_DSP_HSYNC_POL(!!(edid->flags & DISPLAY_FLAGS_HSYNC_HIGH)) |
+		V_DSP_VSYNC_POL(!!(edid->flags & DISPLAY_FLAGS_VSYNC_HIGH));
+
+	clrsetbits_le32(&regs->dsp_ctrl0,
+			M_DSP_OUT_MODE | M_DSP_VSYNC_POL | M_DSP_HSYNC_POL,
+			flags);
+
+	writel(V_HSYNC(hsync_len) |
+	       V_HORPRD(hsync_len + hback_porch + hactive + hfront_porch),
+			&regs->dsp_htotal_hs_end);
+
+	writel(V_HEAP(hsync_len + hback_porch + hactive) |
+	       V_HASP(hsync_len + hback_porch),
+	       &regs->dsp_hact_st_end);
+
+	writel(V_VSYNC(vsync_len) |
+	       V_VERPRD(vsync_len + vback_porch + vactive + vfront_porch),
+	       &regs->dsp_vtotal_vs_end);
+
+	writel(V_VAEP(vsync_len + vback_porch + vactive)|
+	       V_VASP(vsync_len + vback_porch),
+	       &regs->dsp_vact_st_end);
+
+	writel(V_HEAP(hsync_len + hback_porch + hactive) |
+	       V_HASP(hsync_len + hback_porch),
+	       &regs->post_dsp_hact_info);
+
+	writel(V_VAEP(vsync_len + vback_porch + vactive)|
+	       V_VASP(vsync_len + vback_porch),
+	       &regs->post_dsp_vact_info);
+
+	writel(0x01, &regs->reg_cfg_done); /* enable reg config */
+}
+
+/**
+ * rk_display_init() - Try to enable the given display device
+ *
+ * This function performs many steps:
+ * - Finds the display device being referenced by @ep_node
+ * - Puts the VOP's ID into its uclass platform data
+ * - Probes the device to set it up
+ * - Reads the EDID timing information
+ * - Sets up the VOP clocks, etc. for the selected pixel clock and display mode
+ * - Enables the display (the display device handles this and will do different
+ *     things depending on the display type)
+ * - Tells the uclass about the display resolution so that the console will
+ *     appear correctly
+ *
+ * @dev:	VOP device that we want to connect to the display
+ * @fbbase:	Frame buffer address
+ * @l2bpp	Log2 of bits-per-pixels for the display
+ * @ep_node:	Device tree node to process - this is the offset of an endpoint
+ *		node within the VOP's 'port' list.
+ * @return 0 if OK, -ve if something went wrong
+ */
+int rk_display_init(struct udevice *dev, ulong fbbase,
+		    enum video_log2_bpp l2bpp, int ep_node)
+{
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	const void *blob = gd->fdt_blob;
+	struct rk_vop_priv *priv = dev_get_priv(dev);
+	int vop_id, remote_vop_id;
+	struct rk3288_vop *regs = priv->regs;
+	struct display_timing timing;
+	struct udevice *disp;
+	int ret, remote, i, offset;
+	struct display_plat *disp_uc_plat;
+	struct udevice *clk;
+
+	vop_id = fdtdec_get_int(blob, ep_node, "reg", -1);
+	debug("vop_id=%d\n", vop_id);
+	remote = fdtdec_lookup_phandle(blob, ep_node, "remote-endpoint");
+	if (remote < 0)
+		return -EINVAL;
+	remote_vop_id = fdtdec_get_int(blob, remote, "reg", -1);
+	debug("remote vop_id=%d\n", remote_vop_id);
+
+	for (i = 0, offset = remote; i < 3 && offset > 0; i++)
+		offset = fdt_parent_offset(blob, offset);
+	if (offset < 0) {
+		debug("%s: Invalid remote-endpoint position\n", dev->name);
+		return -EINVAL;
+	}
+
+	ret = uclass_find_device_by_of_offset(UCLASS_DISPLAY, offset, &disp);
+	if (ret) {
+		debug("%s: device '%s' display not found (ret=%d)\n", __func__,
+		      dev->name, ret);
+		return ret;
+	}
+
+	disp_uc_plat = dev_get_uclass_platdata(disp);
+	debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
+	disp_uc_plat->source_id = remote_vop_id;
+	disp_uc_plat->src_dev = dev;
+
+	ret = device_probe(disp);
+	if (ret) {
+		debug("%s: device '%s' display won't probe (ret=%d)\n",
+		      __func__, dev->name, ret);
+		return ret;
+	}
+
+	ret = display_read_timing(disp, &timing);
+	if (ret) {
+		debug("%s: Failed to read timings\n", __func__);
+		return ret;
+	}
+
+	ret = rkclk_get_clk(CLK_NEW, &clk);
+	if (!ret) {
+		ret = clk_set_periph_rate(clk, DCLK_VOP0 + vop_id,
+					  timing.pixelclock.typ);
+	}
+	if (ret) {
+		debug("%s: Failed to set pixel clock: ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	rkvop_mode_set(regs, &timing, vop_id);
+
+	rkvop_enable(regs, fbbase, 1 << l2bpp, &timing);
+
+	ret = display_enable(disp, 1 << l2bpp, &timing);
+	if (ret)
+		return ret;
+
+	uc_priv->xsize = timing.hactive.typ;
+	uc_priv->ysize = timing.vactive.typ;
+	uc_priv->bpix = l2bpp;
+	debug("fb=%lx, size=%d %d\n", fbbase, uc_priv->xsize, uc_priv->ysize);
+
+	return 0;
+}
+
+static int rk_vop_probe(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+	const void *blob = gd->fdt_blob;
+	struct rk_vop_priv *priv = dev_get_priv(dev);
+	struct udevice *reg;
+	int ret, port, node;
+
+	/* Before relocation we don't need to do anything */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return 0;
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	priv->regs = (struct rk3288_vop *)dev_get_addr(dev);
+
+	/* lcdc(vop) iodomain select 1.8V */
+	rk_setreg(&priv->grf->io_vsel, 1 << 0);
+
+	/*
+	 * Try some common regulators. We should really get these from the
+	 * device tree somehow.
+	 */
+	ret = regulator_autoset_by_name("vcc18_lcd", &reg);
+	if (ret)
+		debug("%s: Cannot autoset regulator vcc18_lcd\n", __func__);
+	ret = regulator_autoset_by_name("VCC18_LCD", &reg);
+	if (ret)
+		debug("%s: Cannot autoset regulator VCC18_LCD\n", __func__);
+	ret = regulator_autoset_by_name("vdd10_lcd_pwren_h", &reg);
+	if (ret) {
+		debug("%s: Cannot autoset regulator vdd10_lcd_pwren_h\n",
+		      __func__);
+	}
+	ret = regulator_autoset_by_name("vdd10_lcd", &reg);
+	if (ret) {
+		debug("%s: Cannot autoset regulator vdd10_lcd\n",
+		      __func__);
+	}
+	ret = regulator_autoset_by_name("VDD10_LCD", &reg);
+	if (ret) {
+		debug("%s: Cannot autoset regulator VDD10_LCD\n",
+		      __func__);
+	}
+	ret = regulator_autoset_by_name("vcc33_lcd", &reg);
+	if (ret)
+		debug("%s: Cannot autoset regulator vcc33_lcd\n", __func__);
+
+	/*
+	 * Try all the ports until we find one that works. In practice this
+	 * tries EDP first if available, then HDMI.
+	 */
+	port = fdt_subnode_offset(blob, dev->of_offset, "port");
+	if (port < 0)
+		return -EINVAL;
+	for (node = fdt_first_subnode(blob, port);
+	     node > 0;
+	     node = fdt_next_subnode(blob, node)) {
+		ret = rk_display_init(dev, plat->base, VIDEO_BPP16, node);
+		if (ret)
+			debug("Device failed: ret=%d\n", ret);
+		if (!ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int rk_vop_bind(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+	plat->size = 1920 * 1080 * 2;
+
+	return 0;
+}
+
+static const struct video_ops rk_vop_ops = {
+};
+
+static const struct udevice_id rk_vop_ids[] = {
+	{ .compatible = "rockchip,rk3288-vop" },
+	{ }
+};
+
+U_BOOT_DRIVER(rk_vop) = {
+	.name	= "rk_vop",
+	.id	= UCLASS_VIDEO,
+	.of_match = rk_vop_ids,
+	.ops	= &rk_vop_ops,
+	.bind	= rk_vop_bind,
+	.probe	= rk_vop_probe,
+	.priv_auto_alloc_size	= sizeof(struct rk_vop_priv),
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 18/37] rockchip: Don't skip low-level init
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (16 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 17/37] rockchip: video: Add a video-output driver Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 19/37] rockchip: Add a simple 'clock' command Simon Glass
                   ` (19 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

At present the low-level init is skipped on rockchip. Among other things
this means that the instruction cache is left disabled. Fix this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/mach-rockchip/board.c            | 4 ++++
 arch/arm/mach-rockchip/rk3288-board-spl.c | 4 ++++
 include/configs/rk3288_common.h           | 1 -
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index f026abf..380aa91 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -45,3 +45,7 @@ void enable_caches(void)
 	dcache_enable();
 }
 #endif
+
+void lowlevel_init(void)
+{
+}
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index b2c5729..f61eeab 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -270,3 +270,7 @@ err:
 	/* No way to report error here */
 	hang();
 }
+
+void lowlevel_init(void)
+{
+}
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index ebddfb0..b9ff5a5 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -16,7 +16,6 @@
 #define CONFIG_BAUDRATE			115200
 #define CONFIG_SYS_MALLOC_LEN		(32 << 20)
 #define CONFIG_SYS_CBSIZE		1024
-#define CONFIG_SKIP_LOWLEVEL_INIT
 #define CONFIG_SYS_THUMB_BUILD
 #define CONFIG_OF_LIBFDT
 #define CONFIG_DISPLAY_BOARDINFO
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 19/37] rockchip: Add a simple 'clock' command
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (17 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 18/37] rockchip: Don't skip low-level init Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 20/37] rockchip: Add a script to parse datasheets Simon Glass
                   ` (18 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Add a command that displays the PLLs and their current rate.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/mach-rockchip/board.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index 380aa91..133d663 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <ram.h>
 #include <asm/io.h>
@@ -49,3 +50,26 @@ void enable_caches(void)
 void lowlevel_init(void)
 {
 }
+
+static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
+		       char * const argv[])
+{
+	struct udevice *dev;
+
+	for (uclass_first_device(UCLASS_CLK, &dev);
+	     dev;
+	     uclass_next_device(&dev)) {
+		ulong rate;
+
+		rate = clk_get_rate(dev);
+		printf("%s: %lu\n", dev->name, rate);
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	clock, 2, 1, do_clock,
+	"display information about clocks",
+	""
+);
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 20/37] rockchip: Add a script to parse datasheets
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (18 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 19/37] rockchip: Add a simple 'clock' command Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 21/37] rockchip: config: Enable the 'gpio' command Simon Glass
                   ` (17 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

This script has proved useful for parsing datasheets and creating register
shift/mask values for use in header files. Include it in case it is useful
for others.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/README.rockchip |   6 ++
 tools/rkmux.py      | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 224 insertions(+)
 create mode 100755 tools/rkmux.py

diff --git a/doc/README.rockchip b/doc/README.rockchip
index 9a2ebca..7be5a13 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -243,6 +243,12 @@ SPI flash.
 
 See above for instructions on how to write a SPI image.
 
+rkmux.py
+--------
+
+You can use this script to create #defines for SoC register access. See the
+script for usage.
+
 
 Device tree and driver model
 ----------------------------
diff --git a/tools/rkmux.py b/tools/rkmux.py
new file mode 100755
index 0000000..3917335
--- /dev/null
+++ b/tools/rkmux.py
@@ -0,0 +1,218 @@
+#!/usr/bin/python
+
+# Script to create enums from datasheet register tables
+#
+# Usage:
+#
+# First, create a text file from the datasheet:
+#    pdftotext -layout /path/to/rockchip-3288-trm.pdf /tmp/asc
+#
+# Then use this script to output the #defines for a particular register:
+#    ./tools/rkmux.py GRF_GPIO4C_IOMUX
+#
+# It will create output suitable for putting in a header file, with SHIFT and
+# MASK values for each bitfield in the register.
+#
+# Note: this tool is not perfect and you may need to edit the resulting code.
+# But it should speed up the process.
+
+import csv
+import re
+import sys
+
+tab_to_col = 3
+
+class RegField:
+    def __init__(self, cols=None):
+        if cols:
+            self.bits, self.attr, self.reset_val, self.desc = (
+                [x.strip() for x in cols])
+            self.desc = [self.desc]
+        else:
+            self.bits = ''
+            self.attr = ''
+            self.reset_val = ''
+            self.desc = []
+
+    def Setup(self, cols):
+        self.bits, self.attr, self.reset_val = cols[0:3]
+        if len(cols) > 3:
+            self.desc.append(cols[3])
+
+    def AddDesc(self, desc):
+        self.desc.append(desc)
+
+    def Show(self):
+        print self
+        print
+        self.__init__()
+
+    def __str__(self):
+        return '%s,%s,%s,%s' % (self.bits, self.attr, self.reset_val,
+                                '\n'.join(self.desc))
+
+class Printer:
+    def __init__(self, name):
+        self.first = True
+        self.name = name
+        self.re_sel = re.compile("[1-9]'b([01]+): (.*)")
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        if not self.first:
+            self.output_footer()
+
+    def output_header(self):
+        print '/* %s */' % self.name
+        print 'enum {'
+
+    def output_footer(self):
+        print '};';
+
+    def output_regfield(self, regfield):
+        lines = regfield.desc
+        field = lines[0]
+        #print 'field:', field
+        if field in ['reserved', 'reserve', 'write_enable', 'write_mask']:
+            return
+        if field.endswith('_sel') or field.endswith('_con'):
+            field = field[:-4]
+        elif field.endswith(' iomux'):
+            field = field[:-6]
+        elif field.endswith('_mode') or field.endswith('_mask'):
+            field = field[:-5]
+        #else:
+            #print 'bad field %s' % field
+            #return
+        field = field.upper()
+        if ':' in regfield.bits:
+            bit_high, bit_low = [int(x) for x in regfield.bits.split(':')]
+        else:
+            bit_high = bit_low = int(regfield.bits)
+        bit_width = bit_high - bit_low + 1
+        mask = (1 << bit_width) - 1
+        if self.first:
+            self.first = False
+            self.output_header()
+        else:
+            print
+        out_enum(field, 'shift', bit_low)
+        out_enum(field, 'mask', mask)
+        next_val = -1
+        #print 'lines: %s', lines
+        for line in lines:
+            m = self.re_sel.match(line)
+            if m:
+                val, enum = int(m.group(1), 2), m.group(2)
+                if enum not in ['reserved', 'reserve']:
+                    out_enum(field, enum, val, val == next_val)
+                    next_val = val + 1
+
+
+def process_file(name, fd):
+    field = RegField()
+    reg = ''
+
+    fields = []
+
+    def add_it(field):
+        if field.bits:
+            if reg == name:
+                fields.append(field)
+            field = RegField()
+        return field
+
+    def is_field_start(line):
+       if '=' in line or '+' in line:
+           return False
+       if (line.startswith('gpio') or line.startswith('peri_') or
+                line.endswith('_sel') or line.endswith('_con')):
+           return True
+       if not ' ' in line: # and '_' in line:
+           return True
+       return False
+
+    for line in fd:
+        line = line.rstrip()
+        if line[:4] in ['GRF_', 'PMU_', 'CRU_']:
+            field = add_it(field)
+            reg = line
+            do_this = name == reg
+        elif not line or not line.startswith(' '):
+            continue
+        line = line.replace('\xe2\x80\x99', "'")
+        leading = len(line) - len(line.lstrip())
+        line = line.lstrip()
+        cols = re.split(' *', line, 3)
+        if leading > 15 or (len(cols) > 3 and is_field_start(cols[3])):
+            if is_field_start(line):
+                field = add_it(field)
+            field.AddDesc(line)
+        else:
+            if cols[0] == 'Bit' or len(cols) < 3:
+                continue
+            #print
+            #print field
+            field = add_it(field)
+            field.Setup(cols)
+    field = add_it(field)
+
+    with Printer(name) as printer:
+        for field in fields:
+            #print field
+            printer.output_regfield(field)
+            #print
+
+def out_enum(field, suffix, value, skip_val=False):
+    str = '%s_%s' % (field.upper(), suffix.upper())
+    if not skip_val:
+        tabs = tab_to_col - len(str) / 8
+        if value > 9:
+            val_str = '%#x' % value
+        else:
+            val_str = '%d' % value
+
+        str += '%s= %s' % ('\t' * tabs, val_str)
+    print '\t%s,' % str
+
+# Process a CSV file, e.g. from tabula
+def process_csv(name, fd):
+    reader = csv.reader(fd)
+
+    rows = []
+
+    field = RegField()
+    for row in reader:
+        #print field.desc
+        if not row[0]:
+            field.desc.append(row[3])
+            continue
+        if field.bits:
+            if field.bits != 'Bit':
+                rows.append(field)
+        #print row
+        field = RegField(row)
+
+    with Printer(name) as printer:
+        for row in rows:
+            #print field
+            printer.output_regfield(row)
+            #print
+
+fname = sys.argv[1]
+name = sys.argv[2]
+
+# Read output from pdftotext -layout
+if 1:
+    with open(fname, 'r') as fd:
+        process_file(name, fd)
+
+# Use tabula
+# It seems to be better at outputting text for an entire cell in one cell.
+# But it does not always work. E.g. GRF_GPIO7CH_IOMUX.
+# So there is no point in using it.
+if 0:
+    with open(fname, 'r') as fd:
+        process_csv(name, fd)
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 21/37] rockchip: config: Enable the 'gpio' command
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (19 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 20/37] rockchip: Add a script to parse datasheets Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 22/37] rockchip: sdram: Tidy up a few comments Simon Glass
                   ` (16 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Now that we have a pretty good GPIO driver, enable the 'gpio' command on all
rockchip boards.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/configs/rk3288_common.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index b9ff5a5..ebf1ab0 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -79,6 +79,7 @@
 
 #define CONFIG_CMD_CACHE
 #define CONFIG_CMD_TIME
+#define CONFIG_CMD_GPIO
 
 #define CONFIG_SYS_SDRAM_BASE		0
 #define CONFIG_NR_DRAM_BANKS		1
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 22/37] rockchip: sdram: Tidy up a few comments
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (20 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 21/37] rockchip: config: Enable the 'gpio' command Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 23/37] rockchip: sdram: Use syscon_get_first_range() where possible Simon Glass
                   ` (15 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Fix spaces in two comments in this file.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/mach-rockchip/rk3288/sdram_rk3288.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index 5da04b9..2a43574 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -405,7 +405,7 @@ static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
 		/* Data Byte disable*/
 		clrbits_le32(&publ->datx8[2].dxgcr, 1);
 		clrbits_le32(&publ->datx8[3].dxgcr, 1);
-		/*disable DLL */
+		/* disable DLL */
 		setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
 		setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
 	} else {
@@ -416,7 +416,7 @@ static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
 		setbits_le32(&publ->datx8[2].dxgcr, 1);
 		setbits_le32(&publ->datx8[3].dxgcr, 1);
 
-		/*enable DLL */
+		/* enable DLL */
 		clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
 		clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
 		/* reset DLL */
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 23/37] rockchip: sdram: Use syscon_get_first_range() where possible
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (21 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 22/37] rockchip: sdram: Tidy up a few comments Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 24/37] rockchip: Tidy up the register-access macros Simon Glass
                   ` (14 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

This is a shortcut to obtaining a register address. Use it where possible, to
simplify the code.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/mach-rockchip/rk3288/sdram_rk3288.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index 2a43574..074cf518 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -808,20 +808,9 @@ static int rk3288_dmc_probe(struct udevice *dev)
 	priv->chan[1].msch = (struct rk3288_msch *)
 			(regmap_get_range(map, 0) + 0x80);
 
-	map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_GRF);
-	if (IS_ERR(map))
-		return PTR_ERR(map);
-	priv->grf = regmap_get_range(map, 0);
-
-	map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_SGRF);
-	if (IS_ERR(map))
-		return PTR_ERR(map);
-	priv->sgrf = regmap_get_range(map, 0);
-
-	map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_PMU);
-	if (IS_ERR(map))
-		return PTR_ERR(map);
-	priv->pmu = regmap_get_range(map, 0);
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	priv->sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
+	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
 
 	ret = regmap_init_mem(dev, &map);
 	if (ret)
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 24/37] rockchip: Tidy up the register-access macros
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (22 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 23/37] rockchip: sdram: Use syscon_get_first_range() where possible Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 25/37] rockchip: spl: Drop MMC support code when not needed Simon Glass
                   ` (13 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

These work reasonable well, but there are a few errors:

- Brackets should be used to avoid unexpected side-effects
- When setting bits, the corresponding upper 16 bits should be set also

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/arch-rockchip/hardware.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/hardware.h b/arch/arm/include/asm/arch-rockchip/hardware.h
index d5af5b8..08a66ef 100644
--- a/arch/arm/include/asm/arch-rockchip/hardware.h
+++ b/arch/arm/include/asm/arch-rockchip/hardware.h
@@ -7,14 +7,15 @@
 #ifndef _ASM_ARCH_HARDWARE_H
 #define _ASM_ARCH_HARDWARE_H
 
-#define RK_CLRSETBITS(clr, set)		((((clr) | (set)) << 16) | set)
+#define RK_CLRSETBITS(clr, set)		((((clr) | (set)) << 16) | (set))
 #define RK_SETBITS(set)			RK_CLRSETBITS(0, set)
 #define RK_CLRBITS(clr)			RK_CLRSETBITS(clr, 0)
 
 #define TIMER7_BASE		0xff810020
 
-#define rk_clrsetreg(addr, clr, set)	writel((clr) << 16 | (set), addr)
+#define rk_clrsetreg(addr, clr, set)	\
+				writel(((clr) | (set)) << 16 | (set), addr)
 #define rk_clrreg(addr, clr)		writel((clr) << 16, addr)
-#define rk_setreg(addr, set)		writel(set, addr)
+#define rk_setreg(addr, set)		writel((set) << 16 | (set), addr)
 
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 25/37] rockchip: spl: Drop MMC support code when not needed
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (23 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 24/37] rockchip: Tidy up the register-access macros Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 26/37] rockchip: jerry: Fix the SDRAM timing Simon Glass
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

When the board does not use MMC SPL this code is a waste of space. Drop it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/mach-rockchip/rk3288-board-spl.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index f61eeab..9fdd37d 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -111,9 +111,9 @@ static void configure_l2ctlr(void)
 	write_l2ctlr(l2ctlr);
 }
 
+#ifdef CONFIG_SPL_MMC_SUPPORT
 static int configure_emmc(struct udevice *pinctrl)
 {
-#ifdef CONFIG_SPL_MMC_SUPPORT
 	struct gpio_desc desc;
 	int ret;
 
@@ -143,10 +143,10 @@ static int configure_emmc(struct udevice *pinctrl)
 		debug("gpio value ret=%d\n", ret);
 		return ret;
 	}
-#endif
 
 	return 0;
 }
+#endif
 
 void board_init_f(ulong dummy)
 {
@@ -244,6 +244,7 @@ void spl_board_init(void)
 		debug("%s: Cannot find pinctrl device\n", __func__);
 		goto err;
 	}
+#ifdef CONFIG_SPL_MMC_SUPPORT
 	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
 	if (ret) {
 		debug("%s: Failed to set up SD card\n", __func__);
@@ -254,6 +255,7 @@ void spl_board_init(void)
 		debug("%s: Failed to set up eMMC\n", __func__);
 		goto err;
 	}
+#endif
 
 	/* Enable debug UART */
 	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 26/37] rockchip: jerry: Fix the SDRAM timing
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (24 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 25/37] rockchip: spl: Drop MMC support code when not needed Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 27/37] rockchip: rk3288: clock: Fix various minor errors Simon Glass
                   ` (11 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

There is a minor error in the SDRAM timing. It does not seem to affect
anything so far. Fix it just in case.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/rk3288-veyron.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
index a31e00e..c201e85 100644
--- a/arch/arm/dts/rk3288-veyron.dtsi
+++ b/arch/arm/dts/rk3288-veyron.dtsi
@@ -246,7 +246,7 @@
 		666000 1200000
 	>;
 	rockchip,num-channels = <2>;
-	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
+	rockchip,pctl-timing = <0x29a 0xc8 0x1f4 0x42 0x4e 0x4 0xea 0xa
 		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
 		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
 		0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 27/37] rockchip: rk3288: clock: Fix various minor errors
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (25 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 26/37] rockchip: jerry: Fix the SDRAM timing Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 28/37] rockchip: rk3288: pinctrl: Fix HDMI pinctrl Simon Glass
                   ` (10 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Fix a number of small errors which were found in reviewing the clock code.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/clk/clk_rk3288.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
index 42d2f85..79951b6 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/clk_rk3288.c
@@ -83,8 +83,13 @@ enum {
 	 * peripheral bus pclk div:
 	 * aclk_bus: pclk_bus = 1:1 or 2:1 or 4:1 or 8:1
 	 */
+	PERI_SEL_PLL_MASK	 = 1,
+	PERI_SEL_PLL_SHIFT	 = 15,
+	PERI_SEL_CPLL		= 0,
+	PERI_SEL_GPLL,
+
 	PERI_PCLK_DIV_SHIFT	= 12,
-	PERI_PCLK_DIV_MASK	= 7,
+	PERI_PCLK_DIV_MASK	= 3,
 
 	/* peripheral bus hclk div: aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 */
 	PERI_HCLK_DIV_SHIFT	= 8,
@@ -160,13 +165,13 @@ static int rkclk_set_pll(struct rk3288_cru *cru, enum rk_clk_id clk_id,
 	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
 	uint output_hz = vco_hz / div->no;
 
-	debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
-	      pll, div->nf, div->nr, div->no, vco_hz, output_hz);
+	debug("PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
+	      (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
 	       (div->no == 1 || !(div->no % 2)));
 
-	/* enter rest */
+	/* enter reset */
 	rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT);
 
 	rk_clrsetreg(&pll->con0,
@@ -177,7 +182,7 @@ static int rkclk_set_pll(struct rk3288_cru *cru, enum rk_clk_id clk_id,
 
 	udelay(10);
 
-	/* return form rest */
+	/* return from reset */
 	rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);
 
 	return 0;
@@ -199,7 +204,6 @@ static int rkclk_configure_ddr(struct rk3288_cru *cru, struct rk3288_grf *grf,
 	};
 	int cfg;
 
-	debug("%s: cru=%p, grf=%p, hz=%u\n", __func__, cru, grf, hz);
 	switch (hz) {
 	case 300000000:
 		cfg = 0;
@@ -214,7 +218,7 @@ static int rkclk_configure_ddr(struct rk3288_cru *cru, struct rk3288_grf *grf,
 		cfg = 3;
 		break;
 	default:
-		debug("Unsupported SDRAM frequency, add to clock.c!");
+		debug("Unsupported SDRAM frequency");
 		return -EINVAL;
 	}
 
@@ -420,6 +424,7 @@ static void rkclk_init(struct rk3288_cru *cru, struct rk3288_grf *grf)
 		     PERI_PCLK_DIV_MASK << PERI_PCLK_DIV_SHIFT |
 		     PERI_HCLK_DIV_MASK << PERI_HCLK_DIV_SHIFT |
 		     PERI_ACLK_DIV_MASK << PERI_ACLK_DIV_SHIFT,
+		     PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT |
 		     pclk_div << PERI_PCLK_DIV_SHIFT |
 		     hclk_div << PERI_HCLK_DIV_SHIFT |
 		     aclk_div << PERI_ACLK_DIV_SHIFT);
@@ -787,7 +792,7 @@ static const char *const clk_name[CLK_COUNT] = {
 	"dpll",
 	"cpll",
 	"gpll",
-	"mpll",
+	"npll",
 };
 
 static int rk3288_clk_bind(struct udevice *dev)
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 28/37] rockchip: rk3288: pinctrl: Fix HDMI pinctrl
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (26 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 27/37] rockchip: rk3288: clock: Fix various minor errors Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 29/37] rockchip: spl: Support full-speed CPU in SPL Simon Glass
                   ` (9 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Since the device tree does not specify the EDID pinctrl option for HDMI we
must set it manually. Fix the driver to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/pinctrl/rockchip/pinctrl_rk3288.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
index 8356786..7c769bd 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
@@ -503,6 +503,8 @@ static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
 		return PERIPH_ID_I2C4;
 	case 65:
 		return PERIPH_ID_I2C5;
+	case 103:
+		return PERIPH_ID_HDMI;
 	}
 
 	return -ENOENT;
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 29/37] rockchip: spl: Support full-speed CPU in SPL
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (27 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 28/37] rockchip: rk3288: pinctrl: Fix HDMI pinctrl Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 30/37] rockchip: jerry: Add support for timing SPI flash speed Simon Glass
                   ` (8 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Add a feature which speeds up the CPU to full speed in SPL to minimise
boot time. This is only supported for certain boards (at present only
jerry).

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/rk3288-veyron.dtsi                 |  2 +
 arch/arm/include/asm/arch-rockchip/clock.h      |  5 +++
 arch/arm/include/asm/arch-rockchip/cru_rk3288.h | 12 ++++++
 arch/arm/mach-rockchip/rk3288/Kconfig           |  9 ++++
 arch/arm/mach-rockchip/rk3288/sdram_rk3288.c    | 36 ++++++++++++++++
 configs/chromebook_jerry_defconfig              |  1 +
 drivers/clk/clk_rk3288.c                        | 56 +++++++++++++++++++++++++
 include/configs/chromebook_jerry.h              |  3 ++
 8 files changed, 124 insertions(+)

diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
index c201e85..421d212 100644
--- a/arch/arm/dts/rk3288-veyron.dtsi
+++ b/arch/arm/dts/rk3288-veyron.dtsi
@@ -332,6 +332,7 @@
 	clock-frequency = <400000>;
 	i2c-scl-falling-time-ns = <50>;		/* 2.5ns measured */
 	i2c-scl-rising-time-ns = <100>;		/* 45ns measured */
+	u-boot,dm-pre-reloc;
 
 	rk808: pmic at 1b {
 		compatible = "rockchip,rk808";
@@ -344,6 +345,7 @@
 		rockchip,system-power-controller;
 		wakeup-source;
 		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
 
 		vcc1-supply = <&vcc33_sys>;
 		vcc2-supply = <&vcc33_sys>;
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index a9ea268..d66b26f 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -74,4 +74,9 @@ void *rockchip_get_cru(void);
  */
 int rkclk_get_clk(enum rk_clk_id clk_id, struct udevice **devp);
 
+struct rk3288_cru;
+struct rk3288_grf;
+
+void rkclk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf);
+
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
index b0dea70..d2690c7 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
@@ -109,6 +109,18 @@ enum {
 	SPI0_DIV_MASK		= 0x7f,
 };
 
+/* CRU_CLKSEL37_CON */
+enum {
+	PCLK_CORE_DBG_DIV_SHIFT	= 9,
+	PCLK_CORE_DBG_DIV_MASK	= 0x1f,
+
+	ATCLK_CORE_DIV_CON_SHIFT = 4,
+	ATCLK_CORE_DIV_CON_MASK	= 0x1f,
+
+	CLK_L2RAM_DIV_SHIFT	= 0,
+	CLK_L2RAM_DIV_MASK	= 7,
+};
+
 /* CRU_CLKSEL39_CON */
 enum {
 	ACLK_HEVC_PLL_SHIFT	= 0xe,
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
index d0a7276..ed89c3e 100644
--- a/arch/arm/mach-rockchip/rk3288/Kconfig
+++ b/arch/arm/mach-rockchip/rk3288/Kconfig
@@ -16,6 +16,15 @@ config TARGET_CHROMEBOOK_JERRY
 	  WiFi. It includes a Chrome OS EC (Cortex-M3) to provide access to
 	  the keyboard and battery functions.
 
+config ROCKCHIP_FAST_SPL
+	bool "Change the CPU to full speed in SPL"
+	depends on TARGET_CHROMEBOOK_JERRY
+	help
+	  Some boards want to boot as fast as possible. We can increase the
+	  CPU frequency in SPL if the power supply is configured to the correct
+	  voltage. This option is only available on boards which support it
+	  and have the required PMIC code.
+
 config SYS_SOC
 	default "rockchip"
 
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index 074cf518..e9e2211 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -22,6 +22,8 @@
 #include <asm/arch/pmu_rk3288.h>
 #include <asm/arch/sdram.h>
 #include <linux/err.h>
+#include <power/regulator.h>
+#include <power/rk808_pmic.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -748,6 +750,32 @@ size_t sdram_size_mb(struct rk3288_pmu *pmu)
 }
 
 #ifdef CONFIG_SPL_BUILD
+# ifdef CONFIG_ROCKCHIP_FAST_SPL
+static int veyron_init(struct dram_info *priv)
+{
+	struct udevice *pmic;
+	int ret;
+
+	ret = uclass_first_device(UCLASS_PMIC, &pmic);
+	if (ret)
+		return ret;
+
+	/* Slowly raise to max CPU voltage to prevent overshoot */
+	ret = rk808_spl_configure_buck(pmic, 1, 1200000);
+	if (ret)
+		return ret;
+	udelay(175);/* Must wait for voltage to stabilize, 2mV/us */
+	ret = rk808_spl_configure_buck(pmic, 1, 1400000);
+	if (ret)
+		return ret;
+	udelay(100);/* Must wait for voltage to stabilize, 2mV/us */
+
+	rkclk_configure_cpu(priv->cru, priv->grf);
+
+	return 0;
+}
+# endif
+
 static int setup_sdram(struct udevice *dev)
 {
 	struct dram_info *priv = dev_get_priv(dev);
@@ -791,6 +819,14 @@ static int setup_sdram(struct udevice *dev)
 		return -EINVAL;
 	}
 
+# ifdef CONFIG_ROCKCHIP_FAST_SPL
+	if (!fdt_node_check_compatible(blob, 0, "google,veyron")) {
+		ret = veyron_init(priv);
+		if (ret)
+			return ret;
+	}
+# endif
+
 	return sdram_init(priv, &params);
 }
 #endif
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index b2672b8..526306f 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -3,6 +3,7 @@ CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_TARGET_CHROMEBOOK_JERRY=y
+CONFIG_ROCKCHIP_FAST_SPL=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DM_KEYBOARD=y
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-jerry"
diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
index 79951b6..3e376b4 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/clk_rk3288.c
@@ -59,6 +59,16 @@ enum {
 	/* PLL CON3 */
 	PLL_RESET_SHIFT		= 5,
 
+	/* CLKSEL0 */
+	CORE_SEL_PLL_MASK	= 1,
+	CORE_SEL_PLL_SHIFT	= 15,
+	A17_DIV_MASK		= 0x1f,
+	A17_DIV_SHIFT		= 8,
+	MP_DIV_MASK		= 0xf,
+	MP_DIV_SHIFT		= 4,
+	M0_DIV_MASK		= 0xf,
+	M0_DIV_SHIFT		= 0,
+
 	/* CLKSEL1: pd bus clk pll sel: codec or general */
 	PD_BUS_SEL_PLL_MASK	= 15,
 	PD_BUS_SEL_CPLL		= 0,
@@ -438,6 +448,52 @@ static void rkclk_init(struct rk3288_cru *cru, struct rk3288_grf *grf)
 }
 #endif
 
+void rkclk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf)
+{
+	/* pll enter slow-mode */
+	rk_clrsetreg(&cru->cru_mode_con,
+		     APLL_MODE_MASK << APLL_MODE_SHIFT,
+		     APLL_MODE_SLOW << APLL_MODE_SHIFT);
+
+	rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
+
+	/* waiting for pll lock */
+	while (!(readl(&grf->soc_status[1]) & SOCSTS_APLL_LOCK))
+		udelay(1);
+
+	/*
+	 * core clock pll source selection and
+	 * set up dependent divisors for MPAXI/M0AXI and ARM clocks.
+	 * core clock select apll, apll clk = 1800MHz
+	 * arm clk = 1800MHz, mpclk = 450MHz, m0clk = 900MHz
+	 */
+	rk_clrsetreg(&cru->cru_clksel_con[0],
+		     CORE_SEL_PLL_MASK << CORE_SEL_PLL_SHIFT |
+		     A17_DIV_MASK << A17_DIV_SHIFT |
+		     MP_DIV_MASK << MP_DIV_SHIFT |
+		     M0_DIV_MASK << M0_DIV_SHIFT,
+		     0 << A17_DIV_SHIFT |
+		     3 << MP_DIV_SHIFT |
+		     1 << M0_DIV_SHIFT);
+
+	/*
+	 * set up dependent divisors for L2RAM/ATCLK and PCLK clocks.
+	 * l2ramclk = 900MHz, atclk = 450MHz, pclk_dbg = 450MHz
+	 */
+	rk_clrsetreg(&cru->cru_clksel_con[37],
+		     CLK_L2RAM_DIV_MASK << CLK_L2RAM_DIV_SHIFT |
+		     ATCLK_CORE_DIV_CON_MASK << ATCLK_CORE_DIV_CON_SHIFT |
+		     PCLK_CORE_DBG_DIV_MASK >> PCLK_CORE_DBG_DIV_SHIFT,
+		     1 << CLK_L2RAM_DIV_SHIFT |
+		     3 << ATCLK_CORE_DIV_CON_SHIFT |
+		     3 << PCLK_CORE_DBG_DIV_SHIFT);
+
+	/* PLL enter normal-mode */
+	rk_clrsetreg(&cru->cru_mode_con,
+		     APLL_MODE_MASK << APLL_MODE_SHIFT,
+		     APLL_MODE_NORMAL << APLL_MODE_SHIFT);
+}
+
 /* Get pll rate by id */
 static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru,
 				   enum rk_clk_id clk_id)
diff --git a/include/configs/chromebook_jerry.h b/include/configs/chromebook_jerry.h
index 6e32f2c..e07d057 100644
--- a/include/configs/chromebook_jerry.h
+++ b/include/configs/chromebook_jerry.h
@@ -24,4 +24,7 @@
 
 #define CONFIG_KEYBOARD
 
+#define CONFIG_SPL_POWER_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 30/37] rockchip: jerry: Add support for timing SPI flash speed
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (28 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 29/37] rockchip: spl: Support full-speed CPU in SPL Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 31/37] rockchip: jerry: Enable EDP and HDMI video output Simon Glass
                   ` (7 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Add the 'time' and 'sf test' commands so that we can test SPI flash
performance.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/configs/chromebook_jerry.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/configs/chromebook_jerry.h b/include/configs/chromebook_jerry.h
index e07d057..2a0dad4 100644
--- a/include/configs/chromebook_jerry.h
+++ b/include/configs/chromebook_jerry.h
@@ -20,6 +20,9 @@
 #define CONFIG_SPL_SPI_LOAD
 #define CONFIG_SPI_FLASH_GIGADEVICE
 
+#define CONFIG_CMD_SF_TEST
+#define CONFIG_CMD_TIME
+
 #undef CONFIG_SPL_GPIO_SUPPORT
 
 #define CONFIG_KEYBOARD
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 31/37] rockchip: jerry: Enable EDP and HDMI video output
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (29 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 30/37] rockchip: jerry: Add support for timing SPI flash speed Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 32/37] rockchip: firefly-rk3288: Enable HDMI output Simon Glass
                   ` (6 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Enable these devices using the VOPL video output device. We explicitly
disable VOPB in the device tree to avoid it taking over. Since this device
has an LCD display this comes up by default. If the display fails for some
reason then it will attempt to use HDMI. It is possible to force it to fail
(and thus fall back to HDMI) by puting 'return -EPERM' at the top of
rk_edp_probe(). For now there is no easy way to select between the two.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/rk3288-jerry.dts      | 5 +++++
 arch/arm/dts/rk3288.dtsi           | 1 +
 configs/chromebook_jerry_defconfig | 6 ++++++
 include/configs/chromebook_jerry.h | 8 ++++++--
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm/dts/rk3288-jerry.dts b/arch/arm/dts/rk3288-jerry.dts
index da37ea8..2aa3b9f 100644
--- a/arch/arm/dts/rk3288-jerry.dts
+++ b/arch/arm/dts/rk3288-jerry.dts
@@ -108,6 +108,11 @@
 	pinctrl-0 = <&vcc50_hdmi_en>;
 };
 
+&vopb {
+	/* Disable this so that we use vopl */
+	status = "disabled";
+};
+
 &edp {
 	pinctrl-names = "default";
 	pinctrl-0 = <&edp_hpd>;
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
index ac367f8..fb1d1f7 100644
--- a/arch/arm/dts/rk3288.dtsi
+++ b/arch/arm/dts/rk3288.dtsi
@@ -692,6 +692,7 @@
 		iommus = <&vopl_mmu>;
 		power-domains = <&power RK3288_PD_VIO>;
 		status = "disabled";
+		u-boot,dm-pre-reloc;
 		vopl_out: port {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index 526306f..27e53c1 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -42,7 +42,10 @@ CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
 CONFIG_PMIC_RK808=y
 CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_REGULATOR_RK808=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
 CONFIG_DEBUG_UART=y
@@ -51,6 +54,9 @@ CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_ROCKCHIP_SPI=y
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_ROTATION=y
+CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/include/configs/chromebook_jerry.h b/include/configs/chromebook_jerry.h
index 2a0dad4..150e876 100644
--- a/include/configs/chromebook_jerry.h
+++ b/include/configs/chromebook_jerry.h
@@ -9,8 +9,8 @@
 
 #define ROCKCHIP_DEVICE_SETTINGS \
 		"stdin=serial,cros-ec-keyb\0" \
-		"stdout=serial\0" \
-		"stderr=serial\0"
+		"stdout=serial,vidconsole\0" \
+		"stderr=serial,vidconsole\0"
 
 #include <configs/rk3288_common.h>
 
@@ -30,4 +30,8 @@
 #define CONFIG_SPL_POWER_SUPPORT
 #define CONFIG_SPL_I2C_SUPPORT
 
+#define CONFIG_I2C_EDID
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 32/37] rockchip: firefly-rk3288: Enable HDMI output
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (30 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 31/37] rockchip: jerry: Enable EDP and HDMI video output Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 33/37] rockchip: dts: Sync up SPDIF node with Linux Simon Glass
                   ` (5 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Enable HDMI output and a console on firefly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 configs/firefly-rk3288_defconfig | 7 +++++++
 include/configs/firefly-rk3288.h | 9 ++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index d8db532..15eb4d8 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -32,9 +32,13 @@ CONFIG_SPL_PINCTRL=y
 # CONFIG_SPL_PINCTRL_FULL is not set
 CONFIG_ROCKCHIP_PINCTRL=y
 CONFIG_DM_PMIC=y
+# CONFIG_SPL_PMIC_CHILDREN is not set
 CONFIG_PMIC_ACT8846=y
 CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
 CONFIG_DEBUG_UART=y
@@ -42,6 +46,9 @@ CONFIG_DEBUG_UART_BASE=0xff690000
 CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_ROTATION=y
+CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/include/configs/firefly-rk3288.h b/include/configs/firefly-rk3288.h
index 8ac6521..d6423e7 100644
--- a/include/configs/firefly-rk3288.h
+++ b/include/configs/firefly-rk3288.h
@@ -7,7 +7,10 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#define ROCKCHIP_DEVICE_SETTINGS
+#define ROCKCHIP_DEVICE_SETTINGS \
+		"stdin=serial,cros-ec-keyb\0" \
+		"stdout=serial,vidconsole\0" \
+		"stderr=serial,vidconsole\0"
 
 #include <configs/rk3288_common.h>
 
@@ -21,4 +24,8 @@
  */
 #define CONFIG_ENV_OFFSET (96 * 1024)
 
+#define CONFIG_I2C_EDID
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
 #endif
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 33/37] rockchip: dts: Sync up SPDIF node with Linux
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (31 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 32/37] rockchip: firefly-rk3288: Enable HDMI output Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 34/37] rockchip: rock2: Bring in device tree files from Linux Simon Glass
                   ` (4 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

This has been added and we have references to it in the rock2 board. Add
this node.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/rk3288.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
index fb1d1f7..e51c75c 100644
--- a/arch/arm/dts/rk3288.dtsi
+++ b/arch/arm/dts/rk3288.dtsi
@@ -631,6 +631,21 @@
 		status = "disabled";
 	};
 
+	spdif: sound at ff88b0000 {
+		compatible = "rockchip,rk3288-spdif", "rockchip,rk3066-spdif";
+		reg = <0xff8b0000 0x10000>;
+		#sound-dai-cells = <0>;
+		clock-names = "hclk", "mclk";
+		clocks = <&cru HCLK_SPDIF8CH>, <&cru SCLK_SPDIF8CH>;
+		dmas = <&dmac_bus_s 3>;
+		dma-names = "tx";
+		interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spdif_tx>;
+		rockchip,grf = <&grf>;
+		status = "disabled";
+	};
+
 	i2s: i2s at ff890000 {
 		compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
 		reg = <0xff890000 0x10000>;
@@ -1417,6 +1432,12 @@
 						<4 3 3 &pcfg_pull_none>;
 			};
 		};
+
+		spdif {
+			spdif_tx: spdif-tx {
+				rockchip,pins = <RK_GPIO6 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 	};
 
 	power: power-controller {
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 34/37] rockchip: rock2: Bring in device tree files from Linux
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (32 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 33/37] rockchip: dts: Sync up SPDIF node with Linux Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 35/37] rockchip: rock2: dts: Make changes for U-Boot Simon Glass
                   ` (3 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Bring in the current device tree files for rock2 from linux/next commit
719d6c1. Hopefully this is the latest one.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/rk3288-rock2-som.dtsi   | 278 +++++++++++++++++++++++++++++++++++
 arch/arm/dts/rk3288-rock2-square.dts | 180 +++++++++++++++++++++++
 2 files changed, 458 insertions(+)
 create mode 100644 arch/arm/dts/rk3288-rock2-som.dtsi
 create mode 100644 arch/arm/dts/rk3288-rock2-square.dts

diff --git a/arch/arm/dts/rk3288-rock2-som.dtsi b/arch/arm/dts/rk3288-rock2-som.dtsi
new file mode 100644
index 0000000..1ece66f
--- /dev/null
+++ b/arch/arm/dts/rk3288-rock2-som.dtsi
@@ -0,0 +1,278 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/pwm/pwm.h>
+#include "rk3288.dtsi"
+
+/ {
+	memory {
+		reg = <0x0 0x80000000>;
+		device_type = "memory";
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		pinctrl-0 = <&emmc_reset>;
+		pinctrl-names = "default";
+		reset-gpios = <&gpio3 9 GPIO_ACTIVE_LOW>;
+	};
+
+	ext_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	mmc-pwrseq = <&emmc_pwrseq>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+	vmmc-supply = <&vcc_io>;
+	status = "okay";
+};
+
+&gmac {
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	clock_in_out = "input";
+	phy-mode = "rgmii";
+	phy-supply = <&vccio_pmu>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins &phy_rst>;
+	snps,reset-gpio = <&gpio4 8 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 30000>;
+	rx_delay = <0x10>;
+	tx_delay = <0x30>;
+};
+
+&i2c0 {
+	status = "okay";
+
+	act8846: act8846 at 5a {
+		compatible = "active-semi,act8846";
+		reg = <0x5a>;
+		system-power-controller;
+		inl1-supply = <&vcc_io>;
+		inl2-supply = <&vcc_sys>;
+		inl3-supply = <&vcc_20>;
+		vp1-supply = <&vcc_sys>;
+		vp2-supply = <&vcc_sys>;
+		vp3-supply = <&vcc_sys>;
+		vp4-supply = <&vcc_sys>;
+
+		regulators {
+			vcc_ddr: REG1 {
+				regulator-name = "VCC_DDR";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vcc_io: REG2 {
+				regulator-name = "VCC_IO";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_log: REG3 {
+				regulator-name = "VDD_LOG";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcc_20: REG4 {
+				regulator-name = "VCC_20";
+				regulator-min-microvolt = <2000000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-always-on;
+			};
+
+			vccio_sd: REG5 {
+				regulator-name = "VCCIO_SD";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd10_lcd: REG6 {
+				regulator-name = "VDD10_LCD";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcca_codec: REG7 {
+				regulator-name = "VCCA_CODEC";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vcca_tp: REG8 {
+				regulator-name = "VCCA_TP";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vccio_pmu: REG9 {
+				regulator-name = "VCCIO_PMU";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_10: REG10 {
+				regulator-name = "VDD_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcc_18: REG11 {
+				regulator-name = "VCC_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcc18_lcd: REG12 {
+				regulator-name = "VCC18_LCD";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	vdd_cpu: syr827 at 40 {
+		compatible = "silergy,syr827";
+		reg = <0x40>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-enable-ramp-delay = <300>;
+		regulator-name = "vdd_cpu";
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-ramp-delay = <8000>;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vdd_gpu: syr828 at 41 {
+		compatible = "silergy,syr828";
+		reg = <0x41>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-always-on;
+		regulator-enable-ramp-delay = <300>;
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-name = "vdd_gpu";
+		regulator-ramp-delay = <8000>;
+		vin-supply = <&vcc_sys>;
+	};
+};
+
+&pinctrl {
+	pcfg_output_high: pcfg-output-high {
+		output-high;
+	};
+
+	emmc {
+			emmc_reset: emmc-reset {
+				rockchip,pins = <3 9 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+	};
+
+	gmac {
+		phy_rst: phy-rst {
+			rockchip,pins = <4 8 RK_FUNC_GPIO  &pcfg_output_high>;
+		};
+	};
+};
+
+&tsadc {
+	rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
+	rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
+	status = "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3288-rock2-square.dts b/arch/arm/dts/rk3288-rock2-square.dts
new file mode 100644
index 0000000..c5453a0
--- /dev/null
+++ b/arch/arm/dts/rk3288-rock2-square.dts
@@ -0,0 +1,180 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "rk3288-rock2-som.dtsi"
+
+/ {
+	model = "Radxa Rock 2 Square";
+	compatible = "radxa,rock2-square", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	ir: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio8 1 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_int>;
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "SPDIF";
+		simple-audio-card,dai-link at 1 {  /* S/PDIF - S/PDIF */
+			cpu { sound-dai = <&spdif>; };
+			codec { sound-dai = <&spdif_out>; };
+		};
+	};
+
+	spdif_out: spdif-out {
+		compatible = "linux,spdif-dit";
+		#sound-dai-cells = <0>;
+	};
+
+	vcc_usb_host: vcc-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		/* Always on as the rockchip usb phy doesn't have a vbus-supply
+		 * property
+		 */
+		regulator-always-on;
+		regulator-name = "vcc_host";
+	};
+
+	vcc_sd: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwr>;
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;	/* wp not hooked up */
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+	status = "okay";
+};
+
+&gmac {
+	status = "ok";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c5>;
+	status = "okay";
+};
+
+&i2c0 {
+	hym8563 at 51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+		interrupt-parent = <&gpio0>;
+		interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int>;
+
+	};
+};
+
+&i2c5 {
+	status = "okay";
+};
+
+&pinctrl {
+	ir {
+		ir_int: ir-int {
+			rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	pmic {
+		pmic_int: pmic-int {
+			rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&spdif {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 35/37] rockchip: rock2: dts: Make changes for U-Boot
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (33 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 34/37] rockchip: rock2: Bring in device tree files from Linux Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 36/37] rockchip: Add support for Raxda Rock 2 Simon Glass
                   ` (2 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

Add the required pre-relocation tags and SDRAM init information for U-Boot.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/rk3288-rock2-square.dts | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/dts/rk3288-rock2-square.dts b/arch/arm/dts/rk3288-rock2-square.dts
index c5453a0..8d7446f 100644
--- a/arch/arm/dts/rk3288-rock2-square.dts
+++ b/arch/arm/dts/rk3288-rock2-square.dts
@@ -96,6 +96,7 @@
 };
 
 &sdmmc {
+	u-boot,dm-pre-reloc;
 	bus-width = <4>;
 	cap-mmc-highspeed;
 	cap-sd-highspeed;
@@ -138,6 +139,7 @@
 };
 
 &pinctrl {
+	u-boot,dm-pre-reloc;
 	ir {
 		ir_int: ir-int {
 			rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_up>;
@@ -169,6 +171,8 @@
 
 &uart2 {
 	status = "okay";
+	u-boot,dm-pre-reloc;
+	reg-shift = <2>;
 };
 
 &usbphy {
@@ -178,3 +182,20 @@
 &usb_host0_ehci {
 	status = "okay";
 };
+
+&dmc {
+	rockchip,num-channels = <2>;
+	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
+		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
+		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
+		0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
+		0x5 0x0>;
+	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
+		0xa60 0x40 0x10 0x0>;
+	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
+};
+
+&gpio7 {
+	u-boot,dm-pre-reloc;
+};
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 36/37] rockchip: Add support for Raxda Rock 2
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (34 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 35/37] rockchip: rock2: dts: Make changes for U-Boot Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-14 15:58 ` [U-Boot] [PATCH 37/37] rockchip: Update the README Simon Glass
  2016-01-21  2:58 ` [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

This board includes an RK3288 SoC on a SOM. It can be mounted on a
base-board which provides a wide range of peripherals.

So far this is verified to boot to a prompt from a microSD card. The serial
console works as well as HDMI.

Thanks to Tom Cubie for sending me a board.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/dts/Makefile                     |  1 +
 arch/arm/mach-rockchip/rk3288-board-spl.c |  2 ++
 arch/arm/mach-rockchip/rk3288/Kconfig     | 10 ++++++
 board/radxa/rock2/Kconfig                 | 15 +++++++++
 board/radxa/rock2/MAINTAINERS             |  6 ++++
 board/radxa/rock2/Makefile                |  7 ++++
 board/radxa/rock2/rock2.c                 |  7 ++++
 configs/rock2_defconfig                   | 53 +++++++++++++++++++++++++++++++
 doc/README.rockchip                       |  7 +---
 include/configs/rock2.h                   | 31 ++++++++++++++++++
 10 files changed, 133 insertions(+), 6 deletions(-)
 create mode 100644 board/radxa/rock2/Kconfig
 create mode 100644 board/radxa/rock2/MAINTAINERS
 create mode 100644 board/radxa/rock2/Makefile
 create mode 100644 board/radxa/rock2/rock2.c
 create mode 100644 configs/rock2_defconfig
 create mode 100644 include/configs/rock2.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 03f984a..2960cd1 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -22,6 +22,7 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3288-firefly.dtb \
 	rk3288-jerry.dtb \
+	rk3288-rock2-square.dtb \
 	rk3036-sdk.dtb
 dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
 	tegra20-medcom-wide.dtb \
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index 9fdd37d..6a54368 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -114,6 +114,7 @@ static void configure_l2ctlr(void)
 #ifdef CONFIG_SPL_MMC_SUPPORT
 static int configure_emmc(struct udevice *pinctrl)
 {
+#ifndef CONFIG_TARGET_ROCK2
 	struct gpio_desc desc;
 	int ret;
 
@@ -143,6 +144,7 @@ static int configure_emmc(struct udevice *pinctrl)
 		debug("gpio value ret=%d\n", ret);
 		return ret;
 	}
+#endif
 
 	return 0;
 }
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
index ed89c3e..7215624 100644
--- a/arch/arm/mach-rockchip/rk3288/Kconfig
+++ b/arch/arm/mach-rockchip/rk3288/Kconfig
@@ -16,6 +16,14 @@ config TARGET_CHROMEBOOK_JERRY
 	  WiFi. It includes a Chrome OS EC (Cortex-M3) to provide access to
 	  the keyboard and battery functions.
 
+config TARGET_ROCK2
+	bool "Radxa Rock 2"
+	help
+	  Rock 2 is a SOM and base-board combination based on RK3288. It
+	  includes Ethernet, HDMI, 3 USB, micro-SD, audio, SATA, WiFi and
+	  space for a real-time-clock battery. There is also an expansion
+	  interface which provides access to many pins.
+
 config ROCKCHIP_FAST_SPL
 	bool "Change the CPU to full speed in SPL"
 	depends on TARGET_CHROMEBOOK_JERRY
@@ -35,4 +43,6 @@ source "board/google/chromebook_jerry/Kconfig"
 
 source "board/firefly/firefly-rk3288/Kconfig"
 
+source "board/radxa/rock2/Kconfig"
+
 endif
diff --git a/board/radxa/rock2/Kconfig b/board/radxa/rock2/Kconfig
new file mode 100644
index 0000000..c2ff9e9
--- /dev/null
+++ b/board/radxa/rock2/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_ROCK2
+
+config SYS_BOARD
+	default "rock2"
+
+config SYS_VENDOR
+	default "radxa"
+
+config SYS_CONFIG_NAME
+	default "rock2"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/radxa/rock2/MAINTAINERS b/board/radxa/rock2/MAINTAINERS
new file mode 100644
index 0000000..a697e68
--- /dev/null
+++ b/board/radxa/rock2/MAINTAINERS
@@ -0,0 +1,6 @@
+FIREFLY
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/radxa/rock2
+F:	include/configs/rock2.h
+F:	configs/rock2_defconfig
diff --git a/board/radxa/rock2/Makefile b/board/radxa/rock2/Makefile
new file mode 100644
index 0000000..caa305b
--- /dev/null
+++ b/board/radxa/rock2/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= rock2.o
diff --git a/board/radxa/rock2/rock2.c b/board/radxa/rock2/rock2.c
new file mode 100644
index 0000000..5119e95
--- /dev/null
+++ b/board/radxa/rock2/rock2.c
@@ -0,0 +1,7 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
new file mode 100644
index 0000000..2563775
--- /dev/null
+++ b/configs/rock2_defconfig
@@ -0,0 +1,53 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_ROCK2=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-rock2-square"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent"
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_RESET=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_DM_PMIC=y
+# CONFIG_SPL_PMIC_CHILDREN is not set
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_ROTATION=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/doc/README.rockchip b/doc/README.rockchip
index 7be5a13..364affd 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -39,7 +39,7 @@ Building
 At present three RK3288 boards are supported:
 
    - Firefly RK3288 - use firefly-rk3288 configuration
-   - Radxa Rock 2 - also uses firefly-rk3288 configuration
+   - Radxa Rock 2 - use rock2 configuration
    - Haier Chromebook - use chromebook_jerry configuration
 
 one RK3036 board is support:
@@ -52,11 +52,6 @@ For example:
 
 (or you can use another cross compiler if you prefer)
 
-Note that the Radxa Rock 2 uses the Firefly configuration for now as
-device tree files are not yet available for the Rock 2. Clearly the two
-have hardware differences, so this approach will break down as more drivers
-are added.
-
 
 Writing to the board with USB
 =============================
diff --git a/include/configs/rock2.h b/include/configs/rock2.h
new file mode 100644
index 0000000..d6423e7
--- /dev/null
+++ b/include/configs/rock2.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+		"stdin=serial,cros-ec-keyb\0" \
+		"stdout=serial,vidconsole\0" \
+		"stderr=serial,vidconsole\0"
+
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_MMC_SUPPORT
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 0
+/* SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+
+#define CONFIG_I2C_EDID
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
+#endif
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 37/37] rockchip: Update the README
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (35 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 36/37] rockchip: Add support for Raxda Rock 2 Simon Glass
@ 2016-01-14 15:58 ` Simon Glass
  2016-01-21  2:58 ` [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-14 15:58 UTC (permalink / raw)
  To: u-boot

GPIO, I2C, LCD and HDMI are now implemented. We have more than one PMIC.
There is an implementation to run the CPU at full speed although it does
not seem to make much difference.

Update the README to cover recent developments.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/README.rockchip | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/doc/README.rockchip b/doc/README.rockchip
index 364affd..e0572c8 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -14,7 +14,7 @@ many Rockchip devices [1] [2].
 The current mainline support is experimental only and is not useful for
 anything. It should provide a base on which to build.
 
-So far only support for the RK3288 is provided.
+So far only support for the RK3288 and RK3036 is provided.
 
 
 Prerequisites
@@ -22,7 +22,7 @@ Prerequisites
 
 You will need:
 
-   - Firefly RK3288 baord
+   - Firefly RK3288 board or something else with a supported RockChip SoC
    - Power connection to 5V using the supplied micro-USB power cable
    - Separate USB serial cable attached to your computer and the Firefly
         (connect to the micro-USB connector below the logo)
@@ -40,11 +40,12 @@ At present three RK3288 boards are supported:
 
    - Firefly RK3288 - use firefly-rk3288 configuration
    - Radxa Rock 2 - use rock2 configuration
-   - Haier Chromebook - use chromebook_jerry configuration
+   - Hisense Chromebook - use chromebook_jerry configuration
 
-one RK3036 board is support:
+Two RK3036 board are supported:
 
-   - EVB RK3036 - use evb-rk3036_defconfig configuration
+   - EVB RK3036 - use evb-rk3036 configuration
+   - Kylin - use kylin_rk3036 configuration
 
 For example:
 
@@ -103,20 +104,23 @@ corresponds with this setting in U-Boot:
 Put this SD (or micro-SD) card into your board and reset it. You should see
 something like:
 
-   U-Boot SPL 2015.07-rc1-00383-ge345740-dirty (Jun 03 2015 - 11:04:40)
-
-
-   U-Boot 2015.07-rc1-00383-ge345740-dirty (Jun 03 2015 - 11:04:40)
+   U-Boot 2016.01-rc2-00309-ge5bad3b-dirty (Jan 02 2016 - 23:41:59 -0700)
 
+   Model: Radxa Rock 2 Square
    DRAM:  2 GiB
-   MMC:
-   Using default environment
-
-   In:    serial at ff690000
-   Out:   serial at ff690000
-   Err:   serial at ff690000
+   MMC:   dwmmc at ff0f0000: 0, dwmmc at ff0c0000: 1
+   *** Warning - bad CRC, using default environment
+
+   In:    serial
+   Out:   vop at ff940000.vidconsole
+   Err:   serial
+   Net:   Net Initialization Skipped
+   No ethernet found.
+   Hit any key to stop autoboot:  0
    =>
 
+If you have an HDMI cable attached you should see a video console.
+
 For evb_rk3036 board:
 	./evb-rk3036/tools/mkimage -n rk3036 -T rksd  -d evb-rk3036/spl/u-boot-spl.bin out && \
 	cat evb-rk3036/u-boot-dtb.bin >> out && \
@@ -170,13 +174,9 @@ Future work
 
 Immediate priorities are:
 
-- GPIO (driver exists but is lightly tested)
-- I2C (driver exists but is non-functional)
 - USB host
 - USB device
-- PMIC and regulators (only ACT8846 is supported at present)
-- LCD and HDMI
-- Run CPU at full speed
+- Run CPU at full speed (code exists but we only see ~60 DMIPS maximum)
 - Ethernet
 - NAND flash
 - Support for other Rockchip parts
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard
  2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
                   ` (36 preceding siblings ...)
  2016-01-14 15:58 ` [U-Boot] [PATCH 37/37] rockchip: Update the README Simon Glass
@ 2016-01-21  2:58 ` Simon Glass
  37 siblings, 0 replies; 39+ messages in thread
From: Simon Glass @ 2016-01-21  2:58 UTC (permalink / raw)
  To: u-boot

Hi,

On 14 January 2016 at 08:57, Simon Glass <sjg@chromium.org> wrote:
> This series adds display drivers for rockchip and enables them on jerry,
> firefly-rk3288 (HDMI only) and rock2 (HDMI only). It builds on the recent
> keyboard series.
>
> Driver are provided for video displays (EDP and HDMI) and the VOP (video
> output processor).
>
> This series also adds several new uclasses:
> - PWM (Pulse-width modulation)
> - Panel (used for LCD panels)
> - Display (renamed from DisplayPort - a generic display with power, etc.)
> - Backlight (used for LCD backlights)
>
> Since most of this implementation is device-tree-controlled it is fairly
> easy to enable HDMI on the other RK3288 devices. This series adds this for
> Firefly-RK3288. It also includes Radxa Rock 2 as a separate board since a
> device tree file is now available in Linux. HDMI is enabled on that board
> also.
>
> There remain quite a few things still to do for core rockchip support. Here
> are a few noticed while preparing this series:
>
> - Clocks / caches are not working correctly. The 'dhry' command shows
> approximately 60 DMIPS when supposedly running at 1.8GHz. Turning the cache
> on or off makes no difference. The platform should run at over 2000 DMIPS by
> my estimate. This problem is common on ARM platforms. For example I found:
>
> beaver (Tegra) 818 DMIPS
> pit (Exynos) 276 DMIPS
> snow (Exynos) 521 DMIPS
>
> - HDMI EDID-reading does not work on Jerry, perhaps because the clocks are
> not running as they should. It seems to work fine on other boards.
>
> This series is available at u-boot-dm/rkd-working

I know this is pretty soon, but I'd like to apply this to
u-boot-rockchip in the next day or two. If there are any more
comments, please send them through.

Regards,
Simon

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2016-01-21  2:58 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-14 15:57 [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 01/37] stdio: Correct a build error with driver model Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 02/37] gpio: Warn about invalid GPIOs used with the 'gpio' command Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 03/37] video: Name consoles by their number Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 04/37] video: Add a function to control cache flushing Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 05/37] video: bridge: Allow GPIOs to be optional Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 06/37] dm: pwm: Add a PWM uclass Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 07/37] pwm: rockchip: Add a PWM driver for Rockchip SoCs Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 08/37] dm: backlight: Add a backlight uclass Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 09/37] dm: backlight: Add a driver for a PWM backlight Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 10/37] dm: panel: Add a panel uclass Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 11/37] video: panel: Add a simple panel driver Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 12/37] dm: video: Repurpose the 'displayport' uclass to 'display' Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 13/37] rockchip: Rename the CRU_MODE_CON fields Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 14/37] rockchip: clk: Add support for clocks needed by the displays Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 15/37] rockchip: video: Add a display driver for rockchip HDMI Simon Glass
2016-01-14 15:57 ` [U-Boot] [PATCH 16/37] rockchip: video: Add a display driver for rockchip eDP Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 17/37] rockchip: video: Add a video-output driver Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 18/37] rockchip: Don't skip low-level init Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 19/37] rockchip: Add a simple 'clock' command Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 20/37] rockchip: Add a script to parse datasheets Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 21/37] rockchip: config: Enable the 'gpio' command Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 22/37] rockchip: sdram: Tidy up a few comments Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 23/37] rockchip: sdram: Use syscon_get_first_range() where possible Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 24/37] rockchip: Tidy up the register-access macros Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 25/37] rockchip: spl: Drop MMC support code when not needed Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 26/37] rockchip: jerry: Fix the SDRAM timing Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 27/37] rockchip: rk3288: clock: Fix various minor errors Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 28/37] rockchip: rk3288: pinctrl: Fix HDMI pinctrl Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 29/37] rockchip: spl: Support full-speed CPU in SPL Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 30/37] rockchip: jerry: Add support for timing SPI flash speed Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 31/37] rockchip: jerry: Enable EDP and HDMI video output Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 32/37] rockchip: firefly-rk3288: Enable HDMI output Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 33/37] rockchip: dts: Sync up SPDIF node with Linux Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 34/37] rockchip: rock2: Bring in device tree files from Linux Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 35/37] rockchip: rock2: dts: Make changes for U-Boot Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 36/37] rockchip: Add support for Raxda Rock 2 Simon Glass
2016-01-14 15:58 ` [U-Boot] [PATCH 37/37] rockchip: Update the README Simon Glass
2016-01-21  2:58 ` [U-Boot] [PATCH 00/37] rockchip: Add support for display and keyboard Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.