mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* i.MX IPUv3 support
@ 2014-03-14 14:32 Sascha Hauer
  2014-03-14 14:32 ` [PATCH 01/29] err.h: Add PTR_ERR_OR_ZERO from kernel Sascha Hauer
                   ` (27 more replies)
  0 siblings, 28 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

This series adds i.MX IPUv3 support for barebox. There are several things
to prepare for this since we need clk parent rate changing and several
additional clocks. Currently supported are LVDS and HDMI displays. This
also adds Variscite VAR-SOM-MX6 support on which the IPU support was
tested. I may rework some of the commit messages next week but I wanted
to have this series posted before the weekend.

Sascha


  ARM: MMU: Add some debugging aids and hints (2014-03-14 15:25:11 +0100)

are available in the git repository at:

  git://git.pengutronix.de/git/barebox.git imx-ipu-v3

for you to fetch changes up to f37d7bbaf03a220bd61ceb0e59dbc8b84a27a9dd:

  ARM: update imx_v7_defconfig (2014-03-14 15:25:21 +0100)

----------------------------------------------------------------
Sascha Hauer (29):
      err.h: Add PTR_ERR_OR_ZERO from kernel
      ARM: i.MX6: Add initial variscite VAR-SOM-MX6 CPU support
      ARM: dts: i.MX6: Add IPU aliases
      ARM: dts: i.MX6: Add HDMI nodes
      ARM: dts: i.MX53: Fix IPU register size
      i2c: i.MX: move to earlier initcall
      i2c: implement of_find_i2c_adapter_by_node
      clk: implement clk_round_rate
      clk: clk-mux: pass clk flags from initializers
      clk: clk-gate: pass flags to initializers
      clk: clk-fixed-factor: pass flags to initializers
      clk: clk-divider: pass flags to initializers
      clk: introduce CLK_SET_RATE_PARENT flag
      clk: clk-divider: sync with kernel code
      clk: let clk-divider handle the table based divider aswell
      clk: clk-fixed-factor: add set_rate/round_rate callbacks
      clk: Add parent round/set rate for mux and gate
      ARM: i.MX: introduce clk parent rate changes
      ARM: i.MX6: Add video clocks
      video: introduce struct display_timings
      video: rework mode_name parameter setting
      video: Add display timing from devicetree helper
      video: Add edid support
      ARM i.MX6q: Mark VPU and IPU AXI transfers as cacheable, increase IPU priority
      video: Add kernel fourcc defines
      video: Add i.MX IPUv3 support
      video: i.MX IPUv3: Add lvds bridge support
      video: i.MX IPUv3: Add hdmi support
      ARM: update imx_v7_defconfig

 arch/arm/boards/Makefile                           |    1 +
 arch/arm/boards/variscite-mx6/Makefile             |    3 +
 arch/arm/boards/variscite-mx6/board.c              |  135 ++
 .../variscite-mx6/flash-header-variscite.imxcfg    |   86 ++
 arch/arm/boards/variscite-mx6/lowlevel.c           |   74 ++
 arch/arm/configs/imx_v7_defconfig                  |   26 +-
 arch/arm/dts/Makefile                              |    4 +-
 arch/arm/dts/imx53.dtsi                            |    2 +-
 arch/arm/dts/imx6q-var-custom.dts                  |  149 +++
 arch/arm/dts/imx6q-var-som.dtsi                    |   99 ++
 arch/arm/dts/imx6q.dtsi                            |    5 +
 arch/arm/dts/imx6qdl.dtsi                          |   12 +
 arch/arm/mach-imx/Kconfig                          |    6 +
 arch/arm/mach-imx/clk-imx6.c                       |  155 ++-
 arch/arm/mach-imx/clk.h                            |   22 +-
 arch/arm/mach-imx/imx6.c                           |   19 +
 arch/arm/mach-imx/include/mach/imx6-regs.h         |    3 +
 drivers/clk/Makefile                               |    2 +-
 drivers/clk/clk-divider-table.c                    |  119 --
 drivers/clk/clk-divider.c                          |  234 +++-
 drivers/clk/clk-fixed-factor.c                     |   33 +-
 drivers/clk/clk-gate.c                             |   13 +-
 drivers/clk/clk-mux.c                              |   10 +-
 drivers/clk/clk.c                                  |   30 +
 drivers/clk/mvebu/common.c                         |    4 +-
 drivers/clk/mxs/clk.h                              |    6 +-
 drivers/clk/tegra/clk-periph.c                     |    4 +-
 drivers/i2c/busses/i2c-imx.c                       |    2 +-
 drivers/i2c/i2c.c                                  |   11 +
 drivers/video/Kconfig                              |    8 +
 drivers/video/Makefile                             |    3 +
 drivers/video/atmel_lcdfb_core.c                   |    4 +-
 drivers/video/edid.c                               |  909 ++++++++++++++
 drivers/video/edid.h                               |  138 +++
 drivers/video/fb.c                                 |  113 +-
 drivers/video/imx-ipu-fb.c                         |    4 +-
 drivers/video/imx-ipu-v3/Kconfig                   |   14 +
 drivers/video/imx-ipu-v3/Makefile                  |    5 +
 drivers/video/imx-ipu-v3/imx-hdmi.c                | 1297 ++++++++++++++++++++
 drivers/video/imx-ipu-v3/imx-hdmi.h                | 1032 ++++++++++++++++
 drivers/video/imx-ipu-v3/imx-ipu-v3.h              |  344 ++++++
 drivers/video/imx-ipu-v3/imx-ldb.c                 |  310 +++++
 drivers/video/imx-ipu-v3/ipu-common.c              |  836 +++++++++++++
 drivers/video/imx-ipu-v3/ipu-dc.c                  |  392 ++++++
 drivers/video/imx-ipu-v3/ipu-di.c                  |  762 ++++++++++++
 drivers/video/imx-ipu-v3/ipu-dmfc.c                |  397 ++++++
 drivers/video/imx-ipu-v3/ipu-dp.c                  |  313 +++++
 drivers/video/imx-ipu-v3/ipu-prv.h                 |  204 +++
 drivers/video/imx-ipu-v3/ipufb.c                   |  353 ++++++
 drivers/video/imx-ipu-v3/ipuv3-plane.c             |  239 ++++
 drivers/video/imx-ipu-v3/ipuv3-plane.h             |   51 +
 drivers/video/imx.c                                |    6 +-
 drivers/video/of_display_timing.c                  |  238 ++++
 drivers/video/omap.c                               |    4 +-
 drivers/video/s3c24xx.c                            |    4 +-
 drivers/video/sdl.c                                |    4 +-
 drivers/video/stm.c                                |    4 +-
 images/Makefile.imx                                |    5 +
 include/fb.h                                       |   43 +-
 include/i2c/i2c.h                                  |    1 +
 include/linux/clk.h                                |   31 +-
 include/linux/err.h                                |    8 +
 include/mfd/imx6q-iomuxc-gpr.h                     |   18 +
 include/video/fourcc.h                             |  261 ++++
 64 files changed, 9382 insertions(+), 242 deletions(-)
 create mode 100644 arch/arm/boards/variscite-mx6/Makefile
 create mode 100644 arch/arm/boards/variscite-mx6/board.c
 create mode 100644 arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg
 create mode 100644 arch/arm/boards/variscite-mx6/lowlevel.c
 create mode 100644 arch/arm/dts/imx6q-var-custom.dts
 create mode 100644 arch/arm/dts/imx6q-var-som.dtsi
 delete mode 100644 drivers/clk/clk-divider-table.c
 create mode 100644 drivers/video/edid.c
 create mode 100644 drivers/video/edid.h
 create mode 100644 drivers/video/imx-ipu-v3/Kconfig
 create mode 100644 drivers/video/imx-ipu-v3/Makefile
 create mode 100644 drivers/video/imx-ipu-v3/imx-hdmi.c
 create mode 100644 drivers/video/imx-ipu-v3/imx-hdmi.h
 create mode 100644 drivers/video/imx-ipu-v3/imx-ipu-v3.h
 create mode 100644 drivers/video/imx-ipu-v3/imx-ldb.c
 create mode 100644 drivers/video/imx-ipu-v3/ipu-common.c
 create mode 100644 drivers/video/imx-ipu-v3/ipu-dc.c
 create mode 100644 drivers/video/imx-ipu-v3/ipu-di.c
 create mode 100644 drivers/video/imx-ipu-v3/ipu-dmfc.c
 create mode 100644 drivers/video/imx-ipu-v3/ipu-dp.c
 create mode 100644 drivers/video/imx-ipu-v3/ipu-prv.h
 create mode 100644 drivers/video/imx-ipu-v3/ipufb.c
 create mode 100644 drivers/video/imx-ipu-v3/ipuv3-plane.c
 create mode 100644 drivers/video/imx-ipu-v3/ipuv3-plane.h
 create mode 100644 drivers/video/of_display_timing.c
 create mode 100644 include/video/fourcc.h

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 01/29] err.h: Add PTR_ERR_OR_ZERO from kernel
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 02/29] ARM: i.MX6: Add initial variscite VAR-SOM-MX6 CPU support Sascha Hauer
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/linux/err.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/linux/err.h b/include/linux/err.h
index 19fb70d..ed563f2 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -52,6 +52,14 @@ static inline void *ERR_CAST(const void *ptr)
 	return (void *) ptr;
 }
 
+static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
+{
+	if (IS_ERR(ptr))
+		return PTR_ERR(ptr);
+	else
+		return 0;
+}
+
 #endif
 
 #endif /* _LINUX_ERR_H */
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 02/29] ARM: i.MX6: Add initial variscite VAR-SOM-MX6 CPU support
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
  2014-03-14 14:32 ` [PATCH 01/29] err.h: Add PTR_ERR_OR_ZERO from kernel Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 03/29] ARM: dts: i.MX6: Add IPU aliases Sascha Hauer
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

The VAR-SOM-MX6 is a System on module from Variscite, see:

http://www.variscite.com/products/system-on-module-som/cortex-a9/var-som-mx6-cpu-freescale-imx6

This adds support for this module on the VAR-MX6CustomBoard baseboard.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/variscite-mx6/Makefile             |   3 +
 arch/arm/boards/variscite-mx6/board.c              | 135 +++++++++++++++++++
 .../variscite-mx6/flash-header-variscite.imxcfg    |  86 ++++++++++++
 arch/arm/boards/variscite-mx6/lowlevel.c           |  74 ++++++++++
 arch/arm/dts/Makefile                              |   4 +-
 arch/arm/dts/imx6q-var-custom.dts                  | 149 +++++++++++++++++++++
 arch/arm/dts/imx6q-var-som.dtsi                    |  99 ++++++++++++++
 arch/arm/mach-imx/Kconfig                          |   6 +
 images/Makefile.imx                                |   5 +
 10 files changed, 561 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boards/variscite-mx6/Makefile
 create mode 100644 arch/arm/boards/variscite-mx6/board.c
 create mode 100644 arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg
 create mode 100644 arch/arm/boards/variscite-mx6/lowlevel.c
 create mode 100644 arch/arm/dts/imx6q-var-custom.dts
 create mode 100644 arch/arm/dts/imx6q-var-som.dtsi

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 0d8c9cf..ac85093 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -100,3 +100,4 @@ obj-$(CONFIG_MACH_USB_A9G20)			+= usb-a926x/
 obj-$(CONFIG_MACH_VERSATILEPB)			+= versatile/
 obj-$(CONFIG_MACH_VEXPRESS)			+= vexpress/
 obj-$(CONFIG_MACH_ZEDBOARD)			+= avnet-zedboard/
+obj-$(CONFIG_MACH_VARISCITE_MX6)		+= variscite-mx6/
diff --git a/arch/arm/boards/variscite-mx6/Makefile b/arch/arm/boards/variscite-mx6/Makefile
new file mode 100644
index 0000000..35b114b
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/Makefile
@@ -0,0 +1,3 @@
+obj-y += board.o flash-header-variscite.dcd.o
+extra-y += flash-header-variscite.dcd.S flash-header-variscite.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/variscite-mx6/board.c b/arch/arm/boards/variscite-mx6/board.c
new file mode 100644
index 0000000..592b111
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/board.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013 Michael Burkey
+ * Based on code (C) Sascha Hauer, Pengutronix
+ * Based on code (C) Variscite, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) "var-som-mx6: " fmt
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <of.h>
+#include <debug_ll.h>
+
+#include <environment.h>
+#include <asm/armlinux.h>
+#include <generated/mach-types.h>
+#include <partition.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <mach/generic.h>
+#include <sizes.h>
+#include <mach/imx6.h>
+#include <mach/devices-imx6.h>
+#include <mach/iomux-mx6.h>
+#include <spi/spi.h>
+#include <mach/spi.h>
+#include <i2c/i2c.h>
+
+#define ETH_PHY_RST	IMX_GPIO_NR(1, 25)
+
+static int setup_pmic_voltages(void)
+{
+	unsigned char value, rev_id = 0 ;
+	struct i2c_adapter *adapter = NULL;
+	struct i2c_client client;
+	int addr = -1, ret, bus = 0;
+
+	/* I2C2 bus (2-1 = 1 in barebox numbering) */
+	bus = 1;
+
+	/* PFUZE100 device address is 0x08 */
+	addr = 0x08;
+
+	adapter = i2c_get_adapter(bus);
+	if (!adapter) {
+		pr_err("i2c bus %d not found\n", bus);
+		return -ENODEV;
+	}
+
+	client.adapter = adapter;
+	client.addr = addr;
+
+	/* Attempt to locate the PFUZE100 chip. */
+	if (i2c_read_reg(&client, 0x00, &value, 1) != 1) {
+		pr_err("Read device ID error!\n");
+		return -1;
+	}
+	if (i2c_read_reg(&client, 0x03, &rev_id, 1) != 1) {
+		pr_err("Read Rev ID error!\n");
+		return -1;
+	}
+
+	pr_info("Found PFUZE100! deviceid=%x,revid=%x\n", value, rev_id);
+
+	/* Set Gigabit Ethernet voltage (SOM v1.1/1.0)*/
+        value = 0x60;
+	ret = i2c_write_reg(&client, 0x4a, &value, 1);
+
+	/* set VGEN3 to 2.5V */
+	value = 0x77;
+	if (i2c_write_reg(&client, 0x6e, &value, 1) != 1) {
+		pr_err("Set VGEN3 error!\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int eth_phy_reset(void)
+{
+	gpio_request(ETH_PHY_RST, "phy reset");
+	gpio_direction_output(ETH_PHY_RST, 0);
+	mdelay(1);
+	gpio_set_value(ETH_PHY_RST, 1);
+
+	return 0;
+}
+
+static int variscite_custom_init(void)
+{
+	if (!of_machine_is_compatible("variscite,imx6q-custom"))
+		return 0;
+
+	barebox_set_hostname("var-som-mx6");
+
+	setup_pmic_voltages();
+
+	eth_phy_reset();
+
+	armlinux_set_architecture(MACH_TYPE_VAR_SOM_MX6);
+
+	pr_debug("Completing custom_init()\n");
+
+	return 0;
+}
+device_initcall(variscite_custom_init);
+
+static int variscite_custom_core_init(void)
+{
+	if (!of_machine_is_compatible("variscite,imx6q-custom"))
+		return 0;
+
+	imx6_init_lowlevel();
+
+	pr_debug("Completing custom_core_init()\n");
+
+	return 0;
+}
+postcore_initcall(variscite_custom_core_init);
diff --git a/arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg b/arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg
new file mode 100644
index 0000000..ed21057
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg
@@ -0,0 +1,86 @@
+loadaddr 0x10000000
+soc imx6
+dcdofs 0x400
+wm 32 0x020e0798 0x000C0000
+wm 32 0x020e0758 0x00000000
+wm 32 0x020e0588 0x00000030
+wm 32 0x020e0594 0x00000030
+wm 32 0x020e056c 0x00000030
+wm 32 0x020e0578 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e057c 0x00000030
+wm 32 0x020e058c 0x00000000
+wm 32 0x020e059c 0x00000030
+wm 32 0x020e05a0 0x00000030
+wm 32 0x020e078c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e05a8 0x00000030
+wm 32 0x020e05b0 0x00000030
+wm 32 0x020e0524 0x00000030
+wm 32 0x020e051c 0x00000030
+wm 32 0x020e0518 0x00000030
+wm 32 0x020e050c 0x00000030
+wm 32 0x020e05b8 0x00000030
+wm 32 0x020e05c0 0x00000030
+wm 32 0x020e0774 0x00020000
+wm 32 0x020e0784 0x00000030
+wm 32 0x020e0788 0x00000030
+wm 32 0x020e0794 0x00000030
+wm 32 0x020e079c 0x00000030
+wm 32 0x020e07a0 0x00000030
+wm 32 0x020e07a4 0x00000030
+wm 32 0x020e07a8 0x00000030
+wm 32 0x020e0748 0x00000030
+wm 32 0x020e05ac 0x00000030
+wm 32 0x020e05b4 0x00000030
+wm 32 0x020e0528 0x00000030
+wm 32 0x020e0520 0x00000030
+wm 32 0x020e0514 0x00000030
+wm 32 0x020e0510 0x00000030
+wm 32 0x020e05bc 0x00000030
+wm 32 0x020e05c4 0x00000030
+wm 32 0x021b0800 0xA1390003
+wm 32 0x021b080c 0x001F001F
+wm 32 0x021b0810 0x001F001F
+wm 32 0x021b480c 0x001F001F
+wm 32 0x021b4810 0x001F001F
+wm 32 0x021b083c 0x4333033F
+wm 32 0x021b0840 0x032C031D
+wm 32 0x021b483c 0x43200332
+wm 32 0x021b4840 0x031A026A
+wm 32 0x021b0848 0x4D464746
+wm 32 0x021b4848 0x47453F4D
+wm 32 0x021b0850 0x3E434440
+wm 32 0x021b4850 0x47384839
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+wm 32 0x021b0824 0x33333333
+wm 32 0x021b0828 0x33333333
+wm 32 0x021b481c 0x33333333
+wm 32 0x021b4820 0x33333333
+wm 32 0x021b4824 0x33333333
+wm 32 0x021b4828 0x33333333
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b48b8 0x00000800
+wm 32 0x021b0004 0x00020036
+wm 32 0x021b0008 0x09444040
+wm 32 0x021b000c 0x555A7975
+wm 32 0x021b0010 0xFF538F64
+wm 32 0x021b0014 0x01FF00DB
+wm 32 0x021b0018 0x00001740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b002c 0x000026D2
+wm 32 0x021b0030 0x005A1023
+wm 32 0x021b0040 0x00000027
+wm 32 0x021b0000 0x831A0000
+wm 32 0x021b001c 0x04088032
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x09408030
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b0020 0x00005800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b4818 0x00011117
+wm 32 0x021b0004 0x00025576
+wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
diff --git a/arch/arm/boards/variscite-mx6/lowlevel.c b/arch/arm/boards/variscite-mx6/lowlevel.c
new file mode 100644
index 0000000..e93e874
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/lowlevel.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (C) 2013 Michael Burkey
+ * Based on code by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <debug_ll.h>
+#include <common.h>
+#include <sizes.h>
+#include <io.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <asm/sections.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <mach/imx6-mmdc.h>
+#include <mach/imx6.h>
+
+static inline void setup_uart(void)
+{
+	void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
+	void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR;
+	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+	writel(0x03, iomuxbase + 0x0280);
+	writel(0x03, iomuxbase + 0x0284);
+
+	writel(0xffffffff, ccmbase + 0x68);
+	writel(0xffffffff, ccmbase + 0x6c);
+	writel(0xffffffff, ccmbase + 0x70);
+	writel(0xffffffff, ccmbase + 0x74);
+	writel(0xffffffff, ccmbase + 0x78);
+	writel(0xffffffff, ccmbase + 0x7c);
+	writel(0xffffffff, ccmbase + 0x80);
+
+	writel(0x00000000, uartbase + 0x80);
+	writel(0x00004027, uartbase + 0x84);
+	writel(0x00000704, uartbase + 0x88);
+	writel(0x00000a81, uartbase + 0x90);
+	writel(0x0000002b, uartbase + 0x9c);
+	writel(0x00013880, uartbase + 0xb0);
+	writel(0x0000047f, uartbase + 0xa4);
+	writel(0x0000c34f, uartbase + 0xa8);
+	writel(0x00000001, uartbase + 0x80);
+
+	putc_ll('>');
+}
+extern char __dtb_imx6q_var_custom_start[];
+
+ENTRY_FUNCTION(start_variscite_custom, r0, r1, r2)
+{
+	uint32_t fdt;
+
+	arm_cpu_lowlevel_init();
+
+	arm_setup_stack(0x00920000 - 8);
+
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+	    setup_uart();
+
+	fdt = (uint32_t)__dtb_imx6q_var_custom_start - get_runtime_offset();
+
+	barebox_arm_entry(0x10000000, SZ_1G, fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 6bac3b9..d42fde9 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -25,7 +25,8 @@ dtb-$(CONFIG_ARCH_IMX6) += imx6q-gk802.dtb \
 	imx6q-guf-santaro.dtb \
 	imx6q-nitrogen6x.dtb \
 	imx6dl-nitrogen6x.dtb \
-	imx6q-udoo.dtb
+	imx6q-udoo.dtb \
+	imx6q-var-custom.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += dove-cubox-bb.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5_sockit.dtb \
 	socfpga_cyclone5_socrates.dtb
@@ -60,6 +61,7 @@ pbl-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o
 pbl-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
 pbl-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
 pbl-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
+pbl-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
 
 .SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S
 .SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y))
diff --git a/arch/arm/dts/imx6q-var-custom.dts b/arch/arm/dts/imx6q-var-custom.dts
new file mode 100644
index 0000000..bb1193f
--- /dev/null
+++ b/arch/arm/dts/imx6q-var-custom.dts
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2013 Michael Burkey
+ * Based on code written by Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * 		environment@0 {
+			compatible = "barebox,environment";
+			device-path = &usdhc2, "partname:barebox-environment";
+		};
+
+ *
+ */
+
+/dts-v1/;
+#include "imx6q-var-som.dtsi"
+
+/ {
+	model = "Variscite i.MX6 Quad Custom Carrier-Board";
+	compatible = "variscite,imx6q-custom", "variscite,imx6q-som", "fsl,imx6q";
+
+	chosen {
+		linux,stdout-path = &uart1;
+
+		environment@0 {
+			compatible = "barebox,environment";
+			device-path = &gpmi, "partname:barebox-environment";
+		};
+
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-variscite-custom {
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <MX6QDL_I2C3_PINGRP3>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <MX6QDL_USDHC2_PINGRP_D4>;
+		};
+
+		pinctrl_usdhc2_cd: usdhc2cd {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL4__GPIO4_IO14	 0x80000000
+				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15	 0x80000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <MX6QDL_UART1_PINGRP1>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <24>;
+		status = "okay";
+		display-timings {
+			native-mode = &claawvga;
+			claawvga: claawvga {
+				native-mode;
+				clock-frequency = <35714000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <28>;
+				hfront-porch = <17>;
+				vback-porch = <13>;
+				vfront-porch = <20>;
+				hsync-len = <20>;
+				vsync-len = <13>;
+			};
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
+
+&usdhc2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	cd-gpios = <&gpio4 14 0>;
+	wp-gpios = <&gpio4 15 0>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition@0 {
+		label = "barebox";
+		reg = <0x0 0x200000>;
+	};
+
+	partition@1 {
+		label = "barebox-environment";
+		reg = <0x200000 0x20000>;
+	};
+
+	partition@2 {
+		label = "kernel";
+		reg = <0x220000 0x600000>;
+	};
+
+	partition@3 {
+		label = "rootfs";
+		reg = <0x820000 0x18000000>;
+	};
+};
+
+&usbh1 {
+	status = "okay";
+	disable-over-current;
+	dr_mode = "host";
+	phy_type = "utmi";
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+};
+
+&i2c3 {
+	status = "okay";
+	clock-frequency = <1000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+};
diff --git a/arch/arm/dts/imx6q-var-som.dtsi b/arch/arm/dts/imx6q-var-som.dtsi
new file mode 100644
index 0000000..f423f27
--- /dev/null
+++ b/arch/arm/dts/imx6q-var-som.dtsi
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 Michael Burkey
+ * Based on code written by Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6q.dtsi"
+
+/ {
+	model = "Variscite i.MX6 Quad SOM";
+	compatible = "variscite,imx6q-som", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	nand-on-flash-bbt;
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition@0 {
+		label = "barebox";
+		reg = <0x0 0x200000>;
+	};
+
+	partition@1 {
+		label = "barebox-environment";
+		reg = <0x200000 0x20000>;
+	};
+
+	partition@2 {
+		label = "kernel";
+		reg = <0x220000 0x600000>;
+	};
+
+	partition@3 {
+		label = "rootfs";
+		reg = <0x820000 0x1F7E0000>;
+	};
+};
+
+&hdmi {
+	status = "okay";
+	ddc-i2c-bus = <&i2c2>;
+};
+
+&i2c2 {
+	status = "okay";
+	clock-frequency = <1000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-variscite-som {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1	0x80000000
+				MX6QDL_PAD_GPIO_3__CCM_CLKO2	0x80000000
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_ENET_PINGRP_RGMII_MD(0x1b0b0, 0x1b0b0)
+				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000		/* KSZ9031 PHY Reset */
+			  >;
+		};
+
+		pinctrl_gpmi_nand: gpmigrp {
+			fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+		};
+	};
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index b7e7533..b242716 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -39,6 +39,7 @@ config ARCH_TEXT_BASE
 	default 0x4fc00000 if MACH_PHYTEC_PFLA02
 	default 0x4fc00000 if MACH_DFI_FS700_M60
 	default 0x4fc00000 if MACH_UDOO
+	default 0x4fc00000 if MACH_VARISCITE_MX6
 
 config ARCH_IMX_INTERNAL_BOOT
 	bool "support internal boot mode"
@@ -247,6 +248,11 @@ config MACH_UDOO
 	bool "Freescale i.MX6 UDOO Board"
 	select ARCH_IMX6
 
+config MACH_VARISCITE_MX6
+	bool "Variscite i.MX6 Quad SOM"
+	select ARCH_IMX6
+
+
 endif
 
 # ----------------------------------------------------------
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 5b650de..6754a3f 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -143,3 +143,8 @@ pblx-$(CONFIG_MACH_UDOO) += start_imx6_udoo
 CFG_start_imx6_udoo.pblx.imximg = $(board)/udoo/flash-header-mx6-udoo.imxcfg
 FILE_barebox-udoo-imx6q.img = start_imx6_udoo.pblx.imximg
 image-$(CONFIG_MACH_UDOO) += barebox-udoo-imx6q.img
+
+pblx-$(CONFIG_MACH_VARISCITE_MX6) += start_variscite_custom
+CFG_start_variscite_custom.pblx.imximg = $(board)/variscite-mx6/flash-header-variscite.imxcfg
+FILE_barebox-variscite-custom.img = start_variscite_custom.pblx.imximg
+image-$(CONFIG_MACH_VARISCITE_MX6) += barebox-variscite-custom.img
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 03/29] ARM: dts: i.MX6: Add IPU aliases
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
  2014-03-14 14:32 ` [PATCH 01/29] err.h: Add PTR_ERR_OR_ZERO from kernel Sascha Hauer
  2014-03-14 14:32 ` [PATCH 02/29] ARM: i.MX6: Add initial variscite VAR-SOM-MX6 CPU support Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 04/29] ARM: dts: i.MX6: Add HDMI nodes Sascha Hauer
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/imx6q.dtsi   | 1 +
 arch/arm/dts/imx6qdl.dtsi | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi
index 52a9a2b..f9378fa 100644
--- a/arch/arm/dts/imx6q.dtsi
+++ b/arch/arm/dts/imx6q.dtsi
@@ -16,6 +16,7 @@
 / {
 	aliases {
 		spi4 = &ecspi5;
+		ipu1 = &ipu2;
 	};
 
 	cpus {
diff --git a/arch/arm/dts/imx6qdl.dtsi b/arch/arm/dts/imx6qdl.dtsi
index 70424d2..5160db4 100644
--- a/arch/arm/dts/imx6qdl.dtsi
+++ b/arch/arm/dts/imx6qdl.dtsi
@@ -45,6 +45,7 @@
 		spi3 = &ecspi4;
 		usbphy0 = &usbphy1;
 		usbphy1 = &usbphy2;
+		ipu0 = &ipu1;
 	};
 
 	intc: interrupt-controller@00a01000 {
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 04/29] ARM: dts: i.MX6: Add HDMI nodes
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (2 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 03/29] ARM: dts: i.MX6: Add IPU aliases Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 05/29] ARM: dts: i.MX53: Fix IPU register size Sascha Hauer
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/imx6q.dtsi   |  4 ++++
 arch/arm/dts/imx6qdl.dtsi | 11 +++++++++++
 2 files changed, 15 insertions(+)

diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi
index f9378fa..2b8ec43 100644
--- a/arch/arm/dts/imx6q.dtsi
+++ b/arch/arm/dts/imx6q.dtsi
@@ -158,6 +158,10 @@
 	};
 };
 
+&hdmi {
+	compatible = "fsl,imx6q-hdmi";
+};
+
 &ldb {
 	clocks = <&clks 33>, <&clks 34>,
 		 <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>,
diff --git a/arch/arm/dts/imx6qdl.dtsi b/arch/arm/dts/imx6qdl.dtsi
index 5160db4..8dfd7de 100644
--- a/arch/arm/dts/imx6qdl.dtsi
+++ b/arch/arm/dts/imx6qdl.dtsi
@@ -665,6 +665,17 @@
 				};
 			};
 
+			hdmi: hdmi@0120000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x00120000 0x9000>;
+				interrupts = <0 115 0x04>;
+				gpr = <&gpr>;
+				clocks = <&clks 123>, <&clks 124>;
+				clock-names = "iahb", "isfr";
+				status = "disabled";
+			};
+
 			dcic1: dcic@020e4000 {
 				reg = <0x020e4000 0x4000>;
 				interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 05/29] ARM: dts: i.MX53: Fix IPU register size
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (3 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 04/29] ARM: dts: i.MX6: Add HDMI nodes Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 06/29] i2c: i.MX: move to earlier initcall Sascha Hauer
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/imx53.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/dts/imx53.dtsi b/arch/arm/dts/imx53.dtsi
index 91659b8..c3fac43 100644
--- a/arch/arm/dts/imx53.dtsi
+++ b/arch/arm/dts/imx53.dtsi
@@ -87,7 +87,7 @@
 		ipu: ipu@18000000 {
 			#crtc-cells = <1>;
 			compatible = "fsl,imx53-ipu";
-			reg = <0x18000000 0x080000000>;
+			reg = <0x18000000 0x08000000>;
 			interrupts = <11 10>;
 			clocks = <&clks 59>, <&clks 110>, <&clks 61>;
 			clock-names = "bus", "di0", "di1";
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 06/29] i2c: i.MX: move to earlier initcall
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (4 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 05/29] ARM: dts: i.MX53: Fix IPU register size Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 07/29] i2c: implement of_find_i2c_adapter_by_node Sascha Hauer
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index f657c28..6b39047 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -587,4 +587,4 @@ static struct driver_d i2c_fsl_driver = {
 	.name	= DRIVER_NAME,
 	.of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids),
 };
-device_platform_driver(i2c_fsl_driver);
+coredevice_platform_driver(i2c_fsl_driver);
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 07/29] i2c: implement of_find_i2c_adapter_by_node
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (5 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 06/29] i2c: i.MX: move to earlier initcall Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 08/29] clk: implement clk_round_rate Sascha Hauer
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/i2c.c | 11 +++++++++++
 include/i2c/i2c.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index e289a35..9873957 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -405,6 +405,17 @@ struct i2c_adapter *i2c_get_adapter(int busnum)
 	return NULL;
 }
 
+struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
+{
+	struct i2c_adapter *adap;
+
+	list_for_each_entry(adap, &adapter_list, list)
+		if (adap->dev.device_node == node)
+			return adap;
+
+	return NULL;
+}
+
 /**
  * i2c_add_numbered_adapter - declare i2c adapter, use static bus number
  * @adapter: the adapter to register (with adap->nr initialized)
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index 81e5daa..f89fefb 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -133,6 +133,7 @@ static inline int i2c_register_board_info(int busnum,
 #endif
 extern int i2c_add_numbered_adapter(struct i2c_adapter *adapter);
 struct i2c_adapter *i2c_get_adapter(int busnum);
+struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
 
 /* For devices that use several addresses, use i2c_new_dummy() to make
  * client handles for the extra addresses.
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 08/29] clk: implement clk_round_rate
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (6 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 07/29] i2c: implement of_find_i2c_adapter_by_node Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 09/29] clk: clk-mux: pass clk flags from initializers Sascha Hauer
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Instead of returning just the current rate implement clk_round_rate
properly.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 31d73c0..c67b2f4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -104,9 +104,19 @@ unsigned long clk_get_rate(struct clk *clk)
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
+	unsigned long parent_rate = 0;
+	struct clk *parent;
+
 	if (IS_ERR(clk))
 		return 0;
 
+	parent = clk_get_parent(clk);
+	if (parent)
+		parent_rate = clk_get_rate(parent);
+
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate, &parent_rate);
+
 	return clk_get_rate(clk);
 }
 
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 09/29] clk: clk-mux: pass clk flags from initializers
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (7 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 08/29] clk: implement clk_round_rate Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 10/29] clk: clk-gate: pass flags to initializers Sascha Hauer
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

struct clk has a flags field, let the clk-mux initializers set this
field.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk.h        | 2 +-
 drivers/clk/clk-mux.c          | 8 +++++---
 drivers/clk/mxs/clk.h          | 2 +-
 drivers/clk/tegra/clk-periph.c | 2 +-
 include/linux/clk.h            | 6 ++++--
 5 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 4a7298d..8e218fb 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -16,7 +16,7 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 		u8 shift, u8 width, const char **parents, u8 num_parents)
 {
-	return clk_mux(name, reg, shift, width, parents, num_parents);
+	return clk_mux(name, reg, shift, width, parents, num_parents, 0);
 }
 
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index b22bdd1..9dcd39c 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -56,7 +56,8 @@ static struct clk_ops clk_mux_ops = {
 };
 
 struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, u8 num_parents)
+		u8 shift, u8 width, const char **parents, u8 num_parents,
+		unsigned flags)
 {
 	struct clk_mux *m = xzalloc(sizeof(*m));
 
@@ -65,6 +66,7 @@ struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
 	m->width = width;
 	m->clk.ops = &clk_mux_ops;
 	m->clk.name = name;
+	m->clk.flags = flags;
 	m->clk.parent_names = parents;
 	m->clk.num_parents = num_parents;
 
@@ -79,12 +81,12 @@ void clk_mux_free(struct clk *clk_mux)
 }
 
 struct clk *clk_mux(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, u8 num_parents)
+		u8 shift, u8 width, const char **parents, u8 num_parents, unsigned flags)
 {
 	struct clk *m;
 	int ret;
 
-	m = clk_mux_alloc(name, reg, shift, width, parents, num_parents);
+	m = clk_mux_alloc(name, reg, shift, width, parents, num_parents, flags);
 
 	ret = clk_register(m);
 	if (ret) {
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index b4fcfa0..3db38b4 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -40,7 +40,7 @@ static inline struct clk *mxs_clk_gate(const char *name,
 static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
 		u8 shift, u8 width, const char **parent_names, int num_parents)
 {
-	return clk_mux(name, reg, shift, width, parent_names, num_parents);
+	return clk_mux(name, reg, shift, width, parent_names, num_parents, 0);
 }
 
 static inline struct clk *mxs_clk_fixed_factor(const char *name,
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index e969495..0b9c8dc 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -140,7 +140,7 @@ struct clk *_tegra_clk_register_periph(const char *name,
 	}
 
 	periph->mux = clk_mux_alloc(NULL, clk_base + reg_offset, 30, 2,
-				    parent_names, num_parents);
+				    parent_names, num_parents, 0);
 	if (!periph->mux)
 		goto out_mux;
 
diff --git a/include/linux/clk.h b/include/linux/clk.h
index af38c72..439e88c 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -252,10 +252,12 @@ struct clk *clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div);
 
 struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, u8 num_parents);
+		u8 shift, u8 width, const char **parents, u8 num_parents,
+		unsigned flags);
 void clk_mux_free(struct clk *clk_mux);
 struct clk *clk_mux(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, u8 num_parents);
+		u8 shift, u8 width, const char **parents, u8 num_parents,
+		unsigned flags);
 
 struct clk *clk_gate_alloc(const char *name, const char *parent,
 		void __iomem *reg, u8 shift);
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 10/29] clk: clk-gate: pass flags to initializers
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (8 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 09/29] clk: clk-mux: pass clk flags from initializers Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 11/29] clk: clk-fixed-factor: " Sascha Hauer
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk.h        |  2 +-
 drivers/clk/clk-gate.c         | 11 ++++++-----
 drivers/clk/mvebu/common.c     |  2 +-
 drivers/clk/mxs/clk.h          |  2 +-
 drivers/clk/tegra/clk-periph.c |  2 +-
 include/linux/clk.h            |  6 +++---
 6 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 8e218fb..072af55 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -22,7 +22,7 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
-	return clk_gate(name, parent, reg, shift);
+	return clk_gate(name, parent, reg, shift, 0);
 }
 
 struct clk *imx_clk_pllv1(const char *name, const char *parent,
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index baec855..f356de7 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -83,7 +83,7 @@ static struct clk_ops clk_gate_ops = {
 };
 
 struct clk *clk_gate_alloc(const char *name, const char *parent,
-		void __iomem *reg, u8 shift)
+		void __iomem *reg, u8 shift, unsigned flags)
 {
 	struct clk_gate *g = xzalloc(sizeof(*g));
 
@@ -92,6 +92,7 @@ struct clk *clk_gate_alloc(const char *name, const char *parent,
 	g->shift = shift;
 	g->clk.ops = &clk_gate_ops;
 	g->clk.name = name;
+	g->clk.flags = flags;
 	g->clk.parent_names = &g->parent;
 	g->clk.num_parents = 1;
 
@@ -106,12 +107,12 @@ void clk_gate_free(struct clk *clk_gate)
 }
 
 struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
-		u8 shift)
+		u8 shift, unsigned flags)
 {
 	struct clk *g;
 	int ret;
 
-	g = clk_gate_alloc(name , parent, reg, shift);
+	g = clk_gate_alloc(name , parent, reg, shift, flags);
 
 	ret = clk_register(g);
 	if (ret) {
@@ -123,12 +124,12 @@ struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
 }
 
 struct clk *clk_gate_inverted(const char *name, const char *parent,
-		void __iomem *reg, u8 shift)
+		void __iomem *reg, u8 shift, unsigned flags)
 {
 	struct clk *clk;
 	struct clk_gate *g;
 
-	clk = clk_gate(name, parent, reg, shift);
+	clk = clk_gate(name, parent, reg, shift, flags);
 	if (IS_ERR(clk))
 		return clk;
 
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 37cc156..aa1e8f6 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -188,7 +188,7 @@ int mvebu_clk_gating_probe(struct device_d *dev)
 			(desc[n].parent) ? desc[n].parent : default_parent;
 		gate->bit_idx = desc[n].bit_idx;
 		gate->clk = clk_gate(desc[n].name, parent,
-				base, desc[n].bit_idx);
+				base, desc[n].bit_idx, 0);
 		WARN_ON(IS_ERR(gate->clk));
 	}
 
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index 3db38b4..168fa58 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -34,7 +34,7 @@ static inline struct clk *mxs_clk_fixed(const char *name, int rate)
 static inline struct clk *mxs_clk_gate(const char *name,
 			const char *parent_name, void __iomem *reg, u8 shift)
 {
-	return clk_gate_inverted(name, parent_name, reg, shift);
+	return clk_gate_inverted(name, parent_name, reg, shift, 0);
 }
 
 static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 0b9c8dc..c970f63 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -145,7 +145,7 @@ struct clk *_tegra_clk_register_periph(const char *name,
 		goto out_mux;
 
 	periph->gate = clk_gate_alloc(NULL, NULL, clk_base + 0x10 +
-				      ((id >> 3) & 0xc), id & 0x1f);
+				      ((id >> 3) & 0xc), id & 0x1f, 0);
 	if (!periph->gate)
 		goto out_gate;
 
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 439e88c..21edfab 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -260,12 +260,12 @@ struct clk *clk_mux(const char *name, void __iomem *reg,
 		unsigned flags);
 
 struct clk *clk_gate_alloc(const char *name, const char *parent,
-		void __iomem *reg, u8 shift);
+		void __iomem *reg, u8 shift, unsigned flags);
 void clk_gate_free(struct clk *clk_gate);
 struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
-		u8 shift);
+		u8 shift, unsigned flags);
 struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem *reg,
-		u8 shift);
+		u8 shift, unsigned flags);
 int clk_is_enabled(struct clk *clk);
 
 int clk_is_enabled_always(struct clk *clk);
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 11/29] clk: clk-fixed-factor: pass flags to initializers
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (9 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 10/29] clk: clk-gate: pass flags to initializers Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 12/29] clk: clk-divider: " Sascha Hauer
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk.h        | 2 +-
 drivers/clk/clk-fixed-factor.c | 3 ++-
 drivers/clk/mvebu/common.c     | 2 +-
 drivers/clk/mxs/clk.h          | 2 +-
 include/linux/clk.h            | 3 ++-
 5 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 072af55..54f04ed 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -10,7 +10,7 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 static inline struct clk *imx_clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div)
 {
-	return clk_fixed_factor(name, parent, mult, div);
+	return clk_fixed_factor(name, parent, mult, div, 0);
 }
 
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index f0ecbd3..df0d2f3 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -40,7 +40,7 @@ static struct clk_ops clk_fixed_factor_ops = {
 };
 
 struct clk *clk_fixed_factor(const char *name,
-		const char *parent, unsigned int mult, unsigned int div)
+		const char *parent, unsigned int mult, unsigned int div, unsigned flags)
 {
 	struct clk_fixed_factor *f = xzalloc(sizeof(*f));
 	int ret;
@@ -50,6 +50,7 @@ struct clk *clk_fixed_factor(const char *name,
 	f->parent = parent;
 	f->clk.ops = &clk_fixed_factor_ops;
 	f->clk.name = name;
+	f->clk.flags = flags;
 	f->clk.parent_names = &f->parent;
 	f->clk.num_parents = 1;
 
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index aa1e8f6..658ce3e 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -87,7 +87,7 @@ int mvebu_coreclk_probe(struct device_d *dev)
 					      2+n, &rclk_name);
 		desc->get_clk_ratio(base, desc->ratios[n].id, &mult, &div);
 		clk_data.clks[2+n] = clk_fixed_factor(rclk_name, cpuclk_name,
-						mult, div);
+						mult, div, 0);
 		WARN_ON(IS_ERR(clk_data.clks[2+n]));
 	};
 
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index 168fa58..7bab7b5 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -46,7 +46,7 @@ static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
 static inline struct clk *mxs_clk_fixed_factor(const char *name,
 		const char *parent_name, unsigned int mult, unsigned int div)
 {
-	return clk_fixed_factor(name, parent_name, mult, div);
+	return clk_fixed_factor(name, parent_name, mult, div, 0);
 }
 
 #endif /* __MXS_CLK_H */
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 21edfab..e65a62a 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -249,7 +249,8 @@ struct clk *clk_divider_table(const char *name,
 		const char *parent, void __iomem *reg, u8 shift, u8 width,
 		const struct clk_div_table *table);
 struct clk *clk_fixed_factor(const char *name,
-		const char *parent, unsigned int mult, unsigned int div);
+		const char *parent, unsigned int mult, unsigned int div,
+		unsigned flags);
 
 struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
 		u8 shift, u8 width, const char **parents, u8 num_parents,
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 12/29] clk: clk-divider: pass flags to initializers
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (10 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 11/29] clk: clk-fixed-factor: " Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag Sascha Hauer
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk-imx6.c    | 2 +-
 arch/arm/mach-imx/clk.h         | 2 +-
 drivers/clk/clk-divider-table.c | 3 ++-
 drivers/clk/clk-divider.c       | 7 ++++---
 include/linux/clk.h             | 6 +++---
 5 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c
index 5560fff..8d78a18 100644
--- a/arch/arm/mach-imx/clk-imx6.c
+++ b/arch/arm/mach-imx/clk-imx6.c
@@ -214,7 +214,7 @@ static int imx6_ccm_probe(struct device_d *dev)
 	clks[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
 	clks[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
 
-	clks[enet_ref] = clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table);
+	clks[enet_ref] = clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table, 0);
 
 	/*                                name               parent_name         reg          idx */
 	clks[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 54f04ed..cdafad1 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -4,7 +4,7 @@
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 		void __iomem *reg, u8 shift, u8 width)
 {
-	return clk_divider(name, parent, reg, shift, width);
+	return clk_divider(name, parent, reg, shift, width, 0);
 }
 
 static inline struct clk *imx_clk_fixed_factor(const char *name,
diff --git a/drivers/clk/clk-divider-table.c b/drivers/clk/clk-divider-table.c
index fd2d3fc..0caf85d 100644
--- a/drivers/clk/clk-divider-table.c
+++ b/drivers/clk/clk-divider-table.c
@@ -85,7 +85,7 @@ static struct clk_ops clk_divider_table_ops = {
 
 struct clk *clk_divider_table(const char *name,
 		const char *parent, void __iomem *reg, u8 shift, u8 width,
-		const struct clk_div_table *table)
+		const struct clk_div_table *table, unsigned flags)
 {
 	struct clk_divider_table *div = xzalloc(sizeof(*div));
 	const struct clk_div_table *clkt;
@@ -98,6 +98,7 @@ struct clk *clk_divider_table(const char *name,
 	div->clk.ops = &clk_divider_table_ops;
 	div->clk.name = name;
 	div->clk.parent_names = &div->parent;
+	div->clk.flags = flags;
 	div->clk.num_parents = 1;
 	div->table = table;
 
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 3bf8105..bb8bcc1 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -78,7 +78,7 @@ struct clk_ops clk_divider_ops = {
 };
 
 struct clk *clk_divider(const char *name, const char *parent,
-		void __iomem *reg, u8 shift, u8 width)
+		void __iomem *reg, u8 shift, u8 width, unsigned flags)
 {
 	struct clk_divider *div = xzalloc(sizeof(*div));
 	int ret;
@@ -89,6 +89,7 @@ struct clk *clk_divider(const char *name, const char *parent,
 	div->parent = parent;
 	div->clk.ops = &clk_divider_ops;
 	div->clk.name = name;
+	div->clk.flags = flags;
 	div->clk.parent_names = &div->parent;
 	div->clk.num_parents = 1;
 
@@ -102,12 +103,12 @@ struct clk *clk_divider(const char *name, const char *parent,
 }
 
 struct clk *clk_divider_one_based(const char *name, const char *parent,
-		void __iomem *reg, u8 shift, u8 width)
+		void __iomem *reg, u8 shift, u8 width, unsigned flags)
 {
 	struct clk_divider *div;
 	struct clk *clk;
 
-	clk = clk_divider(name, parent, reg, shift, width);
+	clk = clk_divider(name, parent, reg, shift, width, flags);
 	if (IS_ERR(clk))
 		return clk;
 
diff --git a/include/linux/clk.h b/include/linux/clk.h
index e65a62a..7e5010a 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -242,12 +242,12 @@ struct clk_divider {
 extern struct clk_ops clk_divider_ops;
 
 struct clk *clk_divider(const char *name, const char *parent,
-		void __iomem *reg, u8 shift, u8 width);
+		void __iomem *reg, u8 shift, u8 width, unsigned flags);
 struct clk *clk_divider_one_based(const char *name, const char *parent,
-		void __iomem *reg, u8 shift, u8 width);
+		void __iomem *reg, u8 shift, u8 width, unsigned flags);
 struct clk *clk_divider_table(const char *name,
 		const char *parent, void __iomem *reg, u8 shift, u8 width,
-		const struct clk_div_table *table);
+		const struct clk_div_table *table, unsigned flags);
 struct clk *clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div,
 		unsigned flags);
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (11 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 12/29] clk: clk-divider: " Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 16:06   ` Alexander Shiyan
  2014-03-14 14:32 ` [PATCH 14/29] clk: clk-divider: sync with kernel code Sascha Hauer
                   ` (14 subsequent siblings)
  27 siblings, 1 reply; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/linux/clk.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7e5010a..2704b0f 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -196,6 +196,9 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
 #endif
 
 #ifdef CONFIG_COMMON_CLK
+
+#define CLK_SET_RATE_PARENT     (1 << 0) /* propagate rate change up one level */
+
 struct clk_ops {
 	int		(*enable)(struct clk *clk);
 	void		(*disable)(struct clk *clk);
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 14/29] clk: clk-divider: sync with kernel code
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (12 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 15/29] clk: let clk-divider handle the table based divider aswell Sascha Hauer
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

This updates the clk-divider to Kernel code, but without power-of-two
divider support which we do not need yet. This also adds table based
divider support to the divider.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk-divider.c | 191 ++++++++++++++++++++++++++++++++++++++--------
 include/linux/clk.h       |   3 +
 2 files changed, 164 insertions(+), 30 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index bb8bcc1..9634bd3 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -20,61 +20,192 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 
-static unsigned int clk_divider_maxdiv(struct clk_divider *div)
+#define div_mask(d)	((1 << ((d)->width)) - 1)
+
+static unsigned int _get_maxdiv(struct clk_divider *divider)
 {
-	if (div->flags & CLK_DIVIDER_ONE_BASED)
-                return (1 << div->width) - 1;
-	return 1 << div->width;
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		return div_mask(divider);
+	return div_mask(divider) + 1;
 }
 
-static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
+static unsigned int _get_table_div(const struct clk_div_table *table,
+							unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+	return 0;
+}
+
+static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+{
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		return val;
+	if (divider->table)
+		return _get_table_div(divider->table, val);
+	return val + 1;
+}
+
+static unsigned int _get_table_val(const struct clk_div_table *table,
+							unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
+{
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		return div;
+	if (divider->table)
+		return  _get_table_val(divider->table, div);
+	return div - 1;
+}
+
+static unsigned long clk_divider_recalc_rate(struct clk *clk,
 		unsigned long parent_rate)
 {
-	struct clk_divider *div = container_of(clk, struct clk_divider, clk);
-	unsigned int val, divval;
+	struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+	unsigned int div, val;
+
+	val = readl(divider->reg) >> divider->shift;
+	val &= div_mask(divider);
+
+	div = _get_div(divider, val);
+
+	return parent_rate / div;
+}
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+static bool _is_valid_table_div(const struct clk_div_table *table,
+							 unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
+{
+	if (divider->table)
+		return _is_valid_table_div(divider->table, div);
+	return true;
+}
+
+static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
+		unsigned long *best_parent_rate)
+{
+	struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+	int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+	unsigned long parent_rate_saved = *best_parent_rate;
 
-	if (rate > parent_rate)
-		rate = parent_rate;
 	if (!rate)
 		rate = 1;
 
-	divval = DIV_ROUND_UP(parent_rate, rate);
-	if (divval > clk_divider_maxdiv(div))
-		divval = clk_divider_maxdiv(div);
+	maxdiv = _get_maxdiv(divider);
 
-	if (!(div->flags & CLK_DIVIDER_ONE_BASED))
-		divval--;
+	if (!(clk->flags & CLK_SET_RATE_PARENT)) {
+		parent_rate = *best_parent_rate;
+		bestdiv = DIV_ROUND_UP(parent_rate, rate);
+		bestdiv = bestdiv == 0 ? 1 : bestdiv;
+		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+		return bestdiv;
+	}
 
-	val = readl(div->reg);
-	val &= ~(((1 << div->width) - 1) << div->shift);
-	val |= divval << div->shift;
-	writel(val, div->reg);
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		if (!_is_valid_div(divider, i))
+			continue;
+		if (rate * i == parent_rate_saved) {
+			/*
+			 * It's the most ideal case if the requested rate can be
+			 * divided from parent clock without needing to change
+			 * parent rate, so return the divider immediately.
+			 */
+			*best_parent_rate = parent_rate_saved;
+			return i;
+		}
+		parent_rate = clk_round_rate(clk_get_parent(clk),
+				MULT_ROUND_UP(rate, i));
+		now = parent_rate / i;
+		if (now <= rate && now > best) {
+			bestdiv = i;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
 
-	return 0;
+	if (!bestdiv) {
+		bestdiv = _get_maxdiv(divider);
+		*best_parent_rate = clk_round_rate(clk_get_parent(clk), 1);
+	}
+
+	return bestdiv;
 }
 
-static unsigned long clk_divider_recalc_rate(struct clk *clk,
-		unsigned long parent_rate)
+static long clk_divider_round_rate(struct clk *clk, unsigned long rate,
+		unsigned long *parent_rate)
 {
-	struct clk_divider *div = container_of(clk, struct clk_divider, clk);
-	unsigned int val;
+	int div;
 
-	val = readl(div->reg) >> div->shift;
-	val &= (1 << div->width) - 1;
+	div = clk_divider_bestdiv(clk, rate, parent_rate);
 
-	if (div->flags & CLK_DIVIDER_ONE_BASED) {
-		if (!val)
-			val++;
+	return *parent_rate / div;
+}
+
+static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+	unsigned int div, value;
+	u32 val;
+
+	if (clk->flags & CLK_SET_RATE_PARENT) {
+		unsigned long best_parent_rate = parent_rate;
+		div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
+		clk_set_rate(clk_get_parent(clk), best_parent_rate);
 	} else {
-		val++;
+		div = parent_rate / rate;
 	}
 
-	return parent_rate / val;
+	value = _get_val(divider, div);
+
+	if (value > div_mask(divider))
+		value = div_mask(divider);
+
+	val = readl(divider->reg);
+	val &= ~(div_mask(divider) << divider->shift);
+	val |= value << divider->shift;
+	writel(val, divider->reg);
+
+	return 0;
 }
 
 struct clk_ops clk_divider_ops = {
 	.set_rate = clk_divider_set_rate,
 	.recalc_rate = clk_divider_recalc_rate,
+	.round_rate = clk_divider_round_rate,
 };
 
 struct clk *clk_divider(const char *name, const char *parent,
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 2704b0f..71b0466 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -240,6 +240,9 @@ struct clk_divider {
 	const char *parent;
 #define CLK_DIVIDER_ONE_BASED	(1 << 0)
 	unsigned flags;
+	const struct clk_div_table *table;
+	int max_div_index;
+	int table_size;
 };
 
 extern struct clk_ops clk_divider_ops;
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 15/29] clk: let clk-divider handle the table based divider aswell
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (13 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 14/29] clk: clk-divider: sync with kernel code Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 16/29] clk: clk-fixed-factor: add set_rate/round_rate callbacks Sascha Hauer
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/Makefile            |   2 +-
 drivers/clk/clk-divider-table.c | 120 ----------------------------------------
 drivers/clk/clk-divider.c       |  36 ++++++++++++
 3 files changed, 37 insertions(+), 121 deletions(-)
 delete mode 100644 drivers/clk/clk-divider-table.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f5c0592..7506f87 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \
-				clk-mux.o clk-gate.o clk-divider-table.o
+				clk-mux.o clk-gate.o
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 
 obj-$(CONFIG_ARCH_MVEBU)	+= mvebu/
diff --git a/drivers/clk/clk-divider-table.c b/drivers/clk/clk-divider-table.c
deleted file mode 100644
index 0caf85d..0000000
--- a/drivers/clk/clk-divider-table.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * clk-divider-table.c - generic barebox clock support. Based on Linux clk support
- *
- * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#include <common.h>
-#include <io.h>
-#include <malloc.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-struct clk_divider_table {
-	struct clk clk;
-	u8 shift;
-	u8 width;
-	void __iomem *reg;
-	const char *parent;
-	const struct clk_div_table *table;
-	int table_size;
-	int max_div_index;
-};
-
-static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_divider_table *div =
-		container_of(clk, struct clk_divider_table, clk);
-	unsigned int val;
-	int i, div_index = -1;
-	unsigned long best = 0;
-
-	if (rate > parent_rate)
-		rate = parent_rate;
-	if (rate < parent_rate / div->table[div->max_div_index].div)
-		rate = parent_rate / div->table[div->max_div_index].div;
-
-	for (i = 0; i < div->table_size; i++) {
-		unsigned long now = parent_rate / div->table[i].div;
-
-		if (now <= rate && now >= best) {
-			best = now;
-			div_index = i;
-		}
-	}
-
-	val = readl(div->reg);
-	val &= ~(((1 << div->width) - 1) << div->shift);
-	val |= div_index << div->shift;
-	writel(val, div->reg);
-
-	return 0;
-}
-
-static unsigned long clk_divider_recalc_rate(struct clk *clk,
-		unsigned long parent_rate)
-{
-	struct clk_divider_table *div =
-		container_of(clk, struct clk_divider_table, clk);
-	unsigned int val;
-
-	val = readl(div->reg) >> div->shift;
-	val &= (1 << div->width) - 1;
-
-	if (val >= div->table_size)
-		return 0;
-
-	return parent_rate / div->table[val].div;
-}
-
-static struct clk_ops clk_divider_table_ops = {
-	.set_rate = clk_divider_set_rate,
-	.recalc_rate = clk_divider_recalc_rate,
-};
-
-struct clk *clk_divider_table(const char *name,
-		const char *parent, void __iomem *reg, u8 shift, u8 width,
-		const struct clk_div_table *table, unsigned flags)
-{
-	struct clk_divider_table *div = xzalloc(sizeof(*div));
-	const struct clk_div_table *clkt;
-	int ret, max_div = 0;
-
-	div->shift = shift;
-	div->reg = reg;
-	div->width = width;
-	div->parent = parent;
-	div->clk.ops = &clk_divider_table_ops;
-	div->clk.name = name;
-	div->clk.parent_names = &div->parent;
-	div->clk.flags = flags;
-	div->clk.num_parents = 1;
-	div->table = table;
-
-	for (clkt = div->table; clkt->div; clkt++) {
-		if (clkt->div > max_div) {
-			max_div = clkt->div;
-			div->max_div_index = div->table_size;
-		}
-		div->table_size++;
-	}
-
-	ret = clk_register(&div->clk);
-	if (ret) {
-		free(div);
-		return ERR_PTR(ret);
-	}
-
-	return &div->clk;
-}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 9634bd3..67783da 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -248,3 +248,39 @@ struct clk *clk_divider_one_based(const char *name, const char *parent,
 
 	return clk;
 }
+
+struct clk *clk_divider_table(const char *name,
+		const char *parent, void __iomem *reg, u8 shift, u8 width,
+		const struct clk_div_table *table, unsigned flags)
+{
+	struct clk_divider *div = xzalloc(sizeof(*div));
+	const struct clk_div_table *clkt;
+	int ret, max_div = 0;
+
+	div->shift = shift;
+	div->reg = reg;
+	div->width = width;
+	div->parent = parent;
+	div->clk.ops = &clk_divider_ops;
+	div->clk.name = name;
+	div->clk.flags = flags;
+	div->clk.parent_names = &div->parent;
+	div->clk.num_parents = 1;
+	div->table = table;
+
+	for (clkt = div->table; clkt->div; clkt++) {
+		if (clkt->div > max_div) {
+			max_div = clkt->div;
+			div->max_div_index = div->table_size;
+		}
+		div->table_size++;
+	}
+
+	ret = clk_register(&div->clk);
+	if (ret) {
+		free(div);
+		return ERR_PTR(ret);
+	}
+
+	return &div->clk;
+}
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 16/29] clk: clk-fixed-factor: add set_rate/round_rate callbacks
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (14 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 15/29] clk: let clk-divider handle the table based divider aswell Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 17/29] clk: Add parent round/set rate for mux and gate Sascha Hauer
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk-fixed-factor.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index df0d2f3..cb531b1 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -35,7 +35,37 @@ static unsigned long clk_fixed_factor_recalc_rate(struct clk *clk,
 	return (parent_rate / f->div) * f->mult;
 }
 
+static long clk_factor_round_rate(struct clk *clk, unsigned long rate,
+		unsigned long *prate)
+{
+	struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk);
+
+	if (clk->flags & CLK_SET_RATE_PARENT) {
+		unsigned long best_parent;
+
+		best_parent = (rate / fix->mult) * fix->div;
+		*prate = clk_round_rate(clk_get_parent(clk), best_parent);
+	}
+
+	return (*prate / fix->div) * fix->mult;
+}
+
+static int clk_factor_set_rate(struct clk *clk, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk);
+
+	if (clk->flags & CLK_SET_RATE_PARENT) {
+		printk("%s: %ld -> parent %ld\n", __func__, rate, rate * fix->div / fix->mult);
+		return clk_set_rate(clk_get_parent(clk), rate * fix->div / fix->mult);
+	}
+
+	return 0;
+}
+
 static struct clk_ops clk_fixed_factor_ops = {
+	.set_rate = clk_factor_set_rate,
+	.round_rate = clk_factor_round_rate,
 	.recalc_rate = clk_fixed_factor_recalc_rate,
 };
 
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 17/29] clk: Add parent round/set rate for mux and gate
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (15 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 16/29] clk: clk-fixed-factor: add set_rate/round_rate callbacks Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 18/29] ARM: i.MX: introduce clk parent rate changes Sascha Hauer
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk-gate.c |  2 ++
 drivers/clk/clk-mux.c  |  2 ++
 drivers/clk/clk.c      | 20 ++++++++++++++++++++
 include/linux/clk.h    |  4 ++++
 4 files changed, 28 insertions(+)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index f356de7..b298b19 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -77,6 +77,8 @@ static int clk_gate_is_enabled(struct clk *clk)
 }
 
 static struct clk_ops clk_gate_ops = {
+	.set_rate = clk_parent_set_rate,
+	.round_rate = clk_parent_round_rate,
 	.enable = clk_gate_enable,
 	.disable = clk_gate_disable,
 	.is_enabled = clk_gate_is_enabled,
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 9dcd39c..4ce86f4 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -51,6 +51,8 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx)
 }
 
 static struct clk_ops clk_mux_ops = {
+	.set_rate = clk_parent_set_rate,
+	.round_rate = clk_parent_round_rate,
 	.get_parent = clk_mux_get_parent,
 	.set_parent = clk_mux_set_parent,
 };
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c67b2f4..0d25941 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -259,11 +259,31 @@ int clk_is_enabled(struct clk *clk)
 	return clk_is_enabled(clk);
 }
 
+/*
+ * Generic struct clk_ops callbacks
+ */
 int clk_is_enabled_always(struct clk *clk)
 {
 	return 1;
 }
 
+long clk_parent_round_rate(struct clk *clk, unsigned long rate,
+				unsigned long *prate)
+{
+	if (!(clk->flags & CLK_SET_RATE_PARENT))
+		return *prate;
+
+	return clk_round_rate(clk_get_parent(clk), rate);
+}
+
+int clk_parent_set_rate(struct clk *clk, unsigned long rate,
+				unsigned long parent_rate)
+{
+	if (!(clk->flags & CLK_SET_RATE_PARENT))
+		return 0;
+	return clk_set_rate(clk_get_parent(clk), rate);
+}
+
 #if defined(CONFIG_OFTREE) && defined(CONFIG_COMMON_CLK_OF_PROVIDER)
 /**
  * struct of_clk_provider - Clock provider registration structure
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 71b0466..07b27cf 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -276,6 +276,10 @@ struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem
 int clk_is_enabled(struct clk *clk);
 
 int clk_is_enabled_always(struct clk *clk);
+long clk_parent_round_rate(struct clk *clk, unsigned long rate,
+				unsigned long *prate);
+int clk_parent_set_rate(struct clk *clk, unsigned long rate,
+				unsigned long parent_rate);
 
 int clk_register(struct clk *clk);
 
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 18/29] ARM: i.MX: introduce clk parent rate changes
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (16 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 17/29] clk: Add parent round/set rate for mux and gate Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 19/29] ARM: i.MX6: Add video clocks Sascha Hauer
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Let dividers and gates change the parent rates.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk-imx6.c |  2 +-
 arch/arm/mach-imx/clk.h      | 14 +++++++++++---
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c
index 8d78a18..db16bb5 100644
--- a/arch/arm/mach-imx/clk-imx6.c
+++ b/arch/arm/mach-imx/clk-imx6.c
@@ -214,7 +214,7 @@ static int imx6_ccm_probe(struct device_d *dev)
 	clks[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
 	clks[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
 
-	clks[enet_ref] = clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table, 0);
+	clks[enet_ref] = imx_clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table);
 
 	/*                                name               parent_name         reg          idx */
 	clks[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index cdafad1..d83266b 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -4,13 +4,21 @@
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 		void __iomem *reg, u8 shift, u8 width)
 {
-	return clk_divider(name, parent, reg, shift, width, 0);
+	return clk_divider(name, parent, reg, shift, width, CLK_SET_RATE_PARENT);
+}
+
+static inline struct clk *imx_clk_divider_table(const char *name,
+		const char *parent, void __iomem *reg, u8 shift, u8 width,
+		const struct clk_div_table *table)
+{
+	return clk_divider_table(name, parent, reg, shift, width, table,
+			CLK_SET_RATE_PARENT);
 }
 
 static inline struct clk *imx_clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div)
 {
-	return clk_fixed_factor(name, parent, mult, div, 0);
+	return clk_fixed_factor(name, parent, mult, div, CLK_SET_RATE_PARENT);
 }
 
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
@@ -22,7 +30,7 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
-	return clk_gate(name, parent, reg, shift, 0);
+	return clk_gate(name, parent, reg, shift, CLK_SET_RATE_PARENT);
 }
 
 struct clk *imx_clk_pllv1(const char *name, const char *parent,
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 19/29] ARM: i.MX6: Add video clocks
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (17 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 18/29] ARM: i.MX: introduce clk parent rate changes Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 20/29] video: introduce struct display_timings Sascha Hauer
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

This adds the IPU, LVDS and HDMI clocks. As these are many, depend
on the IPU driver being compiled in.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk-imx6.c               | 153 ++++++++++++++++++++++++++++-
 arch/arm/mach-imx/clk.h                    |   6 ++
 arch/arm/mach-imx/include/mach/imx6-regs.h |   3 +
 3 files changed, 158 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c
index db16bb5..518fc00 100644
--- a/arch/arm/mach-imx/clk-imx6.c
+++ b/arch/arm/mach-imx/clk-imx6.c
@@ -19,6 +19,8 @@
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <mach/imx6-regs.h>
+#include <mach/revision.h>
+#include <mach/imx6.h>
 
 #include "clk.h"
 
@@ -84,8 +86,10 @@ enum mx6q_clks {
 	usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
 	pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
 	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
-	sata_ref, pcie_ref, sata_ref_100m, pcie_ref_125m, enet_ref,
-	clk_max
+	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
+	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
+	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
+	lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max
 };
 
 static struct clk *clks[clk_max];
@@ -171,6 +175,62 @@ static const char *cko1_sels[] = {
 	"pll4_audio",
 };
 
+static const char *ipu_sels[] = {
+	"mmdc_ch0_axi_podf",
+	"pll2_pfd2_396m",
+	"pll3_120m",
+	"pll3_pfd1_540m",
+};
+
+static const char *ldb_di_sels[] = {
+	"pll5_video_div",
+	"pll2_pfd0_352m",
+	"pll2_pfd2_396m",
+	"mmdc_ch1_axi_podf",
+	"pll3_usb_otg",
+};
+
+static const char *ipu_di_pre_sels[] = {
+	"mmdc_ch0_axi",
+	"pll3_usb_otg",
+	"pll5_video_div",
+	"pll2_pfd0_352m",
+	"pll2_pfd2_396m",
+	"pll3_pfd1_540m",
+};
+
+static const char *ipu1_di0_sels[] = {
+	"ipu1_di0_pre",
+	"dummy",
+	"dummy",
+	"ldb_di0_podf",
+	"ldb_di1_podf",
+};
+
+static const char *ipu1_di1_sels[] = {
+	"ipu1_di1_pre",
+	"dummy",
+	"dummy",
+	"ldb_di0_podf",
+	"ldb_di1_podf",
+};
+
+static const char *ipu2_di0_sels[] = {
+	"ipu2_di0_pre",
+	"dummy",
+	"dummy",
+	"ldb_di0_podf",
+	"ldb_di1_podf",
+};
+
+static const char *ipu2_di1_sels[] = {
+	"ipu2_di1_pre",
+	"dummy",
+	"dummy",
+	"ldb_di0_podf",
+	"ldb_di1_podf",
+};
+
 static struct clk_div_table clk_enet_ref_table[] = {
 	{ .val = 0, .div = 20, },
 	{ .val = 1, .div = 10, },
@@ -179,6 +239,86 @@ static struct clk_div_table clk_enet_ref_table[] = {
 	{ },
 };
 
+static struct clk_div_table post_div_table[] = {
+	{ .val = 2, .div = 1, },
+	{ .val = 1, .div = 2, },
+	{ .val = 0, .div = 4, },
+	{ /* sentinel */ }
+};
+
+static struct clk_div_table video_div_table[] = {
+	{ .val = 0, .div = 1, },
+	{ .val = 1, .div = 2, },
+	{ .val = 2, .div = 1, },
+	{ .val = 3, .div = 4, },
+	{ /* sentinel */ }
+};
+
+static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb)
+{
+	clks[pll5_post_div] = imx_clk_divider_table("pll5_post_div", "pll5_video", anab + 0xa0, 19, 2, post_div_table);
+	clks[pll5_video_div] = imx_clk_divider_table("pll5_video_div", "pll5_post_div", anab + 0x170, 30, 2, video_div_table);
+
+	clks[ipu1_sel]         = imx_clk_mux("ipu1_sel",         cb + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
+	clks[ipu2_sel]         = imx_clk_mux("ipu2_sel",         cb + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
+	clks[ldb_di0_sel]      = imx_clk_mux_p("ldb_di0_sel",      cb + 0x2c, 9,  3, ldb_di_sels,       ARRAY_SIZE(ldb_di_sels));
+	clks[ldb_di1_sel]      = imx_clk_mux_p("ldb_di1_sel",      cb + 0x2c, 12, 3, ldb_di_sels,       ARRAY_SIZE(ldb_di_sels));
+	clks[ipu1_di0_pre_sel] = imx_clk_mux_p("ipu1_di0_pre_sel", cb + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
+	clks[ipu1_di1_pre_sel] = imx_clk_mux_p("ipu1_di1_pre_sel", cb + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
+	clks[ipu2_di0_pre_sel] = imx_clk_mux_p("ipu2_di0_pre_sel", cb + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
+	clks[ipu2_di1_pre_sel] = imx_clk_mux_p("ipu2_di1_pre_sel", cb + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
+	clks[ipu1_di0_sel]     = imx_clk_mux_p("ipu1_di0_sel",     cb + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels));
+	clks[ipu1_di1_sel]     = imx_clk_mux_p("ipu1_di1_sel",     cb + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels));
+	clks[ipu2_di0_sel]     = imx_clk_mux_p("ipu2_di0_sel",     cb + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels));
+	clks[ipu2_di1_sel]     = imx_clk_mux_p("ipu2_di1_sel",     cb + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels));
+
+	clks[ipu1_podf]        = imx_clk_divider("ipu1_podf",        "ipu1_sel",          cb + 0x3c, 11, 3);
+	clks[ipu2_podf]        = imx_clk_divider("ipu2_podf",        "ipu2_sel",          cb + 0x3c, 16, 3);
+	clks[ldb_di0_div_3_5]  = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+	clks[ldb_di0_podf]     = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", cb + 0x20, 10, 1);
+	clks[ldb_di1_div_3_5]  = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+	clks[ldb_di1_podf]     = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", cb + 0x20, 11, 1);
+	clks[ipu1_di0_pre]     = imx_clk_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  cb + 0x34, 3,  3);
+	clks[ipu1_di1_pre]     = imx_clk_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  cb + 0x34, 12, 3);
+	clks[ipu2_di0_pre]     = imx_clk_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  cb + 0x38, 3,  3);
+	clks[ipu2_di1_pre]     = imx_clk_divider("ipu2_di1_pre",     "ipu2_di1_pre_sel",  cb + 0x38, 12, 3);
+
+	clkdev_add_physbase(clks[ipu1_podf], MX6_IPU1_BASE_ADDR, "bus");
+	clkdev_add_physbase(clks[ipu1_di0_sel], MX6_IPU1_BASE_ADDR, "di0");
+	clkdev_add_physbase(clks[ipu1_di1_sel], MX6_IPU1_BASE_ADDR, "di1");
+	clkdev_add_physbase(clks[ipu2_podf], MX6_IPU2_BASE_ADDR, "bus");
+	clkdev_add_physbase(clks[ipu2_di0_sel], MX6_IPU2_BASE_ADDR, "di0");
+	clkdev_add_physbase(clks[ipu2_di1_sel], MX6_IPU2_BASE_ADDR, "di1");
+
+	clkdev_add_physbase(clks[ldb_di0_sel], 0x020e0008, "di0_pll");
+	clkdev_add_physbase(clks[ldb_di1_sel], 0x020e0008, "di1_pll");
+	clkdev_add_physbase(clks[ipu1_di0_sel], 0x020e0008, "di0_sel");
+	clkdev_add_physbase(clks[ipu1_di1_sel], 0x020e0008, "di1_sel");
+	clkdev_add_physbase(clks[ipu2_di0_sel], 0x020e0008, "di2_sel");
+	clkdev_add_physbase(clks[ipu2_di1_sel], 0x020e0008, "di3_sel");
+	clkdev_add_physbase(clks[ldb_di0], 0x020e0008, "di0");
+	clkdev_add_physbase(clks[ldb_di1], 0x020e0008, "di1");
+	clkdev_add_physbase(clks[ahb], 0x00120000, "iahb");
+	clkdev_add_physbase(clks[pll3_pfd1_540m], 0x00120000, "isfr");
+
+	clk_set_parent(clks[ipu1_di0_sel], clks[ipu1_di0_pre]);
+	clk_set_parent(clks[ipu1_di1_sel], clks[ipu1_di1_pre]);
+	clk_set_parent(clks[ipu2_di0_sel], clks[ipu2_di0_pre]);
+	clk_set_parent(clks[ipu2_di1_sel], clks[ipu2_di1_pre]);
+
+	clk_set_parent(clks[ipu1_di0_pre_sel], clks[pll5_video_div]);
+	clk_set_parent(clks[ipu1_di1_pre_sel], clks[pll5_video_div]);
+	clk_set_parent(clks[ipu2_di0_pre_sel], clks[pll5_video_div]);
+	clk_set_parent(clks[ipu2_di1_pre_sel], clks[pll5_video_div]);
+
+	if ((imx_silicon_revision() != IMX_CHIP_REV_1_0) ||
+	    cpu_is_mx6dl()) {
+		clk_set_parent(clks[ldb_di0_sel], clks[pll5_video_div]);
+		clk_set_parent(clks[ldb_di1_sel], clks[pll5_video_div]);
+	}
+
+}
+
 static int imx6_ccm_probe(struct device_d *dev)
 {
 	void __iomem *base, *anatop_base, *ccm_base;
@@ -281,7 +421,6 @@ static int imx6_ccm_probe(struct device_d *dev)
 	clks[arm]               = imx_clk_busy_divider("arm",               "pll1_sw",     base + 0x10, 0,   3,   base + 0x48, 16);
 	clks[ahb]               = imx_clk_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
 
-
 	clkdev_add_physbase(clks[uart_serial_podf], MX6_UART1_BASE_ADDR, NULL);
 	clkdev_add_physbase(clks[uart_serial_podf], MX6_UART2_BASE_ADDR, NULL);
 	clkdev_add_physbase(clks[uart_serial_podf], MX6_UART3_BASE_ADDR, NULL);
@@ -310,10 +449,16 @@ static int imx6_ccm_probe(struct device_d *dev)
 	clkdev_add_physbase(clks[ipg_per], MX6_PWM3_BASE_ADDR, "per");
 	clkdev_add_physbase(clks[ipg_per], MX6_PWM4_BASE_ADDR, "per");
 
+	if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
+		imx6_add_video_clks(anatop_base, ccm_base);
+
 	writel(0xffffffff, ccm_base + CCGR0);
 	writel(0xf0ffffff, ccm_base + CCGR1); /* gate GPU3D, GPU2D */
 	writel(0xffffffff, ccm_base + CCGR2);
-	writel(0x3fff0000, ccm_base + CCGR3); /* gate OpenVG, LDB, IPU1, IPU2 */
+	if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
+		writel(0xffffffff, ccm_base + CCGR3); /* gate OpenVG */
+	else
+		writel(0x3fffffff, ccm_base + CCGR3); /* gate OpenVG, LDB, IPU1, IPU2 */
 	writel(0xffffffff, ccm_base + CCGR4);
 	writel(0xffffffff, ccm_base + CCGR5);
 	writel(0xffff3fff, ccm_base + CCGR6); /* gate VPU */
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index d83266b..32a02db 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -27,6 +27,12 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 	return clk_mux(name, reg, shift, width, parents, num_parents, 0);
 }
 
+static inline struct clk *imx_clk_mux_p(const char *name, void __iomem *reg,
+		u8 shift, u8 width, const char **parents, u8 num_parents)
+{
+	return clk_mux(name, reg, shift, width, parents, num_parents, CLK_SET_RATE_PARENT);
+}
+
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h
index 833280a..facbe51 100644
--- a/arch/arm/mach-imx/include/mach/imx6-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx6-regs.h
@@ -26,6 +26,9 @@
 #define MX6_SPBA_BASE_ADDR              (MX6_ATZ1_BASE_ADDR + 0x3C000)
 #define MX6_VPU_BASE_ADDR               (MX6_ATZ1_BASE_ADDR + 0x40000)
 
+#define MX6_IPU1_BASE_ADDR		0x02400000
+#define MX6_IPU2_BASE_ADDR		0x02800000
+
 /* ATZ#1- On Platform */
 #define MX6_AIPS1_ON_BASE_ADDR          (MX6_ATZ1_BASE_ADDR + 0x7C000)
 
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 20/29] video: introduce struct display_timings
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (18 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 19/29] ARM: i.MX6: Add video clocks Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 21/29] video: rework mode_name parameter setting Sascha Hauer
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

And use it inside struct fb_info. This struct has the advantage
that the supported modes can be passed around in a single pointer.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/atmel_lcdfb_core.c |  4 ++--
 drivers/video/fb.c               | 20 +++++++++++---------
 drivers/video/imx-ipu-fb.c       |  4 ++--
 drivers/video/imx.c              |  6 +++---
 drivers/video/omap.c             |  4 ++--
 drivers/video/s3c24xx.c          |  4 ++--
 drivers/video/sdl.c              |  4 ++--
 drivers/video/stm.c              |  4 ++--
 include/fb.h                     | 16 ++++++++++++++--
 9 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
index bed540d..4c912cc 100644
--- a/drivers/video/atmel_lcdfb_core.c
+++ b/drivers/video/atmel_lcdfb_core.c
@@ -269,8 +269,8 @@ int atmel_lcdc_register(struct device_d *dev, struct atmel_lcdfb_devdata *data)
 	info = &sinfo->info;
 	info->priv = sinfo;
 	info->fbops = &atmel_lcdc_ops;
-	info->mode_list = pdata->mode_list;
-	info->num_modes = pdata->num_modes;
+	info->modes.modes = pdata->mode_list;
+	info->modes.num_modes = pdata->num_modes;
 	info->mode = &info->mode_list[0];
 	info->xres = info->mode->xres;
 	info->yres = info->mode->yres;
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index c36b9ad..e614d77 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -53,6 +53,7 @@ static int fb_setup_mode(struct device_d *dev, struct param_d *param,
 		const char *val)
 {
 	struct fb_info *info = dev->priv;
+	struct display_timings *dt;
 	int mode, ret;
 
 	if (info->enabled != 0)
@@ -61,14 +62,15 @@ static int fb_setup_mode(struct device_d *dev, struct param_d *param,
 	if (!val)
 		return dev_param_set_generic(dev, param, NULL);
 
-	for (mode = 0; mode < info->num_modes; mode++) {
-		if (!strcmp(info->mode_list[mode].name, val))
+	dt = &info->modes;
+	for (mode = 0; mode < dt->num_modes; mode++) {
+		if (!strcmp(dt->modes[mode].name, val))
 			break;
 	}
-	if (mode >= info->num_modes)
+	if (mode >= dt->num_modes)
 		return -EINVAL;
 
-	info->mode = &info->mode_list[mode];
+	info->mode = &dt->modes[mode];
 
 	info->xres = info->mode->xres;
 	info->yres = info->mode->yres;
@@ -105,13 +107,13 @@ static void fb_info(struct device_d *dev)
 	struct fb_info *info = dev->priv;
 	int i;
 
-	if (!info->num_modes)
+	if (!info->modes.num_modes)
 		return;
 
 	printf("available modes:\n");
 
-	for (i = 0; i < info->num_modes; i++) {
-		struct fb_videomode *mode = &info->mode_list[i];
+	for (i = 0; i < info->modes.num_modes; i++) {
+		struct fb_videomode *mode = &info->modes.modes[i];
 
 		printf("%-10s %dx%d@%d\n", mode->name,
 				mode->xres, mode->yres, mode->refresh);
@@ -155,10 +157,10 @@ int register_framebuffer(struct fb_info *info)
 	dev_add_param_bool(dev, "enable", fb_enable_set, NULL,
 			&info->p_enable, info);
 
-	if (info->num_modes && (info->mode_list != NULL) &&
+	if (info->modes.num_modes &&
 			(info->fbops->fb_activate_var != NULL)) {
 		dev_add_param(dev, "mode_name", fb_setup_mode, NULL, 0);
-		dev_set_param(dev, "mode_name", info->mode_list[0].name);
+		dev_set_param(dev, "mode_name", info->modes.modes[0].name);
 	}
 
 	ret = devfs_create(&info->cdev);
diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c
index 7276647..0ee2b26 100644
--- a/drivers/video/imx-ipu-fb.c
+++ b/drivers/video/imx-ipu-fb.c
@@ -1007,8 +1007,8 @@ static int imxfb_probe(struct device_d *dev)
 	fbi->disable_fractional_divider = pdata->disable_fractional_divider;
 	info->priv = fbi;
 	info->fbops = &imxfb_ops;
-	info->num_modes = pdata->num_modes;
-	info->mode_list = pdata->mode;
+	info->modes.modes = pdata->mode;
+	info->modes.num_modes = pdata->num_modes;
 
 	imxfb_init_info(info, pdata->mode, pdata->bpp);
 
diff --git a/drivers/video/imx.c b/drivers/video/imx.c
index 05c6105..1dd6511 100644
--- a/drivers/video/imx.c
+++ b/drivers/video/imx.c
@@ -294,7 +294,7 @@ static int imxfb_activate_var(struct fb_info *info)
 	u32 pcr;
 	int i;
 
-	for (i = 0; i < info->num_modes; i++) {
+	for (i = 0; i < info->modes.num_modes; i++) {
 		if (!strcmp(fbi->mode[i].mode.name, mode->name)) {
 			fbi->pcr = fbi->mode[i].pcr;
 			break;
@@ -551,8 +551,8 @@ static int imxfb_probe(struct device_d *dev)
 	fbi->enable = pdata->enable;
 	fbi->dev = dev;
 	info->priv = fbi;
-	info->mode_list = mode_list;
-	info->num_modes = pdata->num_modes;
+	info->modes.modes = mode_list;
+	info->modes.num_modes = pdata->num_modes;
 	info->mode = &pdata->mode->mode;
 	info->xres = pdata->mode->mode.xres;
 	info->yres = pdata->mode->mode.yres;
diff --git a/drivers/video/omap.c b/drivers/video/omap.c
index 487aca6..485cc75 100644
--- a/drivers/video/omap.c
+++ b/drivers/video/omap.c
@@ -467,8 +467,8 @@ static int omapfb_probe(struct device_d *dev)
 	for (i = 0; i < pdata->num_displays; ++i)
 		fbi->video_modes[i] = pdata->displays[i].mode;
 
-	info->mode_list = fbi->video_modes;
-	info->num_modes = pdata->num_displays;
+	info->modes.modes = fbi->video_modes;
+	info->modes.num_modes = pdata->num_displays;
 
 	info->priv = fbi;
 	info->fbops = &omapfb_ops;
diff --git a/drivers/video/s3c24xx.c b/drivers/video/s3c24xx.c
index c3e05c6..cf45376 100644
--- a/drivers/video/s3c24xx.c
+++ b/drivers/video/s3c24xx.c
@@ -376,8 +376,8 @@ static int s3cfb_probe(struct device_d *hw_dev)
 	hw_dev->priv = &fbi;
 
 	/* add runtime video info */
-	fbi.info.mode_list = pdata->mode_list;
-	fbi.info.num_modes = pdata->mode_cnt;
+	fbi.info.modes.modes = pdata->mode_list;
+	fbi.info.modes.num_modes = pdata->mode_cnt;
 	fbi.info.mode = &fbi.info.mode_list[1];
 	fbi.info.xres = fbi.info.mode->xres;
 	fbi.info.yres = fbi.info.mode->yres;
diff --git a/drivers/video/sdl.c b/drivers/video/sdl.c
index 8dec5e5..a568340 100644
--- a/drivers/video/sdl.c
+++ b/drivers/video/sdl.c
@@ -37,8 +37,8 @@ static int sdlfb_probe(struct device_d *dev)
 		return -EIO;
 
 	fb = xzalloc(sizeof(*fb));
-	fb->mode_list = fb->mode = dev->platform_data;
-	fb->num_modes = 1;
+	fb->modes.modes = fb->mode = dev->platform_data;
+	fb->modes.num_modes = 1;
 	fb->bits_per_pixel = 4 << 3;
 	fb->xres = fb->mode->xres;
 	fb->yres = fb->mode->yres;
diff --git a/drivers/video/stm.c b/drivers/video/stm.c
index fdeaf9c..b20e552 100644
--- a/drivers/video/stm.c
+++ b/drivers/video/stm.c
@@ -499,8 +499,8 @@ static int stmfb_probe(struct device_d *hw_dev)
 	clk_enable(fbi.clk);
 
 	/* add runtime video info */
-	fbi.info.mode_list = pdata->mode_list;
-	fbi.info.num_modes = pdata->mode_cnt;
+	fbi.info.modes.modes = pdata->mode_list;
+	fbi.info.modes.num_modes = pdata->mode_cnt;
 	fbi.info.mode = &fbi.info.mode_list[0];
 	fbi.info.xres = fbi.info.mode->xres;
 	fbi.info.yres = fbi.info.mode->yres;
diff --git a/include/fb.h b/include/fb.h
index 22fa9b1..1cc352b 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -77,10 +77,22 @@ struct fb_ops {
 	int (*fb_activate_var)(struct fb_info *info);
 };
 
+/*
+ * This describes all timing settings a display provides.
+ * The native_mode is the default setting for this display.
+ * Drivers that can handle multiple videomodes should work with this struct and
+ * convert each entry to the desired end result.
+ */
+struct display_timings {
+	unsigned int native_mode;
+
+	unsigned int num_modes;
+	struct fb_videomode *modes;
+};
+
 struct fb_info {
 	struct fb_videomode *mode;
-	struct fb_videomode *mode_list;
-	unsigned num_modes;
+	struct display_timings modes;
 
 	struct fb_ops *fbops;
 	struct device_d dev;		/* This is this fb device */
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 21/29] video: rework mode_name parameter setting
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (19 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 20/29] video: introduce struct display_timings Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-04-07 14:45   ` Alexander Shiyan
  2014-03-14 14:32 ` [PATCH 22/29] video: Add display timing from devicetree helper Sascha Hauer
                   ` (6 subsequent siblings)
  27 siblings, 1 reply; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

We have dev_add_param_enum() now, so use it for the mode_name
setting. Also drop the special case for single mode framebuffers,
just add the mode_name parameter for this case aswell.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/fb.c | 107 ++++++++++++++++++++++++++++++++++++-----------------
 include/fb.h       |   2 +
 2 files changed, 76 insertions(+), 33 deletions(-)

diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index e614d77..d7a3d3c 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -49,34 +49,42 @@ static int fb_enable_set(struct param_d *param, void *priv)
 	return 0;
 }
 
-static int fb_setup_mode(struct device_d *dev, struct param_d *param,
-		const char *val)
+static struct fb_videomode *fb_num_to_mode(struct fb_info *info, int num)
 {
-	struct fb_info *info = dev->priv;
-	struct display_timings *dt;
-	int mode, ret;
+	int num_modes;
+
+	num_modes = info->modes.num_modes;
+
+	if (num >= num_modes)
+		return NULL;
+
+	return &info->modes.modes[num];
+}
+
+static int fb_setup_mode(struct fb_info *info)
+{
+	struct device_d *dev = &info->dev;
+	int ret;
+	struct fb_videomode *mode;
 
 	if (info->enabled != 0)
 		return -EPERM;
 
-	if (!val)
-		return dev_param_set_generic(dev, param, NULL);
-
-	dt = &info->modes;
-	for (mode = 0; mode < dt->num_modes; mode++) {
-		if (!strcmp(dt->modes[mode].name, val))
-			break;
-	}
-	if (mode >= dt->num_modes)
+	mode = fb_num_to_mode(info, info->current_mode);
+	if (!mode)
 		return -EINVAL;
 
-	info->mode = &dt->modes[mode];
+	info->mode = mode;
 
 	info->xres = info->mode->xres;
 	info->yres = info->mode->yres;
 	info->line_length = 0;
 
-	ret = info->fbops->fb_activate_var(info);
+	if (info->fbops->fb_activate_var) {
+		ret = info->fbops->fb_activate_var(info);
+		if (ret)
+			return ret;
+	}
 
 	if (!info->line_length)
 		info->line_length = info->xres * (info->bits_per_pixel >> 3);
@@ -87,13 +95,24 @@ static int fb_setup_mode(struct device_d *dev, struct param_d *param,
 		dev->resource[0].start = (resource_size_t)info->screen_base;
 		info->cdev.size = info->line_length * info->yres;
 		dev->resource[0].end = dev->resource[0].start + info->cdev.size - 1;
-		dev_param_set_generic(dev, param, val);
 	} else
 		info->cdev.size = 0;
 
 	return ret;
 }
 
+static int fb_set_modename(struct param_d *param, void *priv)
+{
+	struct fb_info *info = priv;
+	int ret;
+
+	ret = fb_setup_mode(info);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static struct file_operations fb_ops = {
 	.read	= mem_read,
 	.write	= mem_write,
@@ -102,22 +121,27 @@ static struct file_operations fb_ops = {
 	.ioctl	= fb_ioctl,
 };
 
-static void fb_info(struct device_d *dev)
+static void fb_print_mode(struct fb_videomode *mode)
+{
+	printf("%-20s %dx%d@%d\n", mode->name,
+			mode->xres, mode->yres, mode->refresh);
+}
+
+static void fb_print_modes(struct display_timings *modes)
 {
-	struct fb_info *info = dev->priv;
 	int i;
 
-	if (!info->modes.num_modes)
-		return;
+	for (i = 0; i < modes->num_modes; i++)
+		fb_print_mode(&modes->modes[i]);
+}
+
+static void fb_info(struct device_d *dev)
+{
+	struct fb_info *info = dev->priv;
 
 	printf("available modes:\n");
 
-	for (i = 0; i < info->modes.num_modes; i++) {
-		struct fb_videomode *mode = &info->modes.modes[i];
-
-		printf("%-10s %dx%d@%d\n", mode->name,
-				mode->xres, mode->yres, mode->refresh);
-	}
+	fb_print_modes(&info->modes);
 
 	printf("\n");
 }
@@ -126,10 +150,20 @@ int register_framebuffer(struct fb_info *info)
 {
 	int id = get_free_deviceid("fb");
 	struct device_d *dev;
-	int ret;
+	int ret, num_modes, i;
+	const char **names;
 
 	dev = &info->dev;
 
+	/*
+	 * If info->mode is set at this point it's the only mode
+	 * the fb supports. move it over to the modes list.
+	 */
+	if (info->mode) {
+		info->modes.modes = info->mode;
+		info->modes.num_modes = 1;
+	}
+
 	if (!info->line_length)
 		info->line_length = info->xres * (info->bits_per_pixel >> 3);
 
@@ -157,11 +191,18 @@ int register_framebuffer(struct fb_info *info)
 	dev_add_param_bool(dev, "enable", fb_enable_set, NULL,
 			&info->p_enable, info);
 
-	if (info->modes.num_modes &&
-			(info->fbops->fb_activate_var != NULL)) {
-		dev_add_param(dev, "mode_name", fb_setup_mode, NULL, 0);
-		dev_set_param(dev, "mode_name", info->modes.modes[0].name);
-	}
+	num_modes = info->modes.num_modes;
+
+	names = xzalloc(sizeof(char *) * num_modes);
+
+	for (i = 0; i < info->modes.num_modes; i++)
+		names[i] = info->modes.modes[i].name;
+
+	dev_add_param_enum(dev, "mode_name", fb_set_modename, NULL, &info->current_mode, names, num_modes, info);
+
+	info->mode = fb_num_to_mode(info, 0);
+
+	fb_setup_mode(info);
 
 	ret = devfs_create(&info->cdev);
 	if (ret)
diff --git a/include/fb.h b/include/fb.h
index 1cc352b..91d3fe4 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -94,6 +94,8 @@ struct fb_info {
 	struct fb_videomode *mode;
 	struct display_timings modes;
 
+	int current_mode;
+
 	struct fb_ops *fbops;
 	struct device_d dev;		/* This is this fb device */
 
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 22/29] video: Add display timing from devicetree helper
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (20 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 21/29] video: rework mode_name parameter setting Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 23/29] video: Add edid support Sascha Hauer
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/Makefile            |   1 +
 drivers/video/of_display_timing.c | 238 ++++++++++++++++++++++++++++++++++++++
 include/fb.h                      |  14 ++-
 3 files changed, 252 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/of_display_timing.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 31edfca..d36d83d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_VIDEO) += fb.o
+obj-$(CONFIG_OFDEVICE) += of_display_timing.o
 
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
new file mode 100644
index 0000000..5dfd5b3
--- /dev/null
+++ b/drivers/video/of_display_timing.c
@@ -0,0 +1,238 @@
+/*
+ * OF helpers for parsing display timings
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ */
+#include <common.h>
+#include <of.h>
+#include <fb.h>
+#include <malloc.h>
+
+void display_timings_release(struct display_timings *disp)
+{
+	free(disp->modes);
+	free(disp);
+}
+EXPORT_SYMBOL_GPL(display_timings_release);
+
+/**
+ * parse_timing_property - parse timing_entry from device_node
+ * @np: device_node with the property
+ * @name: name of the property
+ * @result: will be set to the return value
+ *
+ * DESCRIPTION:
+ * Every display_timing can be specified with either just the typical value or
+ * a range consisting of min/typ/max. This function helps handling this
+ **/
+static int parse_timing_property(const struct device_node *np, const char *name,
+			  u32 *res)
+{
+	struct property *prop;
+	int length, cells, ret;
+
+	prop = of_find_property(np, name, &length);
+	if (!prop) {
+		pr_err("%s: could not find property %s\n",
+			np->full_name, name);
+		return -EINVAL;
+	}
+
+	cells = length / sizeof(u32);
+	if (cells == 1) {
+		ret = of_property_read_u32(np, name, res);
+	} else {
+		pr_err("%s: illegal timing specification in %s\n",
+			np->full_name, name);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * of_parse_display_timing - parse display_timing entry from device_node
+ * @np: device_node with the properties
+ **/
+static int of_parse_display_timing(const struct device_node *np,
+		struct fb_videomode *mode)
+{
+	u32 val = 0, pixelclock = 0;
+	int ret = 0;
+
+	memset(mode, 0, sizeof(*mode));
+
+	ret |= parse_timing_property(np, "hback-porch", &mode->left_margin);
+	ret |= parse_timing_property(np, "hfront-porch", &mode->right_margin);
+	ret |= parse_timing_property(np, "hactive", &mode->xres);
+	ret |= parse_timing_property(np, "hsync-len", &mode->hsync_len);
+	ret |= parse_timing_property(np, "vback-porch", &mode->upper_margin);
+	ret |= parse_timing_property(np, "vfront-porch", &mode->lower_margin);
+	ret |= parse_timing_property(np, "vactive", &mode->yres);
+	ret |= parse_timing_property(np, "vsync-len", &mode->vsync_len);
+	ret |= parse_timing_property(np, "clock-frequency", &pixelclock);
+
+	mode->pixclock = pixelclock ? KHZ2PICOS(pixelclock / 1000) : 0;
+
+	if (!of_property_read_u32(np, "vsync-active", &val))
+		mode->sync |= val ? FB_SYNC_VERT_HIGH_ACT : 0;
+	if (!of_property_read_u32(np, "hsync-active", &val))
+		mode->sync |= val ? FB_SYNC_HOR_HIGH_ACT : 0;
+	if (!of_property_read_u32(np, "de-active", &val))
+		mode->display_flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+				DISPLAY_FLAGS_DE_LOW;
+	if (!of_property_read_u32(np, "pixelclk-active", &val))
+		mode->display_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+
+	if (ret) {
+		pr_err("%s: error reading timing properties\n",
+			np->full_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * of_get_display_timing - parse a display_timing entry
+ * @np: device_node with the timing subnode
+ * @name: name of the timing node
+ * @dt: display_timing struct to fill
+ **/
+int of_get_display_timing(struct device_node *np, const char *name,
+		struct fb_videomode *mode)
+{
+	struct device_node *timing_np;
+
+	if (!np) {
+		pr_err("%s: no devicenode given\n", np->full_name);
+		return -EINVAL;
+	}
+
+	timing_np = of_get_child_by_name(np, name);
+	if (!timing_np) {
+		pr_err("%s: could not find node '%s'\n",
+			np->full_name, name);
+		return -ENOENT;
+	}
+
+	return of_parse_display_timing(timing_np, mode);
+}
+EXPORT_SYMBOL_GPL(of_get_display_timing);
+
+/**
+ * of_get_display_timings - parse all display_timing entries from a device_node
+ * @np: device_node with the subnodes
+ **/
+struct display_timings *of_get_display_timings(struct device_node *np)
+{
+	struct device_node *timings_np;
+	struct device_node *entry;
+	struct device_node *native_mode;
+	struct display_timings *disp;
+
+	if (!np) {
+		pr_err("%s: no device node given\n", np->full_name);
+		return NULL;
+	}
+
+	timings_np = of_get_child_by_name(np, "display-timings");
+	if (!timings_np) {
+		pr_debug("%s: could not find display-timings node\n",
+			np->full_name);
+		return NULL;
+	}
+
+	disp = xzalloc(sizeof(*disp));
+
+	entry = of_parse_phandle(timings_np, "native-mode", 0);
+	/* assume first child as native mode if none provided */
+	if (!entry)
+		entry = of_get_next_available_child(np, NULL);
+	/* if there is no child, it is useless to go on */
+	if (!entry) {
+		pr_err("%s: no timing specifications given\n",
+			np->full_name);
+		goto entryfail;
+	}
+
+	pr_debug("%s: using %s as default timing\n",
+		np->full_name, entry->name);
+
+	native_mode = entry;
+
+	disp->num_modes = of_get_child_count(timings_np);
+	if (disp->num_modes == 0) {
+		/* should never happen, as entry was already found above */
+		pr_err("%s: no timings specified\n", np->full_name);
+		goto entryfail;
+	}
+
+	disp->modes = xzalloc(sizeof(struct fb_videomode) * disp->num_modes);
+
+	disp->num_modes = 0;
+	disp->native_mode = 0;
+
+	for_each_child_of_node(timings_np, entry) {
+		struct fb_videomode *mode;
+		int r;
+
+		mode = &disp->modes[disp->num_modes];
+
+		r = of_parse_display_timing(entry, mode);
+		if (r) {
+			/*
+			 * to not encourage wrong devicetrees, fail in case of
+			 * an error
+			 */
+			pr_err("%s: error in timing %d\n",
+				np->full_name, disp->num_modes + 1);
+			goto timingfail;
+		}
+
+		mode->name = xstrdup(entry->name);
+
+		if (native_mode == entry)
+			disp->native_mode = disp->num_modes;
+
+		disp->num_modes++;
+	}
+
+	pr_debug("%s: got %d timings. Using timing #%d as default\n",
+		np->full_name, disp->num_modes,
+		disp->native_mode + 1);
+
+	return disp;
+
+timingfail:
+	display_timings_release(disp);
+entryfail:
+	free(disp);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_get_display_timings);
+
+/**
+ * of_display_timings_exist - check if a display-timings node is provided
+ * @np: device_node with the timing
+ **/
+int of_display_timings_exist(struct device_node *np)
+{
+	struct device_node *timings_np;
+
+	if (!np)
+		return -EINVAL;
+
+	timings_np = of_parse_phandle(np, "display-timings", 0);
+	if (!timings_np)
+		return -EINVAL;
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(of_display_timings_exist);
diff --git a/include/fb.h b/include/fb.h
index 91d3fe4..8d255c0 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -32,6 +32,16 @@
 #define PICOS2KHZ(a) (1000000000UL/(a))
 #define KHZ2PICOS(a) (1000000000UL/(a))
 
+enum display_flags {
+	/* data enable flag */
+	DISPLAY_FLAGS_DE_LOW		= BIT(4),
+	DISPLAY_FLAGS_DE_HIGH		= BIT(5),
+	/* drive data on pos. edge */
+	DISPLAY_FLAGS_PIXDATA_POSEDGE	= BIT(6),
+	/* drive data on neg. edge */
+	DISPLAY_FLAGS_PIXDATA_NEGEDGE	= BIT(7),
+};
+
 struct fb_videomode {
 	const char *name;	/* optional */
 	u32 refresh;		/* optional */
@@ -46,7 +56,7 @@ struct fb_videomode {
 	u32 vsync_len;
 	u32 sync;
 	u32 vmode;
-	u32 flag;
+	u32 display_flags;
 };
 
 /* Interpretation of offset for color fields: All offsets are from the right,
@@ -125,6 +135,8 @@ struct fb_info {
 					 */
 };
 
+struct display_timings *of_get_display_timings(struct device_node *np);
+
 int register_framebuffer(struct fb_info *info);
 
 #define FBIOGET_SCREENINFO	_IOR('F', 1, loff_t)
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 23/29] video: Add edid support
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (21 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 22/29] video: Add display timing from devicetree helper Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 24/29] ARM i.MX6q: Mark VPU and IPU AXI transfers as cacheable, increase IPU priority Sascha Hauer
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/Kconfig  |   6 +
 drivers/video/Makefile |   1 +
 drivers/video/edid.c   | 909 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/video/edid.h   | 138 ++++++++
 drivers/video/fb.c     |  14 +-
 include/fb.h           |  11 +-
 6 files changed, 1075 insertions(+), 4 deletions(-)
 create mode 100644 drivers/video/edid.c
 create mode 100644 drivers/video/edid.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5539266..2bab957 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -84,4 +84,10 @@ config DRIVER_VIDEO_SIMPLEFB
 	  Add support for setting up the kernel's simple framebuffer driver
 	  based on the active barebox framebuffer.
 
+config DRIVER_VIDEO_EDID
+	bool "Add EDID support"
+	help
+	  This enabled support for reading and parsing EDID data from an attached
+	  monitor.
+
 endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index d36d83d..a332848 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_VIDEO) += fb.o
+obj-$(CONFIG_DRIVER_VIDEO_EDID) += edid.o
 obj-$(CONFIG_OFDEVICE) += of_display_timing.o
 
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
diff --git a/drivers/video/edid.c b/drivers/video/edid.c
new file mode 100644
index 0000000..828c361
--- /dev/null
+++ b/drivers/video/edid.c
@@ -0,0 +1,909 @@
+/*
+ * drivers/video/edid.c
+ *
+ * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ *
+ * Credits:
+ *
+ * The EDID Parser is a conglomeration from the following sources:
+ *
+ *   1. SciTech SNAP Graphics Architecture
+ *      Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
+ *
+ *   2. XFree86 4.3.0, interpret_edid.c
+ *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ *   3. John Fremlin <vii@users.sourceforge.net> and
+ *      Ani Joshi <ajoshi@unixbox.com>
+ *
+ * Generalized Timing Formula is derived from:
+ *
+ *      GTF Spreadsheet by Andy Morrish (1/5/97)
+ *      available at http://www.vesa.org
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#define pr_fmt(fmt)  "EDID: " fmt
+
+#include <common.h>
+#include <fb.h>
+#include <malloc.h>
+#include <i2c/i2c.h>
+
+#include "edid.h"
+
+#define FBMON_FIX_HEADER  1
+#define FBMON_FIX_INPUT   2
+#define FBMON_FIX_TIMINGS 3
+
+struct broken_edid {
+	u8  manufacturer[4];
+	u32 model;
+	u32 fix;
+};
+
+static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0x00
+};
+
+static int edid_is_serial_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xff) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xfe) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xfd) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_monitor_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xfc) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_timing_block(unsigned char *block)
+{
+	if ((block[0] != 0x00) || (block[1] != 0x00) ||
+	    (block[2] != 0x00) || (block[4] != 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int check_edid(unsigned char *edid)
+{
+	unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
+	unsigned char *b;
+	u32 model;
+	int i, fix = 0, ret = 0;
+
+	manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+	manufacturer[1] = ((block[0] & 0x03) << 3) +
+		((block[1] & 0xe0) >> 5) + '@';
+	manufacturer[2] = (block[1] & 0x1f) + '@';
+	manufacturer[3] = 0;
+	model = block[2] + (block[3] << 8);
+
+	switch (fix) {
+	case FBMON_FIX_HEADER:
+		for (i = 0; i < 8; i++) {
+			if (edid[i] != edid_v1_header[i]) {
+				ret = fix;
+				break;
+			}
+		}
+		break;
+	case FBMON_FIX_INPUT:
+		b = edid + EDID_STRUCT_DISPLAY;
+		/* Only if display is GTF capable will
+		   the input type be reset to analog */
+		if (b[4] & 0x01 && b[0] & 0x80)
+			ret = fix;
+		break;
+	case FBMON_FIX_TIMINGS:
+		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+		ret = fix;
+
+		for (i = 0; i < 4; i++) {
+			if (edid_is_limits_block(b)) {
+				ret = 0;
+				break;
+			}
+
+			b += DETAILED_TIMING_DESCRIPTION_SIZE;
+		}
+
+		break;
+	}
+
+	if (ret)
+		printk("fbmon: The EDID Block of "
+		       "Manufacturer: %s Model: 0x%x is known to "
+		       "be broken,\n",  manufacturer, model);
+
+	return ret;
+}
+
+static void fix_edid(unsigned char *edid, int fix)
+{
+	int i;
+	unsigned char *b, csum = 0;
+
+	switch (fix) {
+	case FBMON_FIX_HEADER:
+		printk("fbmon: trying a header reconstruct\n");
+		memcpy(edid, edid_v1_header, 8);
+		break;
+	case FBMON_FIX_INPUT:
+		printk("fbmon: trying to fix input type\n");
+		b = edid + EDID_STRUCT_DISPLAY;
+		b[0] &= ~0x80;
+		edid[127] += 0x80;
+		break;
+	case FBMON_FIX_TIMINGS:
+		printk("fbmon: trying to fix monitor timings\n");
+		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+		for (i = 0; i < 4; i++) {
+			if (!(edid_is_serial_block(b) ||
+			      edid_is_ascii_block(b) ||
+			      edid_is_monitor_block(b) ||
+			      edid_is_timing_block(b))) {
+				b[0] = 0x00;
+				b[1] = 0x00;
+				b[2] = 0x00;
+				b[3] = 0xfd;
+				b[4] = 0x00;
+				b[5] = 60;   /* vfmin */
+				b[6] = 60;   /* vfmax */
+				b[7] = 30;   /* hfmin */
+				b[8] = 75;   /* hfmax */
+				b[9] = 17;   /* pixclock - 170 MHz*/
+				b[10] = 0;   /* GTF */
+				break;
+			}
+
+			b += DETAILED_TIMING_DESCRIPTION_SIZE;
+		}
+
+		for (i = 0; i < EDID_LENGTH - 1; i++)
+			csum += edid[i];
+
+		edid[127] = 256 - csum;
+		break;
+	}
+}
+
+static int edid_checksum(unsigned char *edid)
+{
+	unsigned char csum = 0, all_null = 0;
+	int i, err = 0, fix = check_edid(edid);
+
+	if (fix)
+		fix_edid(edid, fix);
+
+	for (i = 0; i < EDID_LENGTH; i++) {
+		csum += edid[i];
+		all_null |= edid[i];
+	}
+
+	if (csum == 0x00 && all_null) {
+		/* checksum passed, everything's good */
+		err = 1;
+	}
+
+	return err;
+}
+
+static int edid_check_header(unsigned char *edid)
+{
+	int i, err = 1, fix = check_edid(edid);
+
+	if (fix)
+		fix_edid(edid, fix);
+
+	for (i = 0; i < 8; i++) {
+		if (edid[i] != edid_v1_header[i])
+			err = 0;
+	}
+
+	return err;
+}
+
+/*
+ * VESA Generalized Timing Formula (GTF)
+ */
+
+#define FLYBACK                     550
+#define V_FRONTPORCH                1
+#define H_OFFSET                    40
+#define H_SCALEFACTOR               20
+#define H_BLANKSCALE                128
+#define H_GRADIENT                  600
+#define C_VAL                       30
+#define M_VAL                       300
+
+struct __fb_timings {
+	u32 dclk;
+	u32 hfreq;
+	u32 vfreq;
+	u32 hactive;
+	u32 vactive;
+	u32 hblank;
+	u32 vblank;
+	u32 htotal;
+	u32 vtotal;
+};
+
+/**
+ * fb_get_vblank - get vertical blank time
+ * @hfreq: horizontal freq
+ *
+ * DESCRIPTION:
+ * vblank = right_margin + vsync_len + left_margin
+ *
+ *    given: right_margin = 1 (V_FRONTPORCH)
+ *           vsync_len    = 3
+ *           flyback      = 550
+ *
+ *                          flyback * hfreq
+ *           left_margin  = --------------- - vsync_len
+ *                           1000000
+ */
+static u32 fb_get_vblank(u32 hfreq)
+{
+	u32 vblank;
+
+	vblank = (hfreq * FLYBACK)/1000;
+	vblank = (vblank + 500)/1000;
+	return (vblank + V_FRONTPORCH);
+}
+
+/**
+ * fb_get_hblank_by_freq - get horizontal blank time given hfreq
+ * @hfreq: horizontal freq
+ * @xres: horizontal resolution in pixels
+ *
+ * DESCRIPTION:
+ *
+ *           xres * duty_cycle
+ * hblank = ------------------
+ *           100 - duty_cycle
+ *
+ * duty cycle = percent of htotal assigned to inactive display
+ * duty cycle = C - (M/Hfreq)
+ *
+ * where: C = ((offset - scale factor) * blank_scale)
+ *            -------------------------------------- + scale factor
+ *                        256
+ *        M = blank_scale * gradient
+ *
+ */
+static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
+{
+	u32 c_val, m_val, duty_cycle, hblank;
+
+	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
+		 H_SCALEFACTOR) * 1000;
+	m_val = (H_BLANKSCALE * H_GRADIENT)/256;
+	m_val = (m_val * 1000000)/hfreq;
+	duty_cycle = c_val - m_val;
+	hblank = (xres * duty_cycle)/(100000 - duty_cycle);
+	return (hblank);
+}
+
+/**
+ * int_sqrt - rough approximation to sqrt
+ * @x: integer of which to calculate the sqrt
+ *
+ * A very rough approximation to the sqrt() function.
+ */
+unsigned long int_sqrt(unsigned long x)
+{
+	unsigned long b, m, y = 0;
+
+	if (x <= 1)
+		return x;
+
+	m = 1UL << (BITS_PER_LONG - 2);
+	while (m != 0) {
+		b = y + m;
+		y >>= 1;
+
+		if (x >= b) {
+			x -= b;
+			y += m;
+		}
+		m >>= 2;
+	}
+
+	return y;
+}
+EXPORT_SYMBOL(int_sqrt);
+
+/**
+ * fb_get_hfreq - estimate hsync
+ * @vfreq: vertical refresh rate
+ * @yres: vertical resolution
+ *
+ * DESCRIPTION:
+ *
+ *          (yres + front_port) * vfreq * 1000000
+ * hfreq = -------------------------------------
+ *          (1000000 - (vfreq * FLYBACK)
+ *
+ */
+
+static u32 fb_get_hfreq(u32 vfreq, u32 yres)
+{
+	u32 divisor, hfreq;
+
+	divisor = (1000000 - (vfreq * FLYBACK))/1000;
+	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
+	return (hfreq/divisor);
+}
+
+static void fb_timings_vfreq(struct __fb_timings *timings)
+{
+	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
+	timings->vblank = fb_get_vblank(timings->hfreq);
+	timings->vtotal = timings->vactive + timings->vblank;
+	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
+						 timings->hactive);
+	timings->htotal = timings->hactive + timings->hblank;
+	timings->dclk = timings->htotal * timings->hfreq;
+}
+
+/*
+ * fb_get_mode - calculates video mode using VESA GTF
+ * @flags: if: 0 - maximize vertical refresh rate
+ *             1 - vrefresh-driven calculation;
+ *             2 - hscan-driven calculation;
+ *             3 - pixelclock-driven calculation;
+ * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
+ * @var: pointer to fb_var_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Calculates video mode based on monitor specs using VESA GTF.
+ * The GTF is best for VESA GTF compliant monitors but is
+ * specifically formulated to work for older monitors as well.
+ *
+ * If @flag==0, the function will attempt to maximize the
+ * refresh rate.  Otherwise, it will calculate timings based on
+ * the flag and accompanying value.
+ *
+ * If FB_IGNOREMON bit is set in @flags, monitor specs will be
+ * ignored and @var will be filled with the calculated timings.
+ *
+ * All calculations are based on the VESA GTF Spreadsheet
+ * available at VESA's public ftp (http://www.vesa.org).
+ *
+ * NOTES:
+ * The timings generated by the GTF will be different from VESA
+ * DMT.  It might be a good idea to keep a table of standard
+ * VESA modes as well.  The GTF may also not work for some displays,
+ * such as, and especially, analog TV.
+ *
+ * REQUIRES:
+ * A valid info->monspecs, otherwise 'safe numbers' will be used.
+ */
+int fb_get_mode(int flags, u32 val, struct fb_videomode *var)
+{
+	struct __fb_timings *timings;
+	u32 interlace = 1, dscan = 1;
+	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
+
+	timings = xzalloc(sizeof(struct __fb_timings));
+
+	/*
+	 * If monspecs are invalid, use values that are enough
+	 * for 640x480@60
+	 */
+	hfmin = 29000; hfmax = 30000;
+	vfmin = 60; vfmax = 60;
+	dclkmin = 0; dclkmax = 25000000;
+
+	timings->hactive = var->xres;
+	timings->vactive = var->yres;
+	if (var->vmode & FB_VMODE_INTERLACED) {
+		timings->vactive /= 2;
+		interlace = 2;
+	}
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		timings->vactive *= 2;
+		dscan = 2;
+	}
+
+	/* vrefresh driven */
+	timings->vfreq = val;
+	fb_timings_vfreq(timings);
+
+	if (timings->dclk)
+		var->pixclock = KHZ2PICOS(timings->dclk / 1000);
+	var->hsync_len = (timings->htotal * 8) / 100;
+	var->right_margin = (timings->hblank / 2) - var->hsync_len;
+	var->left_margin = timings->hblank - var->right_margin -
+		var->hsync_len;
+	var->vsync_len = (3 * interlace) / dscan;
+	var->lower_margin = (1 * interlace) / dscan;
+	var->upper_margin = (timings->vblank * interlace) / dscan -
+		(var->vsync_len + var->lower_margin);
+
+	free(timings);
+	return err;
+}
+
+static void calc_mode_timings(int xres, int yres, int refresh,
+			      struct fb_videomode *mode)
+{
+	mode->xres = xres;
+	mode->yres = yres;
+	mode->refresh = refresh;
+	fb_get_mode(0, refresh, mode);
+	mode->name = asprintf("%dx%d@%d-calc", mode->xres, mode->yres, mode->refresh);
+	pr_debug("      %s\n", mode->name);
+}
+
+const struct fb_videomode vesa_modes[] = {
+	/* 0 640x350-85 VESA */
+	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 1 640x400-85 VESA */
+	{ NULL, 85, 640, 400, 31746,  96, 32, 41, 01, 64, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 2 720x400-85 VESA */
+	{ NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 3 640x480-60 VESA */
+	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 4 640x480-72 VESA */
+	{ NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 5 640x480-75 VESA */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 6 640x480-85 VESA */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 7 800x600-56 VESA */
+	{ NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 8 800x600-60 VESA */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 9 800x600-72 VESA */
+	{ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 10 800x600-75 VESA */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 11 800x600-85 VESA */
+	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+        /* 12 1024x768i-43 VESA */
+	{ NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_INTERLACED, 0 },
+	/* 13 1024x768-60 VESA */
+	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 14 1024x768-70 VESA */
+	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 15 1024x768-75 VESA */
+	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 16 1024x768-85 VESA */
+	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 17 1152x864-75 VESA */
+	{ NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 18 1280x960-60 VESA */
+	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 19 1280x960-85 VESA */
+	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 20 1280x1024-60 VESA */
+	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 21 1280x1024-75 VESA */
+	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 22 1280x1024-85 VESA */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 23 1600x1200-60 VESA */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 24 1600x1200-65 VESA */
+	{ NULL, 65, 1600, 1200, 5698, 304,  64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 25 1600x1200-70 VESA */
+	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 26 1600x1200-75 VESA */
+	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 27 1600x1200-85 VESA */
+	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 28 1792x1344-60 VESA */
+	{ NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 29 1792x1344-75 VESA */
+	{ NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 30 1856x1392-60 VESA */
+	{ NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 31 1856x1392-75 VESA */
+	{ NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 32 1920x1440-60 VESA */
+	{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+	/* 33 1920x1440-75 VESA */
+	{ NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+};
+
+#define VESA_MODEDB_SIZE ARRAY_SIZE(vesa_modes)
+
+static void add_vesa_mode(struct fb_videomode *mode, int num)
+{
+	*mode = vesa_modes[num];
+	mode->name = asprintf("%dx%d@%d-vesa", mode->xres, mode->yres, mode->refresh);
+	pr_debug("      %s\n", mode->name);
+}
+
+static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
+{
+	int num = 0;
+	unsigned char c;
+
+	c = block[0];
+	if (c & 0x80)
+		calc_mode_timings(720, 400, 70, &mode[num++]);
+	if (c & 0x40)
+		calc_mode_timings(720, 400, 88, &mode[num++]);
+	if (c & 0x20)
+		add_vesa_mode(&mode[num++], 3);
+	if (c & 0x10)
+		calc_mode_timings(640, 480, 67, &mode[num++]);
+	if (c & 0x08)
+		add_vesa_mode(&mode[num++], 4);
+	if (c & 0x04)
+		add_vesa_mode(&mode[num++], 5);
+	if (c & 0x02)
+		add_vesa_mode(&mode[num++], 7);
+	if (c & 0x01)
+		add_vesa_mode(&mode[num++], 8);
+
+	c = block[1];
+	if (c & 0x80)
+		add_vesa_mode(&mode[num++], 9);
+	if (c & 0x40)
+		add_vesa_mode(&mode[num++], 10);
+	if (c & 0x20)
+		calc_mode_timings(832, 624, 75, &mode[num++]);
+	if (c & 0x10)
+		add_vesa_mode(&mode[num++], 12);
+	if (c & 0x08)
+		add_vesa_mode(&mode[num++], 13);
+	if (c & 0x04)
+		add_vesa_mode(&mode[num++], 14);
+	if (c & 0x02)
+		add_vesa_mode(&mode[num++], 15);
+	if (c & 0x01)
+		add_vesa_mode(&mode[num++], 21);
+	c = block[2];
+
+	if (c & 0x80)
+		add_vesa_mode(&mode[num++], 17);
+
+	pr_debug("      Manufacturer's mask: %x\n",c & 0x7F);
+	return num;
+}
+
+static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
+		int ver, int rev)
+{
+	int xres, yres = 0, refresh, ratio, i;
+
+	xres = (block[0] + 31) * 8;
+	if (xres <= 256)
+		return 0;
+
+	ratio = (block[1] & 0xc0) >> 6;
+	switch (ratio) {
+	case 0:
+		/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
+		if (ver < 1 || (ver == 1 && rev < 3))
+			yres = xres;
+		else
+			yres = (xres * 10) / 16;
+		break;
+	case 1:
+		yres = (xres * 3) / 4;
+		break;
+	case 2:
+		yres = (xres * 4) / 5;
+		break;
+	case 3:
+		yres = (xres * 9) / 16;
+		break;
+	}
+	refresh = (block[1] & 0x3f) + 60;
+
+	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+		if (vesa_modes[i].xres == xres &&
+		    vesa_modes[i].yres == yres &&
+		    vesa_modes[i].refresh == refresh) {
+			add_vesa_mode(mode, i);
+			return 1;
+		}
+	}
+
+	calc_mode_timings(xres, yres, refresh, mode);
+
+	return 1;
+}
+
+static int get_dst_timing(unsigned char *block,
+			  struct fb_videomode *mode, int ver, int rev)
+{
+	int j, num = 0;
+
+	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
+		num += get_std_timing(block, &mode[num], ver, rev);
+
+	return num;
+}
+
+static void get_detailed_timing(unsigned char *block,
+				struct fb_videomode *mode)
+{
+	mode->xres = H_ACTIVE;
+	mode->yres = V_ACTIVE;
+	mode->pixclock = PIXEL_CLOCK;
+	mode->pixclock /= 1000;
+	mode->pixclock = KHZ2PICOS(mode->pixclock);
+	mode->right_margin = H_SYNC_OFFSET;
+	mode->left_margin = (H_ACTIVE + H_BLANKING) -
+		(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+		V_SYNC_WIDTH;
+	mode->lower_margin = V_SYNC_OFFSET;
+	mode->hsync_len = H_SYNC_WIDTH;
+	mode->vsync_len = V_SYNC_WIDTH;
+	if (HSYNC_POSITIVE)
+		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (VSYNC_POSITIVE)
+		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+				     (V_ACTIVE + V_BLANKING));
+	if (INTERLACED) {
+		mode->yres *= 2;
+		mode->upper_margin *= 2;
+		mode->lower_margin *= 2;
+		mode->vsync_len *= 2;
+		mode->vmode |= FB_VMODE_INTERLACED;
+	}
+
+	pr_debug("      %d MHz ",  PIXEL_CLOCK/1000000);
+	pr_debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+	       H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+	pr_debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+	       V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+	pr_debug("%sHSync %sVSync\n", (HSYNC_POSITIVE) ? "+" : "-",
+	       (VSYNC_POSITIVE) ? "+" : "-");
+
+	mode->name = asprintf("%dx%d@%d", mode->xres, mode->yres, mode->refresh);
+}
+
+/**
+ * edid_to_display_timings - create video mode database
+ * @edid: EDID data
+ * @dbsize: database size
+ *
+ * RETURNS: struct fb_videomode, @dbsize contains length of database
+ *
+ * DESCRIPTION:
+ * This function builds a mode database using the contents of the EDID
+ * data
+ */
+int edid_to_display_timings(struct display_timings *timings, unsigned char *edid)
+{
+	struct fb_videomode *mode;
+	unsigned char *block;
+	int num = 0, i, first = 1;
+	int ver, rev, ret;
+
+	ver = edid[EDID_STRUCT_VERSION];
+	rev = edid[EDID_STRUCT_REVISION];
+
+	mode = xzalloc(50 * sizeof(struct fb_videomode));
+
+	if (!edid_checksum(edid) ||
+	    !edid_check_header(edid)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	pr_debug("   Detailed Timings\n");
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (!(block[0] == 0x00 && block[1] == 0x00)) {
+			get_detailed_timing(block, &mode[num]);
+			if (first) {
+				first = 0;
+			}
+			num++;
+		}
+	}
+
+	pr_debug("   Supported VESA Modes\n");
+	block = edid + ESTABLISHED_TIMING_1;
+	num += get_est_timing(block, &mode[num]);
+
+	pr_debug("   Standard Timings\n");
+	block = edid + STD_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+		num += get_std_timing(block, &mode[num], ver, rev);
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
+			num += get_dst_timing(block + 5, &mode[num], ver, rev);
+	}
+
+	/* Yikes, EDID data is totally useless */
+	if (!num) {
+		free(mode);
+		return -EINVAL;
+	}
+
+	timings->num_modes = num;
+	timings->modes = mode;
+
+	return 0;
+out:
+	free(timings);
+	free(mode);
+	return ret;
+}
+
+#define DDC_ADDR	0x50
+#define DDC_SEGMENT_ADDR 0x30
+
+/**
+ * Get EDID information via I2C.
+ *
+ * \param adapter : i2c device adaptor
+ * \param buf     : EDID data buffer to be filled
+ * \param len     : EDID data buffer length
+ * \return 0 on success or -1 on failure.
+ *
+ * Try to fetch EDID information by calling i2c driver function.
+ */
+static int
+edid_do_read_i2c(struct i2c_adapter *adapter, unsigned char *buf,
+		      int block, int len)
+{
+	unsigned char start = block * EDID_LENGTH;
+	unsigned char segment = block >> 1;
+	unsigned char xfers = segment ? 3 : 2;
+	int ret, retries = 5;
+
+	/* The core i2c driver will automatically retry the transfer if the
+	 * adapter reports EAGAIN. However, we find that bit-banging transfers
+	 * are susceptible to errors under a heavily loaded machine and
+	 * generate spurious NAKs and timeouts. Retrying the transfer
+	 * of the individual block a few times seems to overcome this.
+	 */
+	do {
+		struct i2c_msg msgs[] = {
+			{
+				.addr	= DDC_SEGMENT_ADDR,
+				.flags	= 0,
+				.len	= 1,
+				.buf	= &segment,
+			}, {
+				.addr	= DDC_ADDR,
+				.flags	= 0,
+				.len	= 1,
+				.buf	= &start,
+			}, {
+				.addr	= DDC_ADDR,
+				.flags	= I2C_M_RD,
+				.len	= len,
+				.buf	= buf,
+			}
+		};
+
+	/*
+	 * Avoid sending the segment addr to not upset non-compliant ddc
+	 * monitors.
+	 */
+		ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers);
+	} while (ret != xfers && --retries);
+
+	return ret == xfers ? 0 : -1;
+}
+
+void *edid_read_i2c(struct i2c_adapter *adapter)
+{
+	u8 *block;
+
+	block = xmalloc(EDID_LENGTH);
+
+	if (edid_do_read_i2c(adapter, block, 0, EDID_LENGTH))
+		goto out;
+
+	return block;
+out:
+	free(block);
+
+	return NULL;
+}
+
+void fb_edid_add_modes(struct fb_info *info)
+{
+	if (info->edid_i2c_adapter)
+		info->edid_data = edid_read_i2c(info->edid_i2c_adapter);
+
+	if (!info->edid_data)
+		return;
+
+	edid_to_display_timings(&info->edid_modes, info->edid_data);
+}
diff --git a/drivers/video/edid.h b/drivers/video/edid.h
new file mode 100644
index 0000000..006d9f2
--- /dev/null
+++ b/drivers/video/edid.h
@@ -0,0 +1,138 @@
+/*
+ * drivers/video/edid.h - EDID/DDC Header
+ *
+ * Based on:
+ *   1. XFree86 4.3.0, edid.h
+ *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ *   2. John Fremlin <vii@users.sourceforge.net> and
+ *      Ani Joshi <ajoshi@unixbox.com>
+ *
+ * DDC is a Trademark of VESA (Video Electronics Standard Association).
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+*/
+
+#ifndef __EDID_H__
+#define __EDID_H__
+
+#define EDID_LENGTH				0x80
+#define EDID_HEADER				0x00
+#define EDID_HEADER_END				0x07
+
+#define ID_MANUFACTURER_NAME			0x08
+#define ID_MANUFACTURER_NAME_END		0x09
+#define ID_MODEL				0x0a
+
+#define ID_SERIAL_NUMBER			0x0c
+
+#define MANUFACTURE_WEEK			0x10
+#define MANUFACTURE_YEAR			0x11
+
+#define EDID_STRUCT_VERSION			0x12
+#define EDID_STRUCT_REVISION			0x13
+
+#define EDID_STRUCT_DISPLAY                     0x14
+
+#define DPMS_FLAGS				0x18
+#define ESTABLISHED_TIMING_1			0x23
+#define ESTABLISHED_TIMING_2			0x24
+#define MANUFACTURERS_TIMINGS			0x25
+
+/* standard timings supported */
+#define STD_TIMING                              8
+#define STD_TIMING_DESCRIPTION_SIZE             2
+#define STD_TIMING_DESCRIPTIONS_START           0x26
+
+#define DETAILED_TIMING_DESCRIPTIONS_START	0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE	18
+#define NO_DETAILED_TIMING_DESCRIPTIONS		4
+
+#define DETAILED_TIMING_DESCRIPTION_1		0x36
+#define DETAILED_TIMING_DESCRIPTION_2		0x48
+#define DETAILED_TIMING_DESCRIPTION_3		0x5a
+#define DETAILED_TIMING_DESCRIPTION_4		0x6c
+
+#define DESCRIPTOR_DATA				5
+
+#define UPPER_NIBBLE( x ) \
+        (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+        ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+        ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+        ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+#define PIXEL_CLOCK_LO     (unsigned)block[ 0 ]
+#define PIXEL_CLOCK_HI     (unsigned)block[ 1 ]
+#define PIXEL_CLOCK	   (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
+#define H_ACTIVE_LO        (unsigned)block[ 2 ]
+#define H_BLANKING_LO      (unsigned)block[ 3 ]
+#define H_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_ACTIVE           COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+#define H_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_BLANKING         COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
+
+#define V_ACTIVE_LO        (unsigned)block[ 5 ]
+#define V_BLANKING_LO      (unsigned)block[ 6 ]
+#define V_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_ACTIVE           COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+#define V_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_BLANKING         COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO   (unsigned)block[ 8 ]
+#define H_SYNC_WIDTH_LO    (unsigned)block[ 9 ]
+
+#define V_SYNC_OFFSET_LO   UPPER_NIBBLE( (unsigned)block[ 10 ] )
+#define V_SYNC_WIDTH_LO    LOWER_NIBBLE( (unsigned)block[ 10 ] )
+
+#define V_SYNC_WIDTH_HI    ((unsigned)block[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI    (((unsigned)block[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH       COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET      COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH       COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET      COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO          (unsigned)block[ 12 ]
+#define V_SIZE_LO          (unsigned)block[ 13 ]
+
+#define H_SIZE_HI          UPPER_NIBBLE( (unsigned)block[ 14 ] )
+#define V_SIZE_HI          LOWER_NIBBLE( (unsigned)block[ 14 ] )
+
+#define H_SIZE             COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE             COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER           (unsigned)block[ 15 ]
+#define V_BORDER           (unsigned)block[ 16 ]
+
+#define FLAGS              (unsigned)block[ 17 ]
+
+#define INTERLACED         (FLAGS&128)
+#define SYNC_TYPE          (FLAGS&3<<3)	/* bits 4,3 */
+#define SYNC_SEPARATE      (3<<3)
+#define HSYNC_POSITIVE     (FLAGS & 4)
+#define VSYNC_POSITIVE     (FLAGS & 2)
+
+#define V_MIN_RATE              block[ 5 ]
+#define V_MAX_RATE              block[ 6 ]
+#define H_MIN_RATE              block[ 7 ]
+#define H_MAX_RATE              block[ 8 ]
+#define MAX_PIXEL_CLOCK         (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT		block[10]
+
+#define DPMS_ACTIVE_OFF		(1 << 5)
+#define DPMS_SUSPEND		(1 << 6)
+#define DPMS_STANDBY		(1 << 7)
+
+#endif /* __EDID_H__ */
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index d7a3d3c..2c8b8eb 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -53,11 +53,14 @@ static struct fb_videomode *fb_num_to_mode(struct fb_info *info, int num)
 {
 	int num_modes;
 
-	num_modes = info->modes.num_modes;
+	num_modes = info->modes.num_modes + info->edid_modes.num_modes;
 
 	if (num >= num_modes)
 		return NULL;
 
+	if (num >= info->modes.num_modes)
+		return &info->edid_modes.modes[num - info->modes.num_modes];
+
 	return &info->modes.modes[num];
 }
 
@@ -142,6 +145,7 @@ static void fb_info(struct device_d *dev)
 	printf("available modes:\n");
 
 	fb_print_modes(&info->modes);
+	fb_print_modes(&info->edid_modes);
 
 	printf("\n");
 }
@@ -191,13 +195,17 @@ int register_framebuffer(struct fb_info *info)
 	dev_add_param_bool(dev, "enable", fb_enable_set, NULL,
 			&info->p_enable, info);
 
-	num_modes = info->modes.num_modes;
+	if (IS_ENABLED(CONFIG_DRIVER_VIDEO_EDID))
+		fb_edid_add_modes(info);
+
+	num_modes = info->modes.num_modes + info->edid_modes.num_modes;
 
 	names = xzalloc(sizeof(char *) * num_modes);
 
 	for (i = 0; i < info->modes.num_modes; i++)
 		names[i] = info->modes.modes[i].name;
-
+	for (i = 0; i < info->edid_modes.num_modes; i++)
+		names[i + info->modes.num_modes] = info->edid_modes.modes[i].name;
 	dev_add_param_enum(dev, "mode_name", fb_set_modename, NULL, &info->current_mode, names, num_modes, info);
 
 	info->mode = fb_num_to_mode(info, 0);
diff --git a/include/fb.h b/include/fb.h
index 8d255c0..7829a0f 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -100,12 +100,18 @@ struct display_timings {
 	struct fb_videomode *modes;
 };
 
+struct i2c_adapter;
+
 struct fb_info {
 	struct fb_videomode *mode;
 	struct display_timings modes;
 
 	int current_mode;
 
+	void *edid_data;
+	struct i2c_adapter *edid_i2c_adapter;
+	struct display_timings edid_modes;
+
 	struct fb_ops *fbops;
 	struct device_d dev;		/* This is this fb device */
 
@@ -149,5 +155,8 @@ extern struct bus_type fb_bus;
 
 int fb_register_simplefb(struct fb_info *info);
 
-#endif /* __FB_H */
+int edid_to_display_timings(struct display_timings *, unsigned char *edid);
+void *edid_read_i2c(struct i2c_adapter *adapter);
+void fb_edid_add_modes(struct fb_info *info);
 
+#endif /* __FB_H */
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 24/29] ARM i.MX6q: Mark VPU and IPU AXI transfers as cacheable, increase IPU priority
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (22 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 23/29] video: Add edid support Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 25/29] video: Add kernel fourcc defines Sascha Hauer
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

This is needed so that the IPU framebuffer scanout cannot be
starved by VPU or GPU activity.
Some boards like the SabreLite and SabreSD seem to set this in
the DCD already, but the documented register reset values do not
contain the necessary settings.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/imx6.c       | 19 +++++++++++++++++++
 include/mfd/imx6q-iomuxc-gpr.h | 18 ++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 304b1c0..e14ce90 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -15,6 +15,7 @@
 #include <common.h>
 #include <io.h>
 #include <sizes.h>
+#include <mfd/imx6q-iomuxc-gpr.h>
 #include <mach/imx6.h>
 #include <mach/generic.h>
 #include <mach/revision.h>
@@ -28,7 +29,9 @@ void imx6_init_lowlevel(void)
 {
 	void __iomem *aips1 = (void *)MX6_AIPS1_ON_BASE_ADDR;
 	void __iomem *aips2 = (void *)MX6_AIPS2_ON_BASE_ADDR;
+	void __iomem *iomux = (void *)MX6_IOMUXC_BASE_ADDR;
 	int is_imx6q = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
+	uint32_t val;
 
 	/*
 	 * Set all MPROTx to be non-bufferable, trusted for R/W,
@@ -87,6 +90,22 @@ void imx6_init_lowlevel(void)
 			BM_ANADIG_PFD_528_PFD0_CLKGATE,
 			MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
 
+	val = readl(iomux + IOMUXC_GPR4);
+	val |= IMX6Q_GPR4_VPU_WR_CACHE_SEL | IMX6Q_GPR4_VPU_RD_CACHE_SEL |
+		IMX6Q_GPR4_VPU_P_WR_CACHE_VAL | IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
+		IMX6Q_GPR4_IPU_WR_CACHE_CTL | IMX6Q_GPR4_IPU_RD_CACHE_CTL;
+	writel(val, iomux + IOMUXC_GPR4);
+
+	/* Increase IPU read QoS priority */
+	val = readl(iomux + IOMUXC_GPR6);
+	val &= ~(IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK | IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK);
+	val |= (0xf << 16) | (0x7 << 20);
+	writel(val, iomux + IOMUXC_GPR6);
+
+	val = readl(iomux + IOMUXC_GPR7);
+	val &= ~(IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK | IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK);
+	val |= (0xf << 16) | (0x7 << 20);
+	writel(val, iomux + IOMUXC_GPR7);
 }
 
 int imx6_init(void)
diff --git a/include/mfd/imx6q-iomuxc-gpr.h b/include/mfd/imx6q-iomuxc-gpr.h
index db43d59..59c86dd 100644
--- a/include/mfd/imx6q-iomuxc-gpr.h
+++ b/include/mfd/imx6q-iomuxc-gpr.h
@@ -241,6 +241,24 @@
 
 #define IMX6Q_GPR5_L2_CLK_STOP			BIT(8)
 
+#define IMX6Q_GPR6_IPU1_ID00_WR_QOS_MASK	(0xf << 0)
+#define IMX6Q_GPR6_IPU1_ID01_WR_QOS_MASK	(0xf << 4)
+#define IMX6Q_GPR6_IPU1_ID10_WR_QOS_MASK	(0xf << 8)
+#define IMX6Q_GPR6_IPU1_ID11_WR_QOS_MASK	(0xf << 12)
+#define IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK	(0xf << 16)
+#define IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK	(0xf << 20)
+#define IMX6Q_GPR6_IPU1_ID10_RD_QOS_MASK	(0xf << 24)
+#define IMX6Q_GPR6_IPU1_ID11_RD_QOS_MASK	(0xf << 28)
+
+#define IMX6Q_GPR7_IPU2_ID00_WR_QOS_MASK	(0xf << 0)
+#define IMX6Q_GPR7_IPU2_ID01_WR_QOS_MASK	(0xf << 4)
+#define IMX6Q_GPR7_IPU2_ID10_WR_QOS_MASK	(0xf << 8)
+#define IMX6Q_GPR7_IPU2_ID11_WR_QOS_MASK	(0xf << 12)
+#define IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK	(0xf << 16)
+#define IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK	(0xf << 20)
+#define IMX6Q_GPR7_IPU2_ID10_RD_QOS_MASK	(0xf << 24)
+#define IMX6Q_GPR7_IPU2_ID11_RD_QOS_MASK	(0xf << 28)
+
 #define IMX6Q_GPR9_TZASC2_BYP			BIT(1)
 #define IMX6Q_GPR9_TZASC1_BYP			BIT(0)
 
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 25/29] video: Add kernel fourcc defines
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (23 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 24/29] ARM i.MX6q: Mark VPU and IPU AXI transfers as cacheable, increase IPU priority Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 27/29] video: i.MX IPUv3: Add lvds bridge support Sascha Hauer
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/video/fourcc.h | 261 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 261 insertions(+)
 create mode 100644 include/video/fourcc.h

diff --git a/include/video/fourcc.h b/include/video/fourcc.h
new file mode 100644
index 0000000..322142c
--- /dev/null
+++ b/include/video/fourcc.h
@@ -0,0 +1,261 @@
+#ifndef __VIDEO_FOURCC_H
+#define __VIDEO_FOURCC_H
+
+/*  Four-character-code (FOURCC) */
+#define v4l2_fourcc(a, b, c, d)\
+	((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
+
+/*      Pixel format         FOURCC                          depth  Description  */
+
+/* RGB formats */
+#define V4L2_PIX_FMT_RGB332  v4l2_fourcc('R', 'G', 'B', '1') /*  8  RGB-3-3-2     */
+#define V4L2_PIX_FMT_RGB444  v4l2_fourcc('R', '4', '4', '4') /* 16  xxxxrrrr ggggbbbb */
+#define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
+#define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
+#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
+#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
+#define V4L2_PIX_FMT_BGR666  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6	  */
+#define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
+#define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
+#define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
+#define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R', 'G', 'B', '4') /* 32  RGB-8-8-8-8   */
+
+/* Grey formats */
+#define V4L2_PIX_FMT_GREY    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
+#define V4L2_PIX_FMT_Y4      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
+#define V4L2_PIX_FMT_Y6      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
+#define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
+#define V4L2_PIX_FMT_Y12     v4l2_fourcc('Y', '1', '2', ' ') /* 12  Greyscale     */
+#define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
+
+/* Grey bit-packed formats */
+#define V4L2_PIX_FMT_Y10BPACK    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
+
+/* Palette formats */
+#define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
+
+/* Chrominance formats */
+#define V4L2_PIX_FMT_UV8     v4l2_fourcc('U', 'V', '8', ' ') /*  8  UV 4:4 */
+
+/* Luminance+Chrominance formats */
+#define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y', 'V', 'U', '9') /*  9  YVU 4:1:0     */
+#define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
+#define V4L2_PIX_FMT_YUYV    v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YVYU    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
+#define V4L2_PIX_FMT_UYVY    v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_VYUY    v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16  YVU422 planar */
+#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 16  YVU411 planar */
+#define V4L2_PIX_FMT_Y41P    v4l2_fourcc('Y', '4', '1', 'P') /* 12  YUV 4:1:1     */
+#define V4L2_PIX_FMT_YUV444  v4l2_fourcc('Y', '4', '4', '4') /* 16  xxxxyyyy uuuuvvvv */
+#define V4L2_PIX_FMT_YUV555  v4l2_fourcc('Y', 'U', 'V', 'O') /* 16  YUV-5-5-5     */
+#define V4L2_PIX_FMT_YUV565  v4l2_fourcc('Y', 'U', 'V', 'P') /* 16  YUV-5-6-5     */
+#define V4L2_PIX_FMT_YUV32   v4l2_fourcc('Y', 'U', 'V', '4') /* 32  YUV-8-8-8-8   */
+#define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
+#define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
+#define V4L2_PIX_FMT_HI240   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
+#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
+#define V4L2_PIX_FMT_M420    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved */
+
+/* two planes -- one Y, one Cr + Cb interleaved  */
+#define V4L2_PIX_FMT_NV12    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define V4L2_PIX_FMT_NV21    v4l2_fourcc('N', 'V', '2', '1') /* 12  Y/CrCb 4:2:0  */
+#define V4L2_PIX_FMT_NV16    v4l2_fourcc('N', 'V', '1', '6') /* 16  Y/CbCr 4:2:2  */
+#define V4L2_PIX_FMT_NV61    v4l2_fourcc('N', 'V', '6', '1') /* 16  Y/CrCb 4:2:2  */
+#define V4L2_PIX_FMT_NV24    v4l2_fourcc('N', 'V', '2', '4') /* 24  Y/CbCr 4:4:4  */
+#define V4L2_PIX_FMT_NV42    v4l2_fourcc('N', 'V', '4', '2') /* 24  Y/CrCb 4:4:4  */
+
+/* two non contiguous planes - one Y, one Cr + Cb interleaved  */
+#define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define V4L2_PIX_FMT_NV21M   v4l2_fourcc('N', 'M', '2', '1') /* 21  Y/CrCb 4:2:0  */
+#define V4L2_PIX_FMT_NV16M   v4l2_fourcc('N', 'M', '1', '6') /* 16  Y/CbCr 4:2:2  */
+#define V4L2_PIX_FMT_NV61M   v4l2_fourcc('N', 'M', '6', '1') /* 16  Y/CrCb 4:2:2  */
+#define V4L2_PIX_FMT_NV12MT  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 16x16 macroblocks */
+
+/* three non contiguous planes - Y, Cb, Cr */
+#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
+#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12  YVU420 planar */
+
+/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
+#define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG8  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG8  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB8  v4l2_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
+#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
+#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12  GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12  RGRG.. GBGB.. */
+	/* 10bit raw bayer a-law compressed to 8 bits */
+#define V4L2_PIX_FMT_SBGGR10ALAW8 v4l2_fourcc('a', 'B', 'A', '8')
+#define V4L2_PIX_FMT_SGBRG10ALAW8 v4l2_fourcc('a', 'G', 'A', '8')
+#define V4L2_PIX_FMT_SGRBG10ALAW8 v4l2_fourcc('a', 'g', 'A', '8')
+#define V4L2_PIX_FMT_SRGGB10ALAW8 v4l2_fourcc('a', 'R', 'A', '8')
+	/* 10bit raw bayer DPCM compressed to 8 bits */
+#define V4L2_PIX_FMT_SBGGR10DPCM8 v4l2_fourcc('b', 'B', 'A', '8')
+#define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8')
+#define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0')
+#define V4L2_PIX_FMT_SRGGB10DPCM8 v4l2_fourcc('b', 'R', 'A', '8')
+	/*
+	 * 10bit raw bayer, expanded to 16 bits
+	 * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
+	 */
+#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16  BGBG.. GRGR.. */
+
+/* compressed formats */
+#define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG   */
+#define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG     */
+#define V4L2_PIX_FMT_DV       v4l2_fourcc('d', 'v', 's', 'd') /* 1394          */
+#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
+#define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
+#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
+#define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
+#define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
+#define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
+#define V4L2_PIX_FMT_MPEG4    v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */
+#define V4L2_PIX_FMT_XVID     v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid           */
+#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
+#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
+#define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
+
+/*  Vendor-specific formats   */
+#define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
+#define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
+#define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
+#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
+#define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
+#define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
+#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
+#define V4L2_PIX_FMT_SPCA501  v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */
+#define V4L2_PIX_FMT_SPCA505  v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */
+#define V4L2_PIX_FMT_SPCA508  v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
+#define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
+#define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */
+#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
+#define V4L2_PIX_FMT_SQ905C   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
+#define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
+#define V4L2_PIX_FMT_OV511    v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
+#define V4L2_PIX_FMT_OV518    v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
+#define V4L2_PIX_FMT_STV0680  v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
+#define V4L2_PIX_FMT_TM6000   v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
+#define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
+#define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
+#define V4L2_PIX_FMT_JPGL	v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
+#define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
+
+#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
+				 ((__u32)(c) << 16) | ((__u32)(d) << 24))
+
+#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+
+/* color index */
+#define DRM_FORMAT_C8		fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
+
+/* 8 bpp RGB */
+#define DRM_FORMAT_RGB332	fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
+#define DRM_FORMAT_BGR233	fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
+
+/* 16 bpp RGB */
+#define DRM_FORMAT_XRGB4444	fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */
+#define DRM_FORMAT_XBGR4444	fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */
+#define DRM_FORMAT_RGBX4444	fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */
+#define DRM_FORMAT_BGRX4444	fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */
+
+#define DRM_FORMAT_ARGB4444	fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */
+#define DRM_FORMAT_ABGR4444	fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */
+#define DRM_FORMAT_RGBA4444	fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */
+#define DRM_FORMAT_BGRA4444	fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */
+
+#define DRM_FORMAT_XRGB1555	fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */
+#define DRM_FORMAT_XBGR1555	fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */
+#define DRM_FORMAT_RGBX5551	fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */
+#define DRM_FORMAT_BGRX5551	fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */
+
+#define DRM_FORMAT_ARGB1555	fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */
+#define DRM_FORMAT_ABGR1555	fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */
+#define DRM_FORMAT_RGBA5551	fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */
+#define DRM_FORMAT_BGRA5551	fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */
+
+#define DRM_FORMAT_RGB565	fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
+#define DRM_FORMAT_BGR565	fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */
+
+/* 24 bpp RGB */
+#define DRM_FORMAT_RGB888	fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
+#define DRM_FORMAT_BGR888	fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */
+
+/* 32 bpp RGB */
+#define DRM_FORMAT_XRGB8888	fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
+#define DRM_FORMAT_XBGR8888	fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */
+#define DRM_FORMAT_RGBX8888	fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */
+#define DRM_FORMAT_BGRX8888	fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */
+
+#define DRM_FORMAT_ARGB8888	fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
+#define DRM_FORMAT_ABGR8888	fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
+#define DRM_FORMAT_RGBA8888	fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
+#define DRM_FORMAT_BGRA8888	fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
+
+#define DRM_FORMAT_XRGB2101010	fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */
+#define DRM_FORMAT_XBGR2101010	fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */
+#define DRM_FORMAT_RGBX1010102	fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */
+#define DRM_FORMAT_BGRX1010102	fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */
+
+#define DRM_FORMAT_ARGB2101010	fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */
+#define DRM_FORMAT_ABGR2101010	fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */
+#define DRM_FORMAT_RGBA1010102	fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */
+#define DRM_FORMAT_BGRA1010102	fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
+
+/* packed YCbCr */
+#define DRM_FORMAT_YUYV		fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
+#define DRM_FORMAT_YVYU		fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
+#define DRM_FORMAT_UYVY		fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
+#define DRM_FORMAT_VYUY		fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
+
+#define DRM_FORMAT_AYUV		fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+#define DRM_FORMAT_NV12		fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV21		fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
+#define DRM_FORMAT_NV16		fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV61		fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
+#define DRM_FORMAT_NV24		fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV42		fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
+
+/* special NV12 tiled format */
+#define DRM_FORMAT_NV12MT	fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */
+
+/*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+#define DRM_FORMAT_YUV410	fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU410	fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV411	fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU411	fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV420	fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU420	fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV422	fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU422	fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV444	fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU444	fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
+
+#endif /* __VIDEO_FOURCC_H */
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 27/29] video: i.MX IPUv3: Add lvds bridge support
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (24 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 25/29] video: Add kernel fourcc defines Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 28/29] video: i.MX IPUv3: Add hdmi support Sascha Hauer
  2014-03-14 14:32 ` [PATCH 29/29] ARM: update imx_v7_defconfig Sascha Hauer
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/imx-ipu-v3/Kconfig   |   3 +
 drivers/video/imx-ipu-v3/Makefile  |   1 +
 drivers/video/imx-ipu-v3/imx-ldb.c | 310 +++++++++++++++++++++++++++++++++++++
 3 files changed, 314 insertions(+)
 create mode 100644 drivers/video/imx-ipu-v3/imx-ldb.c

diff --git a/drivers/video/imx-ipu-v3/Kconfig b/drivers/video/imx-ipu-v3/Kconfig
index 84ef363..e83158a 100644
--- a/drivers/video/imx-ipu-v3/Kconfig
+++ b/drivers/video/imx-ipu-v3/Kconfig
@@ -5,4 +5,7 @@ config DRIVER_VIDEO_IMX_IPUV3
 
 if DRIVER_VIDEO_IMX_IPUV3
 
+config DRIVER_VIDEO_IMX_IPUV3_LVDS
+	bool "IPUv3 LVDS support"
+
 endif
diff --git a/drivers/video/imx-ipu-v3/Makefile b/drivers/video/imx-ipu-v3/Makefile
index 0edc1a4..e2ff43d 100644
--- a/drivers/video/imx-ipu-v3/Makefile
+++ b/drivers/video/imx-ipu-v3/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-common.o ipu-dmfc.o ipu-di.o
 obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-dp.o ipuv3-plane.o ipufb.o
 obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-dc.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS) += imx-ldb.o
diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
new file mode 100644
index 0000000..7367fbe
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -0,0 +1,310 @@
+/*
+ * i.MX drm driver - parallel display implementation
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <fb.h>
+#include <io.h>
+#include <driver.h>
+#include <malloc.h>
+#include <errno.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/div64.h>
+#include <linux/clk.h>
+#include <mach/imx6-regs.h>
+#include <mach/imx53-regs.h>
+
+#include "imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+
+#define LDB_CH0_MODE_EN_TO_DI0		(1 << 0)
+#define LDB_CH0_MODE_EN_TO_DI1		(3 << 0)
+#define LDB_CH0_MODE_EN_MASK		(3 << 0)
+#define LDB_CH1_MODE_EN_TO_DI0		(1 << 2)
+#define LDB_CH1_MODE_EN_TO_DI1		(3 << 2)
+#define LDB_CH1_MODE_EN_MASK		(3 << 2)
+#define LDB_SPLIT_MODE_EN		(1 << 4)
+#define LDB_DATA_WIDTH_CH0_24		(1 << 5)
+#define LDB_BIT_MAP_CH0_JEIDA		(1 << 6)
+#define LDB_DATA_WIDTH_CH1_24		(1 << 7)
+#define LDB_BIT_MAP_CH1_JEIDA		(1 << 8)
+#define LDB_DI0_VS_POL_ACT_LOW		(1 << 9)
+#define LDB_DI1_VS_POL_ACT_LOW		(1 << 10)
+#define LDB_BGREF_RMODE_INT		(1 << 15)
+
+struct imx_ldb;
+
+struct imx_ldb_channel {
+	struct imx_ldb *ldb;
+	int chno;
+	int mode_valid;
+	struct display_timings *modes;
+	struct ipu_output output;
+};
+
+struct imx_ldb_data {
+	void __iomem *base;
+	int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di);
+	unsigned ipu_mask;
+};
+
+struct imx_ldb {
+	struct device_d *dev;
+	u32 interface_pix_fmt;
+	int mode_valid;
+	struct imx_ldb_channel channel[2];
+	u32 ldb_ctrl;
+	void __iomem *base;
+	const struct imx_ldb_data *soc_data;
+};
+
+enum {
+	LVDS_BIT_MAP_SPWG,
+	LVDS_BIT_MAP_JEIDA
+};
+
+static const char * const imx_ldb_bit_mappings[] = {
+	[LVDS_BIT_MAP_SPWG]  = "spwg",
+	[LVDS_BIT_MAP_JEIDA] = "jeida",
+};
+
+static const int of_get_data_mapping(struct device_node *np)
+{
+	const char *bm;
+	int ret, i;
+
+	ret = of_property_read_string(np, "fsl,data-mapping", &bm);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++)
+		if (!strcasecmp(bm, imx_ldb_bit_mappings[i]))
+			return i;
+
+	return -EINVAL;
+}
+
+static int imx_ldb_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+{
+	struct imx_ldb_channel *imx_ldb_ch = container_of(output, struct imx_ldb_channel, output);
+	struct imx_ldb *ldb = imx_ldb_ch->ldb;
+
+	if (PICOS2KHZ(mode->pixclock) > 85000) {
+		dev_warn(ldb->dev,
+			 "%s: mode exceeds 85 MHz pixel clock\n", __func__);
+	}
+
+	ldb->soc_data->prepare(imx_ldb_ch, di);
+
+	/* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
+	if (imx_ldb_ch == &ldb->channel[0]) {
+		if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+			ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW;
+		else
+			ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW;
+	}
+
+	if (imx_ldb_ch == &ldb->channel[1]) {
+		if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+			ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW;
+		else
+			ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW;
+	}
+
+	if (imx_ldb_ch == &ldb->channel[0]) {
+		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
+		ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
+	}
+
+	if (imx_ldb_ch == &ldb->channel[1]) {
+		ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
+		ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1;
+	}
+
+	writel(ldb->ldb_ctrl, ldb->base);
+
+	return 0;
+}
+
+static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+	struct clk *diclk, *ldbclk;
+	struct imx_ldb *ldb = imx_ldb_ch->ldb;
+	int ret, ipuno, dino;
+	char *clkname;
+	void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc;
+	uint32_t val;
+	int shift;
+
+	ipuno = ((di >> 1) & 1) + 1;
+	dino = di & 0x1;
+
+	clkname = asprintf("ipu%d_di%d_sel", ipuno, dino);
+	diclk = clk_lookup(clkname);
+	free(clkname);
+	if (IS_ERR(diclk)) {
+		dev_err(ldb->dev, "failed to get di clk: %s\n", strerror(PTR_ERR(diclk)));
+		return PTR_ERR(diclk);
+	}
+
+	clkname = asprintf("ldb_di%d_podf", imx_ldb_ch->chno);
+	ldbclk = clk_lookup(clkname);
+	free(clkname);
+	if (IS_ERR(ldbclk)) {
+		dev_err(ldb->dev, "failed to get ldb clk: %s\n", strerror(PTR_ERR(ldbclk)));
+		return PTR_ERR(ldbclk);
+	}
+
+	ret = clk_set_parent(diclk, ldbclk);
+	if (ret) {
+		dev_err(ldb->dev, "failed to set display clock parent: %s\n", strerror(-ret));
+		return ret;
+	}
+printk("%s: %d\n", __func__, di);
+	val = readl(gpr3);
+	shift = (imx_ldb_ch->chno == 0) ? 6 : 8;
+	val &= ~(3 << shift);
+	val |= di << shift;
+	writel(val, gpr3);
+
+	return 0;
+}
+
+static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+	return -ENOSYS;
+}
+
+static struct imx_ldb_data imx_ldb_data_imx6q = {
+	.base = (void *)MX6_IOMUXC_BASE_ADDR + 0x8,
+	.prepare = imx6q_ldb_prepare,
+	.ipu_mask = 0xf,
+};
+
+static struct imx_ldb_data imx_ldb_data_imx53 = {
+	.base = (void *)MX53_IOMUXC_BASE_ADDR + 0x8,
+	.prepare = imx53_ldb_prepare,
+	.ipu_mask = 0x3,
+};
+
+static struct ipu_output_ops imx_ldb_ops = {
+	.prepare = imx_ldb_prepare,
+};
+
+static int imx_ldb_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	struct device_node *child;
+	struct imx_ldb *imx_ldb;
+	int ret, i;
+	int dual = 0;
+	int datawidth;
+	int mapping;
+	const struct imx_ldb_data *devtype;
+
+	ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
+	if (ret)
+		return ret;
+
+	imx_ldb = xzalloc(sizeof(*imx_ldb));
+	imx_ldb->base = devtype->base;
+	imx_ldb->soc_data = devtype;
+
+	for_each_child_of_node(np, child) {
+		struct imx_ldb_channel *channel;
+
+		ret = of_property_read_u32(child, "reg", &i);
+		if (ret || i < 0 || i > 1)
+			return -EINVAL;
+
+		if (dual && i > 0) {
+			dev_warn(dev, "dual-channel mode, ignoring second output\n");
+			continue;
+		}
+
+		if (!of_device_is_available(child))
+			continue;
+
+		channel = &imx_ldb->channel[i];
+		channel->ldb = imx_ldb;
+		channel->chno = i;
+
+		ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
+		if (ret)
+			datawidth = 0;
+		else if (datawidth != 18 && datawidth != 24)
+			return -EINVAL;
+
+		mapping = of_get_data_mapping(child);
+		switch (mapping) {
+		case LVDS_BIT_MAP_SPWG:
+			if (datawidth == 24) {
+				if (i == 0 || dual)
+					imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
+				if (i == 1 || dual)
+					imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
+			}
+			break;
+		case LVDS_BIT_MAP_JEIDA:
+			if (datawidth == 18) {
+				dev_err(dev, "JEIDA standard only supported in 24 bit\n");
+				return -EINVAL;
+			}
+			if (i == 0 || dual)
+				imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | LDB_BIT_MAP_CH0_JEIDA;
+			if (i == 1 || dual)
+				imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA;
+			break;
+		default:
+			dev_err(dev, "data mapping not specified or invalid\n");
+			return -EINVAL;
+		}
+
+		channel->output.ops = &imx_ldb_ops;
+		channel->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+		channel->output.out_pixel_fmt = (datawidth == 24) ?
+			V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
+		channel->output.modes = of_get_display_timings(child);
+		channel->output.name = asprintf("ldb-%d", i);
+		channel->output.ipu_mask = devtype->ipu_mask;
+
+		ipu_register_output(&channel->output);
+	}
+
+	return 0;
+}
+
+static struct of_device_id imx_ldb_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-ldb", (unsigned long)&imx_ldb_data_imx6q},
+	{ .compatible = "fsl,imx53-ldb", (unsigned long)&imx_ldb_data_imx53},
+	{ /* sentinel */ }
+};
+
+static struct driver_d imx_ldb_driver = {
+	.probe		= imx_ldb_probe,
+	.of_compatible	= imx_ldb_dt_ids,
+	.name		= "imx-ldb",
+};
+device_platform_driver(imx_ldb_driver);
+
+MODULE_DESCRIPTION("i.MX LVDS display driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 28/29] video: i.MX IPUv3: Add hdmi support
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (25 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 27/29] video: i.MX IPUv3: Add lvds bridge support Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  2014-03-14 14:32 ` [PATCH 29/29] ARM: update imx_v7_defconfig Sascha Hauer
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/imx-ipu-v3/Kconfig    |    3 +
 drivers/video/imx-ipu-v3/Makefile   |    1 +
 drivers/video/imx-ipu-v3/imx-hdmi.c | 1297 +++++++++++++++++++++++++++++++++++
 drivers/video/imx-ipu-v3/imx-hdmi.h | 1032 ++++++++++++++++++++++++++++
 4 files changed, 2333 insertions(+)
 create mode 100644 drivers/video/imx-ipu-v3/imx-hdmi.c
 create mode 100644 drivers/video/imx-ipu-v3/imx-hdmi.h

diff --git a/drivers/video/imx-ipu-v3/Kconfig b/drivers/video/imx-ipu-v3/Kconfig
index e83158a..3d656e5 100644
--- a/drivers/video/imx-ipu-v3/Kconfig
+++ b/drivers/video/imx-ipu-v3/Kconfig
@@ -8,4 +8,7 @@ if DRIVER_VIDEO_IMX_IPUV3
 config DRIVER_VIDEO_IMX_IPUV3_LVDS
 	bool "IPUv3 LVDS support"
 
+config DRIVER_VIDEO_IMX_IPUV3_HDMI
+	bool "IPUv3 HDMI support"
+
 endif
diff --git a/drivers/video/imx-ipu-v3/Makefile b/drivers/video/imx-ipu-v3/Makefile
index e2ff43d..2bc0aec 100644
--- a/drivers/video/imx-ipu-v3/Makefile
+++ b/drivers/video/imx-ipu-v3/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-common.o ipu-dmfc.o ipu-di.o
 obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-dp.o ipuv3-plane.o ipufb.o
 obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-dc.o
 obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS) += imx-ldb.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3_HDMI) += imx-hdmi.o
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c b/drivers/video/imx-ipu-v3/imx-hdmi.c
new file mode 100644
index 0000000..4f46288
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.c
@@ -0,0 +1,1297 @@
+/*
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
+ * for SLISHDMI13T and SLIPHDMIT IP cores
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ */
+#include <common.h>
+#include <fb.h>
+#include <io.h>
+#include <driver.h>
+#include <malloc.h>
+#include <errno.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/div64.h>
+#include <linux/clk.h>
+#include <i2c/i2c.h>
+#include <mach/imx6-regs.h>
+#include <mach/imx53-regs.h>
+
+#include "imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+#include "imx-hdmi.h"
+
+#define HDMI_EDID_LEN		512
+
+#define RGB			0
+#define YCBCR444		1
+#define YCBCR422_16BITS		2
+#define YCBCR422_8BITS		3
+#define XVYCC444		4
+
+enum hdmi_colorimetry {
+	HDMI_COLORIMETRY_NONE,
+	HDMI_COLORIMETRY_ITU_601,
+	HDMI_COLORIMETRY_ITU_709,
+	HDMI_COLORIMETRY_EXTENDED,
+};
+
+enum hdmi_datamap {
+	RGB444_8B = 0x01,
+	RGB444_10B = 0x03,
+	RGB444_12B = 0x05,
+	RGB444_16B = 0x07,
+	YCbCr444_8B = 0x09,
+	YCbCr444_10B = 0x0B,
+	YCbCr444_12B = 0x0D,
+	YCbCr444_16B = 0x0F,
+	YCbCr422_8B = 0x16,
+	YCbCr422_10B = 0x14,
+	YCbCr422_12B = 0x12,
+};
+
+enum imx_hdmi_devtype {
+	IMX6Q_HDMI,
+	IMX6DL_HDMI,
+};
+
+static const u16 csc_coeff_default[3][4] = {
+	{ 0x2000, 0x0000, 0x0000, 0x0000 },
+	{ 0x0000, 0x2000, 0x0000, 0x0000 },
+	{ 0x0000, 0x0000, 0x2000, 0x0000 }
+};
+
+static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
+	{ 0x2000, 0x6926, 0x74fd, 0x010e },
+	{ 0x2000, 0x2cdd, 0x0000, 0x7e9a },
+	{ 0x2000, 0x0000, 0x38b4, 0x7e3b }
+};
+
+static const u16 csc_coeff_rgb_out_eitu709[3][4] = {
+	{ 0x2000, 0x7106, 0x7a02, 0x00a7 },
+	{ 0x2000, 0x3264, 0x0000, 0x7e6d },
+	{ 0x2000, 0x0000, 0x3b61, 0x7e25 }
+};
+
+static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
+	{ 0x2591, 0x1322, 0x074b, 0x0000 },
+	{ 0x6535, 0x2000, 0x7acc, 0x0200 },
+	{ 0x6acd, 0x7534, 0x2000, 0x0200 }
+};
+
+static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
+	{ 0x2dc5, 0x0d9b, 0x049e, 0x0000 },
+	{ 0x62f0, 0x2000, 0x7d11, 0x0200 },
+	{ 0x6756, 0x78ab, 0x2000, 0x0200 }
+};
+
+struct hdmi_vmode {
+	bool mdvi;
+	bool mhsyncpolarity;
+	bool mvsyncpolarity;
+	bool minterlaced;
+	bool mdataenablepolarity;
+
+	unsigned int mpixelclock;
+	unsigned int mpixelrepetitioninput;
+	unsigned int mpixelrepetitionoutput;
+};
+
+struct hdmi_data_info {
+	unsigned int enc_in_format;
+	unsigned int enc_out_format;
+	unsigned int enc_color_depth;
+	unsigned int colorimetry;
+	unsigned int pix_repet_factor;
+	unsigned int hdcp_enable;
+	struct hdmi_vmode video_mode;
+};
+
+struct imx_hdmi {
+	enum imx_hdmi_devtype dev_type;
+	struct device_d *dev;
+	struct clk *isfr_clk;
+	struct clk *iahb_clk;
+
+	bool connected;
+
+	struct hdmi_data_info hdmi_data;
+	int vic;
+
+	u8 edid[HDMI_EDID_LEN];
+	bool cable_plugin;
+
+	bool phy_enabled;
+
+	struct regmap *regmap;
+	struct i2c_adapter *ddc;
+	void __iomem *regs;
+
+	unsigned int sample_rate;
+	int ratio;
+
+	struct ipu_output output;
+};
+
+static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
+{
+	void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc;
+	uint32_t val;
+
+	dev_info(hdmi->dev, "setup hdmi mux to %d\n", ipu_di);
+
+	val = readl(gpr3);
+	val &= ~(3 << 2);
+	val |= ipu_di << 2;
+	writel(val, gpr3);
+}
+
+static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset)
+{
+	writeb(val, hdmi->regs + offset);
+}
+
+static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset)
+{
+	return readb(hdmi->regs + offset);
+}
+
+static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+{
+	u8 val = hdmi_readb(hdmi, reg) & ~mask;
+	val |= data & mask;
+	hdmi_writeb(hdmi, val, reg);
+}
+
+static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
+		      u8 shift, u8 mask)
+{
+	hdmi_modb(hdmi, data << shift, mask, reg);
+}
+
+static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
+					 unsigned int value)
+{
+	hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
+	hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
+	hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
+
+	/* nshift factor = 0 */
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
+}
+
+static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
+{
+	/* Must be set/cleared first */
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+
+	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
+	hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+		    HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+}
+
+static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
+				   unsigned int ratio)
+{
+	unsigned int n = (128 * freq) / 1000;
+
+	switch (freq) {
+	case 32000:
+		if (pixel_clk == 25170000)
+			n = (ratio == 150) ? 9152 : 4576;
+		else if (pixel_clk == 27020000)
+			n = (ratio == 150) ? 8192 : 4096;
+		else if (pixel_clk == 74170000 || pixel_clk == 148350000)
+			n = 11648;
+		else
+			n = 4096;
+		break;
+
+	case 44100:
+		if (pixel_clk == 25170000)
+			n = 7007;
+		else if (pixel_clk == 74170000)
+			n = 17836;
+		else if (pixel_clk == 148350000)
+			n = (ratio == 150) ? 17836 : 8918;
+		else
+			n = 6272;
+		break;
+
+	case 48000:
+		if (pixel_clk == 25170000)
+			n = (ratio == 150) ? 9152 : 6864;
+		else if (pixel_clk == 27020000)
+			n = (ratio == 150) ? 8192 : 6144;
+		else if (pixel_clk == 74170000)
+			n = 11648;
+		else if (pixel_clk == 148350000)
+			n = (ratio == 150) ? 11648 : 5824;
+		else
+			n = 6144;
+		break;
+
+	case 88200:
+		n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
+		break;
+
+	case 96000:
+		n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
+		break;
+
+	case 176400:
+		n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
+		break;
+
+	case 192000:
+		n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
+		break;
+
+	default:
+		break;
+	}
+
+	return n;
+}
+
+static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
+				     unsigned int ratio)
+{
+	unsigned int cts = 0;
+
+	pr_debug("%s: freq: %d pixel_clk: %ld ratio: %d\n", __func__, freq,
+		 pixel_clk, ratio);
+
+	switch (freq) {
+	case 32000:
+		if (pixel_clk == 297000000) {
+			cts = 222750;
+			break;
+		}
+	case 48000:
+	case 96000:
+	case 192000:
+		switch (pixel_clk) {
+		case 25200000:
+		case 27000000:
+		case 54000000:
+		case 74250000:
+		case 148500000:
+			cts = pixel_clk / 1000;
+			break;
+		case 297000000:
+			cts = 247500;
+			break;
+		/*
+		 * All other TMDS clocks are not supported by
+		 * DWC_hdmi_tx. The TMDS clocks divided or
+		 * multiplied by 1,001 coefficients are not
+		 * supported.
+		 */
+		default:
+			break;
+		}
+		break;
+	case 44100:
+	case 88200:
+	case 176400:
+		switch (pixel_clk) {
+		case 25200000:
+			cts = 28000;
+			break;
+		case 27000000:
+			cts = 30000;
+			break;
+		case 54000000:
+			cts = 60000;
+			break;
+		case 74250000:
+			cts = 82500;
+			break;
+		case 148500000:
+			cts = 165000;
+			break;
+		case 297000000:
+			cts = 247500;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+	if (ratio == 100)
+		return cts;
+	else
+		return (cts * ratio) / 100;
+}
+
+static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
+	unsigned long pixel_clk)
+{
+	unsigned int clk_n, clk_cts;
+
+	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
+			       hdmi->ratio);
+	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
+				   hdmi->ratio);
+
+	if (!clk_cts) {
+		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
+			 __func__, pixel_clk);
+		return;
+	}
+
+	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
+		__func__, hdmi->sample_rate, hdmi->ratio,
+		pixel_clk, clk_n, clk_cts);
+
+	hdmi_set_clock_regenerator_n(hdmi, clk_n);
+	hdmi_regenerate_cts(hdmi, clk_cts);
+}
+
+static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
+{
+	hdmi_set_clk_regenerator(hdmi, 74250000);
+}
+
+/*
+ * 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 imx_hdmi *hdmi)
+{
+	int color_format = 0;
+	u8 val;
+
+	if (hdmi->hdmi_data.enc_in_format == RGB) {
+		if (hdmi->hdmi_data.enc_color_depth == 8)
+			color_format = 0x01;
+		else if (hdmi->hdmi_data.enc_color_depth == 10)
+			color_format = 0x03;
+		else if (hdmi->hdmi_data.enc_color_depth == 12)
+			color_format = 0x05;
+		else if (hdmi->hdmi_data.enc_color_depth == 16)
+			color_format = 0x07;
+		else
+			return;
+	} else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
+		if (hdmi->hdmi_data.enc_color_depth == 8)
+			color_format = 0x09;
+		else if (hdmi->hdmi_data.enc_color_depth == 10)
+			color_format = 0x0B;
+		else if (hdmi->hdmi_data.enc_color_depth == 12)
+			color_format = 0x0D;
+		else if (hdmi->hdmi_data.enc_color_depth == 16)
+			color_format = 0x0F;
+		else
+			return;
+	} else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
+		if (hdmi->hdmi_data.enc_color_depth == 8)
+			color_format = 0x16;
+		else if (hdmi->hdmi_data.enc_color_depth == 10)
+			color_format = 0x14;
+		else if (hdmi->hdmi_data.enc_color_depth == 12)
+			color_format = 0x12;
+		else
+			return;
+	}
+
+	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
+		((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
+		HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
+	hdmi_writeb(hdmi, val, HDMI_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;
+	hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING);
+	hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0);
+	hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1);
+	hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0);
+	hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1);
+	hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0);
+	hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
+}
+
+static int is_color_space_conversion(struct imx_hdmi *hdmi)
+{
+	return (hdmi->hdmi_data.enc_in_format !=
+		hdmi->hdmi_data.enc_out_format);
+}
+
+static int is_color_space_decimation(struct imx_hdmi *hdmi)
+{
+	return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) &&
+		(hdmi->hdmi_data.enc_in_format == RGB ||
+		hdmi->hdmi_data.enc_in_format == YCBCR444));
+}
+
+static int is_color_space_interpolation(struct imx_hdmi *hdmi)
+{
+	return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) &&
+		(hdmi->hdmi_data.enc_out_format == RGB ||
+		hdmi->hdmi_data.enc_out_format == YCBCR444));
+}
+
+static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
+{
+	const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
+	unsigned i;
+	u32 csc_scale = 1;
+
+	if (is_color_space_conversion(hdmi)) {
+		if (hdmi->hdmi_data.enc_out_format == RGB) {
+			if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
+				csc_coeff = &csc_coeff_rgb_out_eitu601;
+			else
+				csc_coeff = &csc_coeff_rgb_out_eitu709;
+		} else if (hdmi->hdmi_data.enc_in_format == RGB) {
+			if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
+				csc_coeff = &csc_coeff_rgb_in_eitu601;
+			else
+				csc_coeff = &csc_coeff_rgb_in_eitu709;
+			csc_scale = 0;
+		}
+	}
+
+	/* The CSC registers are sequential, alternating MSB then LSB */
+	for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
+		u16 coeff_a = (*csc_coeff)[0][i];
+		u16 coeff_b = (*csc_coeff)[1][i];
+		u16 coeff_c = (*csc_coeff)[2][i];
+
+		hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
+		hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
+		hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
+	}
+
+	hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+		  HDMI_CSC_SCALE);
+}
+
+static void hdmi_video_csc(struct imx_hdmi *hdmi)
+{
+	int color_depth = 0;
+	int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
+	int decimation = 0;
+
+	/* YCC422 interpolation to 444 mode */
+	if (is_color_space_interpolation(hdmi))
+		interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
+	else if (is_color_space_decimation(hdmi))
+		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
+
+	if (hdmi->hdmi_data.enc_color_depth == 8)
+		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
+	else if (hdmi->hdmi_data.enc_color_depth == 10)
+		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
+	else if (hdmi->hdmi_data.enc_color_depth == 12)
+		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
+	else if (hdmi->hdmi_data.enc_color_depth == 16)
+		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
+	else
+		return;
+
+	/* Configure the CSC registers */
+	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
+	hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
+		  HDMI_CSC_SCALE);
+
+	imx_hdmi_update_csc_coeffs(hdmi);
+}
+
+/*
+ * HDMI video packetizer is used to packetize the data.
+ * for example, if input is YCC422 mode or repeater is used,
+ * data should be repacked this module can be bypassed.
+ */
+static void hdmi_video_packetize(struct imx_hdmi *hdmi)
+{
+	unsigned int color_depth = 0;
+	unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
+	unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
+	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
+	u8 val, vp_conf;
+
+	if (hdmi_data->enc_out_format == RGB
+		|| hdmi_data->enc_out_format == YCBCR444) {
+		if (!hdmi_data->enc_color_depth)
+			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+		else if (hdmi_data->enc_color_depth == 8) {
+			color_depth = 4;
+			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+		} else if (hdmi_data->enc_color_depth == 10)
+			color_depth = 5;
+		else if (hdmi_data->enc_color_depth == 12)
+			color_depth = 6;
+		else if (hdmi_data->enc_color_depth == 16)
+			color_depth = 7;
+		else
+			return;
+	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
+		if (!hdmi_data->enc_color_depth ||
+		    hdmi_data->enc_color_depth == 8)
+			remap_size = HDMI_VP_REMAP_YCC422_16bit;
+		else if (hdmi_data->enc_color_depth == 10)
+			remap_size = HDMI_VP_REMAP_YCC422_20bit;
+		else if (hdmi_data->enc_color_depth == 12)
+			remap_size = HDMI_VP_REMAP_YCC422_24bit;
+		else
+			return;
+		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
+	} else
+		return;
+
+	/* set the packetizer registers */
+	val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
+		HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
+		((hdmi_data->pix_repet_factor <<
+		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
+		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
+	hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
+
+	hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
+		  HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
+
+	/* Data from pixel repeater block */
+	if (hdmi_data->pix_repet_factor > 1) {
+		vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
+			  HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
+	} else { /* data from packetizer block */
+		vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+			  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
+	}
+
+	hdmi_modb(hdmi, vp_conf,
+		  HDMI_VP_CONF_PR_EN_MASK |
+		  HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
+
+	hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
+		  HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
+
+	hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
+
+	if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+			  HDMI_VP_CONF_PP_EN_ENABLE |
+			  HDMI_VP_CONF_YCC422_EN_DISABLE;
+	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+			  HDMI_VP_CONF_PP_EN_DISABLE |
+			  HDMI_VP_CONF_YCC422_EN_ENABLE;
+	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+			  HDMI_VP_CONF_PP_EN_DISABLE |
+			  HDMI_VP_CONF_YCC422_EN_DISABLE;
+	} else {
+		return;
+	}
+
+	hdmi_modb(hdmi, vp_conf,
+		  HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
+		  HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
+
+	hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+			HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
+		  HDMI_VP_STUFF_PP_STUFFING_MASK |
+		  HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
+
+	hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+		  HDMI_VP_CONF);
+}
+
+static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
+						unsigned char bit)
+{
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
+		  HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
+						unsigned char bit)
+{
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
+		  HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
+						unsigned char bit)
+{
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
+		  HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
+						unsigned char bit)
+{
+	hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
+}
+
+static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi,
+						unsigned char bit)
+{
+	hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
+}
+
+static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec)
+{
+	unsigned char val = 0;
+	val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3;
+	while (!val) {
+		udelay(1000);
+		if (msec-- == 0)
+			return false;
+		val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3;
+	}
+	return true;
+}
+
+static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
+			      unsigned char addr)
+{
+	hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
+	hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+	hdmi_writeb(hdmi, (unsigned char)(data >> 8),
+		HDMI_PHY_I2CM_DATAO_1_ADDR);
+	hdmi_writeb(hdmi, (unsigned char)(data >> 0),
+		HDMI_PHY_I2CM_DATAO_0_ADDR);
+	hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
+		HDMI_PHY_I2CM_OPERATION_ADDR);
+	hdmi_phy_wait_i2c_done(hdmi, 1000);
+}
+
+static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
+				     unsigned char addr)
+{
+	__hdmi_phy_i2c_write(hdmi, data, addr);
+	return 0;
+}
+
+static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable)
+{
+	hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+			 HDMI_PHY_CONF0_PDZ_OFFSET,
+			 HDMI_PHY_CONF0_PDZ_MASK);
+}
+
+static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable)
+{
+	hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+			 HDMI_PHY_CONF0_ENTMDS_OFFSET,
+			 HDMI_PHY_CONF0_ENTMDS_MASK);
+}
+
+static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable)
+{
+	hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+			 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
+			 HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
+}
+
+static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable)
+{
+	hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+			 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
+			 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
+}
+
+static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable)
+{
+	hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+			 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
+			 HDMI_PHY_CONF0_SELDATAENPOL_MASK);
+}
+
+static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable)
+{
+	hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+			 HDMI_PHY_CONF0_SELDIPIF_OFFSET,
+			 HDMI_PHY_CONF0_SELDIPIF_MASK);
+}
+
+enum {
+	RES_8,
+	RES_10,
+	RES_12,
+	RES_MAX,
+};
+
+struct mpll_config {
+	unsigned long mpixelclock;
+	struct {
+		u16 cpce;
+		u16 gmp;
+	} res[RES_MAX];
+};
+
+static const struct mpll_config mpll_config[] = {
+	{
+		45250000, {
+			{ 0x01e0, 0x0000 },
+			{ 0x21e1, 0x0000 },
+			{ 0x41e2, 0x0000 }
+		},
+	}, {
+		92500000, {
+			{ 0x0140, 0x0005 },
+			{ 0x2141, 0x0005 },
+			{ 0x4142, 0x0005 },
+		},
+	}, {
+		148500000, {
+			{ 0x00a0, 0x000a },
+			{ 0x20a1, 0x000a },
+			{ 0x40a2, 0x000a },
+		},
+	}, {
+		~0UL, {
+			{ 0x00a0, 0x000a },
+			{ 0x2001, 0x000f },
+			{ 0x4002, 0x000f },
+		},
+	}
+};
+
+struct curr_ctrl {
+	unsigned long mpixelclock;
+	u16 curr[RES_MAX];
+};
+
+static const struct curr_ctrl curr_ctrl[] = {
+	/*	pixelclk     bpp8    bpp10   bpp12 */
+	{
+		 54000000, { 0x091c, 0x091c, 0x06dc },
+	}, {
+		 58400000, { 0x091c, 0x06dc, 0x06dc },
+	}, {
+		 72000000, { 0x06dc, 0x06dc, 0x091c },
+	}, {
+		 74250000, { 0x06dc, 0x0b5c, 0x091c },
+	}, {
+		118800000, { 0x091c, 0x091c, 0x06dc },
+	}, {
+		216000000, { 0x06dc, 0x0b5c, 0x091c },
+	}
+};
+
+static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
+			      unsigned char res, int cscon)
+{
+	unsigned res_idx, i;
+	u8 val, msec;
+
+	if (prep)
+		return -EINVAL;
+
+	switch (res) {
+	case 0:	/* color resolution 0 is 8 bit colour depth */
+	case 8:
+		res_idx = RES_8;
+		break;
+	case 10:
+		res_idx = RES_10;
+		break;
+	case 12:
+		res_idx = RES_12;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Enable csc path */
+	if (cscon)
+		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
+	else
+		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
+
+	hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
+
+	/* gen2 tx power off */
+	imx_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+	/* gen2 pddq */
+	imx_hdmi_phy_gen2_pddq(hdmi, 1);
+
+	/* PHY reset */
+	hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
+	hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
+
+	hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
+
+	hdmi_phy_test_clear(hdmi, 1);
+	hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
+			HDMI_PHY_I2CM_SLAVE_ADDR);
+	hdmi_phy_test_clear(hdmi, 0);
+
+	/* PLL/MPLL Cfg - always match on final entry */
+	for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    mpll_config[i].mpixelclock)
+			break;
+
+	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
+	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+
+	for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    curr_ctrl[i].mpixelclock)
+			break;
+
+	if (i >= ARRAY_SIZE(curr_ctrl)) {
+		dev_err(hdmi->dev,
+				"Pixel clock %d - unsupported by HDMI\n",
+				hdmi->hdmi_data.video_mode.mpixelclock);
+		return -EINVAL;
+	}
+
+	/* CURRCTRL */
+	hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+
+	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
+	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
+	/* RESISTANCE TERM 133Ohm Cfg */
+	hdmi_phy_i2c_write(hdmi, 0x0005, 0x19);  /* TXTERM */
+	/* PREEMP Cgf 0.00 */
+	hdmi_phy_i2c_write(hdmi, 0x800d, 0x09);  /* CKSYMTXCTRL */
+	/* TX/CK LVL 10 */
+	hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E);  /* VLEVCTRL */
+	/* REMOVE CLK TERM */
+	hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);  /* CKCALCTRL */
+
+	imx_hdmi_phy_enable_power(hdmi, 1);
+
+	/* toggle TMDS enable */
+	imx_hdmi_phy_enable_tmds(hdmi, 0);
+	imx_hdmi_phy_enable_tmds(hdmi, 1);
+
+	/* gen2 tx power on */
+	imx_hdmi_phy_gen2_txpwron(hdmi, 1);
+	imx_hdmi_phy_gen2_pddq(hdmi, 0);
+
+	/*Wait for PHY PLL lock */
+	msec = 5;
+	do {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+		if (!val)
+			break;
+
+		if (msec == 0) {
+			dev_err(hdmi->dev, "PHY PLL not locked\n");
+			return -ETIMEDOUT;
+		}
+
+		udelay(1000);
+		msec--;
+	} while (1);
+
+	return 0;
+}
+
+static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
+{
+	int i, ret;
+	bool cscon = false;
+
+	/*check csc whether needed activated in HDMI mode */
+	cscon = (is_color_space_conversion(hdmi) &&
+			!hdmi->hdmi_data.video_mode.mdvi);
+
+	/* HDMI Phy spec says to do the phy initialization sequence twice */
+	for (i = 0; i < 2; i++) {
+		imx_hdmi_phy_sel_data_en_pol(hdmi, 1);
+		imx_hdmi_phy_sel_interface_control(hdmi, 0);
+		imx_hdmi_phy_enable_tmds(hdmi, 0);
+		imx_hdmi_phy_enable_power(hdmi, 0);
+
+		/* Enable CSC */
+		ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
+		if (ret)
+			return ret;
+	}
+
+	hdmi->phy_enabled = true;
+	return 0;
+}
+
+static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
+{
+	u8 de;
+
+	if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
+		de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
+	else
+		de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
+
+	/* disable rx detect */
+	hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
+		  HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
+
+	hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
+
+	hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
+		  HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
+}
+
+static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi)
+{
+	if (!hdmi->phy_enabled)
+		return;
+
+	imx_hdmi_phy_enable_tmds(hdmi, 0);
+	imx_hdmi_phy_enable_power(hdmi, 0);
+
+	hdmi->phy_enabled = false;
+}
+
+/* HDMI Initialization Step B.4 */
+static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
+{
+	u8 clkdis;
+
+	/* control period minimum duration */
+	hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
+	hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
+	hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC);
+
+	/* Set to fill TMDS data channels */
+	hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM);
+	hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM);
+	hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
+
+	/* Enable pixel clock and tmds data path */
+	clkdis = 0x7F;
+	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+	/* Enable csc path */
+	if (is_color_space_conversion(hdmi)) {
+		clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+	}
+}
+
+/* Workaround to clear the overflow condition */
+static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
+{
+	int count;
+	u8 val;
+
+	/* TMDS software reset */
+	hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
+
+	val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
+	if (hdmi->dev_type == IMX6DL_HDMI) {
+		hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
+		return;
+	}
+
+	for (count = 0; count < 4; count++)
+		hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
+}
+
+static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct fb_videomode *mode)
+{
+	int ret;
+
+	hdmi->vic = 0;
+
+	dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
+	hdmi->hdmi_data.video_mode.mdvi = true;
+
+	hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
+	hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
+	hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
+
+	/* TODO: Get input format from IPU (via FB driver interface) */
+	hdmi->hdmi_data.enc_in_format = RGB;
+
+	hdmi->hdmi_data.enc_out_format = RGB;
+
+	hdmi->hdmi_data.enc_color_depth = 8;
+	hdmi->hdmi_data.pix_repet_factor = 0;
+	hdmi->hdmi_data.hdcp_enable = 0;
+	hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
+
+	/* HDMI Initializateion Step B.2 */
+	ret = imx_hdmi_phy_init(hdmi);
+	if (ret)
+		return ret;
+
+	/* HDMI Initialization Step B.3 */
+	imx_hdmi_enable_video_path(hdmi);
+
+	/* not for DVI mode */
+	dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
+
+	hdmi_video_packetize(hdmi);
+	hdmi_video_csc(hdmi);
+	hdmi_video_sample(hdmi);
+	hdmi_tx_hdcp_config(hdmi);
+
+	imx_hdmi_clear_overflow(hdmi);
+
+	return 0;
+}
+
+static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi)
+{
+	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 = hdmi_readb(hdmi, HDMI_IH_MUTE) |
+		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+	hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+
+	/* by default mask all interrupts */
+	hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK);
+	hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0);
+	hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1);
+	hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2);
+	hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0);
+	hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR);
+	hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
+	hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT);
+	hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT);
+	hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
+	hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
+	hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
+	hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
+	hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
+	hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
+
+	/* Disable interrupts in the IH_MUTE_* registers */
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
+	hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+	/* Enable top level interrupt bits in HDMI block */
+	ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+		    HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
+	hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+}
+
+struct imx_hdmi_data {
+	unsigned ipu_mask;
+	enum imx_hdmi_devtype devtype;
+};
+
+static struct imx_hdmi_data imx6q_hdmi_data = {
+	.ipu_mask = 0xf,
+	.devtype = IMX6Q_HDMI,
+};
+
+static struct imx_hdmi_data imx6dl_hdmi_data = {
+	.ipu_mask = 0x3,
+	.devtype = IMX6DL_HDMI,
+};
+
+static struct of_device_id imx_hdmi_dt_ids[] = {
+	{
+		.compatible = "fsl,imx6q-hdmi",
+		.data = (unsigned long)&imx6q_hdmi_data,
+	}, {
+		.compatible = "fsl,imx6dl-hdmi",
+		.data = (unsigned long)&imx6dl_hdmi_data,
+	}, {
+		/* sentinel */
+	}
+};
+
+static int imx_hdmi_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+{
+	struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+
+	imx_hdmi_set_ipu_di_mux(hdmi, di);
+
+	return 0;
+}
+
+static int imx_hdmi_commit(struct ipu_output *output, struct fb_videomode *mode, int di)
+{
+	struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+
+	imx_hdmi_setup(hdmi, mode);
+
+	return 0;
+}
+
+static int imx_hdmi_disable(struct ipu_output *output)
+{
+	struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+
+	imx_hdmi_phy_disable(hdmi);
+
+	return 0;
+}
+
+static struct ipu_output_ops imx_hdmi_ops = {
+	.prepare = imx_hdmi_prepare,
+	.enable = imx_hdmi_commit,
+	.disable = imx_hdmi_disable,
+};
+
+static int imx_hdmi_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	struct device_node *ddc_node;
+	struct imx_hdmi *hdmi;
+	int ret;
+	const struct imx_hdmi_data *devtype;
+
+	ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
+	if (ret)
+		return ret;
+
+	hdmi = xzalloc(sizeof(*hdmi));
+
+	hdmi->dev = dev;
+	hdmi->connected = 0;
+	hdmi->sample_rate = 48000;
+	hdmi->ratio = 100;
+
+	ret = dev_get_drvdata(dev, (unsigned long *)&hdmi->dev_type);
+	if (ret)
+		return ret;
+
+	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
+	if (ddc_node) {
+		hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+		if (!hdmi->ddc)
+			dev_dbg(hdmi->dev, "failed to read ddc node\n");
+	} else {
+		dev_dbg(hdmi->dev, "no ddc property found\n");
+	}
+
+	ddc_node = NULL;
+
+	hdmi->regs = dev_request_mem_region(dev, 0);
+	if (!hdmi->regs)
+		return -EBUSY;
+
+	hdmi->isfr_clk = clk_get(hdmi->dev, "isfr");
+	if (IS_ERR(hdmi->isfr_clk)) {
+		ret = PTR_ERR(hdmi->isfr_clk);
+		dev_err(dev,
+			"Unable to get HDMI isfr clk: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(hdmi->isfr_clk);
+	if (ret)
+		return ret;
+
+	hdmi->iahb_clk = clk_get(hdmi->dev, "iahb");
+	if (IS_ERR(hdmi->iahb_clk)) {
+		ret = PTR_ERR(hdmi->iahb_clk);
+		dev_err(dev,
+			"Unable to get HDMI iahb clk: %d\n", ret);
+		goto err_isfr;
+	}
+
+	ret = clk_enable(hdmi->iahb_clk);
+	if (ret)
+		goto err_isfr;
+
+	/* Product and revision IDs */
+	dev_info(dev,
+		"Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
+		hdmi_readb(hdmi, HDMI_DESIGN_ID),
+		hdmi_readb(hdmi, HDMI_REVISION_ID),
+		hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
+		hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
+
+	initialize_hdmi_ih_mutes(hdmi);
+
+	/*
+	 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
+	 * N and cts values before enabling phy
+	 */
+	hdmi_init_clk_regenerator(hdmi);
+
+	/*
+	 * Configure registers related to HDMI interrupt
+	 * generation before registering IRQ.
+	 */
+	hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
+
+	/* Clear Hotplug interrupts */
+	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+	hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
+		    HDMI_PHY_I2CM_INT_ADDR);
+
+	hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
+		    HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
+		    HDMI_PHY_I2CM_CTLINT_ADDR);
+
+	/* enable cable hot plug irq */
+	hdmi_writeb(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
+
+	/* Unmute interrupts */
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+
+	hdmi->output.ops = &imx_hdmi_ops;
+	hdmi->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+	hdmi->output.out_pixel_fmt = V4L2_PIX_FMT_RGB24;
+	hdmi->output.name = asprintf("hdmi-0");
+	hdmi->output.ipu_mask = devtype->ipu_mask;
+	hdmi->output.edid_i2c_adapter = hdmi->ddc;
+	hdmi->output.modes = of_get_display_timings(np);
+
+	ipu_register_output(&hdmi->output);
+
+	return 0;
+
+err_isfr:
+	clk_disable(hdmi->isfr_clk);
+
+	return ret;
+}
+
+static struct driver_d imx_hdmi_driver = {
+	.probe		= imx_hdmi_probe,
+	.of_compatible	= imx_hdmi_dt_ids,
+	.name		= "imx-hdmi",
+};
+device_platform_driver(imx_hdmi_driver);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.h b/drivers/video/imx-ipu-v3/imx-hdmi.h
new file mode 100644
index 0000000..39b6776
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.h
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __IMX_HDMI_H__
+#define __IMX_HDMI_H__
+
+/* Identification Registers */
+#define HDMI_DESIGN_ID                          0x0000
+#define HDMI_REVISION_ID                        0x0001
+#define HDMI_PRODUCT_ID0                        0x0002
+#define HDMI_PRODUCT_ID1                        0x0003
+#define HDMI_CONFIG0_ID                         0x0004
+#define HDMI_CONFIG1_ID                         0x0005
+#define HDMI_CONFIG2_ID                         0x0006
+#define HDMI_CONFIG3_ID                         0x0007
+
+/* Interrupt Registers */
+#define HDMI_IH_FC_STAT0                        0x0100
+#define HDMI_IH_FC_STAT1                        0x0101
+#define HDMI_IH_FC_STAT2                        0x0102
+#define HDMI_IH_AS_STAT0                        0x0103
+#define HDMI_IH_PHY_STAT0                       0x0104
+#define HDMI_IH_I2CM_STAT0                      0x0105
+#define HDMI_IH_CEC_STAT0                       0x0106
+#define HDMI_IH_VP_STAT0                        0x0107
+#define HDMI_IH_I2CMPHY_STAT0                   0x0108
+#define HDMI_IH_AHBDMAAUD_STAT0                 0x0109
+
+#define HDMI_IH_MUTE_FC_STAT0                   0x0180
+#define HDMI_IH_MUTE_FC_STAT1                   0x0181
+#define HDMI_IH_MUTE_FC_STAT2                   0x0182
+#define HDMI_IH_MUTE_AS_STAT0                   0x0183
+#define HDMI_IH_MUTE_PHY_STAT0                  0x0184
+#define HDMI_IH_MUTE_I2CM_STAT0                 0x0185
+#define HDMI_IH_MUTE_CEC_STAT0                  0x0186
+#define HDMI_IH_MUTE_VP_STAT0                   0x0187
+#define HDMI_IH_MUTE_I2CMPHY_STAT0              0x0188
+#define HDMI_IH_MUTE_AHBDMAAUD_STAT0            0x0189
+#define HDMI_IH_MUTE                            0x01FF
+
+/* Video Sample Registers */
+#define HDMI_TX_INVID0                          0x0200
+#define HDMI_TX_INSTUFFING                      0x0201
+#define HDMI_TX_GYDATA0                         0x0202
+#define HDMI_TX_GYDATA1                         0x0203
+#define HDMI_TX_RCRDATA0                        0x0204
+#define HDMI_TX_RCRDATA1                        0x0205
+#define HDMI_TX_BCBDATA0                        0x0206
+#define HDMI_TX_BCBDATA1                        0x0207
+
+/* Video Packetizer Registers */
+#define HDMI_VP_STATUS                          0x0800
+#define HDMI_VP_PR_CD                           0x0801
+#define HDMI_VP_STUFF                           0x0802
+#define HDMI_VP_REMAP                           0x0803
+#define HDMI_VP_CONF                            0x0804
+#define HDMI_VP_STAT                            0x0805
+#define HDMI_VP_INT                             0x0806
+#define HDMI_VP_MASK                            0x0807
+#define HDMI_VP_POL                             0x0808
+
+/* Frame Composer Registers */
+#define HDMI_FC_INVIDCONF                       0x1000
+#define HDMI_FC_INHACTV0                        0x1001
+#define HDMI_FC_INHACTV1                        0x1002
+#define HDMI_FC_INHBLANK0                       0x1003
+#define HDMI_FC_INHBLANK1                       0x1004
+#define HDMI_FC_INVACTV0                        0x1005
+#define HDMI_FC_INVACTV1                        0x1006
+#define HDMI_FC_INVBLANK                        0x1007
+#define HDMI_FC_HSYNCINDELAY0                   0x1008
+#define HDMI_FC_HSYNCINDELAY1                   0x1009
+#define HDMI_FC_HSYNCINWIDTH0                   0x100A
+#define HDMI_FC_HSYNCINWIDTH1                   0x100B
+#define HDMI_FC_VSYNCINDELAY                    0x100C
+#define HDMI_FC_VSYNCINWIDTH                    0x100D
+#define HDMI_FC_INFREQ0                         0x100E
+#define HDMI_FC_INFREQ1                         0x100F
+#define HDMI_FC_INFREQ2                         0x1010
+#define HDMI_FC_CTRLDUR                         0x1011
+#define HDMI_FC_EXCTRLDUR                       0x1012
+#define HDMI_FC_EXCTRLSPAC                      0x1013
+#define HDMI_FC_CH0PREAM                        0x1014
+#define HDMI_FC_CH1PREAM                        0x1015
+#define HDMI_FC_CH2PREAM                        0x1016
+#define HDMI_FC_AVICONF3                        0x1017
+#define HDMI_FC_GCP                             0x1018
+#define HDMI_FC_AVICONF0                        0x1019
+#define HDMI_FC_AVICONF1                        0x101A
+#define HDMI_FC_AVICONF2                        0x101B
+#define HDMI_FC_AVIVID                          0x101C
+#define HDMI_FC_AVIETB0                         0x101D
+#define HDMI_FC_AVIETB1                         0x101E
+#define HDMI_FC_AVISBB0                         0x101F
+#define HDMI_FC_AVISBB1                         0x1020
+#define HDMI_FC_AVIELB0                         0x1021
+#define HDMI_FC_AVIELB1                         0x1022
+#define HDMI_FC_AVISRB0                         0x1023
+#define HDMI_FC_AVISRB1                         0x1024
+#define HDMI_FC_AUDICONF0                       0x1025
+#define HDMI_FC_AUDICONF1                       0x1026
+#define HDMI_FC_AUDICONF2                       0x1027
+#define HDMI_FC_AUDICONF3                       0x1028
+#define HDMI_FC_VSDIEEEID0                      0x1029
+#define HDMI_FC_VSDSIZE                         0x102A
+#define HDMI_FC_VSDIEEEID1                      0x1030
+#define HDMI_FC_VSDIEEEID2                      0x1031
+#define HDMI_FC_VSDPAYLOAD0                     0x1032
+#define HDMI_FC_VSDPAYLOAD1                     0x1033
+#define HDMI_FC_VSDPAYLOAD2                     0x1034
+#define HDMI_FC_VSDPAYLOAD3                     0x1035
+#define HDMI_FC_VSDPAYLOAD4                     0x1036
+#define HDMI_FC_VSDPAYLOAD5                     0x1037
+#define HDMI_FC_VSDPAYLOAD6                     0x1038
+#define HDMI_FC_VSDPAYLOAD7                     0x1039
+#define HDMI_FC_VSDPAYLOAD8                     0x103A
+#define HDMI_FC_VSDPAYLOAD9                     0x103B
+#define HDMI_FC_VSDPAYLOAD10                    0x103C
+#define HDMI_FC_VSDPAYLOAD11                    0x103D
+#define HDMI_FC_VSDPAYLOAD12                    0x103E
+#define HDMI_FC_VSDPAYLOAD13                    0x103F
+#define HDMI_FC_VSDPAYLOAD14                    0x1040
+#define HDMI_FC_VSDPAYLOAD15                    0x1041
+#define HDMI_FC_VSDPAYLOAD16                    0x1042
+#define HDMI_FC_VSDPAYLOAD17                    0x1043
+#define HDMI_FC_VSDPAYLOAD18                    0x1044
+#define HDMI_FC_VSDPAYLOAD19                    0x1045
+#define HDMI_FC_VSDPAYLOAD20                    0x1046
+#define HDMI_FC_VSDPAYLOAD21                    0x1047
+#define HDMI_FC_VSDPAYLOAD22                    0x1048
+#define HDMI_FC_VSDPAYLOAD23                    0x1049
+#define HDMI_FC_SPDVENDORNAME0                  0x104A
+#define HDMI_FC_SPDVENDORNAME1                  0x104B
+#define HDMI_FC_SPDVENDORNAME2                  0x104C
+#define HDMI_FC_SPDVENDORNAME3                  0x104D
+#define HDMI_FC_SPDVENDORNAME4                  0x104E
+#define HDMI_FC_SPDVENDORNAME5                  0x104F
+#define HDMI_FC_SPDVENDORNAME6                  0x1050
+#define HDMI_FC_SPDVENDORNAME7                  0x1051
+#define HDMI_FC_SDPPRODUCTNAME0                 0x1052
+#define HDMI_FC_SDPPRODUCTNAME1                 0x1053
+#define HDMI_FC_SDPPRODUCTNAME2                 0x1054
+#define HDMI_FC_SDPPRODUCTNAME3                 0x1055
+#define HDMI_FC_SDPPRODUCTNAME4                 0x1056
+#define HDMI_FC_SDPPRODUCTNAME5                 0x1057
+#define HDMI_FC_SDPPRODUCTNAME6                 0x1058
+#define HDMI_FC_SDPPRODUCTNAME7                 0x1059
+#define HDMI_FC_SDPPRODUCTNAME8                 0x105A
+#define HDMI_FC_SDPPRODUCTNAME9                 0x105B
+#define HDMI_FC_SDPPRODUCTNAME10                0x105C
+#define HDMI_FC_SDPPRODUCTNAME11                0x105D
+#define HDMI_FC_SDPPRODUCTNAME12                0x105E
+#define HDMI_FC_SDPPRODUCTNAME13                0x105F
+#define HDMI_FC_SDPPRODUCTNAME14                0x1060
+#define HDMI_FC_SPDPRODUCTNAME15                0x1061
+#define HDMI_FC_SPDDEVICEINF                    0x1062
+#define HDMI_FC_AUDSCONF                        0x1063
+#define HDMI_FC_AUDSSTAT                        0x1064
+#define HDMI_FC_DATACH0FILL                     0x1070
+#define HDMI_FC_DATACH1FILL                     0x1071
+#define HDMI_FC_DATACH2FILL                     0x1072
+#define HDMI_FC_CTRLQHIGH                       0x1073
+#define HDMI_FC_CTRLQLOW                        0x1074
+#define HDMI_FC_ACP0                            0x1075
+#define HDMI_FC_ACP28                           0x1076
+#define HDMI_FC_ACP27                           0x1077
+#define HDMI_FC_ACP26                           0x1078
+#define HDMI_FC_ACP25                           0x1079
+#define HDMI_FC_ACP24                           0x107A
+#define HDMI_FC_ACP23                           0x107B
+#define HDMI_FC_ACP22                           0x107C
+#define HDMI_FC_ACP21                           0x107D
+#define HDMI_FC_ACP20                           0x107E
+#define HDMI_FC_ACP19                           0x107F
+#define HDMI_FC_ACP18                           0x1080
+#define HDMI_FC_ACP17                           0x1081
+#define HDMI_FC_ACP16                           0x1082
+#define HDMI_FC_ACP15                           0x1083
+#define HDMI_FC_ACP14                           0x1084
+#define HDMI_FC_ACP13                           0x1085
+#define HDMI_FC_ACP12                           0x1086
+#define HDMI_FC_ACP11                           0x1087
+#define HDMI_FC_ACP10                           0x1088
+#define HDMI_FC_ACP9                            0x1089
+#define HDMI_FC_ACP8                            0x108A
+#define HDMI_FC_ACP7                            0x108B
+#define HDMI_FC_ACP6                            0x108C
+#define HDMI_FC_ACP5                            0x108D
+#define HDMI_FC_ACP4                            0x108E
+#define HDMI_FC_ACP3                            0x108F
+#define HDMI_FC_ACP2                            0x1090
+#define HDMI_FC_ACP1                            0x1091
+#define HDMI_FC_ISCR1_0                         0x1092
+#define HDMI_FC_ISCR1_16                        0x1093
+#define HDMI_FC_ISCR1_15                        0x1094
+#define HDMI_FC_ISCR1_14                        0x1095
+#define HDMI_FC_ISCR1_13                        0x1096
+#define HDMI_FC_ISCR1_12                        0x1097
+#define HDMI_FC_ISCR1_11                        0x1098
+#define HDMI_FC_ISCR1_10                        0x1099
+#define HDMI_FC_ISCR1_9                         0x109A
+#define HDMI_FC_ISCR1_8                         0x109B
+#define HDMI_FC_ISCR1_7                         0x109C
+#define HDMI_FC_ISCR1_6                         0x109D
+#define HDMI_FC_ISCR1_5                         0x109E
+#define HDMI_FC_ISCR1_4                         0x109F
+#define HDMI_FC_ISCR1_3                         0x10A0
+#define HDMI_FC_ISCR1_2                         0x10A1
+#define HDMI_FC_ISCR1_1                         0x10A2
+#define HDMI_FC_ISCR2_15                        0x10A3
+#define HDMI_FC_ISCR2_14                        0x10A4
+#define HDMI_FC_ISCR2_13                        0x10A5
+#define HDMI_FC_ISCR2_12                        0x10A6
+#define HDMI_FC_ISCR2_11                        0x10A7
+#define HDMI_FC_ISCR2_10                        0x10A8
+#define HDMI_FC_ISCR2_9                         0x10A9
+#define HDMI_FC_ISCR2_8                         0x10AA
+#define HDMI_FC_ISCR2_7                         0x10AB
+#define HDMI_FC_ISCR2_6                         0x10AC
+#define HDMI_FC_ISCR2_5                         0x10AD
+#define HDMI_FC_ISCR2_4                         0x10AE
+#define HDMI_FC_ISCR2_3                         0x10AF
+#define HDMI_FC_ISCR2_2                         0x10B0
+#define HDMI_FC_ISCR2_1                         0x10B1
+#define HDMI_FC_ISCR2_0                         0x10B2
+#define HDMI_FC_DATAUTO0                        0x10B3
+#define HDMI_FC_DATAUTO1                        0x10B4
+#define HDMI_FC_DATAUTO2                        0x10B5
+#define HDMI_FC_DATMAN                          0x10B6
+#define HDMI_FC_DATAUTO3                        0x10B7
+#define HDMI_FC_RDRB0                           0x10B8
+#define HDMI_FC_RDRB1                           0x10B9
+#define HDMI_FC_RDRB2                           0x10BA
+#define HDMI_FC_RDRB3                           0x10BB
+#define HDMI_FC_RDRB4                           0x10BC
+#define HDMI_FC_RDRB5                           0x10BD
+#define HDMI_FC_RDRB6                           0x10BE
+#define HDMI_FC_RDRB7                           0x10BF
+#define HDMI_FC_STAT0                           0x10D0
+#define HDMI_FC_INT0                            0x10D1
+#define HDMI_FC_MASK0                           0x10D2
+#define HDMI_FC_POL0                            0x10D3
+#define HDMI_FC_STAT1                           0x10D4
+#define HDMI_FC_INT1                            0x10D5
+#define HDMI_FC_MASK1                           0x10D6
+#define HDMI_FC_POL1                            0x10D7
+#define HDMI_FC_STAT2                           0x10D8
+#define HDMI_FC_INT2                            0x10D9
+#define HDMI_FC_MASK2                           0x10DA
+#define HDMI_FC_POL2                            0x10DB
+#define HDMI_FC_PRCONF                          0x10E0
+
+#define HDMI_FC_GMD_STAT                        0x1100
+#define HDMI_FC_GMD_EN                          0x1101
+#define HDMI_FC_GMD_UP                          0x1102
+#define HDMI_FC_GMD_CONF                        0x1103
+#define HDMI_FC_GMD_HB                          0x1104
+#define HDMI_FC_GMD_PB0                         0x1105
+#define HDMI_FC_GMD_PB1                         0x1106
+#define HDMI_FC_GMD_PB2                         0x1107
+#define HDMI_FC_GMD_PB3                         0x1108
+#define HDMI_FC_GMD_PB4                         0x1109
+#define HDMI_FC_GMD_PB5                         0x110A
+#define HDMI_FC_GMD_PB6                         0x110B
+#define HDMI_FC_GMD_PB7                         0x110C
+#define HDMI_FC_GMD_PB8                         0x110D
+#define HDMI_FC_GMD_PB9                         0x110E
+#define HDMI_FC_GMD_PB10                        0x110F
+#define HDMI_FC_GMD_PB11                        0x1110
+#define HDMI_FC_GMD_PB12                        0x1111
+#define HDMI_FC_GMD_PB13                        0x1112
+#define HDMI_FC_GMD_PB14                        0x1113
+#define HDMI_FC_GMD_PB15                        0x1114
+#define HDMI_FC_GMD_PB16                        0x1115
+#define HDMI_FC_GMD_PB17                        0x1116
+#define HDMI_FC_GMD_PB18                        0x1117
+#define HDMI_FC_GMD_PB19                        0x1118
+#define HDMI_FC_GMD_PB20                        0x1119
+#define HDMI_FC_GMD_PB21                        0x111A
+#define HDMI_FC_GMD_PB22                        0x111B
+#define HDMI_FC_GMD_PB23                        0x111C
+#define HDMI_FC_GMD_PB24                        0x111D
+#define HDMI_FC_GMD_PB25                        0x111E
+#define HDMI_FC_GMD_PB26                        0x111F
+#define HDMI_FC_GMD_PB27                        0x1120
+
+#define HDMI_FC_DBGFORCE                        0x1200
+#define HDMI_FC_DBGAUD0CH0                      0x1201
+#define HDMI_FC_DBGAUD1CH0                      0x1202
+#define HDMI_FC_DBGAUD2CH0                      0x1203
+#define HDMI_FC_DBGAUD0CH1                      0x1204
+#define HDMI_FC_DBGAUD1CH1                      0x1205
+#define HDMI_FC_DBGAUD2CH1                      0x1206
+#define HDMI_FC_DBGAUD0CH2                      0x1207
+#define HDMI_FC_DBGAUD1CH2                      0x1208
+#define HDMI_FC_DBGAUD2CH2                      0x1209
+#define HDMI_FC_DBGAUD0CH3                      0x120A
+#define HDMI_FC_DBGAUD1CH3                      0x120B
+#define HDMI_FC_DBGAUD2CH3                      0x120C
+#define HDMI_FC_DBGAUD0CH4                      0x120D
+#define HDMI_FC_DBGAUD1CH4                      0x120E
+#define HDMI_FC_DBGAUD2CH4                      0x120F
+#define HDMI_FC_DBGAUD0CH5                      0x1210
+#define HDMI_FC_DBGAUD1CH5                      0x1211
+#define HDMI_FC_DBGAUD2CH5                      0x1212
+#define HDMI_FC_DBGAUD0CH6                      0x1213
+#define HDMI_FC_DBGAUD1CH6                      0x1214
+#define HDMI_FC_DBGAUD2CH6                      0x1215
+#define HDMI_FC_DBGAUD0CH7                      0x1216
+#define HDMI_FC_DBGAUD1CH7                      0x1217
+#define HDMI_FC_DBGAUD2CH7                      0x1218
+#define HDMI_FC_DBGTMDS0                        0x1219
+#define HDMI_FC_DBGTMDS1                        0x121A
+#define HDMI_FC_DBGTMDS2                        0x121B
+
+/* HDMI Source PHY Registers */
+#define HDMI_PHY_CONF0                          0x3000
+#define HDMI_PHY_TST0                           0x3001
+#define HDMI_PHY_TST1                           0x3002
+#define HDMI_PHY_TST2                           0x3003
+#define HDMI_PHY_STAT0                          0x3004
+#define HDMI_PHY_INT0                           0x3005
+#define HDMI_PHY_MASK0                          0x3006
+#define HDMI_PHY_POL0                           0x3007
+
+/* HDMI Master PHY Registers */
+#define HDMI_PHY_I2CM_SLAVE_ADDR                0x3020
+#define HDMI_PHY_I2CM_ADDRESS_ADDR              0x3021
+#define HDMI_PHY_I2CM_DATAO_1_ADDR              0x3022
+#define HDMI_PHY_I2CM_DATAO_0_ADDR              0x3023
+#define HDMI_PHY_I2CM_DATAI_1_ADDR              0x3024
+#define HDMI_PHY_I2CM_DATAI_0_ADDR              0x3025
+#define HDMI_PHY_I2CM_OPERATION_ADDR            0x3026
+#define HDMI_PHY_I2CM_INT_ADDR                  0x3027
+#define HDMI_PHY_I2CM_CTLINT_ADDR               0x3028
+#define HDMI_PHY_I2CM_DIV_ADDR                  0x3029
+#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR             0x302a
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR        0x302b
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR        0x302c
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR        0x302d
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR        0x302e
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR        0x302f
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR        0x3030
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR        0x3031
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR        0x3032
+
+/* Audio Sampler Registers */
+#define HDMI_AUD_CONF0                          0x3100
+#define HDMI_AUD_CONF1                          0x3101
+#define HDMI_AUD_INT                            0x3102
+#define HDMI_AUD_CONF2                          0x3103
+#define HDMI_AUD_N1                             0x3200
+#define HDMI_AUD_N2                             0x3201
+#define HDMI_AUD_N3                             0x3202
+#define HDMI_AUD_CTS1                           0x3203
+#define HDMI_AUD_CTS2                           0x3204
+#define HDMI_AUD_CTS3                           0x3205
+#define HDMI_AUD_INPUTCLKFS                     0x3206
+#define HDMI_AUD_SPDIFINT			0x3302
+#define HDMI_AUD_CONF0_HBR                      0x3400
+#define HDMI_AUD_HBR_STATUS                     0x3401
+#define HDMI_AUD_HBR_INT                        0x3402
+#define HDMI_AUD_HBR_POL                        0x3403
+#define HDMI_AUD_HBR_MASK                       0x3404
+
+/*
+ * Generic Parallel Audio Interface Registers
+ * Not used as GPAUD interface is not enabled in hw
+ */
+#define HDMI_GP_CONF0                           0x3500
+#define HDMI_GP_CONF1                           0x3501
+#define HDMI_GP_CONF2                           0x3502
+#define HDMI_GP_STAT                            0x3503
+#define HDMI_GP_INT                             0x3504
+#define HDMI_GP_MASK                            0x3505
+#define HDMI_GP_POL                             0x3506
+
+/* Audio DMA Registers */
+#define HDMI_AHB_DMA_CONF0                      0x3600
+#define HDMI_AHB_DMA_START                      0x3601
+#define HDMI_AHB_DMA_STOP                       0x3602
+#define HDMI_AHB_DMA_THRSLD                     0x3603
+#define HDMI_AHB_DMA_STRADDR0                   0x3604
+#define HDMI_AHB_DMA_STRADDR1                   0x3605
+#define HDMI_AHB_DMA_STRADDR2                   0x3606
+#define HDMI_AHB_DMA_STRADDR3                   0x3607
+#define HDMI_AHB_DMA_STPADDR0                   0x3608
+#define HDMI_AHB_DMA_STPADDR1                   0x3609
+#define HDMI_AHB_DMA_STPADDR2                   0x360a
+#define HDMI_AHB_DMA_STPADDR3                   0x360b
+#define HDMI_AHB_DMA_BSTADDR0                   0x360c
+#define HDMI_AHB_DMA_BSTADDR1                   0x360d
+#define HDMI_AHB_DMA_BSTADDR2                   0x360e
+#define HDMI_AHB_DMA_BSTADDR3                   0x360f
+#define HDMI_AHB_DMA_MBLENGTH0                  0x3610
+#define HDMI_AHB_DMA_MBLENGTH1                  0x3611
+#define HDMI_AHB_DMA_STAT                       0x3612
+#define HDMI_AHB_DMA_INT                        0x3613
+#define HDMI_AHB_DMA_MASK                       0x3614
+#define HDMI_AHB_DMA_POL                        0x3615
+#define HDMI_AHB_DMA_CONF1                      0x3616
+#define HDMI_AHB_DMA_BUFFSTAT                   0x3617
+#define HDMI_AHB_DMA_BUFFINT                    0x3618
+#define HDMI_AHB_DMA_BUFFMASK                   0x3619
+#define HDMI_AHB_DMA_BUFFPOL                    0x361a
+
+/* Main Controller Registers */
+#define HDMI_MC_SFRDIV                          0x4000
+#define HDMI_MC_CLKDIS                          0x4001
+#define HDMI_MC_SWRSTZ                          0x4002
+#define HDMI_MC_OPCTRL                          0x4003
+#define HDMI_MC_FLOWCTRL                        0x4004
+#define HDMI_MC_PHYRSTZ                         0x4005
+#define HDMI_MC_LOCKONCLOCK                     0x4006
+#define HDMI_MC_HEACPHY_RST                     0x4007
+
+/* Color Space  Converter Registers */
+#define HDMI_CSC_CFG                            0x4100
+#define HDMI_CSC_SCALE                          0x4101
+#define HDMI_CSC_COEF_A1_MSB                    0x4102
+#define HDMI_CSC_COEF_A1_LSB                    0x4103
+#define HDMI_CSC_COEF_A2_MSB                    0x4104
+#define HDMI_CSC_COEF_A2_LSB                    0x4105
+#define HDMI_CSC_COEF_A3_MSB                    0x4106
+#define HDMI_CSC_COEF_A3_LSB                    0x4107
+#define HDMI_CSC_COEF_A4_MSB                    0x4108
+#define HDMI_CSC_COEF_A4_LSB                    0x4109
+#define HDMI_CSC_COEF_B1_MSB                    0x410A
+#define HDMI_CSC_COEF_B1_LSB                    0x410B
+#define HDMI_CSC_COEF_B2_MSB                    0x410C
+#define HDMI_CSC_COEF_B2_LSB                    0x410D
+#define HDMI_CSC_COEF_B3_MSB                    0x410E
+#define HDMI_CSC_COEF_B3_LSB                    0x410F
+#define HDMI_CSC_COEF_B4_MSB                    0x4110
+#define HDMI_CSC_COEF_B4_LSB                    0x4111
+#define HDMI_CSC_COEF_C1_MSB                    0x4112
+#define HDMI_CSC_COEF_C1_LSB                    0x4113
+#define HDMI_CSC_COEF_C2_MSB                    0x4114
+#define HDMI_CSC_COEF_C2_LSB                    0x4115
+#define HDMI_CSC_COEF_C3_MSB                    0x4116
+#define HDMI_CSC_COEF_C3_LSB                    0x4117
+#define HDMI_CSC_COEF_C4_MSB                    0x4118
+#define HDMI_CSC_COEF_C4_LSB                    0x4119
+
+/* HDCP Encryption Engine Registers */
+#define HDMI_A_HDCPCFG0                         0x5000
+#define HDMI_A_HDCPCFG1                         0x5001
+#define HDMI_A_HDCPOBS0                         0x5002
+#define HDMI_A_HDCPOBS1                         0x5003
+#define HDMI_A_HDCPOBS2                         0x5004
+#define HDMI_A_HDCPOBS3                         0x5005
+#define HDMI_A_APIINTCLR                        0x5006
+#define HDMI_A_APIINTSTAT                       0x5007
+#define HDMI_A_APIINTMSK                        0x5008
+#define HDMI_A_VIDPOLCFG                        0x5009
+#define HDMI_A_OESSWCFG                         0x500A
+#define HDMI_A_TIMER1SETUP0                     0x500B
+#define HDMI_A_TIMER1SETUP1                     0x500C
+#define HDMI_A_TIMER2SETUP0                     0x500D
+#define HDMI_A_TIMER2SETUP1                     0x500E
+#define HDMI_A_100MSCFG                         0x500F
+#define HDMI_A_2SCFG0                           0x5010
+#define HDMI_A_2SCFG1                           0x5011
+#define HDMI_A_5SCFG0                           0x5012
+#define HDMI_A_5SCFG1                           0x5013
+#define HDMI_A_SRMVERLSB                        0x5014
+#define HDMI_A_SRMVERMSB                        0x5015
+#define HDMI_A_SRMCTRL                          0x5016
+#define HDMI_A_SFRSETUP                         0x5017
+#define HDMI_A_I2CHSETUP                        0x5018
+#define HDMI_A_INTSETUP                         0x5019
+#define HDMI_A_PRESETUP                         0x501A
+#define HDMI_A_SRM_BASE                         0x5020
+
+/* CEC Engine Registers */
+#define HDMI_CEC_CTRL                           0x7D00
+#define HDMI_CEC_STAT                           0x7D01
+#define HDMI_CEC_MASK                           0x7D02
+#define HDMI_CEC_POLARITY                       0x7D03
+#define HDMI_CEC_INT                            0x7D04
+#define HDMI_CEC_ADDR_L                         0x7D05
+#define HDMI_CEC_ADDR_H                         0x7D06
+#define HDMI_CEC_TX_CNT                         0x7D07
+#define HDMI_CEC_RX_CNT                         0x7D08
+#define HDMI_CEC_TX_DATA0                       0x7D10
+#define HDMI_CEC_TX_DATA1                       0x7D11
+#define HDMI_CEC_TX_DATA2                       0x7D12
+#define HDMI_CEC_TX_DATA3                       0x7D13
+#define HDMI_CEC_TX_DATA4                       0x7D14
+#define HDMI_CEC_TX_DATA5                       0x7D15
+#define HDMI_CEC_TX_DATA6                       0x7D16
+#define HDMI_CEC_TX_DATA7                       0x7D17
+#define HDMI_CEC_TX_DATA8                       0x7D18
+#define HDMI_CEC_TX_DATA9                       0x7D19
+#define HDMI_CEC_TX_DATA10                      0x7D1a
+#define HDMI_CEC_TX_DATA11                      0x7D1b
+#define HDMI_CEC_TX_DATA12                      0x7D1c
+#define HDMI_CEC_TX_DATA13                      0x7D1d
+#define HDMI_CEC_TX_DATA14                      0x7D1e
+#define HDMI_CEC_TX_DATA15                      0x7D1f
+#define HDMI_CEC_RX_DATA0                       0x7D20
+#define HDMI_CEC_RX_DATA1                       0x7D21
+#define HDMI_CEC_RX_DATA2                       0x7D22
+#define HDMI_CEC_RX_DATA3                       0x7D23
+#define HDMI_CEC_RX_DATA4                       0x7D24
+#define HDMI_CEC_RX_DATA5                       0x7D25
+#define HDMI_CEC_RX_DATA6                       0x7D26
+#define HDMI_CEC_RX_DATA7                       0x7D27
+#define HDMI_CEC_RX_DATA8                       0x7D28
+#define HDMI_CEC_RX_DATA9                       0x7D29
+#define HDMI_CEC_RX_DATA10                      0x7D2a
+#define HDMI_CEC_RX_DATA11                      0x7D2b
+#define HDMI_CEC_RX_DATA12                      0x7D2c
+#define HDMI_CEC_RX_DATA13                      0x7D2d
+#define HDMI_CEC_RX_DATA14                      0x7D2e
+#define HDMI_CEC_RX_DATA15                      0x7D2f
+#define HDMI_CEC_LOCK                           0x7D30
+#define HDMI_CEC_WKUPCTRL                       0x7D31
+
+/* I2C Master Registers (E-DDC) */
+#define HDMI_I2CM_SLAVE                         0x7E00
+#define HDMI_I2CMESS                            0x7E01
+#define HDMI_I2CM_DATAO                         0x7E02
+#define HDMI_I2CM_DATAI                         0x7E03
+#define HDMI_I2CM_OPERATION                     0x7E04
+#define HDMI_I2CM_INT                           0x7E05
+#define HDMI_I2CM_CTLINT                        0x7E06
+#define HDMI_I2CM_DIV                           0x7E07
+#define HDMI_I2CM_SEGADDR                       0x7E08
+#define HDMI_I2CM_SOFTRSTZ                      0x7E09
+#define HDMI_I2CM_SEGPTR                        0x7E0A
+#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR            0x7E0B
+#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR            0x7E0C
+#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR            0x7E0D
+#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR            0x7E0E
+#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR            0x7E0F
+#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR            0x7E10
+#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR            0x7E11
+#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
+
+enum {
+/* IH_FC_INT2 field values */
+	HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
+	HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+	HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_FC_STAT2 field values */
+	HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
+	HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+	HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_PHY_STAT0 field values */
+	HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
+	HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
+	HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
+	HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
+	HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
+	HDMI_IH_PHY_STAT0_HPD = 0x1,
+
+/* IH_MUTE_I2CMPHY_STAT0 field values */
+	HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
+	HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
+
+/* IH_AHBDMAAUD_STAT0 field values */
+	HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
+	HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
+	HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
+	HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
+	HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+	HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE_FC_STAT2 field values */
+	HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
+	HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+	HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_MUTE_AHBDMAAUD_STAT0 field values */
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* 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_MASK = 0x80,
+	HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
+	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_MASK = 0x4,
+	HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
+	HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
+	HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
+	HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
+	HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
+	HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
+	HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
+	HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
+
+/* 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_IFIX_PP_TO_LAST_MASK = 0x10,
+	HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
+	HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
+	HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
+	HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
+	HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
+	HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
+	HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
+	HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
+	HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
+	HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
+	HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
+	HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
+
+/* VP_CONF field values */
+	HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
+	HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
+	HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
+	HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
+	HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
+	HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
+	HDMI_VP_CONF_PR_EN_MASK = 0x10,
+	HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
+	HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
+	HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
+	HDMI_VP_CONF_YCC422_EN_ENABLE = 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_BYPASS_SELECT_PIX_REPEATER = 0x0,
+	HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
+	HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
+	HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
+	HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
+
+/* VP_REMAP field values */
+	HDMI_VP_REMAP_MASK = 0x3,
+	HDMI_VP_REMAP_YCC422_24bit = 0x2,
+	HDMI_VP_REMAP_YCC422_20bit = 0x1,
+	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_AUDICONF0 field values */
+	HDMI_FC_AUDICONF0_CC_OFFSET = 4,
+	HDMI_FC_AUDICONF0_CC_MASK = 0x70,
+	HDMI_FC_AUDICONF0_CT_OFFSET = 0,
+	HDMI_FC_AUDICONF0_CT_MASK = 0xF,
+
+/* FC_AUDICONF1 field values */
+	HDMI_FC_AUDICONF1_SS_OFFSET = 3,
+	HDMI_FC_AUDICONF1_SS_MASK = 0x18,
+	HDMI_FC_AUDICONF1_SF_OFFSET = 0,
+	HDMI_FC_AUDICONF1_SF_MASK = 0x7,
+
+/* FC_AUDICONF3 field values */
+	HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
+	HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
+	HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
+	HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
+	HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
+	HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
+
+/* FC_AUDSCHNLS0 field values */
+	HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
+	HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
+	HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
+
+/* FC_AUDSCHNLS3-6 field values */
+	HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
+	HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
+	HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
+	HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
+	HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
+	HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
+
+	HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
+	HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
+	HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
+	HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
+	HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
+	HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
+
+/* HDMI_FC_AUDSCHNLS7 field values */
+	HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
+
+/* HDMI_FC_AUDSCHNLS8 field values */
+	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
+	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
+	HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
+	HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
+
+/* FC_AUDSCONF field values */
+	HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
+	HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
+	HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
+	HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
+	HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
+	HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
+
+/* FC_STAT2 field values */
+	HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
+	HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+	HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_INT2 field values */
+	HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
+	HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+	HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_MASK2 field values */
+	HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
+	HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
+	HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_PRCONF field values */
+	HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
+	HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
+	HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
+	HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
+
+/* 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_DBGFORCE field values */
+	HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
+	HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
+
+/* 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 = 0x20,
+	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_GEN2_ENHPDRXSENSE_MASK = 0x4,
+	HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
+	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,
+	HDMI_PHY_TST0_TSTEN_MASK = 0x10,
+	HDMI_PHY_TST0_TSTEN_OFFSET = 4,
+	HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
+	HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
+
+/* PHY_STAT0 field values */
+	HDMI_PHY_RX_SENSE3 = 0x80,
+	HDMI_PHY_RX_SENSE2 = 0x40,
+	HDMI_PHY_RX_SENSE1 = 0x20,
+	HDMI_PHY_RX_SENSE0 = 0x10,
+	HDMI_PHY_HPD = 0x02,
+	HDMI_PHY_TX_PHY_LOCK = 0x01,
+
+/* PHY_I2CM_SLAVE_ADDR field values */
+	HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
+	HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
+
+/* PHY_I2CM_OPERATION_ADDR field values */
+	HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
+	HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
+
+/* HDMI_PHY_I2CM_INT_ADDR */
+	HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
+	HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
+
+/* HDMI_PHY_I2CM_CTLINT_ADDR */
+	HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
+	HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
+	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
+	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
+
+/* 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,
+	/* note that the CTS3 MANUAL bit has been removed
+	   from our part. Can't set it, will read as 0. */
+	HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
+	HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
+
+/* AHB_DMA_CONF0 field values */
+	HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
+	HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
+	HDMI_AHB_DMA_CONF0_HBR = 0x10,
+	HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
+	HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
+	HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
+	HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
+	HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
+	HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
+	HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
+	HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
+
+/* HDMI_AHB_DMA_START field values */
+	HDMI_AHB_DMA_START_START_OFFSET = 0,
+	HDMI_AHB_DMA_START_START_MASK = 0x01,
+
+/* HDMI_AHB_DMA_STOP field values */
+	HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
+	HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
+
+/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
+	HDMI_AHB_DMA_DONE = 0x80,
+	HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
+	HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
+	HDMI_AHB_DMA_ERROR = 0x10,
+	HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
+	HDMI_AHB_DMA_FIFO_FULL = 0x02,
+	HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
+
+/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */
+	HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
+	HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
+
+/* MC_CLKDIS field values */
+	HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
+	HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
+	HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
+	HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
+	HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
+	HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
+	HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
+
+/* MC_SWRSTZ field values */
+	HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
+
+/* MC_FLOWCTRL field values */
+	HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
+	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,
+	HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
+
+/* CSC_CFG field values */
+	HDMI_CSC_CFG_INTMODE_MASK = 0x30,
+	HDMI_CSC_CFG_INTMODE_OFFSET = 4,
+	HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
+	HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
+	HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
+	HDMI_CSC_CFG_DECMODE_MASK = 0x3,
+	HDMI_CSC_CFG_DECMODE_OFFSET = 0,
+	HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
+	HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
+	HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
+	HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
+
+/* 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,
+
+/* A_HDCPCFG0 field values */
+	HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80,
+	HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80,
+	HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00,
+	HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40,
+	HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40,
+	HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00,
+	HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20,
+	HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20,
+	HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00,
+	HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10,
+	HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10,
+	HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00,
+	HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8,
+	HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8,
+	HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0,
+	HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4,
+	HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4,
+	HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0,
+	HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2,
+	HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2,
+	HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0,
+	HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1,
+	HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1,
+	HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0,
+
+/* A_HDCPCFG1 field values */
+	HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8,
+	HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8,
+	HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0,
+	HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4,
+	HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4,
+	HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0,
+	HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2,
+	HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2,
+	HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0,
+	HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1,
+	HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0,
+
+/* A_VIDPOLCFG field values */
+	HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60,
+	HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5,
+	HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10,
+	HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10,
+	HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0,
+	HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8,
+	HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8,
+	HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0,
+	HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
+	HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
+	HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
+};
+#endif /* __IMX_HDMI_H__ */
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 29/29] ARM: update imx_v7_defconfig
  2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
                   ` (26 preceding siblings ...)
  2014-03-14 14:32 ` [PATCH 28/29] video: i.MX IPUv3: Add hdmi support Sascha Hauer
@ 2014-03-14 14:32 ` Sascha Hauer
  27 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-14 14:32 UTC (permalink / raw)
  To: barebox

- Enable loadenv command
- Enable mtd/NAND/UBI/UBIFS support
- Enable IPUv3 support
- Enable splash support

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/configs/imx_v7_defconfig | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index e821061..f29c968 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -12,9 +12,11 @@ CONFIG_MACH_REALQ7=y
 CONFIG_MACH_GK802=y
 CONFIG_MACH_TQMA6X=y
 CONFIG_MACH_SABRELITE=y
+CONFIG_MACH_SABRESD=y
 CONFIG_MACH_NITROGEN6X=y
 CONFIG_MACH_SOLIDRUN_HUMMINGBOARD=y
 CONFIG_MACH_UDOO=y
+CONFIG_MACH_VARISCITE_MX6=y
 CONFIG_IMX_IIM=y
 CONFIG_IMX_IIM_FUSE_BLOW=y
 CONFIG_IMX_OCOTP=y
@@ -41,9 +43,11 @@ CONFIG_CMD_EDIT=y
 CONFIG_CMD_SLEEP=y
 CONFIG_CMD_MSLEEP=y
 CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_PRINTENV=y
 CONFIG_CMD_READLINE=y
+CONFIG_CMD_READF=y
 CONFIG_CMD_LET=y
 CONFIG_CMD_MENU=y
 CONFIG_CMD_MENU_MANAGEMENT=y
@@ -72,6 +76,7 @@ CONFIG_CMD_OFTREE=y
 CONFIG_CMD_OF_PROPERTY=y
 CONFIG_CMD_OF_NODE=y
 CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_SPLASH=y
 CONFIG_CMD_BAREBOX_UPDATE=y
 CONFIG_CMD_TIMEOUT=y
 CONFIG_CMD_PARTITION=y
@@ -94,8 +99,8 @@ CONFIG_NET_NETCONSOLE=y
 CONFIG_NET_RESOLV=y
 CONFIG_OFDEVICE=y
 CONFIG_OF_BAREBOX_DRIVERS=y
-CONFIG_AT803X_PHY=y
 CONFIG_DRIVER_NET_FEC_IMX=y
+CONFIG_AT803X_PHY=y
 CONFIG_NET_USB=y
 CONFIG_NET_USB_ASIX=y
 CONFIG_NET_USB_SMSC95XX=y
@@ -107,6 +112,13 @@ CONFIG_MTD_RAW_DEVICE=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SST25L=y
+CONFIG_NAND=y
+CONFIG_NAND_ALLOW_ERASE_BAD=y
+CONFIG_NAND_IMX=y
+CONFIG_NAND_IMX_BBM=y
+CONFIG_NAND_MXS=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_DISK_AHCI=y
 CONFIG_DISK_AHCI_IMX=y
 CONFIG_DISK_INTF_PLATFORM_IDE=y
@@ -118,6 +130,12 @@ CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DFU=y
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_IMX_IPUV3=y
+CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS=y
+CONFIG_DRIVER_VIDEO_IMX_IPUV3_HDMI=y
+CONFIG_DRIVER_VIDEO_SIMPLEFB=y
+CONFIG_DRIVER_VIDEO_EDID=y
 CONFIG_MCI=y
 CONFIG_MCI_MMC_BOOT_PARTITIONS=y
 CONFIG_MCI_IMX_ESDHC=y
@@ -133,6 +151,9 @@ CONFIG_EEPROM_AT24=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_IMX=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX=y
+CONFIG_MXS_APBH_DMA=y
 CONFIG_GPIO_STMPE=y
 CONFIG_FS_EXT4=y
 CONFIG_FS_TFTP=y
@@ -140,4 +161,5 @@ CONFIG_FS_NFS=y
 CONFIG_FS_FAT=y
 CONFIG_FS_FAT_WRITE=y
 CONFIG_FS_FAT_LFN=y
-CONFIG_LZO_DECOMPRESS=y
+CONFIG_FS_UBIFS=y
+CONFIG_FS_UBIFS_COMPRESSION_LZO=y
-- 
1.9.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag
  2014-03-14 14:32 ` [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag Sascha Hauer
@ 2014-03-14 16:06   ` Alexander Shiyan
  2014-03-17  6:43     ` Sascha Hauer
  0 siblings, 1 reply; 33+ messages in thread
From: Alexander Shiyan @ 2014-03-14 16:06 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Пятница, 14 марта 2014, 15:32 +01:00 от Sascha Hauer <s.hauer@pengutronix.de>:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  include/linux/clk.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 7e5010a..2704b0f 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -196,6 +196,9 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
>  #endif
>  
>  #ifdef CONFIG_COMMON_CLK
> +
> +#define CLK_SET_RATE_PARENT     (1 << 0) /* propagate rate change up one level */

Lets do it same value as in the kernel, ie  CLK_SET_RATE_PARENT BIT(2)

---
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag
  2014-03-14 16:06   ` Alexander Shiyan
@ 2014-03-17  6:43     ` Sascha Hauer
  0 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-03-17  6:43 UTC (permalink / raw)
  To: Alexander Shiyan; +Cc: barebox

On Fri, Mar 14, 2014 at 08:06:41PM +0400, Alexander Shiyan wrote:
> Пятница, 14 марта 2014, 15:32 +01:00 от Sascha Hauer <s.hauer@pengutronix.de>:
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  include/linux/clk.h | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 7e5010a..2704b0f 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -196,6 +196,9 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
> >  #endif
> >  
> >  #ifdef CONFIG_COMMON_CLK
> > +
> > +#define CLK_SET_RATE_PARENT     (1 << 0) /* propagate rate change up one level */
> 
> Lets do it same value as in the kernel, ie  CLK_SET_RATE_PARENT BIT(2)

Ok, can do. Maybe it's better when we add more flags from the kernel.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 21/29] video: rework mode_name parameter setting
  2014-03-14 14:32 ` [PATCH 21/29] video: rework mode_name parameter setting Sascha Hauer
@ 2014-04-07 14:45   ` Alexander Shiyan
  2014-04-08  6:39     ` Sascha Hauer
  0 siblings, 1 reply; 33+ messages in thread
From: Alexander Shiyan @ 2014-04-07 14:45 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Fri, 14 Mar 2014 15:32:41 +0100 от Sascha Hauer <s.hauer@pengutronix.de>:
> We have dev_add_param_enum() now, so use it for the mode_name
> setting. Also drop the special case for single mode framebuffers,
> just add the mode_name parameter for this case aswell.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
...
> +static int fb_setup_mode(struct fb_info *info)
> +{
> +	struct device_d *dev = &info->dev;
> +	int ret;
...
> -	ret = info->fbops->fb_activate_var(info);
> +	if (info->fbops->fb_activate_var) {
> +		ret = info->fbops->fb_activate_var(info);
> +		if (ret)
> +			return ret;
> +	}

So, "ret" is unitialized without fb_activate_var().
It is wrong since this variable is used in code below.

	if (!ret) {
		dev->resource[0].start = (resource_size_t)info->screen_base;
		info->cdev.size = info->line_length * info->yres;
		dev->resource[0].end = dev->resource[0].start + info->cdev.size - 1;
	} else
		info->cdev.size = 0;

---

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 21/29] video: rework mode_name parameter setting
  2014-04-07 14:45   ` Alexander Shiyan
@ 2014-04-08  6:39     ` Sascha Hauer
  0 siblings, 0 replies; 33+ messages in thread
From: Sascha Hauer @ 2014-04-08  6:39 UTC (permalink / raw)
  To: Alexander Shiyan; +Cc: barebox

On Mon, Apr 07, 2014 at 06:45:55PM +0400, Alexander Shiyan wrote:
> Fri, 14 Mar 2014 15:32:41 +0100 от Sascha Hauer <s.hauer@pengutronix.de>:
> > We have dev_add_param_enum() now, so use it for the mode_name
> > setting. Also drop the special case for single mode framebuffers,
> > just add the mode_name parameter for this case aswell.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> ...
> > +static int fb_setup_mode(struct fb_info *info)
> > +{
> > +	struct device_d *dev = &info->dev;
> > +	int ret;
> ...
> > -	ret = info->fbops->fb_activate_var(info);
> > +	if (info->fbops->fb_activate_var) {
> > +		ret = info->fbops->fb_activate_var(info);
> > +		if (ret)
> > +			return ret;
> > +	}
> 
> So, "ret" is unitialized without fb_activate_var().
> It is wrong since this variable is used in code below.

Damn. I remember times when compilers used to warn on unitialized
variables :(

The following should fix this.

Thanks for reporting.

Sascha

--------------------8<--------------------------------

From 7b8779541f86bbc6f6b461f1ea1c2f4310bb8335 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Tue, 8 Apr 2014 08:37:09 +0200
Subject: [PATCH] fb: Fix use of unitialized variable

'ret' is only initialized when info->fbops->fb_activate_var exists, so
only use it in this case.

Reported-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/fb.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 2c8b8eb..ecf6142 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -85,8 +85,10 @@ static int fb_setup_mode(struct fb_info *info)
 
 	if (info->fbops->fb_activate_var) {
 		ret = info->fbops->fb_activate_var(info);
-		if (ret)
+		if (ret) {
+			info->cdev.size = 0;
 			return ret;
+		}
 	}
 
 	if (!info->line_length)
@@ -94,14 +96,11 @@ static int fb_setup_mode(struct fb_info *info)
 	if (!info->screen_size)
 		info->screen_size = info->line_length * info->yres;
 
-	if (!ret) {
-		dev->resource[0].start = (resource_size_t)info->screen_base;
-		info->cdev.size = info->line_length * info->yres;
-		dev->resource[0].end = dev->resource[0].start + info->cdev.size - 1;
-	} else
-		info->cdev.size = 0;
+	dev->resource[0].start = (resource_size_t)info->screen_base;
+	info->cdev.size = info->line_length * info->yres;
+	dev->resource[0].end = dev->resource[0].start + info->cdev.size - 1;
 
-	return ret;
+	return 0;
 }
 
 static int fb_set_modename(struct param_d *param, void *priv)
-- 
1.9.1

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2014-04-08  6:40 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-14 14:32 i.MX IPUv3 support Sascha Hauer
2014-03-14 14:32 ` [PATCH 01/29] err.h: Add PTR_ERR_OR_ZERO from kernel Sascha Hauer
2014-03-14 14:32 ` [PATCH 02/29] ARM: i.MX6: Add initial variscite VAR-SOM-MX6 CPU support Sascha Hauer
2014-03-14 14:32 ` [PATCH 03/29] ARM: dts: i.MX6: Add IPU aliases Sascha Hauer
2014-03-14 14:32 ` [PATCH 04/29] ARM: dts: i.MX6: Add HDMI nodes Sascha Hauer
2014-03-14 14:32 ` [PATCH 05/29] ARM: dts: i.MX53: Fix IPU register size Sascha Hauer
2014-03-14 14:32 ` [PATCH 06/29] i2c: i.MX: move to earlier initcall Sascha Hauer
2014-03-14 14:32 ` [PATCH 07/29] i2c: implement of_find_i2c_adapter_by_node Sascha Hauer
2014-03-14 14:32 ` [PATCH 08/29] clk: implement clk_round_rate Sascha Hauer
2014-03-14 14:32 ` [PATCH 09/29] clk: clk-mux: pass clk flags from initializers Sascha Hauer
2014-03-14 14:32 ` [PATCH 10/29] clk: clk-gate: pass flags to initializers Sascha Hauer
2014-03-14 14:32 ` [PATCH 11/29] clk: clk-fixed-factor: " Sascha Hauer
2014-03-14 14:32 ` [PATCH 12/29] clk: clk-divider: " Sascha Hauer
2014-03-14 14:32 ` [PATCH 13/29] clk: introduce CLK_SET_RATE_PARENT flag Sascha Hauer
2014-03-14 16:06   ` Alexander Shiyan
2014-03-17  6:43     ` Sascha Hauer
2014-03-14 14:32 ` [PATCH 14/29] clk: clk-divider: sync with kernel code Sascha Hauer
2014-03-14 14:32 ` [PATCH 15/29] clk: let clk-divider handle the table based divider aswell Sascha Hauer
2014-03-14 14:32 ` [PATCH 16/29] clk: clk-fixed-factor: add set_rate/round_rate callbacks Sascha Hauer
2014-03-14 14:32 ` [PATCH 17/29] clk: Add parent round/set rate for mux and gate Sascha Hauer
2014-03-14 14:32 ` [PATCH 18/29] ARM: i.MX: introduce clk parent rate changes Sascha Hauer
2014-03-14 14:32 ` [PATCH 19/29] ARM: i.MX6: Add video clocks Sascha Hauer
2014-03-14 14:32 ` [PATCH 20/29] video: introduce struct display_timings Sascha Hauer
2014-03-14 14:32 ` [PATCH 21/29] video: rework mode_name parameter setting Sascha Hauer
2014-04-07 14:45   ` Alexander Shiyan
2014-04-08  6:39     ` Sascha Hauer
2014-03-14 14:32 ` [PATCH 22/29] video: Add display timing from devicetree helper Sascha Hauer
2014-03-14 14:32 ` [PATCH 23/29] video: Add edid support Sascha Hauer
2014-03-14 14:32 ` [PATCH 24/29] ARM i.MX6q: Mark VPU and IPU AXI transfers as cacheable, increase IPU priority Sascha Hauer
2014-03-14 14:32 ` [PATCH 25/29] video: Add kernel fourcc defines Sascha Hauer
2014-03-14 14:32 ` [PATCH 27/29] video: i.MX IPUv3: Add lvds bridge support Sascha Hauer
2014-03-14 14:32 ` [PATCH 28/29] video: i.MX IPUv3: Add hdmi support Sascha Hauer
2014-03-14 14:32 ` [PATCH 29/29] ARM: update imx_v7_defconfig Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox