Browse Source

update kernels

Waldemar Brodkorb 10 years ago
parent
commit
309009db48
97 changed files with 7854 additions and 843 deletions
  1. 6 6
      mk/kernel-ver.mk
  2. 4 1
      mk/modules.mk
  3. 0 0
      target/arm/raspberry-pi/patches/3.14.22/raspberry-pi.patch
  4. 0 0
      target/arm/raspberry-pi/patches/3.16.6/raspberry-pi.patch
  5. 229 250
      target/arm/solidrun-imx6/patches/3.14.22/solidrun.patch
  6. 0 569
      target/arm/solidrun-imx6/patches/3.16.4/rmk-wifi.patch
  7. 7601 0
      target/arm/solidrun-imx6/patches/3.16.6/rmk.patch
  8. 6 6
      target/config/Config.in.kernelversion.choice
  9. 2 2
      target/config/Config.in.kernelversion.default
  10. 0 3
      target/linux/config/Config.in.gpio
  11. 3 6
      target/linux/config/Config.in.graphics
  12. 3 0
      target/linux/config/Config.in.kernel
  13. 0 0
      target/linux/patches/3.14.22/bsd-compatibility.patch
  14. 0 0
      target/linux/patches/3.14.22/cleankernel.patch
  15. 0 0
      target/linux/patches/3.14.22/defaults.patch
  16. 0 0
      target/linux/patches/3.14.22/disable-netfilter.patch
  17. 0 0
      target/linux/patches/3.14.22/export-symbol-for-exmap.patch
  18. 0 0
      target/linux/patches/3.14.22/gemalto.patch
  19. 0 0
      target/linux/patches/3.14.22/initramfs-nosizelimit.patch
  20. 0 0
      target/linux/patches/3.14.22/lemote-rfkill.patch
  21. 0 0
      target/linux/patches/3.14.22/microblaze-axi.patch
  22. 0 0
      target/linux/patches/3.14.22/microblaze-ethernet.patch
  23. 0 0
      target/linux/patches/3.14.22/mkpiggy.patch
  24. 0 0
      target/linux/patches/3.14.22/mtd-rootfs.patch
  25. 0 0
      target/linux/patches/3.14.22/nfsv3-tcp.patch
  26. 0 0
      target/linux/patches/3.14.22/non-static.patch
  27. 0 0
      target/linux/patches/3.14.22/patch-fblogo
  28. 0 0
      target/linux/patches/3.14.22/patch-grsec
  29. 0 0
      target/linux/patches/3.14.22/patch-mptcp
  30. 0 0
      target/linux/patches/3.14.22/patch-yaffs2
  31. 0 0
      target/linux/patches/3.14.22/ppc64-missing-zlib.patch
  32. 0 0
      target/linux/patches/3.14.22/regmap-boolean.patch
  33. 0 0
      target/linux/patches/3.14.22/relocs.patch
  34. 0 0
      target/linux/patches/3.14.22/sgidefs.patch
  35. 0 0
      target/linux/patches/3.14.22/sortext.patch
  36. 0 0
      target/linux/patches/3.14.22/startup.patch
  37. 0 0
      target/linux/patches/3.14.22/tcp-fastopen.patch
  38. 0 0
      target/linux/patches/3.14.22/wlan-cf.patch
  39. 0 0
      target/linux/patches/3.14.22/xargs.patch
  40. 0 0
      target/linux/patches/3.14.22/zlib-inflate.patch
  41. 0 0
      target/linux/patches/3.16.6/bsd-compatibility.patch
  42. 0 0
      target/linux/patches/3.16.6/cleankernel.patch
  43. 0 0
      target/linux/patches/3.16.6/cris-header.patch
  44. 0 0
      target/linux/patches/3.16.6/defaults.patch
  45. 0 0
      target/linux/patches/3.16.6/disable-netfilter.patch
  46. 0 0
      target/linux/patches/3.16.6/export-symbol-for-exmap.patch
  47. 0 0
      target/linux/patches/3.16.6/gemalto.patch
  48. 0 0
      target/linux/patches/3.16.6/initramfs-nosizelimit.patch
  49. 0 0
      target/linux/patches/3.16.6/lemote-rfkill.patch
  50. 0 0
      target/linux/patches/3.16.6/microblaze-axi.patch
  51. 0 0
      target/linux/patches/3.16.6/microblaze-ethernet.patch
  52. 0 0
      target/linux/patches/3.16.6/mkpiggy.patch
  53. 0 0
      target/linux/patches/3.16.6/mtd-rootfs.patch
  54. 0 0
      target/linux/patches/3.16.6/nfsv3-tcp.patch
  55. 0 0
      target/linux/patches/3.16.6/non-static.patch
  56. 0 0
      target/linux/patches/3.16.6/patch-fblogo
  57. 0 0
      target/linux/patches/3.16.6/patch-yaffs2
  58. 0 0
      target/linux/patches/3.16.6/ppc64-missing-zlib.patch
  59. 0 0
      target/linux/patches/3.16.6/regmap-boolean.patch
  60. 0 0
      target/linux/patches/3.16.6/relocs.patch
  61. 0 0
      target/linux/patches/3.16.6/sgidefs.patch
  62. 0 0
      target/linux/patches/3.16.6/sortext.patch
  63. 0 0
      target/linux/patches/3.16.6/sparc-memset.patch
  64. 0 0
      target/linux/patches/3.16.6/startup.patch
  65. 0 0
      target/linux/patches/3.16.6/wlan-cf.patch
  66. 0 0
      target/linux/patches/3.16.6/xargs.patch
  67. 0 0
      target/m68k/qemu-m68k/patches/3.16.6/m68k-coldfire-fec.patch
  68. 0 0
      target/m68k/qemu-m68k/patches/3.16.6/qemu-coldfire.patch
  69. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0001-mtd-add-rb4xx-nand-driver.patch
  70. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch
  71. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0003-net-add-ag71xx-mac-driver.patch
  72. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0004-drivers-link-SPI-drivers-before-MTD-drivers.patch
  73. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0005-spi-add-various-flags-to-spi_transfer-and-spi_messag.patch
  74. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0006-spi-add-rb4xx-SPI-driver.patch
  75. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0007-spi-add-rb4xx-cpld-driver.patch
  76. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0008-gpio-add-GPIO-latch-driver.patch
  77. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0009-spi-export-spi_bitbang_bufs-function.patch
  78. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0010-spi-add-type-field-to-spi_transfer-struct.patch
  79. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0011-mtd-m25p80-set-SPI-transfer-type.patch
  80. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0012-mips-ath79-swizzle-PCI-address-for-ar71xx.patch
  81. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0013-net-add-swconfig-support.patch
  82. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0014-phy-add-detach-callback-to-struct-phy_driver.patch
  83. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0015-phy-add-ar8216-PHY-support.patch
  84. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0016-phy-mdio-bitbang-ignore-TA-value.patch
  85. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0017-MIPS-ath79-fix-maximum-timeout.patch
  86. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0018-net-allow-PHY-drivers-to-insert-packet-mangle-hooks.patch
  87. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0019-MIPS-ath79-process-board-cmdline-option.patch
  88. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0020-spi-ath79-add-fast-flash-read-support.patch
  89. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0021-phy-add-mdio-boardinfo.patch
  90. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0022-mips-ath79-add-ath79-ethernet-driver.patch
  91. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0023-MIPS-ath79-add-Mikrotik-rb4xx-device-support.patch
  92. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0024-various-fixups-for-Werror.patch
  93. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0025-rb4xx_nand-add-partition-for-cfgfs.patch
  94. 0 0
      target/mips/mikrotik-rb4xx/patches/3.14.22/0026-various-fixups-for-ath5k-fixing-system-freezes.patch
  95. 0 0
      target/mips/mikrotik-rb532/patches/3.14.22/rb532-cfgfs.patch
  96. 0 0
      target/mips/mikrotik-rb532/patches/3.14.22/rb532-pci.patch
  97. 0 0
      target/mips64/lemote-yeelong/patches/3.16.6/sm7xx-fb.patch

+ 6 - 6
mk/kernel-ver.mk

@@ -1,14 +1,14 @@
-ifeq ($(ADK_KERNEL_VERSION_3_16_4),y)
-KERNEL_VERSION:=	3.16.4
+ifeq ($(ADK_KERNEL_VERSION_3_16_6),y)
+KERNEL_VERSION:=	3.16.6
 KERNEL_MOD_VERSION:=	$(KERNEL_VERSION)
 KERNEL_RELEASE:=	1
-KERNEL_MD5SUM:=		33594ef9526373afb193761d8fc6ba43
+KERNEL_MD5SUM:=		2edc96a1272b04d58245707eb12b4902
 endif
-ifeq ($(ADK_KERNEL_VERSION_3_14_17),y)
-KERNEL_VERSION:=	3.14.17
+ifeq ($(ADK_KERNEL_VERSION_3_14_22),y)
+KERNEL_VERSION:=	3.14.22
 KERNEL_MOD_VERSION:=	$(KERNEL_VERSION)
 KERNEL_RELEASE:=	1
-KERNEL_MD5SUM:=		44668489163952357678bab42e38e184
+KERNEL_MD5SUM:=		cb00fadd0a720cc2d1690792e72e0134
 endif
 ifeq ($(ADK_KERNEL_VERSION_3_12_27),y)
 KERNEL_VERSION:=	3.12.27

+ 4 - 1
mk/modules.mk

@@ -1311,8 +1311,11 @@ $(eval $(call KMOD_template,SND_USB_AUDIO,snd-usb-audio,\
 # Bluetooth
 #
 
-$(eval $(call KMOD_template,BT,bt,\
+$(eval $(call KMOD_template,IEEE802154_6LOWPAN,ieee802154_6lowpan,\
 	$(MODULES_DIR)/kernel/net/ieee802154/6lowpan_iphc \
+,65))
+
+$(eval $(call KMOD_template,BT,bt,\
 	$(MODULES_DIR)/kernel/net/bluetooth/bluetooth \
 ,70))
 

+ 0 - 0
target/arm/raspberry-pi/patches/3.14.17/raspberry-pi.patch → target/arm/raspberry-pi/patches/3.14.22/raspberry-pi.patch


+ 0 - 0
target/arm/raspberry-pi/patches/3.16.4/raspberry-pi.patch → target/arm/raspberry-pi/patches/3.16.6/raspberry-pi.patch


File diff suppressed because it is too large
+ 229 - 250
target/arm/solidrun-imx6/patches/3.14.22/solidrun.patch


+ 0 - 569
target/arm/solidrun-imx6/patches/3.16.4/rmk-wifi.patch

@@ -1,569 +0,0 @@
-diff -Nur linux-3.16.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.16/arch/arm/boot/dts/imx6qdl-microsom.dtsi
---- linux-3.16.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/arch/arm/boot/dts/imx6qdl-microsom.dtsi	2014-08-11 12:34:43.603892919 +0200
-@@ -2,14 +2,92 @@
-  * Copyright (C) 2013,2014 Russell King
-  */
- 
-+#include <dt-bindings/gpio/gpio.h>
-+/ {
-+	regulators {
-+		compatible = "simple-bus";
-+
-+		reg_brcm_osc: brcm-osc-reg {
-+			compatible = "regulator-fixed";
-+			enable-active-high;
-+			gpio = <&gpio5 5 0>;
-+			pinctrl-names = "default";
-+			pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>;
-+			regulator-name = "brcm_osc_reg";
-+			regulator-min-microvolt = <3300000>;
-+			regulator-max-microvolt = <3300000>;
-+			regulator-always-on;
-+			regulator-boot-on;
-+		};
-+
-+		reg_brcm: brcm-reg {
-+			compatible = "regulator-fixed";
-+			enable-active-high;
-+			gpio = <&gpio3 19 0>;
-+			pinctrl-names = "default";
-+			pinctrl-0 = <&pinctrl_microsom_brcm_reg>;
-+			regulator-name = "brcm_reg";
-+			regulator-min-microvolt = <3300000>;
-+			regulator-max-microvolt = <3300000>;
-+			startup-delay-us = <200000>;
-+		};
-+	};
-+};
-+
- &iomuxc {
- 	microsom {
-+		pinctrl_microsom_brcm_bt: microsom-brcm-bt {
-+			fsl,pins = <
-+				MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00	0x40013070
-+				MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01	0x40013070
-+				MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04	0x40013070
-+			>;
-+		};
-+
-+		pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg {
-+			fsl,pins = <
-+				MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05	0x40013070
-+			>;
-+		};
-+
-+		pinctrl_microsom_brcm_reg: microsom-brcm-reg {
-+			fsl,pins = <
-+				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x40013070
-+			>;
-+		};
-+
-+		pinctrl_microsom_brcm_wifi: microsom-brcm-wifi {
-+			fsl,pins = <
-+				MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K	0x1b0b0
-+				MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20	0x40013070
-+				MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26	0x40013070
-+				MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27	0x40013070
-+			>;
-+		};
- 		pinctrl_microsom_uart1: microsom-uart1 {
- 			fsl,pins = <
- 				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
- 				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
- 			>;
- 		};
-+		pinctrl_microsom_uart4_1: microsom-uart4 {
-+			fsl,pins = <
-+				MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
-+				MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
-+				MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
-+				MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
-+			>;
-+		};
-+		pinctrl_microsom_usdhc1: microsom-usdhc1 {
-+			fsl,pins = <
-+				MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
-+				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
-+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-+			>;
-+		};
- 	};
- };
- 
-@@ -18,3 +96,23 @@
- 	pinctrl-0 = <&pinctrl_microsom_uart1>;
- 	status = "okay";
- };
-+
-+/* UART4 - Connected to optional BRCM Wifi/BT/FM */
-+&uart4 {
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>;
-+	fsl,uart-has-rtscts;
-+	status = "okay";
-+};
-+
-+/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */
-+&usdhc1 {
-+	card-external-vcc-supply = <&reg_brcm>;
-+	card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>;
-+	keep-power-in-suspend;
-+	non-removable;
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>;
-+	vmmc-supply = <&reg_brcm>;
-+	status = "okay";
-+};
-diff -Nur linux-3.16.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.16/Documentation/devicetree/bindings/mmc/mmc.txt
---- linux-3.16.orig/Documentation/devicetree/bindings/mmc/mmc.txt	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/Documentation/devicetree/bindings/mmc/mmc.txt	2014-08-11 12:34:15.535644516 +0200
-@@ -5,6 +5,8 @@
- Interpreted by the OF core:
- - reg: Registers location and length.
- - interrupts: Interrupts used by the MMC controller.
-+- clocks: Clocks needed for the host controller, if any.
-+- clock-names: Goes with clocks above.
- 
- Card detection:
- If no property below is supplied, host native card detect is used.
-@@ -41,6 +43,15 @@
- - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
- - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
- 
-+Card power and reset control:
-+The following properties can be specified for cases where the MMC
-+peripheral needs additional reset, regulator and clock lines. It is for
-+example common for WiFi/BT adapters to have these separate from the main
-+MMC bus:
-+  - card-reset-gpios: Specify GPIOs for card reset (reset active low)
-+  - card-external-vcc-supply: Regulator to drive (independent) card VCC
-+  - clock with name "card_ext_clock": External clock provided to the card
-+
- *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
- polarity properties, we have to fix the meaning of the "normal" and "inverted"
- line levels. We choose to follow the SDHCI standard, which specifies both those
-diff -Nur linux-3.16.orig/drivers/mmc/core/core.c linux-3.16/drivers/mmc/core/core.c
---- linux-3.16.orig/drivers/mmc/core/core.c	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/drivers/mmc/core/core.c	2014-08-11 12:34:15.555644693 +0200
-@@ -13,11 +13,13 @@
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
-+#include <linux/clk.h>
- #include <linux/completion.h>
- #include <linux/device.h>
- #include <linux/delay.h>
- #include <linux/pagemap.h>
- #include <linux/err.h>
-+#include <linux/gpio/consumer.h>
- #include <linux/leds.h>
- #include <linux/scatterlist.h>
- #include <linux/log2.h>
-@@ -1515,6 +1517,43 @@
- 	mmc_host_clk_release(host);
- }
- 
-+static void mmc_card_power_up(struct mmc_host *host)
-+{
-+	int i;
-+	struct gpio_desc **gds = host->card_reset_gpios;
-+
-+	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-+		if (gds[i]) {
-+			dev_dbg(host->parent, "Asserting reset line %d", i);
-+			gpiod_set_value(gds[i], 1);
-+		}
-+	}
-+
-+	if (host->card_regulator) {
-+		dev_dbg(host->parent, "Enabling external regulator");
-+		if (regulator_enable(host->card_regulator))
-+			dev_err(host->parent, "Failed to enable external regulator");
-+	}
-+
-+	if (host->card_clk) {
-+		dev_dbg(host->parent, "Enabling external clock");
-+		clk_prepare_enable(host->card_clk);
-+	}
-+
-+	/* 2ms delay to let clocks and power settle */
-+	mmc_delay(20);
-+
-+	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-+		if (gds[i]) {
-+			dev_dbg(host->parent, "Deasserting reset line %d", i);
-+			gpiod_set_value(gds[i], 0);
-+		}
-+	}
-+
-+	/* 2ms delay to after reset release */
-+	mmc_delay(20);
-+}
-+
- /*
-  * Apply power to the MMC stack.  This is a two-stage process.
-  * First, we enable power to the card without the clock running.
-@@ -1531,6 +1570,9 @@
- 	if (host->ios.power_mode == MMC_POWER_ON)
- 		return;
- 
-+	/* Power up the card/module first, if needed */
-+	mmc_card_power_up(host);
-+
- 	mmc_host_clk_hold(host);
- 
- 	host->ios.vdd = fls(ocr) - 1;
-diff -Nur linux-3.16.orig/drivers/mmc/core/host.c linux-3.16/drivers/mmc/core/host.c
---- linux-3.16.orig/drivers/mmc/core/host.c	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/drivers/mmc/core/host.c	2014-08-11 12:34:27.995754826 +0200
-@@ -12,14 +12,18 @@
-  *  MMC host class device management
-  */
- 
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
- #include <linux/device.h>
- #include <linux/err.h>
-+#include <linux/gpio/consumer.h>
- #include <linux/idr.h>
- #include <linux/of.h>
- #include <linux/of_gpio.h>
- #include <linux/pagemap.h>
- #include <linux/export.h>
- #include <linux/leds.h>
-+#include <linux/regulator/consumer.h>
- #include <linux/slab.h>
- #include <linux/suspend.h>
- 
-@@ -461,6 +465,66 @@
- 
- EXPORT_SYMBOL(mmc_of_parse);
- 
-+static int mmc_of_parse_child(struct mmc_host *host)
-+{
-+	struct device_node *np;
-+	struct clk *clk;
-+	int i;
-+
-+	if (!host->parent || !host->parent->of_node)
-+		return 0;
-+
-+	np = host->parent->of_node;
-+
-+	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
-+	if (IS_ERR(host->card_regulator)) {
-+		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
-+			return PTR_ERR(host->card_regulator);
-+		host->card_regulator = NULL;
-+	}
-+
-+	/* Parse card power/reset/clock control */
-+	if (of_find_property(np, "card-reset-gpios", NULL)) {
-+		struct gpio_desc *gpd;
-+		int level = 0;
-+
-+		/*
-+		 * If the regulator is enabled, then we can hold the
-+		 * card in reset with an active high resets.  Otherwise,
-+		 * hold the resets low.
-+		 */
-+		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
-+			level = 1;
-+
-+		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-+			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
-+			if (IS_ERR(gpd)) {
-+				if (PTR_ERR(gpd) == -EPROBE_DEFER)
-+					return PTR_ERR(gpd);
-+				break;
-+			}
-+			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
-+			host->card_reset_gpios[i] = gpd;
-+		}
-+
-+		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
-+		if (!IS_ERR(gpd)) {
-+			dev_warn(host->parent, "More reset gpios than we can handle");
-+			gpiod_put(gpd);
-+		}
-+	}
-+
-+	clk = of_clk_get_by_name(np, "card_ext_clock");
-+	if (IS_ERR(clk)) {
-+		if (PTR_ERR(clk) == -EPROBE_DEFER)
-+			return PTR_ERR(clk);
-+		clk = NULL;
-+	}
-+	host->card_clk = clk;
-+
-+	return 0;
-+}
-+
- /**
-  *	mmc_alloc_host - initialise the per-host structure.
-  *	@extra: sizeof private data structure
-@@ -540,6 +604,10 @@
- {
- 	int err;
- 
-+	err = mmc_of_parse_child(host);
-+	if (err)
-+		return err;
-+
- 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
- 		!host->ops->enable_sdio_irq);
- 
-diff -Nur linux-3.16.orig/drivers/mmc/host/dw_mmc.c linux-3.16/drivers/mmc/host/dw_mmc.c
---- linux-3.16.orig/drivers/mmc/host/dw_mmc.c	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/drivers/mmc/host/dw_mmc.c	2014-08-11 12:34:22.043702140 +0200
-@@ -2049,6 +2049,8 @@
- 	if (!mmc)
- 		return -ENOMEM;
- 
-+	mmc_of_parse(mmc);
-+
- 	slot = mmc_priv(mmc);
- 	slot->id = id;
- 	slot->mmc = mmc;
-diff -Nur linux-3.16.orig/drivers/mmc/host/Kconfig linux-3.16/drivers/mmc/host/Kconfig
---- linux-3.16.orig/drivers/mmc/host/Kconfig	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/drivers/mmc/host/Kconfig	2014-08-11 12:34:03.391536946 +0200
-@@ -25,8 +25,7 @@
- 	  If unsure, say N.
- 
- config MMC_SDHCI
--	tristate "Secure Digital Host Controller Interface support"
--	depends on HAS_DMA
-+	tristate
- 	help
- 	  This selects the generic Secure Digital Host Controller Interface.
- 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
-@@ -59,7 +58,8 @@
- 
- config MMC_SDHCI_PCI
- 	tristate "SDHCI support on PCI bus"
--	depends on MMC_SDHCI && PCI
-+	depends on PCI && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects the PCI Secure Digital Host Controller Interface.
- 	  Most controllers found today are PCI devices.
-@@ -83,7 +83,8 @@
- 
- config MMC_SDHCI_ACPI
- 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
--	depends on MMC_SDHCI && ACPI
-+	depends on ACPI && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects support for ACPI enumerated SDHCI controllers,
- 	  identified by ACPI Compatibility ID PNP0D40 or specific
-@@ -94,8 +95,8 @@
- 	  If unsure, say N.
- 
- config MMC_SDHCI_PLTFM
--	tristate "SDHCI platform and OF driver helper"
--	depends on MMC_SDHCI
-+	tristate
-+	select MMC_SDHCI
- 	help
- 	  This selects the common helper functions support for Secure Digital
- 	  Host Controller Interface based platform and OF drivers.
-@@ -106,8 +107,8 @@
- 
- config MMC_SDHCI_OF_ARASAN
- 	tristate "SDHCI OF support for the Arasan SDHCI controllers"
--	depends on MMC_SDHCI_PLTFM
--	depends on OF
-+	depends on OF && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Arasan Secure Digital Host Controller Interface
- 	  (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
-@@ -118,9 +119,9 @@
- 
- config MMC_SDHCI_OF_ESDHC
- 	tristate "SDHCI OF support for the Freescale eSDHC controller"
--	depends on MMC_SDHCI_PLTFM
--	depends on PPC_OF
-+	depends on PPC_OF && HAS_DMA
- 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Freescale eSDHC controller support.
- 
-@@ -130,9 +131,9 @@
- 
- config MMC_SDHCI_OF_HLWD
- 	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
--	depends on MMC_SDHCI_PLTFM
--	depends on PPC_OF
-+	depends on PPC_OF && HAS_DMA
- 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Secure Digital Host Controller Interface (SDHCI)
- 	  found in the "Hollywood" chipset of the Nintendo Wii video game
-@@ -144,8 +145,8 @@
- 
- config MMC_SDHCI_CNS3XXX
- 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
--	depends on ARCH_CNS3XXX
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_CNS3XXX && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
- 
-@@ -155,9 +156,9 @@
- 
- config MMC_SDHCI_ESDHC_IMX
- 	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
--	depends on ARCH_MXC
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_MXC && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Freescale eSDHC/uSDHC controller support
- 	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
-@@ -168,9 +169,9 @@
- 
- config MMC_SDHCI_DOVE
- 	tristate "SDHCI support on Marvell's Dove SoC"
--	depends on ARCH_DOVE || MACH_DOVE
--	depends on MMC_SDHCI_PLTFM
-+	depends on (ARCH_DOVE || MACH_DOVE) && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Secure Digital Host Controller Interface in
- 	  Marvell's Dove SoC.
-@@ -181,9 +182,9 @@
- 
- config MMC_SDHCI_TEGRA
- 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
--	depends on ARCH_TEGRA
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_TEGRA && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Tegra SD/MMC controller. If you have a Tegra
- 	  platform with SD or MMC devices, say Y or M here.
-@@ -192,7 +193,8 @@
- 
- config MMC_SDHCI_S3C
- 	tristate "SDHCI support on Samsung S3C SoC"
--	depends on MMC_SDHCI && PLAT_SAMSUNG
-+	depends on PLAT_SAMSUNG && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects the Secure Digital Host Controller Interface (SDHCI)
- 	  often referrered to as the HSMMC block in some of the Samsung S3C
-@@ -204,8 +206,8 @@
- 
- config MMC_SDHCI_SIRF
- 	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
--	depends on ARCH_SIRF
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_SIRF && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the SDHCI support for SiRF System-on-Chip devices.
- 
-@@ -215,8 +217,8 @@
- 
- config MMC_SDHCI_PXAV3
- 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
--	depends on CLKDEV_LOOKUP
--	depends on MMC_SDHCI_PLTFM
-+	depends on CLKDEV_LOOKUP && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	default CPU_MMP2
- 	help
- 	  This selects the Marvell(R) PXAV3 SD Host Controller.
-@@ -227,8 +229,8 @@
- 
- config MMC_SDHCI_PXAV2
- 	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
--	depends on CLKDEV_LOOKUP
--	depends on MMC_SDHCI_PLTFM
-+	depends on CLKDEV_LOOKUP && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	default CPU_PXA910
- 	help
- 	  This selects the Marvell(R) PXAV2 SD Host Controller.
-@@ -239,7 +241,8 @@
- 
- config MMC_SDHCI_SPEAR
- 	tristate "SDHCI support on ST SPEAr platform"
--	depends on MMC_SDHCI && PLAT_SPEAR
-+	depends on PLAT_SPEAR && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects the Secure Digital Host Controller Interface (SDHCI)
- 	  often referrered to as the HSMMC block in some of the ST SPEAR range
-@@ -261,8 +264,8 @@
- 
- config MMC_SDHCI_BCM_KONA
- 	tristate "SDHCI support on Broadcom KONA platform"
--	depends on ARCH_BCM_MOBILE
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_BCM_MOBILE && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Broadcom Kona Secure Digital Host Controller
- 	  Interface(SDHCI) support.
-@@ -272,9 +275,9 @@
- 
- config MMC_SDHCI_BCM2835
- 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
--	depends on ARCH_BCM2835
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_BCM2835 && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
- 	  platform with SD or MMC devices, say Y or M here.
-diff -Nur linux-3.16.orig/drivers/mmc/host/sdhci.c linux-3.16/drivers/mmc/host/sdhci.c
---- linux-3.16.orig/drivers/mmc/host/sdhci.c	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/drivers/mmc/host/sdhci.c	2014-08-11 12:34:08.763584537 +0200
-@@ -1530,7 +1530,6 @@
- 			host->ops->set_clock(host, host->clock);
- 		}
- 
--
- 		/* Reset SD Clock Enable */
- 		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- 		clk &= ~SDHCI_CLOCK_CARD_EN;
-@@ -1763,9 +1762,6 @@
- 		ctrl |= SDHCI_CTRL_VDD_180;
- 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- 
--		/* Wait for 5ms */
--		usleep_range(5000, 5500);
--
- 		/* 1.8V regulator output should be stable within 5 ms */
- 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- 		if (ctrl & SDHCI_CTRL_VDD_180)
-diff -Nur linux-3.16.orig/include/linux/mmc/host.h linux-3.16/include/linux/mmc/host.h
---- linux-3.16.orig/include/linux/mmc/host.h	2014-08-04 00:25:02.000000000 +0200
-+++ linux-3.16/include/linux/mmc/host.h	2014-08-11 12:34:15.559644729 +0200
-@@ -298,6 +298,11 @@
- 	unsigned long           clkgate_delay;
- #endif
- 
-+	/* card specific properties to deal with power and reset */
-+	struct regulator	*card_regulator; /* External VCC needed by the card */
-+	struct gpio_desc	*card_reset_gpios[2]; /* External resets, active low */
-+	struct clk		*card_clk;	/* External clock needed by the card */
-+
- 	/* host specific block data */
- 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
- 	unsigned short		max_segs;	/* see blk_queue_max_segments */

+ 7601 - 0
target/arm/solidrun-imx6/patches/3.16.6/rmk.patch

@@ -0,0 +1,7601 @@
+diff -Nur linux-3.16.6.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts linux-3.16.6/arch/arm/boot/dts/imx6dl-hummingboard.dts
+--- linux-3.16.6.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/arch/arm/boot/dts/imx6dl-hummingboard.dts	2014-10-23 12:37:45.114220003 -0500
+@@ -56,15 +56,32 @@
+ 		};
+ 	};
+ 
++	sound-sgtl5000 {
++		audio-codec = <&sgtl5000>;
++		audio-routing =
++			"MIC_IN", "Mic Jack",
++			"Mic Jack", "Mic Bias",
++			"Headphone Jack", "HP_OUT";
++		compatible = "fsl,imx-audio-sgtl5000";
++		model = "On-board Codec";
++		mux-ext-port = <5>;
++		mux-int-port = <1>;
++		ssi-controller = <&ssi1>;
++	};
++
+ 	sound-spdif {
+ 		compatible = "fsl,imx-audio-spdif";
+-		model = "imx-spdif";
++		model = "On-board SPDIF";
+ 		/* IMX6 doesn't implement this yet */
+ 		spdif-controller = <&spdif>;
+ 		spdif-out;
+ 	};
+ };
+ 
++&audmux {
++	status = "okay";
++};
++
+ &can1 {
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_hummingboard_flexcan1>;
+@@ -81,16 +98,24 @@
+ &i2c1 {
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
+-
+-	/*
+-	 * Not fitted on Carrier-1 board... yet
+ 	status = "okay";
+ 
++	/* Pro model */
+ 	rtc: pcf8523@68 {
+ 		compatible = "nxp,pcf8523";
+ 		reg = <0x68>;
+ 	};
+-	 */
++
++	/* Pro model */
++	sgtl5000: sgtl5000@0a {
++		clocks = <&clks 201>;
++		compatible = "fsl,sgtl5000";
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_hummingboard_sgtl5000>;
++		reg = <0x0a>;
++		VDDA-supply = <&reg_3p3v>;
++		VDDIO-supply = <&reg_3p3v>;
++	};
+ };
+ 
+ &i2c2 {
+@@ -135,6 +160,16 @@
+ 			>;
+ 		};
+ 
++		pinctrl_hummingboard_sgtl5000: hummingboard-sgtl5000 {
++			fsl,pins = <
++				MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0 /*brk*/
++				MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /*ok*/
++				MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /*brk*/
++				MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /*ok*/
++				MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
++			>;
++		};
++
+ 		pinctrl_hummingboard_spdif: hummingboard-spdif {
+ 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
+ 		};
+@@ -180,12 +215,19 @@
+ 	status = "okay";
+ };
+ 
++&ssi1 {
++	fsl,mode = "i2s-slave";
++	status = "okay";
++};
++
+ &usbh1 {
++	disable-over-current;
+ 	vbus-supply = <&reg_usbh1_vbus>;
+ 	status = "okay";
+ };
+ 
+ &usbotg {
++	disable-over-current;
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>;
+ 	vbus-supply = <&reg_usbotg_vbus>;
+diff -Nur linux-3.16.6.orig/arch/arm/boot/dts/imx6q-cubox-i.dts linux-3.16.6/arch/arm/boot/dts/imx6q-cubox-i.dts
+--- linux-3.16.6.orig/arch/arm/boot/dts/imx6q-cubox-i.dts	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/arch/arm/boot/dts/imx6q-cubox-i.dts	2014-10-23 12:26:42.106220014 -0500
+@@ -13,4 +13,8 @@
+ 
+ &sata {
+ 	status = "okay";
++	fsl,transmit-level-mV = <1104>;
++	fsl,transmit-boost-mdB = <0>;
++	fsl,transmit-atten-16ths = <9>;
++	fsl,no-spread-spectrum;
+ };
+diff -Nur linux-3.16.6.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-3.16.6/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+--- linux-3.16.6.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi	2014-10-23 12:34:41.266219992 -0500
+@@ -61,7 +61,7 @@
+ 
+ 	sound-spdif {
+ 		compatible = "fsl,imx-audio-spdif";
+-		model = "imx-spdif";
++		model = "Integrated SPDIF";
+ 		/* IMX6 doesn't implement this yet */
+ 		spdif-controller = <&spdif>;
+ 		spdif-out;
+@@ -130,16 +130,23 @@
+ 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
+ 		};
+ 
++		pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
++			fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
++		};
++
+ 		pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
+ 			fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
+ 		};
+ 
+-		pinctrl_cubox_i_usbotg_id: cubox-i-usbotg-id {
++		pinctrl_cubox_i_usbotg: cubox-i-usbotg {
+ 			/*
+-			 * The Cubox-i pulls this low, but as it's pointless
++			 * The Cubox-i pulls ID low, but as it's pointless
+ 			 * leaving it as a pull-up, even if it is just 10uA.
+ 			 */
+-			fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
++			fsl,pins = <
++				MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
++				MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
++			>;
+ 		};
+ 
+ 		pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
+@@ -163,6 +170,28 @@
+ 				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+ 			>;
+ 		};
++
++		pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz {
++			fsl,pins = <
++				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170b9
++				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100b9
++				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
++				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
++				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
++				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
++			>;
++		};
++
++		pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz {
++			fsl,pins = <
++				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170f9
++				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100f9
++				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
++				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
++				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
++				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
++			>;
++		};
+ 	};
+ };
+ 
+@@ -173,20 +202,24 @@
+ };
+ 
+ &usbh1 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_usbh1>;
+ 	vbus-supply = <&reg_usbh1_vbus>;
+ 	status = "okay";
+ };
+ 
+ &usbotg {
+ 	pinctrl-names = "default";
+-	pinctrl-0 = <&pinctrl_cubox_i_usbotg_id>;
++	pinctrl-0 = <&pinctrl_cubox_i_usbotg>;
+ 	vbus-supply = <&reg_usbotg_vbus>;
+ 	status = "okay";
+ };
+ 
+ &usdhc2 {
+-	pinctrl-names = "default";
++	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ 	pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
++	pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>;
++	pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>;
+ 	vmmc-supply = <&reg_3p3v>;
+ 	cd-gpios = <&gpio1 4 0>;
+ 	status = "okay";
+diff -Nur linux-3.16.6.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi.orig linux-3.16.6/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi.orig
+--- linux-3.16.6.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi.orig	2014-10-23 12:27:10.986220036 -0500
+@@ -0,0 +1,202 @@
++/*
++ * Copyright (C) 2014 Russell King
++ */
++#include "imx6qdl-microsom.dtsi"
++#include "imx6qdl-microsom-ar8035.dtsi"
++
++/ {
++	ir_recv: ir-receiver {
++		compatible = "gpio-ir-receiver";
++		gpios = <&gpio3 9 1>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_cubox_i_ir>;
++	};
++
++	pwmleds {
++		compatible = "pwm-leds";
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_cubox_i_pwm1>;
++
++		front {
++			active-low;
++			label = "imx6:red:front";
++			max-brightness = <248>;
++			pwms = <&pwm1 0 50000>;
++		};
++	};
++
++	regulators {
++		compatible = "simple-bus";
++
++		reg_3p3v: 3p3v {
++			compatible = "regulator-fixed";
++			regulator-name = "3P3V";
++			regulator-min-microvolt = <3300000>;
++			regulator-max-microvolt = <3300000>;
++			regulator-always-on;
++		};
++
++		reg_usbh1_vbus: usb-h1-vbus {
++			compatible = "regulator-fixed";
++			enable-active-high;
++			gpio = <&gpio1 0 0>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_cubox_i_usbh1_vbus>;
++			regulator-name = "usb_h1_vbus";
++			regulator-min-microvolt = <5000000>;
++			regulator-max-microvolt = <5000000>;
++		};
++
++		reg_usbotg_vbus: usb-otg-vbus {
++			compatible = "regulator-fixed";
++			enable-active-high;
++			gpio = <&gpio3 22 0>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_cubox_i_usbotg_vbus>;
++			regulator-name = "usb_otg_vbus";
++			regulator-min-microvolt = <5000000>;
++			regulator-max-microvolt = <5000000>;
++		};
++	};
++
++	sound-spdif {
++		compatible = "fsl,imx-audio-spdif";
++		model = "Integrated SPDIF";
++		/* IMX6 doesn't implement this yet */
++		spdif-controller = <&spdif>;
++		spdif-out;
++	};
++};
++
++&hdmi {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_hdmi>;
++	ddc-i2c-bus = <&i2c2>;
++	status = "okay";
++};
++
++&i2c2 {
++	clock-frequency = <100000>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_i2c2>;
++	status = "okay";
++};
++
++&i2c3 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_i2c3>;
++
++	status = "okay";
++
++	rtc: pcf8523@68 {
++		compatible = "nxp,pcf8523";
++		reg = <0x68>;
++	};
++};
++
++&iomuxc {
++	cubox_i {
++		pinctrl_cubox_i_hdmi: cubox-i-hdmi {
++			fsl,pins = <
++				MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
++			>;
++		};
++
++		pinctrl_cubox_i_i2c2: cubox-i-i2c2 {
++			fsl,pins = <
++				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
++				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
++			>;
++		};
++
++		pinctrl_cubox_i_i2c3: cubox-i-i2c3 {
++			fsl,pins = <
++				MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
++				MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
++			>;
++		};
++
++		pinctrl_cubox_i_ir: cubox-i-ir {
++			fsl,pins = <
++				MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
++			>;
++		};
++
++		pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led {
++			fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
++		};
++
++		pinctrl_cubox_i_spdif: cubox-i-spdif {
++			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
++		};
++
++		pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
++			fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
++		};
++
++		pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
++			fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
++		};
++
++		pinctrl_cubox_i_usbotg: cubox-i-usbotg {
++			/*
++			 * The Cubox-i pulls ID low, but as it's pointless
++			 * leaving it as a pull-up, even if it is just 10uA.
++			 */
++			fsl,pins = <
++				MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
++				MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
++			>;
++		};
++
++		pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
++			fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x4001b0b0>;
++		};
++
++		pinctrl_cubox_i_usdhc2_aux: cubox-i-usdhc2-aux {
++			fsl,pins = <
++				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
++				MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
++			>;
++		};
++
++		pinctrl_cubox_i_usdhc2: cubox-i-usdhc2 {
++			fsl,pins = <
++				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
++				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
++				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
++				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
++				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
++				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
++			>;
++		};
++	};
++};
++
++&spdif {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_spdif>;
++	status = "okay";
++};
++
++&usbh1 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_usbh1>;
++	vbus-supply = <&reg_usbh1_vbus>;
++	status = "okay";
++};
++
++&usbotg {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_usbotg>;
++	vbus-supply = <&reg_usbotg_vbus>;
++	status = "okay";
++};
++
++&usdhc2 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
++	vmmc-supply = <&reg_3p3v>;
++	cd-gpios = <&gpio1 4 0>;
++	status = "okay";
++};
+diff -Nur linux-3.16.6.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.16.6/arch/arm/boot/dts/imx6qdl-microsom.dtsi
+--- linux-3.16.6.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/arch/arm/boot/dts/imx6qdl-microsom.dtsi	2014-10-23 12:34:48.394220240 -0500
+@@ -1,15 +1,95 @@
+ /*
+  * Copyright (C) 2013,2014 Russell King
+  */
++#include <dt-bindings/gpio/gpio.h>
++/ {
++	regulators {
++		compatible = "simple-bus";
++
++		reg_brcm_osc: brcm-osc-reg {
++			compatible = "regulator-fixed";
++			enable-active-high;
++			gpio = <&gpio5 5 0>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>;
++			regulator-name = "brcm_osc_reg";
++			regulator-min-microvolt = <3300000>;
++			regulator-max-microvolt = <3300000>;
++			regulator-always-on;
++			regulator-boot-on;
++		};
++
++		reg_brcm: brcm-reg {
++			compatible = "regulator-fixed";
++			enable-active-high;
++			gpio = <&gpio3 19 0>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_microsom_brcm_reg>;
++			regulator-name = "brcm_reg";
++			regulator-min-microvolt = <3300000>;
++			regulator-max-microvolt = <3300000>;
++			startup-delay-us = <200000>;
++		};
++	};
++};
+ 
+ &iomuxc {
+ 	microsom {
++		pinctrl_microsom_brcm_bt: microsom-brcm-bt {
++			fsl,pins = <
++				MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00	0x40013070
++				MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01	0x40013070
++				MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04	0x40013070
++			>;
++		};
++
++		pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg {
++			fsl,pins = <
++				MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05	0x40013070
++			>;
++		};
++
++		pinctrl_microsom_brcm_reg: microsom-brcm-reg {
++			fsl,pins = <
++				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x40013070
++			>;
++		};
++
++		pinctrl_microsom_brcm_wifi: microsom-brcm-wifi {
++			fsl,pins = <
++				MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K	0x1b0b0
++				MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20	0x40013070
++				MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26	0x40013070
++				MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27	0x40013070
++			>;
++		};
++
+ 		pinctrl_microsom_uart1: microsom-uart1 {
+ 			fsl,pins = <
+ 				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+ 				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+ 			>;
+ 		};
++
++		pinctrl_microsom_uart4_1: microsom-uart4 {
++			fsl,pins = <
++				MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
++				MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
++				MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
++				MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
++			>;
++		};
++
++		pinctrl_microsom_usdhc1: microsom-usdhc1 {
++			fsl,pins = <
++				MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
++				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
++				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
++				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
++				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
++				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
++			>;
++		};
+ 	};
+ };
+ 
+@@ -18,3 +98,23 @@
+ 	pinctrl-0 = <&pinctrl_microsom_uart1>;
+ 	status = "okay";
+ };
++
++/* UART4 - Connected to optional BRCM Wifi/BT/FM */
++&uart4 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>;
++	fsl,uart-has-rtscts;
++	status = "okay";
++};
++
++/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */
++&usdhc1 {
++	card-external-vcc-supply = <&reg_brcm>;
++	card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>;
++	keep-power-in-suspend;
++	non-removable;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>;
++	vmmc-supply = <&reg_brcm>;
++	status = "okay";
++};
+diff -Nur linux-3.16.6.orig/arch/arm/mach-imx/clk-imx6q.c linux-3.16.6/arch/arm/mach-imx/clk-imx6q.c
+--- linux-3.16.6.orig/arch/arm/mach-imx/clk-imx6q.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/arch/arm/mach-imx/clk-imx6q.c	2014-10-23 12:36:09.214219998 -0500
+@@ -461,6 +461,9 @@
+ 	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+ 	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+ 
++	if (cpu_is_imx6dl())
++		clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]);
++
+ 	/*
+ 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
+ 	 * We can not get the 100MHz from the pll2_pfd0_352m.
+diff -Nur linux-3.16.6.orig/arch/arm/mach-imx/clk-pllv3.c linux-3.16.6/arch/arm/mach-imx/clk-pllv3.c
+--- linux-3.16.6.orig/arch/arm/mach-imx/clk-pllv3.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/arch/arm/mach-imx/clk-pllv3.c	2014-10-23 12:36:01.390219997 -0500
+@@ -273,9 +273,10 @@
+ 	struct clk_pllv3 *pll = to_clk_pllv3(hw);
+ 	unsigned long min_rate = parent_rate * 27;
+ 	unsigned long max_rate = parent_rate * 54;
+-	u32 val, div;
++	u32 val, newval, div;
+ 	u32 mfn, mfd = 1000000;
+ 	s64 temp64;
++	int ret;
+ 
+ 	if (rate < min_rate || rate > max_rate)
+ 		return -EINVAL;
+@@ -287,13 +288,27 @@
+ 	mfn = temp64;
+ 
+ 	val = readl_relaxed(pll->base);
+-	val &= ~pll->div_mask;
+-	val |= div;
+-	writel_relaxed(val, pll->base);
++
++	/* set the PLL into bypass mode */
++	newval = val | BM_PLL_BYPASS;
++	writel_relaxed(newval, pll->base);
++
++	/* configure the new frequency */
++	newval &= ~pll->div_mask;
++	newval |= div;
++	writel_relaxed(newval, pll->base);
+ 	writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
+-	writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
++	writel(mfd, pll->base + PLL_DENOM_OFFSET);
++
++	ret = clk_pllv3_wait_lock(pll);
++	if (ret == 0 && val & BM_PLL_POWER) {
++		/* only if it locked can we switch back to the PLL */
++		newval &= ~BM_PLL_BYPASS;
++		newval |= val & BM_PLL_BYPASS;
++		writel(newval, pll->base);
++	}
+ 
+-	return clk_pllv3_wait_lock(pll);
++	return ret;
+ }
+ 
+ static const struct clk_ops clk_pllv3_av_ops = {
+diff -Nur linux-3.16.6.orig/Documentation/devicetree/bindings/ata/ahci-platform.txt linux-3.16.6/Documentation/devicetree/bindings/ata/ahci-platform.txt
+--- linux-3.16.6.orig/Documentation/devicetree/bindings/ata/ahci-platform.txt	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/Documentation/devicetree/bindings/ata/ahci-platform.txt	2014-10-23 12:15:35.154220017 -0500
+@@ -6,8 +6,6 @@
+ Required properties:
+ - compatible        : compatible string, one of:
+   - "allwinner,sun4i-a10-ahci"
+-  - "fsl,imx53-ahci"
+-  - "fsl,imx6q-ahci"
+   - "hisilicon,hisi-ahci"
+   - "ibm,476gtr-ahci"
+   - "marvell,armada-380-ahci"
+@@ -22,10 +20,6 @@
+ - clocks            : a list of phandle + clock specifier pairs
+ - target-supply     : regulator for SATA target power
+ 
+-"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
+-- clocks            : must contain the sata, sata_ref and ahb clocks
+-- clock-names       : must contain "ahb" for the ahb clock
+-
+ Examples:
+         sata@ffe08000 {
+ 		compatible = "snps,spear-ahci";
+diff -Nur linux-3.16.6.orig/Documentation/devicetree/bindings/ata/imx-sata.txt linux-3.16.6/Documentation/devicetree/bindings/ata/imx-sata.txt
+--- linux-3.16.6.orig/Documentation/devicetree/bindings/ata/imx-sata.txt	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/Documentation/devicetree/bindings/ata/imx-sata.txt	2014-10-23 12:26:27.434219953 -0500
+@@ -0,0 +1,36 @@
++* Freescale i.MX AHCI SATA Controller
++
++The Freescale i.MX SATA controller mostly conforms to the AHCI interface
++with some special extensions at integration level.
++
++Required properties:
++- compatible : should be one of the following:
++   - "fsl,imx53-ahci" for i.MX53 SATA controller
++   - "fsl,imx6q-ahci" for i.MX6Q SATA controller
++- interrupts : interrupt mapping for SATA IRQ
++- reg : registers mapping
++- clocks : list of clock specifiers, must contain an entry for each
++  required entry in clock-names
++- clock-names : should include "sata", "sata_ref" and "ahb" entries
++
++Optional properties:
++- fsl,transmit-level-mV : transmit voltage level, in millivolts.
++- fsl,transmit-boost-mdB : transmit boost level, in milli-decibels
++- fsl,transmit-atten-16ths : transmit attenuation, in 16ths
++- fsl,receive-eq-mdB : receive equalisation, in milli-decibels
++  Please refer to the technical documentation or the driver source code
++  for the list of legal values for these options.
++- fsl,no-spread-spectrum : disable spread-spectrum clocking on the SATA
++  link.
++
++Examples:
++
++sata@02200000 {
++	compatible = "fsl,imx6q-ahci";
++	reg = <0x02200000 0x4000>;
++	interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
++	clocks = <&clks IMX6QDL_CLK_SATA>,
++		 <&clks IMX6QDL_CLK_SATA_REF_100M>,
++		 <&clks IMX6QDL_CLK_AHB>;
++	clock-names = "sata", "sata_ref", "ahb";
++};
+diff -Nur linux-3.16.6.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.16.6/Documentation/devicetree/bindings/mmc/mmc.txt
+--- linux-3.16.6.orig/Documentation/devicetree/bindings/mmc/mmc.txt	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/Documentation/devicetree/bindings/mmc/mmc.txt	2014-10-23 12:34:18.694220003 -0500
+@@ -5,6 +5,8 @@
+ Interpreted by the OF core:
+ - reg: Registers location and length.
+ - interrupts: Interrupts used by the MMC controller.
++- clocks: Clocks needed for the host controller, if any.
++- clock-names: Goes with clocks above.
+ 
+ Card detection:
+ If no property below is supplied, host native card detect is used.
+@@ -41,6 +43,15 @@
+ - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
+ - mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
+ 
++Card power and reset control:
++The following properties can be specified for cases where the MMC
++peripheral needs additional reset, regulator and clock lines. It is for
++example common for WiFi/BT adapters to have these separate from the main
++MMC bus:
++  - card-reset-gpios: Specify GPIOs for card reset (reset active low)
++  - card-external-vcc-supply: Regulator to drive (independent) card VCC
++  - clock with name "card_ext_clock": External clock provided to the card
++
+ *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
+ polarity properties, we have to fix the meaning of the "normal" and "inverted"
+ line levels. We choose to follow the SDHCI standard, which specifies both those
+diff -Nur linux-3.16.6.orig/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt linux-3.16.6/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+--- linux-3.16.6.orig/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt	2014-10-23 12:35:30.946219998 -0500
+@@ -60,8 +60,8 @@
+ - compatible: Should be "fsl,imx-parallel-display"
+ Optional properties:
+ - interface_pix_fmt: How this display is connected to the
+-  display interface. Currently supported types: "rgb24", "rgb565", "bgr666"
+-  and "lvds666".
++  display interface. Currently supported types: "rgb24", "rgb565", "bgr666",
++  "rgb666" and "lvds666".
+ - edid: verbatim EDID data block describing attached display.
+ - ddc: phandle describing the i2c bus handling the display data
+   channel
+diff -Nur linux-3.16.6.orig/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml linux-3.16.6/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+--- linux-3.16.6.orig/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml	2014-10-23 12:35:23.678220004 -0500
+@@ -279,6 +279,45 @@
+ 	    <entry></entry>
+ 	    <entry></entry>
+ 	  </row>
++	  <row id="V4L2-PIX-FMT-RGB666">
++	    <entry><constant>V4L2_PIX_FMT_RGB666</constant></entry>
++	    <entry>'RGBH'</entry>
++	    <entry></entry>
++	    <entry>r<subscript>5</subscript></entry>
++	    <entry>r<subscript>4</subscript></entry>
++	    <entry>r<subscript>3</subscript></entry>
++	    <entry>r<subscript>2</subscript></entry>
++	    <entry>r<subscript>1</subscript></entry>
++	    <entry>r<subscript>0</subscript></entry>
++	    <entry>g<subscript>5</subscript></entry>
++	    <entry>g<subscript>4</subscript></entry>
++	    <entry></entry>
++	    <entry>g<subscript>3</subscript></entry>
++	    <entry>g<subscript>2</subscript></entry>
++	    <entry>g<subscript>1</subscript></entry>
++	    <entry>g<subscript>0</subscript></entry>
++	    <entry>b<subscript>5</subscript></entry>
++	    <entry>b<subscript>4</subscript></entry>
++	    <entry>b<subscript>3</subscript></entry>
++	    <entry>b<subscript>2</subscript></entry>
++	    <entry></entry>
++	    <entry>b<subscript>1</subscript></entry>
++	    <entry>b<subscript>0</subscript></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	  </row>
+ 	  <row id="V4L2-PIX-FMT-BGR24">
+ 	    <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
+ 	    <entry>'BGR3'</entry>
+diff -Nur linux-3.16.6.orig/drivers/ata/ahci_imx.c linux-3.16.6/drivers/ata/ahci_imx.c
+--- linux-3.16.6.orig/drivers/ata/ahci_imx.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/ata/ahci_imx.c	2014-10-23 12:26:19.770220044 -0500
+@@ -64,6 +64,7 @@
+ 	struct regmap *gpr;
+ 	bool no_device;
+ 	bool first_time;
++	u32 phy_params;
+ };
+ 
+ static int ahci_imx_hotplug;
+@@ -248,14 +249,7 @@
+ 				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
+ 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
+ 				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
+-				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
+-				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+-				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+-				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+-				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
+-				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
+-				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
+-				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
++				   imxpriv->phy_params);
+ 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+ 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+ 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+@@ -369,6 +363,165 @@
+ };
+ MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
+ 
++struct reg_value {
++	u32 of_value;
++	u32 reg_value;
++};
++
++struct reg_property {
++	const char *name;
++	const struct reg_value *values;
++	size_t num_values;
++	u32 def_value;
++	u32 set_value;
++};
++
++static const struct reg_value gpr13_tx_level[] = {
++	{  937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
++	{  947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
++	{  957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
++	{  966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
++	{  976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
++	{  986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
++	{  996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
++	{ 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
++	{ 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
++	{ 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
++	{ 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
++	{ 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
++	{ 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
++	{ 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
++	{ 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
++	{ 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
++	{ 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
++	{ 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
++	{ 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
++	{ 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
++	{ 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
++	{ 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
++	{ 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
++	{ 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
++	{ 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
++	{ 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
++	{ 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
++	{ 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
++	{ 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
++	{ 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
++	{ 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
++	{ 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
++};
++
++static const struct reg_value gpr13_tx_boost[] = {
++	{    0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
++	{  370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
++	{  740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
++	{ 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
++	{ 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
++	{ 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
++	{ 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
++	{ 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
++	{ 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
++	{ 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
++	{ 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
++	{ 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
++	{ 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
++	{ 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
++	{ 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
++	{ 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
++};
++
++static const struct reg_value gpr13_tx_atten[] = {
++	{  8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
++	{  9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
++	{ 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
++	{ 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
++	{ 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
++	{ 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
++};
++
++static const struct reg_value gpr13_rx_eq[] = {
++	{  500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
++	{ 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
++	{ 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
++	{ 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
++	{ 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
++	{ 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
++	{ 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
++	{ 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
++};
++
++static const struct reg_property gpr13_props[] = {
++	{
++		.name = "fsl,transmit-level-mV",
++		.values = gpr13_tx_level,
++		.num_values = ARRAY_SIZE(gpr13_tx_level),
++		.def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
++	}, {
++		.name = "fsl,transmit-boost-mdB",
++		.values = gpr13_tx_boost,
++		.num_values = ARRAY_SIZE(gpr13_tx_boost),
++		.def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
++	}, {
++		.name = "fsl,transmit-atten-16ths",
++		.values = gpr13_tx_atten,
++		.num_values = ARRAY_SIZE(gpr13_tx_atten),
++		.def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
++	}, {
++		.name = "fsl,receive-eq-mdB",
++		.values = gpr13_rx_eq,
++		.num_values = ARRAY_SIZE(gpr13_rx_eq),
++		.def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
++	}, {
++		.name = "fsl,no-spread-spectrum",
++		.def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN,
++		.set_value = 0,
++	},
++};
++
++static u32 imx_ahci_parse_props(struct device *dev,
++				const struct reg_property *prop, size_t num)
++{
++	struct device_node *np = dev->of_node;
++	u32 reg_value = 0;
++	int i, j;
++
++	for (i = 0; i < num; i++, prop++) {
++		u32 of_val;
++
++		if (prop->num_values == 0) {
++			if (of_property_read_bool(np, prop->name))
++				reg_value |= prop->set_value;
++			else
++				reg_value |= prop->def_value;
++			continue;
++		}
++
++		if (of_property_read_u32(np, prop->name, &of_val)) {
++			dev_info(dev, "%s not specified, using %08x\n",
++				prop->name, prop->def_value);
++			reg_value |= prop->def_value;
++			continue;
++		}
++
++		for (j = 0; j < prop->num_values; j++) {
++			if (prop->values[j].of_value == of_val) {
++				dev_info(dev, "%s value %u, using %08x\n",
++					prop->name, of_val, prop->values[j].reg_value);
++				reg_value |= prop->values[j].reg_value;
++				break;
++			}
++		}
++
++		if (j == prop->num_values) {
++			dev_err(dev, "DT property %s is not a valid value\n",
++				prop->name);
++			reg_value |= prop->def_value;
++		}
++	}
++
++	return reg_value;
++}
++
+ static int imx_ahci_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+@@ -410,6 +563,8 @@
+ 	}
+ 
+ 	if (imxpriv->type == AHCI_IMX6Q) {
++		u32 reg_value;
++
+ 		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
+ 							"fsl,imx6q-iomuxc-gpr");
+ 		if (IS_ERR(imxpriv->gpr)) {
+@@ -417,6 +572,15 @@
+ 				"failed to find fsl,imx6q-iomux-gpr regmap\n");
+ 			return PTR_ERR(imxpriv->gpr);
+ 		}
++
++		reg_value = imx_ahci_parse_props(dev, gpr13_props,
++						 ARRAY_SIZE(gpr13_props));
++
++		imxpriv->phy_params =
++				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
++				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
++				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
++				   reg_value;
+ 	}
+ 
+ 	hpriv = ahci_platform_get_resources(pdev);
+diff -Nur linux-3.16.6.orig/drivers/ata/ahci_imx.c.orig linux-3.16.6/drivers/ata/ahci_imx.c.orig
+--- linux-3.16.6.orig/drivers/ata/ahci_imx.c.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/ata/ahci_imx.c.orig	2014-10-23 12:18:59.602219672 -0500
+@@ -0,0 +1,679 @@
++/*
++ * copyright (c) 2013 Freescale Semiconductor, Inc.
++ * Freescale IMX AHCI SATA platform driver
++ *
++ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/ahci_platform.h>
++#include <linux/of_device.h>
++#include <linux/mfd/syscon.h>
++#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
++#include <linux/libata.h>
++#include "ahci.h"
++
++enum {
++	/* Timer 1-ms Register */
++	IMX_TIMER1MS				= 0x00e0,
++	/* Port0 PHY Control Register */
++	IMX_P0PHYCR				= 0x0178,
++	IMX_P0PHYCR_TEST_PDDQ			= 1 << 20,
++	IMX_P0PHYCR_CR_READ			= 1 << 19,
++	IMX_P0PHYCR_CR_WRITE			= 1 << 18,
++	IMX_P0PHYCR_CR_CAP_DATA			= 1 << 17,
++	IMX_P0PHYCR_CR_CAP_ADDR			= 1 << 16,
++	/* Port0 PHY Status Register */
++	IMX_P0PHYSR				= 0x017c,
++	IMX_P0PHYSR_CR_ACK			= 1 << 18,
++	IMX_P0PHYSR_CR_DATA_OUT			= 0xffff << 0,
++	/* Lane0 Output Status Register */
++	IMX_LANE0_OUT_STAT			= 0x2003,
++	IMX_LANE0_OUT_STAT_RX_PLL_STATE		= 1 << 1,
++	/* Clock Reset Register */
++	IMX_CLOCK_RESET				= 0x7f3f,
++	IMX_CLOCK_RESET_RESET			= 1 << 0,
++};
++
++enum ahci_imx_type {
++	AHCI_IMX53,
++	AHCI_IMX6Q,
++};
++
++struct imx_ahci_priv {
++	struct platform_device *ahci_pdev;
++	enum ahci_imx_type type;
++	struct clk *sata_clk;
++	struct clk *sata_ref_clk;
++	struct clk *ahb_clk;
++	struct regmap *gpr;
++	bool no_device;
++	bool first_time;
++	u32 phy_params;
++};
++
++static int ahci_imx_hotplug;
++module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
++MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
++
++static void ahci_imx_host_stop(struct ata_host *host);
++
++static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert)
++{
++	int timeout = 10;
++	u32 crval;
++	u32 srval;
++
++	/* Assert or deassert the bit */
++	crval = readl(mmio + IMX_P0PHYCR);
++	if (assert)
++		crval |= bit;
++	else
++		crval &= ~bit;
++	writel(crval, mmio + IMX_P0PHYCR);
++
++	/* Wait for the cr_ack signal */
++	do {
++		srval = readl(mmio + IMX_P0PHYSR);
++		if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK)
++			break;
++		usleep_range(100, 200);
++	} while (--timeout);
++
++	return timeout ? 0 : -ETIMEDOUT;
++}
++
++static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio)
++{
++	u32 crval = addr;
++	int ret;
++
++	/* Supply the address on cr_data_in */
++	writel(crval, mmio + IMX_P0PHYCR);
++
++	/* Assert the cr_cap_addr signal */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true);
++	if (ret)
++		return ret;
++
++	/* Deassert cr_cap_addr */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false);
++	if (ret)
++		return ret;
++
++	return 0;
++}
++
++static int imx_phy_reg_write(u16 val, void __iomem *mmio)
++{
++	u32 crval = val;
++	int ret;
++
++	/* Supply the data on cr_data_in */
++	writel(crval, mmio + IMX_P0PHYCR);
++
++	/* Assert the cr_cap_data signal */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true);
++	if (ret)
++		return ret;
++
++	/* Deassert cr_cap_data */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false);
++	if (ret)
++		return ret;
++
++	if (val & IMX_CLOCK_RESET_RESET) {
++		/*
++		 * In case we're resetting the phy, it's unable to acknowledge,
++		 * so we return immediately here.
++		 */
++		crval |= IMX_P0PHYCR_CR_WRITE;
++		writel(crval, mmio + IMX_P0PHYCR);
++		goto out;
++	}
++
++	/* Assert the cr_write signal */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true);
++	if (ret)
++		return ret;
++
++	/* Deassert cr_write */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false);
++	if (ret)
++		return ret;
++
++out:
++	return 0;
++}
++
++static int imx_phy_reg_read(u16 *val, void __iomem *mmio)
++{
++	int ret;
++
++	/* Assert the cr_read signal */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true);
++	if (ret)
++		return ret;
++
++	/* Capture the data from cr_data_out[] */
++	*val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT;
++
++	/* Deassert cr_read */
++	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false);
++	if (ret)
++		return ret;
++
++	return 0;
++}
++
++static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
++{
++	void __iomem *mmio = hpriv->mmio;
++	int timeout = 10;
++	u16 val;
++	int ret;
++
++	/* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */
++	ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio);
++	if (ret)
++		return ret;
++	ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio);
++	if (ret)
++		return ret;
++
++	/* Wait for PHY RX_PLL to be stable */
++	do {
++		usleep_range(100, 200);
++		ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio);
++		if (ret)
++			return ret;
++		ret = imx_phy_reg_read(&val, mmio);
++		if (ret)
++			return ret;
++		if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE)
++			break;
++	} while (--timeout);
++
++	return timeout ? 0 : -ETIMEDOUT;
++}
++
++static int imx_sata_enable(struct ahci_host_priv *hpriv)
++{
++	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
++	struct device *dev = &imxpriv->ahci_pdev->dev;
++	int ret;
++
++	if (imxpriv->no_device)
++		return 0;
++
++	if (hpriv->target_pwr) {
++		ret = regulator_enable(hpriv->target_pwr);
++		if (ret)
++			return ret;
++	}
++
++	ret = clk_prepare_enable(imxpriv->sata_ref_clk);
++	if (ret < 0)
++		goto disable_regulator;
++
++	if (imxpriv->type == AHCI_IMX6Q) {
++		/*
++		 * set PHY Paremeters, two steps to configure the GPR13,
++		 * one write for rest of parameters, mask of first write
++		 * is 0x07ffffff, and the other one write for setting
++		 * the mpll_clk_en.
++		 */
++		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
++				   IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
++				   IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
++				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
++				   IMX6Q_GPR13_SATA_SPD_MODE_MASK |
++				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
++				   IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
++				   IMX6Q_GPR13_SATA_TX_BOOST_MASK |
++				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
++				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
++				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
++				   imxpriv->phy_params);
++		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
++				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
++				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
++
++		usleep_range(100, 200);
++
++		ret = imx_sata_phy_reset(hpriv);
++		if (ret) {
++			dev_err(dev, "failed to reset phy: %d\n", ret);
++			goto disable_regulator;
++		}
++	}
++
++	usleep_range(1000, 2000);
++
++	return 0;
++
++disable_regulator:
++	if (hpriv->target_pwr)
++		regulator_disable(hpriv->target_pwr);
++
++	return ret;
++}
++
++static void imx_sata_disable(struct ahci_host_priv *hpriv)
++{
++	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
++
++	if (imxpriv->no_device)
++		return;
++
++	if (imxpriv->type == AHCI_IMX6Q) {
++		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
++				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
++				   !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
++	}
++
++	clk_disable_unprepare(imxpriv->sata_ref_clk);
++
++	if (hpriv->target_pwr)
++		regulator_disable(hpriv->target_pwr);
++}
++
++static void ahci_imx_error_handler(struct ata_port *ap)
++{
++	u32 reg_val;
++	struct ata_device *dev;
++	struct ata_host *host = dev_get_drvdata(ap->dev);
++	struct ahci_host_priv *hpriv = host->private_data;
++	void __iomem *mmio = hpriv->mmio;
++	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
++
++	ahci_error_handler(ap);
++
++	if (!(imxpriv->first_time) || ahci_imx_hotplug)
++		return;
++
++	imxpriv->first_time = false;
++
++	ata_for_each_dev(dev, &ap->link, ENABLED)
++		return;
++	/*
++	 * Disable link to save power.  An imx ahci port can't be recovered
++	 * without full reset once the pddq mode is enabled making it
++	 * impossible to use as part of libata LPM.
++	 */
++	reg_val = readl(mmio + IMX_P0PHYCR);
++	writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
++	imx_sata_disable(hpriv);
++	imxpriv->no_device = true;
++
++	dev_info(ap->dev, "no device found, disabling link.\n");
++	dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX ".hotplug=1 to enable hotplug\n");
++}
++
++static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
++		       unsigned long deadline)
++{
++	struct ata_port *ap = link->ap;
++	struct ata_host *host = dev_get_drvdata(ap->dev);
++	struct ahci_host_priv *hpriv = host->private_data;
++	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
++	int ret = -EIO;
++
++	if (imxpriv->type == AHCI_IMX53)
++		ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
++	else if (imxpriv->type == AHCI_IMX6Q)
++		ret = ahci_ops.softreset(link, class, deadline);
++
++	return ret;
++}
++
++static struct ata_port_operations ahci_imx_ops = {
++	.inherits	= &ahci_ops,
++	.host_stop	= ahci_imx_host_stop,
++	.error_handler	= ahci_imx_error_handler,
++	.softreset	= ahci_imx_softreset,
++};
++
++static const struct ata_port_info ahci_imx_port_info = {
++	.flags		= AHCI_FLAG_COMMON,
++	.pio_mask	= ATA_PIO4,
++	.udma_mask	= ATA_UDMA6,
++	.port_ops	= &ahci_imx_ops,
++};
++
++static const struct of_device_id imx_ahci_of_match[] = {
++	{ .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
++	{ .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
++	{},
++};
++MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
++
++struct reg_value {
++	u32 of_value;
++	u32 reg_value;
++};
++
++struct reg_property {
++	const char *name;
++	const struct reg_value *values;
++	size_t num_values;
++	u32 def_value;
++};
++
++static const struct reg_value gpr13_tx_level[] = {
++	{  937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
++	{  947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
++	{  957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
++	{  966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
++	{  976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
++	{  986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
++	{  996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
++	{ 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
++	{ 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
++	{ 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
++	{ 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
++	{ 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
++	{ 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
++	{ 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
++	{ 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
++	{ 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
++	{ 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
++	{ 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
++	{ 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
++	{ 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
++	{ 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
++	{ 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
++	{ 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
++	{ 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
++	{ 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
++	{ 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
++	{ 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
++	{ 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
++	{ 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
++	{ 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
++	{ 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
++	{ 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
++};
++
++static const struct reg_value gpr13_tx_boost[] = {
++	{    0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
++	{  370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
++	{  740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
++	{ 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
++	{ 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
++	{ 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
++	{ 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
++	{ 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
++	{ 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
++	{ 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
++	{ 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
++	{ 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
++	{ 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
++	{ 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
++	{ 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
++	{ 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
++};
++
++static const struct reg_value gpr13_tx_atten[] = {
++	{  8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
++	{  9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
++	{ 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
++	{ 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
++	{ 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
++	{ 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
++};
++
++static const struct reg_value gpr13_rx_eq[] = {
++	{  500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
++	{ 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
++	{ 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
++	{ 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
++	{ 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
++	{ 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
++	{ 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
++	{ 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
++};
++
++static const struct reg_property gpr13_props[] = {
++	{
++		.name = "fsl,transmit-level-mV",
++		.values = gpr13_tx_level,
++		.num_values = ARRAY_SIZE(gpr13_tx_level),
++		.def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
++	}, {
++		.name = "fsl,transmit-boost-mdB",
++		.values = gpr13_tx_boost,
++		.num_values = ARRAY_SIZE(gpr13_tx_boost),
++		.def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
++	}, {
++		.name = "fsl,transmit-atten-16ths",
++		.values = gpr13_tx_atten,
++		.num_values = ARRAY_SIZE(gpr13_tx_atten),
++		.def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
++	}, {
++		.name = "fsl,receive-eq-mdB",
++		.values = gpr13_rx_eq,
++		.num_values = ARRAY_SIZE(gpr13_rx_eq),
++		.def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
++	},
++};
++
++static u32 imx_ahci_parse_props(struct device *dev,
++				const struct reg_property *prop, size_t num)
++{
++	struct device_node *np = dev->of_node;
++	u32 reg_value = 0;
++	int i, j;
++
++	for (i = 0; i < num; i++, prop++) {
++		u32 of_val;
++
++		if (of_property_read_u32(np, prop->name, &of_val)) {
++			dev_info(dev, "%s not specified, using %08x\n",
++				prop->name, prop->def_value);
++			reg_value |= prop->def_value;
++			continue;
++		}
++
++		for (j = 0; j < prop->num_values; j++) {
++			if (prop->values[j].of_value == of_val) {
++				dev_info(dev, "%s value %u, using %08x\n",
++					prop->name, of_val, prop->values[j].reg_value);
++				reg_value |= prop->values[j].reg_value;
++				break;
++			}
++		}
++
++		if (j == prop->num_values) {
++			dev_err(dev, "DT property %s is not a valid value\n",
++				prop->name);
++			reg_value |= prop->def_value;
++		}
++	}
++
++	return reg_value;
++}
++
++static int imx_ahci_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	const struct of_device_id *of_id;
++	struct ahci_host_priv *hpriv;
++	struct imx_ahci_priv *imxpriv;
++	unsigned int reg_val;
++	int ret;
++
++	of_id = of_match_device(imx_ahci_of_match, dev);
++	if (!of_id)
++		return -EINVAL;
++
++	imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
++	if (!imxpriv)
++		return -ENOMEM;
++
++	imxpriv->ahci_pdev = pdev;
++	imxpriv->no_device = false;
++	imxpriv->first_time = true;
++	imxpriv->type = (enum ahci_imx_type)of_id->data;
++
++	imxpriv->sata_clk = devm_clk_get(dev, "sata");
++	if (IS_ERR(imxpriv->sata_clk)) {
++		dev_err(dev, "can't get sata clock.\n");
++		return PTR_ERR(imxpriv->sata_clk);
++	}
++
++	imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
++	if (IS_ERR(imxpriv->sata_ref_clk)) {
++		dev_err(dev, "can't get sata_ref clock.\n");
++		return PTR_ERR(imxpriv->sata_ref_clk);
++	}
++
++	imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
++	if (IS_ERR(imxpriv->ahb_clk)) {
++		dev_err(dev, "can't get ahb clock.\n");
++		return PTR_ERR(imxpriv->ahb_clk);
++	}
++
++	if (imxpriv->type == AHCI_IMX6Q) {
++		u32 reg_value;
++
++		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
++							"fsl,imx6q-iomuxc-gpr");
++		if (IS_ERR(imxpriv->gpr)) {
++			dev_err(dev,
++				"failed to find fsl,imx6q-iomux-gpr regmap\n");
++			return PTR_ERR(imxpriv->gpr);
++		}
++
++		reg_value = imx_ahci_parse_props(dev, gpr13_props,
++						 ARRAY_SIZE(gpr13_props));
++
++		imxpriv->phy_params =
++				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
++				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
++				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
++				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
++				   reg_value;
++	}
++
++	hpriv = ahci_platform_get_resources(pdev);
++	if (IS_ERR(hpriv))
++		return PTR_ERR(hpriv);
++
++	hpriv->plat_data = imxpriv;
++
++	ret = clk_prepare_enable(imxpriv->sata_clk);
++	if (ret)
++		return ret;
++
++	ret = imx_sata_enable(hpriv);
++	if (ret)
++		goto disable_clk;
++
++	/*
++	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
++	 * and IP vendor specific register IMX_TIMER1MS.
++	 * Configure CAP_SSS (support stagered spin up).
++	 * Implement the port0.
++	 * Get the ahb clock rate, and configure the TIMER1MS register.
++	 */
++	reg_val = readl(hpriv->mmio + HOST_CAP);
++	if (!(reg_val & HOST_CAP_SSS)) {
++		reg_val |= HOST_CAP_SSS;
++		writel(reg_val, hpriv->mmio + HOST_CAP);
++	}
++	reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL);
++	if (!(reg_val & 0x1)) {
++		reg_val |= 0x1;
++		writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL);
++	}
++
++	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
++	writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
++
++	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
++				      0, 0, 0);
++	if (ret)
++		goto disable_sata;
++
++	return 0;
++
++disable_sata:
++	imx_sata_disable(hpriv);
++disable_clk:
++	clk_disable_unprepare(imxpriv->sata_clk);
++	return ret;
++}
++
++static void ahci_imx_host_stop(struct ata_host *host)
++{
++	struct ahci_host_priv *hpriv = host->private_data;
++	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
++
++	imx_sata_disable(hpriv);
++	clk_disable_unprepare(imxpriv->sata_clk);
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int imx_ahci_suspend(struct device *dev)
++{
++	struct ata_host *host = dev_get_drvdata(dev);
++	struct ahci_host_priv *hpriv = host->private_data;
++	int ret;
++
++	ret = ahci_platform_suspend_host(dev);
++	if (ret)
++		return ret;
++
++	imx_sata_disable(hpriv);
++
++	return 0;
++}
++
++static int imx_ahci_resume(struct device *dev)
++{
++	struct ata_host *host = dev_get_drvdata(dev);
++	struct ahci_host_priv *hpriv = host->private_data;
++	int ret;
++
++	ret = imx_sata_enable(hpriv);
++	if (ret)
++		return ret;
++
++	return ahci_platform_resume_host(dev);
++}
++#endif
++
++static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
++
++static struct platform_driver imx_ahci_driver = {
++	.probe = imx_ahci_probe,
++	.remove = ata_platform_remove_one,
++	.driver = {
++		.name = "ahci-imx",
++		.owner = THIS_MODULE,
++		.of_match_table = imx_ahci_of_match,
++		.pm = &ahci_imx_pm_ops,
++	},
++};
++module_platform_driver(imx_ahci_driver);
++
++MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
++MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("ahci:imx");
+diff -Nur linux-3.16.6.orig/drivers/cec/cec-dev.c linux-3.16.6/drivers/cec/cec-dev.c
+--- linux-3.16.6.orig/drivers/cec/cec-dev.c	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/cec/cec-dev.c	2014-10-23 12:37:18.374219998 -0500
+@@ -0,0 +1,384 @@
++/*
++ * HDMI Consumer Electronics Control
++ *
++ * This provides the user API for communication with HDMI CEC complaint
++ * devices in kernel drivers, and is based upon the protocol developed
++ * by Freescale for their i.MX SoCs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/cec-dev.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++
++struct cec_event {
++	struct cec_user_event usr;
++	struct list_head node;
++};
++
++static struct class *cec_class;
++static int cec_major;
++
++static void cec_dev_send_message(struct cec_dev *cec_dev, u8 *msg,
++	size_t count)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&cec_dev->lock, flags);
++	cec_dev->retries = 5;
++	cec_dev->write_busy = 1;
++	cec_dev->send_message(cec_dev, msg, count);
++	spin_unlock_irqrestore(&cec_dev->lock, flags);
++}
++
++void cec_dev_event(struct cec_dev *cec_dev, int type, u8 *msg, size_t len)
++{
++	struct cec_event *event;
++	unsigned long flags;
++
++	event = kzalloc(sizeof(*event), GFP_ATOMIC);
++	if (event) {
++		event->usr.event_type = type;
++		event->usr.msg_len = len;
++		if (msg)
++			memcpy(event->usr.msg, msg, len);
++
++		spin_lock_irqsave(&cec_dev->lock, flags);
++		list_add_tail(&event->node, &cec_dev->events);
++		spin_unlock_irqrestore(&cec_dev->lock, flags);
++		wake_up(&cec_dev->waitq);
++	}
++}
++EXPORT_SYMBOL_GPL(cec_dev_event);
++
++static int cec_dev_lock_write(struct cec_dev *cec_dev, struct file *file)
++	__acquires(cec_dev->mutex)
++{
++	int ret;
++
++	do {
++		if (file->f_flags & O_NONBLOCK) {
++			if (cec_dev->write_busy)
++				return -EAGAIN;
++		} else {
++			ret = wait_event_interruptible(cec_dev->waitq,
++						       !cec_dev->write_busy);
++			if (ret)
++				break;
++		}
++
++		ret = mutex_lock_interruptible(&cec_dev->mutex);
++		if (ret)
++			break;
++
++		if (!cec_dev->write_busy)
++			break;
++
++		mutex_unlock(&cec_dev->mutex);
++	} while (1);
++
++	return ret;
++}
++
++static ssize_t cec_dev_read(struct file *file, char __user *buf,
++	size_t count, loff_t *ppos)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	ssize_t ret;
++
++	if (count > sizeof(struct cec_user_event))
++		count = sizeof(struct cec_user_event);
++
++	if (!access_ok(VERIFY_WRITE, buf, count))
++		return -EFAULT;
++
++	do {
++		struct cec_event *event = NULL;
++		unsigned long flags;
++
++		spin_lock_irqsave(&cec_dev->lock, flags);
++		if (!list_empty(&cec_dev->events)) {
++			event = list_first_entry(&cec_dev->events,
++					struct cec_event, node);
++			list_del(&event->node);
++		}
++		spin_unlock_irqrestore(&cec_dev->lock, flags);
++
++		if (event) {
++			ret = __copy_to_user(buf, &event->usr, count) ?
++				 -EFAULT : count;
++			kfree(event);
++			break;
++		}
++
++		if (file->f_flags & O_NONBLOCK) {
++			ret = -EAGAIN;
++			break;
++		}
++
++		ret = wait_event_interruptible(cec_dev->waitq,
++					       !list_empty(&cec_dev->events));
++		if (ret)
++			break;
++	} while (1);
++
++	return ret;
++}
++
++static ssize_t cec_dev_write(struct file *file, const char __user *buf,
++	size_t count, loff_t *ppos)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	u8 msg[MAX_MESSAGE_LEN];
++	int ret;
++
++	if (count > sizeof(msg))
++		return -E2BIG;
++
++	if (copy_from_user(msg, buf, count))
++		return -EFAULT;
++
++	ret = cec_dev_lock_write(cec_dev, file);
++	if (ret)
++		return ret;
++
++	cec_dev_send_message(cec_dev, msg, count);
++
++	mutex_unlock(&cec_dev->mutex);
++
++	return count;
++}
++
++static long cec_dev_ioctl(struct file *file, u_int cmd, unsigned long arg)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	int ret;
++
++	switch (cmd) {
++	case HDMICEC_IOC_O_SETLOGICALADDRESS:
++	case HDMICEC_IOC_SETLOGICALADDRESS:
++		if (arg > 15) {
++			ret = -EINVAL;
++			break;
++		}
++
++		ret = cec_dev_lock_write(cec_dev, file);
++		if (ret == 0) {
++			unsigned char msg[1];
++
++			cec_dev->addresses = BIT(arg);
++			cec_dev->set_address(cec_dev, cec_dev->addresses);
++
++			/*
++			 * Send a ping message with the source and destination
++			 * set to our address; the result indicates whether
++			 * unit has chosen our address simultaneously.
++			 */
++			msg[0] = arg << 4 | arg;
++			cec_dev_send_message(cec_dev, msg, sizeof(msg));
++			mutex_unlock(&cec_dev->mutex);
++		}
++		break;
++
++	case HDMICEC_IOC_STARTDEVICE:
++		ret = mutex_lock_interruptible(&cec_dev->mutex);
++		if (ret == 0) {
++			cec_dev->addresses = BIT(15);
++			cec_dev->set_address(cec_dev, cec_dev->addresses);
++			mutex_unlock(&cec_dev->mutex);
++		}
++		break;
++
++	case HDMICEC_IOC_STOPDEVICE:
++		ret = 0;
++		break;
++
++	case HDMICEC_IOC_GETPHYADDRESS:
++		ret = put_user(cec_dev->physical, (u16 __user *)arg);
++		ret = -ENOIOCTLCMD;
++		break;
++
++	default:
++		ret = -ENOIOCTLCMD;
++		break;
++	}
++
++	return ret;
++}
++
++static unsigned cec_dev_poll(struct file *file, poll_table *wait)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	unsigned mask = 0;
++
++	poll_wait(file, &cec_dev->waitq, wait);
++
++	if (cec_dev->write_busy == 0)
++		mask |= POLLOUT | POLLWRNORM;
++	if (!list_empty(&cec_dev->events))
++		mask |= POLLIN | POLLRDNORM;
++
++	return mask;
++}
++
++static int cec_dev_release(struct inode *inode, struct file *file)
++{
++	struct cec_dev *cec_dev = file->private_data;
++
++	mutex_lock(&cec_dev->mutex);
++	if (cec_dev->users >= 1)
++		cec_dev->users -= 1;
++	if (cec_dev->users == 0) {
++		/*
++		 * Wait for any write to complete before shutting down.
++		 * A message should complete in a maximum of 2.75ms *
++		 * 160 bits + 4.7ms, or 444.7ms.  Let's call that 500ms.
++		 * If we time out, shutdown anyway.
++		 */
++		wait_event_timeout(cec_dev->waitq, !cec_dev->write_busy,
++				   msecs_to_jiffies(500));
++
++		cec_dev->release(cec_dev);
++
++		while (!list_empty(&cec_dev->events)) {
++			struct cec_event *event;
++
++			event = list_first_entry(&cec_dev->events,
++					struct cec_event, node);
++			list_del(&event->node);
++			kfree(event);
++		}
++	}
++	mutex_unlock(&cec_dev->mutex);
++	return 0;
++}
++
++static int cec_dev_open(struct inode *inode, struct file *file)
++{
++	struct cec_dev *cec_dev = container_of(inode->i_cdev, struct cec_dev,
++					       cdev);
++	int ret = 0;
++
++	nonseekable_open(inode, file);
++
++	file->private_data = cec_dev;
++
++	ret = mutex_lock_interruptible(&cec_dev->mutex);
++	if (ret)
++		return ret;
++
++	if (cec_dev->users++ == 0) {
++		cec_dev->addresses = BIT(15);
++
++		ret = cec_dev->open(cec_dev);
++		if (ret < 0)
++			cec_dev->users = 0;
++	}
++	mutex_unlock(&cec_dev->mutex);
++
++	return ret;
++}
++
++static const struct file_operations hdmi_cec_fops = {
++	.owner = THIS_MODULE,
++	.read = cec_dev_read,
++	.write = cec_dev_write,
++	.open = cec_dev_open,
++	.unlocked_ioctl = cec_dev_ioctl,
++	.release = cec_dev_release,
++	.poll = cec_dev_poll,
++};
++
++void cec_dev_init(struct cec_dev *cec_dev, struct module *module)
++{
++	cec_dev->devn = MKDEV(cec_major, 0);
++
++	INIT_LIST_HEAD(&cec_dev->events);
++	init_waitqueue_head(&cec_dev->waitq);
++	spin_lock_init(&cec_dev->lock);
++	mutex_init(&cec_dev->mutex);
++
++	cec_dev->addresses = BIT(15);
++
++	cdev_init(&cec_dev->cdev, &hdmi_cec_fops);
++	cec_dev->cdev.owner = module;
++}
++EXPORT_SYMBOL_GPL(cec_dev_init);
++
++int cec_dev_add(struct cec_dev *cec_dev, struct device *dev, const char *name)
++{
++	struct device *cd;
++	int ret;
++
++	ret = cdev_add(&cec_dev->cdev, cec_dev->devn, 1);
++	if (ret < 0)
++		goto err_cdev;
++
++	cd = device_create(cec_class, dev, cec_dev->devn, NULL, name);
++	if (IS_ERR(cd)) {
++		ret = PTR_ERR(cd);
++		dev_err(dev, "can't create device: %d\n", ret);
++		goto err_dev;
++	}
++
++	return 0;
++
++ err_dev:
++	cdev_del(&cec_dev->cdev);
++ err_cdev:
++	return ret;
++}
++EXPORT_SYMBOL_GPL(cec_dev_add);
++
++void cec_dev_remove(struct cec_dev *cec_dev)
++{
++	device_destroy(cec_class, cec_dev->devn);
++	cdev_del(&cec_dev->cdev);
++}
++EXPORT_SYMBOL_GPL(cec_dev_remove);
++
++static int cec_init(void)
++{
++	dev_t dev;
++	int ret;
++
++	cec_class = class_create(THIS_MODULE, "hdmi-cec");
++	if (IS_ERR(cec_class)) {
++		ret = PTR_ERR(cec_class);
++		pr_err("cec: can't create cec class: %d\n", ret);
++		goto err_class;
++	}
++
++	ret = alloc_chrdev_region(&dev, 0, 1, "hdmi-cec");
++	if (ret) {
++		pr_err("cec: can't create character devices: %d\n", ret);
++		goto err_chrdev;
++	}
++
++	cec_major = MAJOR(dev);
++
++	return 0;
++
++ err_chrdev:
++	class_destroy(cec_class);
++ err_class:
++	return ret;
++}
++subsys_initcall(cec_init);
++
++static void cec_exit(void)
++{
++	unregister_chrdev_region(MKDEV(cec_major, 0), 1);
++	class_destroy(cec_class);
++}
++module_exit(cec_exit);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_DESCRIPTION("Generic HDMI CEC driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.16.6.orig/drivers/cec/Kconfig linux-3.16.6/drivers/cec/Kconfig
+--- linux-3.16.6.orig/drivers/cec/Kconfig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/cec/Kconfig	2014-10-23 12:37:18.350220009 -0500
+@@ -0,0 +1,14 @@
++#
++# Consumer Electroncs Control support
++#
++
++menu "Consumer Electronics Control devices"
++
++config CEC
++	bool
++
++config HDMI_CEC_CORE
++	tristate
++	select CEC
++
++endmenu
+diff -Nur linux-3.16.6.orig/drivers/cec/Makefile linux-3.16.6/drivers/cec/Makefile
+--- linux-3.16.6.orig/drivers/cec/Makefile	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/cec/Makefile	2014-10-23 12:37:18.374219998 -0500
+@@ -0,0 +1 @@
++obj-$(CONFIG_HDMI_CEC_CORE) += cec-dev.o
+diff -Nur linux-3.16.6.orig/drivers/dma/imx-sdma.c linux-3.16.6/drivers/dma/imx-sdma.c
+--- linux-3.16.6.orig/drivers/dma/imx-sdma.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/dma/imx-sdma.c	2014-10-23 12:35:52.990220019 -0500
+@@ -255,7 +255,6 @@
+ 	enum dma_slave_buswidth		word_size;
+ 	unsigned int			buf_tail;
+ 	unsigned int			num_bd;
+-	unsigned int			period_len;
+ 	struct sdma_buffer_descriptor	*bd;
+ 	dma_addr_t			bd_phys;
+ 	unsigned int			pc_from_device, pc_to_device;
+@@ -594,12 +593,6 @@
+ 
+ static void sdma_handle_channel_loop(struct sdma_channel *sdmac)
+ {
+-	if (sdmac->desc.callback)
+-		sdmac->desc.callback(sdmac->desc.callback_param);
+-}
+-
+-static void sdma_update_channel_loop(struct sdma_channel *sdmac)
+-{
+ 	struct sdma_buffer_descriptor *bd;
+ 
+ 	/*
+@@ -618,6 +611,9 @@
+ 		bd->mode.status |= BD_DONE;
+ 		sdmac->buf_tail++;
+ 		sdmac->buf_tail %= sdmac->num_bd;
++
++		if (sdmac->desc.callback)
++			sdmac->desc.callback(sdmac->desc.callback_param);
+ 	}
+ }
+ 
+@@ -673,9 +669,6 @@
+ 		int channel = fls(stat) - 1;
+ 		struct sdma_channel *sdmac = &sdma->channel[channel];
+ 
+-		if (sdmac->flags & IMX_DMA_SG_LOOP)
+-			sdma_update_channel_loop(sdmac);
+-
+ 		tasklet_schedule(&sdmac->tasklet);
+ 
+ 		__clear_bit(channel, &stat);
+@@ -1136,7 +1129,6 @@
+ 	sdmac->status = DMA_IN_PROGRESS;
+ 
+ 	sdmac->buf_tail = 0;
+-	sdmac->period_len = period_len;
+ 
+ 	sdmac->flags |= IMX_DMA_SG_LOOP;
+ 	sdmac->direction = direction;
+@@ -1233,15 +1225,9 @@
+ 				      struct dma_tx_state *txstate)
+ {
+ 	struct sdma_channel *sdmac = to_sdma_chan(chan);
+-	u32 residue;
+-
+-	if (sdmac->flags & IMX_DMA_SG_LOOP)
+-		residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len;
+-	else
+-		residue = sdmac->chn_count - sdmac->chn_real_count;
+ 
+ 	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
+-			 residue);
++			sdmac->chn_count - sdmac->chn_real_count);
+ 
+ 	return sdmac->status;
+ }
+diff -Nur linux-3.16.6.orig/drivers/dma/imx-sdma.c.orig linux-3.16.6/drivers/dma/imx-sdma.c.orig
+--- linux-3.16.6.orig/drivers/dma/imx-sdma.c.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/dma/imx-sdma.c.orig	2014-10-15 05:05:43.000000000 -0500
+@@ -0,0 +1,1656 @@
++/*
++ * drivers/dma/imx-sdma.c
++ *
++ * This file contains a driver for the Freescale Smart DMA engine
++ *
++ * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
++ *
++ * Based on code from Freescale:
++ *
++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
++ *
++ * 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 <linux/init.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/bitops.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/semaphore.h>
++#include <linux/spinlock.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/firmware.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/dmaengine.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_dma.h>
++
++#include <asm/irq.h>
++#include <linux/platform_data/dma-imx-sdma.h>
++#include <linux/platform_data/dma-imx.h>
++
++#include "dmaengine.h"
++
++/* SDMA registers */
++#define SDMA_H_C0PTR		0x000
++#define SDMA_H_INTR		0x004
++#define SDMA_H_STATSTOP		0x008
++#define SDMA_H_START		0x00c
++#define SDMA_H_EVTOVR		0x010
++#define SDMA_H_DSPOVR		0x014
++#define SDMA_H_HOSTOVR		0x018
++#define SDMA_H_EVTPEND		0x01c
++#define SDMA_H_DSPENBL		0x020
++#define SDMA_H_RESET		0x024
++#define SDMA_H_EVTERR		0x028
++#define SDMA_H_INTRMSK		0x02c
++#define SDMA_H_PSW		0x030
++#define SDMA_H_EVTERRDBG	0x034
++#define SDMA_H_CONFIG		0x038
++#define SDMA_ONCE_ENB		0x040
++#define SDMA_ONCE_DATA		0x044
++#define SDMA_ONCE_INSTR		0x048
++#define SDMA_ONCE_STAT		0x04c
++#define SDMA_ONCE_CMD		0x050
++#define SDMA_EVT_MIRROR		0x054
++#define SDMA_ILLINSTADDR	0x058
++#define SDMA_CHN0ADDR		0x05c
++#define SDMA_ONCE_RTB		0x060
++#define SDMA_XTRIG_CONF1	0x070
++#define SDMA_XTRIG_CONF2	0x074
++#define SDMA_CHNENBL0_IMX35	0x200
++#define SDMA_CHNENBL0_IMX31	0x080
++#define SDMA_CHNPRI_0		0x100
++
++/*
++ * Buffer descriptor status values.
++ */
++#define BD_DONE  0x01
++#define BD_WRAP  0x02
++#define BD_CONT  0x04
++#define BD_INTR  0x08
++#define BD_RROR  0x10
++#define BD_LAST  0x20
++#define BD_EXTD  0x80
++
++/*
++ * Data Node descriptor status values.
++ */
++#define DND_END_OF_FRAME  0x80
++#define DND_END_OF_XFER   0x40
++#define DND_DONE          0x20
++#define DND_UNUSED        0x01
++
++/*
++ * IPCV2 descriptor status values.
++ */
++#define BD_IPCV2_END_OF_FRAME  0x40
++
++#define IPCV2_MAX_NODES        50
++/*
++ * Error bit set in the CCB status field by the SDMA,
++ * in setbd routine, in case of a transfer error
++ */
++#define DATA_ERROR  0x10000000
++
++/*
++ * Buffer descriptor commands.
++ */
++#define C0_ADDR             0x01
++#define C0_LOAD             0x02
++#define C0_DUMP             0x03
++#define C0_SETCTX           0x07
++#define C0_GETCTX           0x03
++#define C0_SETDM            0x01
++#define C0_SETPM            0x04
++#define C0_GETDM            0x02
++#define C0_GETPM            0x08
++/*
++ * Change endianness indicator in the BD command field
++ */
++#define CHANGE_ENDIANNESS   0x80
++
++/*
++ * Mode/Count of data node descriptors - IPCv2
++ */
++struct sdma_mode_count {
++	u32 count   : 16; /* size of the buffer pointed by this BD */
++	u32 status  :  8; /* E,R,I,C,W,D status bits stored here */
++	u32 command :  8; /* command mostlky used for channel 0 */
++};
++
++/*
++ * Buffer descriptor
++ */
++struct sdma_buffer_descriptor {
++	struct sdma_mode_count  mode;
++	u32 buffer_addr;	/* address of the buffer described */
++	u32 ext_buffer_addr;	/* extended buffer address */
++} __attribute__ ((packed));
++
++/**
++ * struct sdma_channel_control - Channel control Block
++ *
++ * @current_bd_ptr	current buffer descriptor processed
++ * @base_bd_ptr		first element of buffer descriptor array
++ * @unused		padding. The SDMA engine expects an array of 128 byte
++ *			control blocks
++ */
++struct sdma_channel_control {
++	u32 current_bd_ptr;
++	u32 base_bd_ptr;
++	u32 unused[2];
++} __attribute__ ((packed));
++
++/**
++ * struct sdma_state_registers - SDMA context for a channel
++ *
++ * @pc:		program counter
++ * @t:		test bit: status of arithmetic & test instruction
++ * @rpc:	return program counter
++ * @sf:		source fault while loading data
++ * @spc:	loop start program counter
++ * @df:		destination fault while storing data
++ * @epc:	loop end program counter
++ * @lm:		loop mode
++ */
++struct sdma_state_registers {
++	u32 pc     :14;
++	u32 unused1: 1;
++	u32 t      : 1;
++	u32 rpc    :14;
++	u32 unused0: 1;
++	u32 sf     : 1;
++	u32 spc    :14;
++	u32 unused2: 1;
++	u32 df     : 1;
++	u32 epc    :14;
++	u32 lm     : 2;
++} __attribute__ ((packed));
++
++/**
++ * struct sdma_context_data - sdma context specific to a channel
++ *
++ * @channel_state:	channel state bits
++ * @gReg:		general registers
++ * @mda:		burst dma destination address register
++ * @msa:		burst dma source address register
++ * @ms:			burst dma status register
++ * @md:			burst dma data register
++ * @pda:		peripheral dma destination address register
++ * @psa:		peripheral dma source address register
++ * @ps:			peripheral dma status register
++ * @pd:			peripheral dma data register
++ * @ca:			CRC polynomial register
++ * @cs:			CRC accumulator register
++ * @dda:		dedicated core destination address register
++ * @dsa:		dedicated core source address register
++ * @ds:			dedicated core status register
++ * @dd:			dedicated core data register
++ */
++struct sdma_context_data {
++	struct sdma_state_registers  channel_state;
++	u32  gReg[8];
++	u32  mda;
++	u32  msa;
++	u32  ms;
++	u32  md;
++	u32  pda;
++	u32  psa;
++	u32  ps;
++	u32  pd;
++	u32  ca;
++	u32  cs;
++	u32  dda;
++	u32  dsa;
++	u32  ds;
++	u32  dd;
++	u32  scratch0;
++	u32  scratch1;
++	u32  scratch2;
++	u32  scratch3;
++	u32  scratch4;
++	u32  scratch5;
++	u32  scratch6;
++	u32  scratch7;
++} __attribute__ ((packed));
++
++#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
++
++struct sdma_engine;
++
++/**
++ * struct sdma_channel - housekeeping for a SDMA channel
++ *
++ * @sdma		pointer to the SDMA engine for this channel
++ * @channel		the channel number, matches dmaengine chan_id + 1
++ * @direction		transfer type. Needed for setting SDMA script
++ * @peripheral_type	Peripheral type. Needed for setting SDMA script
++ * @event_id0		aka dma request line
++ * @event_id1		for channels that use 2 events
++ * @word_size		peripheral access size
++ * @buf_tail		ID of the buffer that was processed
++ * @num_bd		max NUM_BD. number of descriptors currently handling
++ */
++struct sdma_channel {
++	struct sdma_engine		*sdma;
++	unsigned int			channel;
++	enum dma_transfer_direction		direction;
++	enum sdma_peripheral_type	peripheral_type;
++	unsigned int			event_id0;
++	unsigned int			event_id1;
++	enum dma_slave_buswidth		word_size;
++	unsigned int			buf_tail;
++	unsigned int			num_bd;
++	unsigned int			period_len;
++	struct sdma_buffer_descriptor	*bd;
++	dma_addr_t			bd_phys;
++	unsigned int			pc_from_device, pc_to_device;
++	unsigned long			flags;
++	dma_addr_t			per_address;
++	unsigned long			event_mask[2];
++	unsigned long			watermark_level;
++	u32				shp_addr, per_addr;
++	struct dma_chan			chan;
++	spinlock_t			lock;
++	struct dma_async_tx_descriptor	desc;
++	enum dma_status			status;
++	unsigned int			chn_count;
++	unsigned int			chn_real_count;
++	struct tasklet_struct		tasklet;
++};
++
++#define IMX_DMA_SG_LOOP		BIT(0)
++
++#define MAX_DMA_CHANNELS 32
++#define MXC_SDMA_DEFAULT_PRIORITY 1
++#define MXC_SDMA_MIN_PRIORITY 1
++#define MXC_SDMA_MAX_PRIORITY 7
++
++#define SDMA_FIRMWARE_MAGIC 0x414d4453
++
++/**
++ * struct sdma_firmware_header - Layout of the firmware image
++ *
++ * @magic		"SDMA"
++ * @version_major	increased whenever layout of struct sdma_script_start_addrs
++ *			changes.
++ * @version_minor	firmware minor version (for binary compatible changes)
++ * @script_addrs_start	offset of struct sdma_script_start_addrs in this image
++ * @num_script_addrs	Number of script addresses in this image
++ * @ram_code_start	offset of SDMA ram image in this firmware image
++ * @ram_code_size	size of SDMA ram image
++ * @script_addrs	Stores the start address of the SDMA scripts
++ *			(in SDMA memory space)
++ */
++struct sdma_firmware_header {
++	u32	magic;
++	u32	version_major;
++	u32	version_minor;
++	u32	script_addrs_start;
++	u32	num_script_addrs;
++	u32	ram_code_start;
++	u32	ram_code_size;
++};
++
++struct sdma_driver_data {
++	int chnenbl0;
++	int num_events;
++	struct sdma_script_start_addrs	*script_addrs;
++};
++
++struct sdma_engine {
++	struct device			*dev;
++	struct device_dma_parameters	dma_parms;
++	struct sdma_channel		channel[MAX_DMA_CHANNELS];
++	struct sdma_channel_control	*channel_control;
++	void __iomem			*regs;
++	struct sdma_context_data	*context;
++	dma_addr_t			context_phys;
++	struct dma_device		dma_device;
++	struct clk			*clk_ipg;
++	struct clk			*clk_ahb;
++	spinlock_t			channel_0_lock;
++	u32				script_number;
++	struct sdma_script_start_addrs	*script_addrs;
++	const struct sdma_driver_data	*drvdata;
++};
++
++static struct sdma_driver_data sdma_imx31 = {
++	.chnenbl0 = SDMA_CHNENBL0_IMX31,
++	.num_events = 32,
++};
++
++static struct sdma_script_start_addrs sdma_script_imx25 = {
++	.ap_2_ap_addr = 729,
++	.uart_2_mcu_addr = 904,
++	.per_2_app_addr = 1255,
++	.mcu_2_app_addr = 834,
++	.uartsh_2_mcu_addr = 1120,
++	.per_2_shp_addr = 1329,
++	.mcu_2_shp_addr = 1048,
++	.ata_2_mcu_addr = 1560,
++	.mcu_2_ata_addr = 1479,
++	.app_2_per_addr = 1189,
++	.app_2_mcu_addr = 770,
++	.shp_2_per_addr = 1407,
++	.shp_2_mcu_addr = 979,
++};
++
++static struct sdma_driver_data sdma_imx25 = {
++	.chnenbl0 = SDMA_CHNENBL0_IMX35,
++	.num_events = 48,
++	.script_addrs = &sdma_script_imx25,
++};
++
++static struct sdma_driver_data sdma_imx35 = {
++	.chnenbl0 = SDMA_CHNENBL0_IMX35,
++	.num_events = 48,
++};
++
++static struct sdma_script_start_addrs sdma_script_imx51 = {
++	.ap_2_ap_addr = 642,
++	.uart_2_mcu_addr = 817,
++	.mcu_2_app_addr = 747,
++	.mcu_2_shp_addr = 961,
++	.ata_2_mcu_addr = 1473,
++	.mcu_2_ata_addr = 1392,
++	.app_2_per_addr = 1033,
++	.app_2_mcu_addr = 683,
++	.shp_2_per_addr = 1251,
++	.shp_2_mcu_addr = 892,
++};
++
++static struct sdma_driver_data sdma_imx51 = {
++	.chnenbl0 = SDMA_CHNENBL0_IMX35,
++	.num_events = 48,
++	.script_addrs = &sdma_script_imx51,
++};
++
++static struct sdma_script_start_addrs sdma_script_imx53 = {
++	.ap_2_ap_addr = 642,
++	.app_2_mcu_addr = 683,
++	.mcu_2_app_addr = 747,
++	.uart_2_mcu_addr = 817,
++	.shp_2_mcu_addr = 891,
++	.mcu_2_shp_addr = 960,
++	.uartsh_2_mcu_addr = 1032,
++	.spdif_2_mcu_addr = 1100,
++	.mcu_2_spdif_addr = 1134,
++	.firi_2_mcu_addr = 1193,
++	.mcu_2_firi_addr = 1290,
++};
++
++static struct sdma_driver_data sdma_imx53 = {
++	.chnenbl0 = SDMA_CHNENBL0_IMX35,
++	.num_events = 48,
++	.script_addrs = &sdma_script_imx53,
++};
++
++static struct sdma_script_start_addrs sdma_script_imx6q = {
++	.ap_2_ap_addr = 642,
++	.uart_2_mcu_addr = 817,
++	.mcu_2_app_addr = 747,
++	.per_2_per_addr = 6331,
++	.uartsh_2_mcu_addr = 1032,
++	.mcu_2_shp_addr = 960,
++	.app_2_mcu_addr = 683,
++	.shp_2_mcu_addr = 891,
++	.spdif_2_mcu_addr = 1100,
++	.mcu_2_spdif_addr = 1134,
++};
++
++static struct sdma_driver_data sdma_imx6q = {
++	.chnenbl0 = SDMA_CHNENBL0_IMX35,
++	.num_events = 48,
++	.script_addrs = &sdma_script_imx6q,
++};
++
++static struct platform_device_id sdma_devtypes[] = {
++	{
++		.name = "imx25-sdma",
++		.driver_data = (unsigned long)&sdma_imx25,
++	}, {
++		.name = "imx31-sdma",
++		.driver_data = (unsigned long)&sdma_imx31,
++	}, {
++		.name = "imx35-sdma",
++		.driver_data = (unsigned long)&sdma_imx35,
++	}, {
++		.name = "imx51-sdma",
++		.driver_data = (unsigned long)&sdma_imx51,
++	}, {
++		.name = "imx53-sdma",
++		.driver_data = (unsigned long)&sdma_imx53,
++	}, {
++		.name = "imx6q-sdma",
++		.driver_data = (unsigned long)&sdma_imx6q,
++	}, {
++		/* sentinel */
++	}
++};
++MODULE_DEVICE_TABLE(platform, sdma_devtypes);
++
++static const struct of_device_id sdma_dt_ids[] = {
++	{ .compatible = "fsl,imx6q-sdma", .data = &sdma_imx6q, },
++	{ .compatible = "fsl,imx53-sdma", .data = &sdma_imx53, },
++	{ .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, },
++	{ .compatible = "fsl,imx35-sdma", .data = &sdma_imx35, },
++	{ .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, },
++	{ .compatible = "fsl,imx25-sdma", .data = &sdma_imx25, },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, sdma_dt_ids);
++
++#define SDMA_H_CONFIG_DSPDMA	BIT(12) /* indicates if the DSPDMA is used */
++#define SDMA_H_CONFIG_RTD_PINS	BIT(11) /* indicates if Real-Time Debug pins are enabled */
++#define SDMA_H_CONFIG_ACR	BIT(4)  /* indicates if AHB freq /core freq = 2 or 1 */
++#define SDMA_H_CONFIG_CSM	(3)       /* indicates which context switch mode is selected*/
++
++static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
++{
++	u32 chnenbl0 = sdma->drvdata->chnenbl0;
++	return chnenbl0 + event * 4;
++}
++
++static int sdma_config_ownership(struct sdma_channel *sdmac,
++		bool event_override, bool mcu_override, bool dsp_override)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++	unsigned long evt, mcu, dsp;
++
++	if (event_override && mcu_override && dsp_override)
++		return -EINVAL;
++
++	evt = readl_relaxed(sdma->regs + SDMA_H_EVTOVR);
++	mcu = readl_relaxed(sdma->regs + SDMA_H_HOSTOVR);
++	dsp = readl_relaxed(sdma->regs + SDMA_H_DSPOVR);
++
++	if (dsp_override)
++		__clear_bit(channel, &dsp);
++	else
++		__set_bit(channel, &dsp);
++
++	if (event_override)
++		__clear_bit(channel, &evt);
++	else
++		__set_bit(channel, &evt);
++
++	if (mcu_override)
++		__clear_bit(channel, &mcu);
++	else
++		__set_bit(channel, &mcu);
++
++	writel_relaxed(evt, sdma->regs + SDMA_H_EVTOVR);
++	writel_relaxed(mcu, sdma->regs + SDMA_H_HOSTOVR);
++	writel_relaxed(dsp, sdma->regs + SDMA_H_DSPOVR);
++
++	return 0;
++}
++
++static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
++{
++	writel(BIT(channel), sdma->regs + SDMA_H_START);
++}
++
++/*
++ * sdma_run_channel0 - run a channel and wait till it's done
++ */
++static int sdma_run_channel0(struct sdma_engine *sdma)
++{
++	int ret;
++	unsigned long timeout = 500;
++
++	sdma_enable_channel(sdma, 0);
++
++	while (!(ret = readl_relaxed(sdma->regs + SDMA_H_INTR) & 1)) {
++		if (timeout-- <= 0)
++			break;
++		udelay(1);
++	}
++
++	if (ret) {
++		/* Clear the interrupt status */
++		writel_relaxed(ret, sdma->regs + SDMA_H_INTR);
++	} else {
++		dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
++	}
++
++	return ret ? 0 : -ETIMEDOUT;
++}
++
++static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
++		u32 address)
++{
++	struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
++	void *buf_virt;
++	dma_addr_t buf_phys;
++	int ret;
++	unsigned long flags;
++
++	buf_virt = dma_alloc_coherent(NULL,
++			size,
++			&buf_phys, GFP_KERNEL);
++	if (!buf_virt) {
++		return -ENOMEM;
++	}
++
++	spin_lock_irqsave(&sdma->channel_0_lock, flags);
++
++	bd0->mode.command = C0_SETPM;
++	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
++	bd0->mode.count = size / 2;
++	bd0->buffer_addr = buf_phys;
++	bd0->ext_buffer_addr = address;
++
++	memcpy(buf_virt, buf, size);
++
++	ret = sdma_run_channel0(sdma);
++
++	spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
++
++	dma_free_coherent(NULL, size, buf_virt, buf_phys);
++
++	return ret;
++}
++
++static void sdma_event_enable(struct sdma_channel *sdmac, unsigned int event)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++	unsigned long val;
++	u32 chnenbl = chnenbl_ofs(sdma, event);
++
++	val = readl_relaxed(sdma->regs + chnenbl);
++	__set_bit(channel, &val);
++	writel_relaxed(val, sdma->regs + chnenbl);
++}
++
++static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++	u32 chnenbl = chnenbl_ofs(sdma, event);
++	unsigned long val;
++
++	val = readl_relaxed(sdma->regs + chnenbl);
++	__clear_bit(channel, &val);
++	writel_relaxed(val, sdma->regs + chnenbl);
++}
++
++static void sdma_handle_channel_loop(struct sdma_channel *sdmac)
++{
++	if (sdmac->desc.callback)
++		sdmac->desc.callback(sdmac->desc.callback_param);
++}
++
++static void sdma_update_channel_loop(struct sdma_channel *sdmac)
++{
++	struct sdma_buffer_descriptor *bd;
++
++	/*
++	 * loop mode. Iterate over descriptors, re-setup them and
++	 * call callback function.
++	 */
++	while (1) {
++		bd = &sdmac->bd[sdmac->buf_tail];
++
++		if (bd->mode.status & BD_DONE)
++			break;
++
++		if (bd->mode.status & BD_RROR)
++			sdmac->status = DMA_ERROR;
++
++		bd->mode.status |= BD_DONE;
++		sdmac->buf_tail++;
++		sdmac->buf_tail %= sdmac->num_bd;
++	}
++}
++
++static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
++{
++	struct sdma_buffer_descriptor *bd;
++	int i, error = 0;
++
++	sdmac->chn_real_count = 0;
++	/*
++	 * non loop mode. Iterate over all descriptors, collect
++	 * errors and call callback function
++	 */
++	for (i = 0; i < sdmac->num_bd; i++) {
++		bd = &sdmac->bd[i];
++
++		 if (bd->mode.status & (BD_DONE | BD_RROR))
++			error = -EIO;
++		 sdmac->chn_real_count += bd->mode.count;
++	}
++
++	if (error)
++		sdmac->status = DMA_ERROR;
++	else
++		sdmac->status = DMA_COMPLETE;
++
++	dma_cookie_complete(&sdmac->desc);
++	if (sdmac->desc.callback)
++		sdmac->desc.callback(sdmac->desc.callback_param);
++}
++
++static void sdma_tasklet(unsigned long data)
++{
++	struct sdma_channel *sdmac = (struct sdma_channel *) data;
++
++	if (sdmac->flags & IMX_DMA_SG_LOOP)
++		sdma_handle_channel_loop(sdmac);
++	else
++		mxc_sdma_handle_channel_normal(sdmac);
++}
++
++static irqreturn_t sdma_int_handler(int irq, void *dev_id)
++{
++	struct sdma_engine *sdma = dev_id;
++	unsigned long stat;
++
++	stat = readl_relaxed(sdma->regs + SDMA_H_INTR);
++	/* not interested in channel 0 interrupts */
++	stat &= ~1;
++	writel_relaxed(stat, sdma->regs + SDMA_H_INTR);
++
++	while (stat) {
++		int channel = fls(stat) - 1;
++		struct sdma_channel *sdmac = &sdma->channel[channel];
++
++		if (sdmac->flags & IMX_DMA_SG_LOOP)
++			sdma_update_channel_loop(sdmac);
++
++		tasklet_schedule(&sdmac->tasklet);
++
++		__clear_bit(channel, &stat);
++	}
++
++	return IRQ_HANDLED;
++}
++
++/*
++ * sets the pc of SDMA script according to the peripheral type
++ */
++static void sdma_get_pc(struct sdma_channel *sdmac,
++		enum sdma_peripheral_type peripheral_type)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int per_2_emi = 0, emi_2_per = 0;
++	/*
++	 * These are needed once we start to support transfers between
++	 * two peripherals or memory-to-memory transfers
++	 */
++	int per_2_per = 0, emi_2_emi = 0;
++
++	sdmac->pc_from_device = 0;
++	sdmac->pc_to_device = 0;
++
++	switch (peripheral_type) {
++	case IMX_DMATYPE_MEMORY:
++		emi_2_emi = sdma->script_addrs->ap_2_ap_addr;
++		break;
++	case IMX_DMATYPE_DSP:
++		emi_2_per = sdma->script_addrs->bp_2_ap_addr;
++		per_2_emi = sdma->script_addrs->ap_2_bp_addr;
++		break;
++	case IMX_DMATYPE_FIRI:
++		per_2_emi = sdma->script_addrs->firi_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_firi_addr;
++		break;
++	case IMX_DMATYPE_UART:
++		per_2_emi = sdma->script_addrs->uart_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_app_addr;
++		break;
++	case IMX_DMATYPE_UART_SP:
++		per_2_emi = sdma->script_addrs->uartsh_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_shp_addr;
++		break;
++	case IMX_DMATYPE_ATA:
++		per_2_emi = sdma->script_addrs->ata_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_ata_addr;
++		break;
++	case IMX_DMATYPE_CSPI:
++	case IMX_DMATYPE_EXT:
++	case IMX_DMATYPE_SSI:
++		per_2_emi = sdma->script_addrs->app_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_app_addr;
++		break;
++	case IMX_DMATYPE_SSI_DUAL:
++		per_2_emi = sdma->script_addrs->ssish_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_ssish_addr;
++		break;
++	case IMX_DMATYPE_SSI_SP:
++	case IMX_DMATYPE_MMC:
++	case IMX_DMATYPE_SDHC:
++	case IMX_DMATYPE_CSPI_SP:
++	case IMX_DMATYPE_ESAI:
++	case IMX_DMATYPE_MSHC_SP:
++		per_2_emi = sdma->script_addrs->shp_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_shp_addr;
++		break;
++	case IMX_DMATYPE_ASRC:
++		per_2_emi = sdma->script_addrs->asrc_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->asrc_2_mcu_addr;
++		per_2_per = sdma->script_addrs->per_2_per_addr;
++		break;
++	case IMX_DMATYPE_MSHC:
++		per_2_emi = sdma->script_addrs->mshc_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_mshc_addr;
++		break;
++	case IMX_DMATYPE_CCM:
++		per_2_emi = sdma->script_addrs->dptc_dvfs_addr;
++		break;
++	case IMX_DMATYPE_SPDIF:
++		per_2_emi = sdma->script_addrs->spdif_2_mcu_addr;
++		emi_2_per = sdma->script_addrs->mcu_2_spdif_addr;
++		break;
++	case IMX_DMATYPE_IPU_MEMORY:
++		emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr;
++		break;
++	default:
++		break;
++	}
++
++	sdmac->pc_from_device = per_2_emi;
++	sdmac->pc_to_device = emi_2_per;
++}
++
++static int sdma_load_context(struct sdma_channel *sdmac)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++	int load_address;
++	struct sdma_context_data *context = sdma->context;
++	struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
++	int ret;
++	unsigned long flags;
++
++	if (sdmac->direction == DMA_DEV_TO_MEM) {
++		load_address = sdmac->pc_from_device;
++	} else {
++		load_address = sdmac->pc_to_device;
++	}
++
++	if (load_address < 0)
++		return load_address;
++
++	dev_dbg(sdma->dev, "load_address = %d\n", load_address);
++	dev_dbg(sdma->dev, "wml = 0x%08x\n", (u32)sdmac->watermark_level);
++	dev_dbg(sdma->dev, "shp_addr = 0x%08x\n", sdmac->shp_addr);
++	dev_dbg(sdma->dev, "per_addr = 0x%08x\n", sdmac->per_addr);
++	dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", (u32)sdmac->event_mask[0]);
++	dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", (u32)sdmac->event_mask[1]);
++
++	spin_lock_irqsave(&sdma->channel_0_lock, flags);
++
++	memset(context, 0, sizeof(*context));
++	context->channel_state.pc = load_address;
++
++	/* Send by context the event mask,base address for peripheral
++	 * and watermark level
++	 */
++	context->gReg[0] = sdmac->event_mask[1];
++	context->gReg[1] = sdmac->event_mask[0];
++	context->gReg[2] = sdmac->per_addr;
++	context->gReg[6] = sdmac->shp_addr;
++	context->gReg[7] = sdmac->watermark_level;
++
++	bd0->mode.command = C0_SETDM;
++	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
++	bd0->mode.count = sizeof(*context) / 4;
++	bd0->buffer_addr = sdma->context_phys;
++	bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * channel;
++	ret = sdma_run_channel0(sdma);
++
++	spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
++
++	return ret;
++}
++
++static void sdma_disable_channel(struct sdma_channel *sdmac)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++
++	writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
++	sdmac->status = DMA_ERROR;
++}
++
++static int sdma_config_channel(struct sdma_channel *sdmac)
++{
++	int ret;
++
++	sdma_disable_channel(sdmac);
++
++	sdmac->event_mask[0] = 0;
++	sdmac->event_mask[1] = 0;
++	sdmac->shp_addr = 0;
++	sdmac->per_addr = 0;
++
++	if (sdmac->event_id0) {
++		if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
++			return -EINVAL;
++		sdma_event_enable(sdmac, sdmac->event_id0);
++	}
++
++	switch (sdmac->peripheral_type) {
++	case IMX_DMATYPE_DSP:
++		sdma_config_ownership(sdmac, false, true, true);
++		break;
++	case IMX_DMATYPE_MEMORY:
++		sdma_config_ownership(sdmac, false, true, false);
++		break;
++	default:
++		sdma_config_ownership(sdmac, true, true, false);
++		break;
++	}
++
++	sdma_get_pc(sdmac, sdmac->peripheral_type);
++
++	if ((sdmac->peripheral_type != IMX_DMATYPE_MEMORY) &&
++			(sdmac->peripheral_type != IMX_DMATYPE_DSP)) {
++		/* Handle multiple event channels differently */
++		if (sdmac->event_id1) {
++			sdmac->event_mask[1] = BIT(sdmac->event_id1 % 32);
++			if (sdmac->event_id1 > 31)
++				__set_bit(31, &sdmac->watermark_level);
++			sdmac->event_mask[0] = BIT(sdmac->event_id0 % 32);
++			if (sdmac->event_id0 > 31)
++				__set_bit(30, &sdmac->watermark_level);
++		} else {
++			__set_bit(sdmac->event_id0, sdmac->event_mask);
++		}
++		/* Watermark Level */
++		sdmac->watermark_level |= sdmac->watermark_level;
++		/* Address */
++		sdmac->shp_addr = sdmac->per_address;
++	} else {
++		sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
++	}
++
++	ret = sdma_load_context(sdmac);
++
++	return ret;
++}
++
++static int sdma_set_channel_priority(struct sdma_channel *sdmac,
++		unsigned int priority)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++
++	if (priority < MXC_SDMA_MIN_PRIORITY
++	    || priority > MXC_SDMA_MAX_PRIORITY) {
++		return -EINVAL;
++	}
++
++	writel_relaxed(priority, sdma->regs + SDMA_CHNPRI_0 + 4 * channel);
++
++	return 0;
++}
++
++static int sdma_request_channel(struct sdma_channel *sdmac)
++{
++	struct sdma_engine *sdma = sdmac->sdma;
++	int channel = sdmac->channel;
++	int ret = -EBUSY;
++
++	sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL);
++	if (!sdmac->bd) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	memset(sdmac->bd, 0, PAGE_SIZE);
++
++	sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
++	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
++
++	sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
++	return 0;
++out:
++
++	return ret;
++}
++
++static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
++{
++	return container_of(chan, struct sdma_channel, chan);
++}
++
++static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
++{
++	unsigned long flags;
++	struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
++	dma_cookie_t cookie;
++
++	spin_lock_irqsave(&sdmac->lock, flags);
++
++	cookie = dma_cookie_assign(tx);
++
++	spin_unlock_irqrestore(&sdmac->lock, flags);
++
++	return cookie;
++}
++
++static int sdma_alloc_chan_resources(struct dma_chan *chan)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	struct imx_dma_data *data = chan->private;
++	int prio, ret;
++
++	if (!data)
++		return -EINVAL;
++
++	switch (data->priority) {
++	case DMA_PRIO_HIGH:
++		prio = 3;
++		break;
++	case DMA_PRIO_MEDIUM:
++		prio = 2;
++		break;
++	case DMA_PRIO_LOW:
++	default:
++		prio = 1;
++		break;
++	}
++
++	sdmac->peripheral_type = data->peripheral_type;
++	sdmac->event_id0 = data->dma_request;
++
++	clk_enable(sdmac->sdma->clk_ipg);
++	clk_enable(sdmac->sdma->clk_ahb);
++
++	ret = sdma_request_channel(sdmac);
++	if (ret)
++		return ret;
++
++	ret = sdma_set_channel_priority(sdmac, prio);
++	if (ret)
++		return ret;
++
++	dma_async_tx_descriptor_init(&sdmac->desc, chan);
++	sdmac->desc.tx_submit = sdma_tx_submit;
++	/* txd.flags will be overwritten in prep funcs */
++	sdmac->desc.flags = DMA_CTRL_ACK;
++
++	return 0;
++}
++
++static void sdma_free_chan_resources(struct dma_chan *chan)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	struct sdma_engine *sdma = sdmac->sdma;
++
++	sdma_disable_channel(sdmac);
++
++	if (sdmac->event_id0)
++		sdma_event_disable(sdmac, sdmac->event_id0);
++	if (sdmac->event_id1)
++		sdma_event_disable(sdmac, sdmac->event_id1);
++
++	sdmac->event_id0 = 0;
++	sdmac->event_id1 = 0;
++
++	sdma_set_channel_priority(sdmac, 0);
++
++	dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
++
++	clk_disable(sdma->clk_ipg);
++	clk_disable(sdma->clk_ahb);
++}
++
++static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
++		struct dma_chan *chan, struct scatterlist *sgl,
++		unsigned int sg_len, enum dma_transfer_direction direction,
++		unsigned long flags, void *context)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	struct sdma_engine *sdma = sdmac->sdma;
++	int ret, i, count;
++	int channel = sdmac->channel;
++	struct scatterlist *sg;
++
++	if (sdmac->status == DMA_IN_PROGRESS)
++		return NULL;
++	sdmac->status = DMA_IN_PROGRESS;
++
++	sdmac->flags = 0;
++
++	sdmac->buf_tail = 0;
++
++	dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
++			sg_len, channel);
++
++	sdmac->direction = direction;
++	ret = sdma_load_context(sdmac);
++	if (ret)
++		goto err_out;
++
++	if (sg_len > NUM_BD) {
++		dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
++				channel, sg_len, NUM_BD);
++		ret = -EINVAL;
++		goto err_out;
++	}
++
++	sdmac->chn_count = 0;
++	for_each_sg(sgl, sg, sg_len, i) {
++		struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
++		int param;
++
++		bd->buffer_addr = sg->dma_address;
++
++		count = sg_dma_len(sg);
++
++		if (count > 0xffff) {
++			dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
++					channel, count, 0xffff);
++			ret = -EINVAL;
++			goto err_out;
++		}
++
++		bd->mode.count = count;
++		sdmac->chn_count += count;
++
++		if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
++			ret =  -EINVAL;
++			goto err_out;
++		}
++
++		switch (sdmac->word_size) {
++		case DMA_SLAVE_BUSWIDTH_4_BYTES:
++			bd->mode.command = 0;
++			if (count & 3 || sg->dma_address & 3)
++				return NULL;
++			break;
++		case DMA_SLAVE_BUSWIDTH_2_BYTES:
++			bd->mode.command = 2;
++			if (count & 1 || sg->dma_address & 1)
++				return NULL;
++			break;
++		case DMA_SLAVE_BUSWIDTH_1_BYTE:
++			bd->mode.command = 1;
++			break;
++		default:
++			return NULL;
++		}
++
++		param = BD_DONE | BD_EXTD | BD_CONT;
++
++		if (i + 1 == sg_len) {
++			param |= BD_INTR;
++			param |= BD_LAST;
++			param &= ~BD_CONT;
++		}
++
++		dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
++				i, count, (u64)sg->dma_address,
++				param & BD_WRAP ? "wrap" : "",
++				param & BD_INTR ? " intr" : "");
++
++		bd->mode.status = param;
++	}
++
++	sdmac->num_bd = sg_len;
++	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
++
++	return &sdmac->desc;
++err_out:
++	sdmac->status = DMA_ERROR;
++	return NULL;
++}
++
++static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
++		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
++		size_t period_len, enum dma_transfer_direction direction,
++		unsigned long flags, void *context)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	struct sdma_engine *sdma = sdmac->sdma;
++	int num_periods = buf_len / period_len;
++	int channel = sdmac->channel;
++	int ret, i = 0, buf = 0;
++
++	dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
++
++	if (sdmac->status == DMA_IN_PROGRESS)
++		return NULL;
++
++	sdmac->status = DMA_IN_PROGRESS;
++
++	sdmac->buf_tail = 0;
++	sdmac->period_len = period_len;
++
++	sdmac->flags |= IMX_DMA_SG_LOOP;
++	sdmac->direction = direction;
++	ret = sdma_load_context(sdmac);
++	if (ret)
++		goto err_out;
++
++	if (num_periods > NUM_BD) {
++		dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
++				channel, num_periods, NUM_BD);
++		goto err_out;
++	}
++
++	if (period_len > 0xffff) {
++		dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %d > %d\n",
++				channel, period_len, 0xffff);
++		goto err_out;
++	}
++
++	while (buf < buf_len) {
++		struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
++		int param;
++
++		bd->buffer_addr = dma_addr;
++
++		bd->mode.count = period_len;
++
++		if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
++			goto err_out;
++		if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES)
++			bd->mode.command = 0;
++		else
++			bd->mode.command = sdmac->word_size;
++
++		param = BD_DONE | BD_EXTD | BD_CONT | BD_INTR;
++		if (i + 1 == num_periods)
++			param |= BD_WRAP;
++
++		dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
++				i, period_len, (u64)dma_addr,
++				param & BD_WRAP ? "wrap" : "",
++				param & BD_INTR ? " intr" : "");
++
++		bd->mode.status = param;
++
++		dma_addr += period_len;
++		buf += period_len;
++
++		i++;
++	}
++
++	sdmac->num_bd = num_periods;
++	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
++
++	return &sdmac->desc;
++err_out:
++	sdmac->status = DMA_ERROR;
++	return NULL;
++}
++
++static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
++		unsigned long arg)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	struct dma_slave_config *dmaengine_cfg = (void *)arg;
++
++	switch (cmd) {
++	case DMA_TERMINATE_ALL:
++		sdma_disable_channel(sdmac);
++		return 0;
++	case DMA_SLAVE_CONFIG:
++		if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
++			sdmac->per_address = dmaengine_cfg->src_addr;
++			sdmac->watermark_level = dmaengine_cfg->src_maxburst *
++						dmaengine_cfg->src_addr_width;
++			sdmac->word_size = dmaengine_cfg->src_addr_width;
++		} else {
++			sdmac->per_address = dmaengine_cfg->dst_addr;
++			sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
++						dmaengine_cfg->dst_addr_width;
++			sdmac->word_size = dmaengine_cfg->dst_addr_width;
++		}
++		sdmac->direction = dmaengine_cfg->direction;
++		return sdma_config_channel(sdmac);
++	default:
++		return -ENOSYS;
++	}
++
++	return -EINVAL;
++}
++
++static enum dma_status sdma_tx_status(struct dma_chan *chan,
++				      dma_cookie_t cookie,
++				      struct dma_tx_state *txstate)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	u32 residue;
++
++	if (sdmac->flags & IMX_DMA_SG_LOOP)
++		residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len;
++	else
++		residue = sdmac->chn_count - sdmac->chn_real_count;
++
++	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
++			 residue);
++
++	return sdmac->status;
++}
++
++static void sdma_issue_pending(struct dma_chan *chan)
++{
++	struct sdma_channel *sdmac = to_sdma_chan(chan);
++	struct sdma_engine *sdma = sdmac->sdma;
++
++	if (sdmac->status == DMA_IN_PROGRESS)
++		sdma_enable_channel(sdma, sdmac->channel);
++}
++
++#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1	34
++#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2	38
++
++static void sdma_add_scripts(struct sdma_engine *sdma,
++		const struct sdma_script_start_addrs *addr)
++{
++	s32 *addr_arr = (u32 *)addr;
++	s32 *saddr_arr = (u32 *)sdma->script_addrs;
++	int i;
++
++	/* use the default firmware in ROM if missing external firmware */
++	if (!sdma->script_number)
++		sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
++
++	for (i = 0; i < sdma->script_number; i++)
++		if (addr_arr[i] > 0)
++			saddr_arr[i] = addr_arr[i];
++}
++
++static void sdma_load_firmware(const struct firmware *fw, void *context)
++{
++	struct sdma_engine *sdma = context;
++	const struct sdma_firmware_header *header;
++	const struct sdma_script_start_addrs *addr;
++	unsigned short *ram_code;
++
++	if (!fw) {
++		dev_err(sdma->dev, "firmware not found\n");
++		return;
++	}
++
++	if (fw->size < sizeof(*header))
++		goto err_firmware;
++
++	header = (struct sdma_firmware_header *)fw->data;
++
++	if (header->magic != SDMA_FIRMWARE_MAGIC)
++		goto err_firmware;
++	if (header->ram_code_start + header->ram_code_size > fw->size)
++		goto err_firmware;
++	switch (header->version_major) {
++		case 1:
++			sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
++			break;
++		case 2:
++			sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
++			break;
++		default:
++			dev_err(sdma->dev, "unknown firmware version\n");
++			goto err_firmware;
++	}
++
++	addr = (void *)header + header->script_addrs_start;
++	ram_code = (void *)header + header->ram_code_start;
++
++	clk_enable(sdma->clk_ipg);
++	clk_enable(sdma->clk_ahb);
++	/* download the RAM image for SDMA */
++	sdma_load_script(sdma, ram_code,
++			header->ram_code_size,
++			addr->ram_code_start_addr);
++	clk_disable(sdma->clk_ipg);
++	clk_disable(sdma->clk_ahb);
++
++	sdma_add_scripts(sdma, addr);
++
++	dev_info(sdma->dev, "loaded firmware %d.%d\n",
++			header->version_major,
++			header->version_minor);
++
++err_firmware:
++	release_firmware(fw);
++}
++
++static int __init sdma_get_firmware(struct sdma_engine *sdma,
++		const char *fw_name)
++{
++	int ret;
++
++	ret = request_firmware_nowait(THIS_MODULE,
++			FW_ACTION_HOTPLUG, fw_name, sdma->dev,
++			GFP_KERNEL, sdma, sdma_load_firmware);
++
++	return ret;
++}
++
++static int __init sdma_init(struct sdma_engine *sdma)
++{
++	int i, ret;
++	dma_addr_t ccb_phys;
++
++	clk_enable(sdma->clk_ipg);
++	clk_enable(sdma->clk_ahb);
++
++	/* Be sure SDMA has not started yet */
++	writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
++
++	sdma->channel_control = dma_alloc_coherent(NULL,
++			MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
++			sizeof(struct sdma_context_data),
++			&ccb_phys, GFP_KERNEL);
++
++	if (!sdma->channel_control) {
++		ret = -ENOMEM;
++		goto err_dma_alloc;
++	}
++
++	sdma->context = (void *)sdma->channel_control +
++		MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
++	sdma->context_phys = ccb_phys +
++		MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
++
++	/* Zero-out the CCB structures array just allocated */
++	memset(sdma->channel_control, 0,
++			MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control));
++
++	/* disable all channels */
++	for (i = 0; i < sdma->drvdata->num_events; i++)
++		writel_relaxed(0, sdma->regs + chnenbl_ofs(sdma, i));
++
++	/* All channels have priority 0 */
++	for (i = 0; i < MAX_DMA_CHANNELS; i++)
++		writel_relaxed(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
++
++	ret = sdma_request_channel(&sdma->channel[0]);
++	if (ret)
++		goto err_dma_alloc;
++
++	sdma_config_ownership(&sdma->channel[0], false, true, false);
++
++	/* Set Command Channel (Channel Zero) */
++	writel_relaxed(0x4050, sdma->regs + SDMA_CHN0ADDR);
++
++	/* Set bits of CONFIG register but with static context switching */
++	/* FIXME: Check whether to set ACR bit depending on clock ratios */
++	writel_relaxed(0, sdma->regs + SDMA_H_CONFIG);
++
++	writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
++
++	/* Set bits of CONFIG register with given context switching mode */
++	writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
++
++	/* Initializes channel's priorities */
++	sdma_set_channel_priority(&sdma->channel[0], 7);
++
++	clk_disable(sdma->clk_ipg);
++	clk_disable(sdma->clk_ahb);
++
++	return 0;
++
++err_dma_alloc:
++	clk_disable(sdma->clk_ipg);
++	clk_disable(sdma->clk_ahb);
++	dev_err(sdma->dev, "initialisation failed with %d\n", ret);
++	return ret;
++}
++
++static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param)
++{
++	struct imx_dma_data *data = fn_param;
++
++	if (!imx_dma_is_general_purpose(chan))
++		return false;
++
++	chan->private = data;
++
++	return true;
++}
++
++static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
++				   struct of_dma *ofdma)
++{
++	struct sdma_engine *sdma = ofdma->of_dma_data;
++	dma_cap_mask_t mask = sdma->dma_device.cap_mask;
++	struct imx_dma_data data;
++
++	if (dma_spec->args_count != 3)
++		return NULL;
++
++	data.dma_request = dma_spec->args[0];
++	data.peripheral_type = dma_spec->args[1];
++	data.priority = dma_spec->args[2];
++
++	return dma_request_channel(mask, sdma_filter_fn, &data);
++}
++
++static int __init sdma_probe(struct platform_device *pdev)
++{
++	const struct of_device_id *of_id =
++			of_match_device(sdma_dt_ids, &pdev->dev);
++	struct device_node *np = pdev->dev.of_node;
++	const char *fw_name;
++	int ret;
++	int irq;
++	struct resource *iores;
++	struct sdma_platform_data *pdata = dev_get_platdata(&pdev->dev);
++	int i;
++	struct sdma_engine *sdma;
++	s32 *saddr_arr;
++	const struct sdma_driver_data *drvdata = NULL;
++
++	if (of_id)
++		drvdata = of_id->data;
++	else if (pdev->id_entry)
++		drvdata = (void *)pdev->id_entry->driver_data;
++
++	if (!drvdata) {
++		dev_err(&pdev->dev, "unable to find driver data\n");
++		return -EINVAL;
++	}
++
++	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
++	if (ret)
++		return ret;
++
++	sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
++	if (!sdma)
++		return -ENOMEM;
++
++	spin_lock_init(&sdma->channel_0_lock);
++
++	sdma->dev = &pdev->dev;
++	sdma->drvdata = drvdata;
++
++	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	irq = platform_get_irq(pdev, 0);
++	if (!iores || irq < 0) {
++		ret = -EINVAL;
++		goto err_irq;
++	}
++
++	if (!request_mem_region(iores->start, resource_size(iores), pdev->name)) {
++		ret = -EBUSY;
++		goto err_request_region;
++	}
++
++	sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
++	if (IS_ERR(sdma->clk_ipg)) {
++		ret = PTR_ERR(sdma->clk_ipg);
++		goto err_clk;
++	}
++
++	sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
++	if (IS_ERR(sdma->clk_ahb)) {
++		ret = PTR_ERR(sdma->clk_ahb);
++		goto err_clk;
++	}
++
++	clk_prepare(sdma->clk_ipg);
++	clk_prepare(sdma->clk_ahb);
++
++	sdma->regs = ioremap(iores->start, resource_size(iores));
++	if (!sdma->regs) {
++		ret = -ENOMEM;
++		goto err_ioremap;
++	}
++
++	ret = request_irq(irq, sdma_int_handler, 0, "sdma", sdma);
++	if (ret)
++		goto err_request_irq;
++
++	sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
++	if (!sdma->script_addrs) {
++		ret = -ENOMEM;
++		goto err_alloc;
++	}
++
++	/* initially no scripts available */
++	saddr_arr = (s32 *)sdma->script_addrs;
++	for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
++		saddr_arr[i] = -EINVAL;
++
++	dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
++	dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
++
++	INIT_LIST_HEAD(&sdma->dma_device.channels);
++	/* Initialize channel parameters */
++	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++		struct sdma_channel *sdmac = &sdma->channel[i];
++
++		sdmac->sdma = sdma;
++		spin_lock_init(&sdmac->lock);
++
++		sdmac->chan.device = &sdma->dma_device;
++		dma_cookie_init(&sdmac->chan);
++		sdmac->channel = i;
++
++		tasklet_init(&sdmac->tasklet, sdma_tasklet,
++			     (unsigned long) sdmac);
++		/*
++		 * Add the channel to the DMAC list. Do not add channel 0 though
++		 * because we need it internally in the SDMA driver. This also means
++		 * that channel 0 in dmaengine counting matches sdma channel 1.
++		 */
++		if (i)
++			list_add_tail(&sdmac->chan.device_node,
++					&sdma->dma_device.channels);
++	}
++
++	ret = sdma_init(sdma);
++	if (ret)
++		goto err_init;
++
++	if (sdma->drvdata->script_addrs)
++		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
++	if (pdata && pdata->script_addrs)
++		sdma_add_scripts(sdma, pdata->script_addrs);
++
++	if (pdata) {
++		ret = sdma_get_firmware(sdma, pdata->fw_name);
++		if (ret)
++			dev_warn(&pdev->dev, "failed to get firmware from platform data\n");
++	} else {
++		/*
++		 * Because that device tree does not encode ROM script address,
++		 * the RAM script in firmware is mandatory for device tree
++		 * probe, otherwise it fails.
++		 */
++		ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
++					      &fw_name);
++		if (ret)
++			dev_warn(&pdev->dev, "failed to get firmware name\n");
++		else {
++			ret = sdma_get_firmware(sdma, fw_name);
++			if (ret)
++				dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
++		}
++	}
++
++	sdma->dma_device.dev = &pdev->dev;
++
++	sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
++	sdma->dma_device.device_free_chan_resources = sdma_free_chan_resources;
++	sdma->dma_device.device_tx_status = sdma_tx_status;
++	sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg;
++	sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
++	sdma->dma_device.device_control = sdma_control;
++	sdma->dma_device.device_issue_pending = sdma_issue_pending;
++	sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
++	dma_set_max_seg_size(sdma->dma_device.dev, 65535);
++
++	ret = dma_async_device_register(&sdma->dma_device);
++	if (ret) {
++		dev_err(&pdev->dev, "unable to register\n");
++		goto err_init;
++	}
++
++	if (np) {
++		ret = of_dma_controller_register(np, sdma_xlate, sdma);
++		if (ret) {
++			dev_err(&pdev->dev, "failed to register controller\n");
++			goto err_register;
++		}
++	}
++
++	dev_info(sdma->dev, "initialized\n");
++
++	return 0;
++
++err_register:
++	dma_async_device_unregister(&sdma->dma_device);
++err_init:
++	kfree(sdma->script_addrs);
++err_alloc:
++	free_irq(irq, sdma);
++err_request_irq:
++	iounmap(sdma->regs);
++err_ioremap:
++err_clk:
++	release_mem_region(iores->start, resource_size(iores));
++err_request_region:
++err_irq:
++	kfree(sdma);
++	return ret;
++}
++
++static int sdma_remove(struct platform_device *pdev)
++{
++	return -EBUSY;
++}
++
++static struct platform_driver sdma_driver = {
++	.driver		= {
++		.name	= "imx-sdma",
++		.of_match_table = sdma_dt_ids,
++	},
++	.id_table	= sdma_devtypes,
++	.remove		= sdma_remove,
++};
++
++static int __init sdma_module_init(void)
++{
++	return platform_driver_probe(&sdma_driver, sdma_probe);
++}
++module_init(sdma_module_init);
++
++MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
++MODULE_DESCRIPTION("i.MX SDMA driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.16.6.orig/drivers/gpu/ipu-v3/ipu-dc.c linux-3.16.6/drivers/gpu/ipu-v3/ipu-dc.c
+--- linux-3.16.6.orig/drivers/gpu/ipu-v3/ipu-dc.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/gpu/ipu-v3/ipu-dc.c	2014-10-23 12:35:30.966220009 -0500
+@@ -93,6 +93,7 @@
+ 	IPU_DC_MAP_BGR666,
+ 	IPU_DC_MAP_LVDS666,
+ 	IPU_DC_MAP_BGR24,
++	IPU_DC_MAP_RGB666,
+ };
+ 
+ struct ipu_dc {
+@@ -161,6 +162,8 @@
+ 		return IPU_DC_MAP_LVDS666;
+ 	case V4L2_PIX_FMT_BGR24:
+ 		return IPU_DC_MAP_BGR24;
++	case V4L2_PIX_FMT_RGB666:
++		return IPU_DC_MAP_RGB666;
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -452,6 +455,12 @@
+ 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
+ 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
+ 
++	/* rgb666 */
++	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB666);
++	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 0, 5, 0xfc); /* blue */
++	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 1, 11, 0xfc); /* green */
++	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 2, 17, 0xfc); /* red */
++
+ 	return 0;
+ }
+ 
+diff -Nur linux-3.16.6.orig/drivers/gpu/ipu-v3/ipu-di.c linux-3.16.6/drivers/gpu/ipu-v3/ipu-di.c
+--- linux-3.16.6.orig/drivers/gpu/ipu-v3/ipu-di.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/gpu/ipu-v3/ipu-di.c	2014-10-23 12:35:38.078220007 -0500
+@@ -595,7 +595,7 @@
+ 		}
+ 	}
+ 
+-	if (sig->clk_pol)
++	if (sig->clk_pol == CLK_POL_POSEDGE)
+ 		di_gen |= DI_GEN_POLARITY_DISP_CLK;
+ 
+ 	ipu_di_write(di, di_gen, DI_GENERAL);
+@@ -606,7 +606,7 @@
+ 	reg = ipu_di_read(di, DI_POL);
+ 	reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
+ 
+-	if (sig->enable_pol)
++	if (sig->enable_pol == ENABLE_POL_HIGH)
+ 		reg |= DI_POL_DRDY_POLARITY_15;
+ 	if (sig->data_pol)
+ 		reg |= DI_POL_DRDY_DATA_POLARITY;
+diff -Nur linux-3.16.6.orig/drivers/Kconfig linux-3.16.6/drivers/Kconfig
+--- linux-3.16.6.orig/drivers/Kconfig	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/Kconfig	2014-10-23 12:37:18.314220004 -0500
+@@ -176,4 +176,6 @@
+ 
+ source "drivers/mcb/Kconfig"
+ 
++source "drivers/cec/Kconfig"
++
+ endmenu
+diff -Nur linux-3.16.6.orig/drivers/Makefile linux-3.16.6/drivers/Makefile
+--- linux-3.16.6.orig/drivers/Makefile	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/Makefile	2014-10-23 12:37:18.350220009 -0500
+@@ -158,3 +158,4 @@
+ obj-$(CONFIG_FMC)		+= fmc/
+ obj-$(CONFIG_POWERCAP)		+= powercap/
+ obj-$(CONFIG_MCB)		+= mcb/
++obj-$(CONFIG_CEC)		+= cec/
+diff -Nur linux-3.16.6.orig/drivers/mmc/core/core.c linux-3.16.6/drivers/mmc/core/core.c
+--- linux-3.16.6.orig/drivers/mmc/core/core.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/mmc/core/core.c	2014-10-23 12:34:18.710219997 -0500
+@@ -13,11 +13,13 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
++#include <linux/clk.h>
+ #include <linux/completion.h>
+ #include <linux/device.h>
+ #include <linux/delay.h>
+ #include <linux/pagemap.h>
+ #include <linux/err.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/leds.h>
+ #include <linux/scatterlist.h>
+ #include <linux/log2.h>
+@@ -1515,6 +1517,43 @@
+ 	mmc_host_clk_release(host);
+ }
+ 
++static void mmc_card_power_up(struct mmc_host *host)
++{
++	int i;
++	struct gpio_desc **gds = host->card_reset_gpios;
++
++	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
++		if (gds[i]) {
++			dev_dbg(host->parent, "Asserting reset line %d", i);
++			gpiod_set_value(gds[i], 1);
++		}
++	}
++
++	if (host->card_regulator) {
++		dev_dbg(host->parent, "Enabling external regulator");
++		if (regulator_enable(host->card_regulator))
++			dev_err(host->parent, "Failed to enable external regulator");
++	}
++
++	if (host->card_clk) {
++		dev_dbg(host->parent, "Enabling external clock");
++		clk_prepare_enable(host->card_clk);
++	}
++
++	/* 2ms delay to let clocks and power settle */
++	mmc_delay(20);
++
++	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
++		if (gds[i]) {
++			dev_dbg(host->parent, "Deasserting reset line %d", i);
++			gpiod_set_value(gds[i], 0);
++		}
++	}
++
++	/* 2ms delay to after reset release */
++	mmc_delay(20);
++}
++
+ /*
+  * Apply power to the MMC stack.  This is a two-stage process.
+  * First, we enable power to the card without the clock running.
+@@ -1531,6 +1570,9 @@
+ 	if (host->ios.power_mode == MMC_POWER_ON)
+ 		return;
+ 
++	/* Power up the card/module first, if needed */
++	mmc_card_power_up(host);
++
+ 	mmc_host_clk_hold(host);
+ 
+ 	host->ios.vdd = fls(ocr) - 1;
+diff -Nur linux-3.16.6.orig/drivers/mmc/core/host.c linux-3.16.6/drivers/mmc/core/host.c
+--- linux-3.16.6.orig/drivers/mmc/core/host.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/mmc/core/host.c	2014-10-23 12:34:34.134220000 -0500
+@@ -12,14 +12,18 @@
+  *  MMC host class device management
+  */
+ 
++#include <linux/kernel.h>
++#include <linux/clk.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/idr.h>
+ #include <linux/of.h>
+ #include <linux/of_gpio.h>
+ #include <linux/pagemap.h>
+ #include <linux/export.h>
+ #include <linux/leds.h>
++#include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/suspend.h>
+ 
+@@ -461,6 +465,66 @@
+ 
+ EXPORT_SYMBOL(mmc_of_parse);
+ 
++static int mmc_of_parse_child(struct mmc_host *host)
++{
++	struct device_node *np;
++	struct clk *clk;
++	int i;
++
++	if (!host->parent || !host->parent->of_node)
++		return 0;
++
++	np = host->parent->of_node;
++
++	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
++	if (IS_ERR(host->card_regulator)) {
++		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
++			return PTR_ERR(host->card_regulator);
++		host->card_regulator = NULL;
++	}
++
++	/* Parse card power/reset/clock control */
++	if (of_find_property(np, "card-reset-gpios", NULL)) {
++		struct gpio_desc *gpd;
++		int level = 0;
++
++		/*
++		 * If the regulator is enabled, then we can hold the
++		 * card in reset with an active high resets.  Otherwise,
++		 * hold the resets low.
++		 */
++		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
++			level = 1;
++
++		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
++			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
++			if (IS_ERR(gpd)) {
++				if (PTR_ERR(gpd) == -EPROBE_DEFER)
++					return PTR_ERR(gpd);
++				break;
++			}
++			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
++			host->card_reset_gpios[i] = gpd;
++		}
++
++		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
++		if (!IS_ERR(gpd)) {
++			dev_warn(host->parent, "More reset gpios than we can handle");
++			gpiod_put(gpd);
++		}
++	}
++
++	clk = of_clk_get_by_name(np, "card_ext_clock");
++	if (IS_ERR(clk)) {
++		if (PTR_ERR(clk) == -EPROBE_DEFER)
++			return PTR_ERR(clk);
++		clk = NULL;
++	}
++	host->card_clk = clk;
++
++	return 0;
++}
++
+ /**
+  *	mmc_alloc_host - initialise the per-host structure.
+  *	@extra: sizeof private data structure
+@@ -540,6 +604,10 @@
+ {
+ 	int err;
+ 
++	err = mmc_of_parse_child(host);
++	if (err)
++		return err;
++
+ 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
+ 		!host->ops->enable_sdio_irq);
+ 
+diff -Nur linux-3.16.6.orig/drivers/mmc/host/dw_mmc.c linux-3.16.6/drivers/mmc/host/dw_mmc.c
+--- linux-3.16.6.orig/drivers/mmc/host/dw_mmc.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/mmc/host/dw_mmc.c	2014-10-23 12:34:26.238219996 -0500
+@@ -2049,6 +2049,8 @@
+ 	if (!mmc)
+ 		return -ENOMEM;
+ 
++	mmc_of_parse(mmc);
++
+ 	slot = mmc_priv(mmc);
+ 	slot->id = id;
+ 	slot->mmc = mmc;
+diff -Nur linux-3.16.6.orig/drivers/mmc/host/Kconfig linux-3.16.6/drivers/mmc/host/Kconfig
+--- linux-3.16.6.orig/drivers/mmc/host/Kconfig	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/mmc/host/Kconfig	2014-10-23 12:34:04.318220041 -0500
+@@ -25,8 +25,7 @@
+ 	  If unsure, say N.
+ 
+ config MMC_SDHCI
+-	tristate "Secure Digital Host Controller Interface support"
+-	depends on HAS_DMA
++	tristate
+ 	help
+ 	  This selects the generic Secure Digital Host Controller Interface.
+ 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
+@@ -59,7 +58,8 @@
+ 
+ config MMC_SDHCI_PCI
+ 	tristate "SDHCI support on PCI bus"
+-	depends on MMC_SDHCI && PCI
++	depends on PCI && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects the PCI Secure Digital Host Controller Interface.
+ 	  Most controllers found today are PCI devices.
+@@ -83,7 +83,8 @@
+ 
+ config MMC_SDHCI_ACPI
+ 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
+-	depends on MMC_SDHCI && ACPI
++	depends on ACPI && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects support for ACPI enumerated SDHCI controllers,
+ 	  identified by ACPI Compatibility ID PNP0D40 or specific
+@@ -94,8 +95,8 @@
+ 	  If unsure, say N.
+ 
+ config MMC_SDHCI_PLTFM
+-	tristate "SDHCI platform and OF driver helper"
+-	depends on MMC_SDHCI
++	tristate
++	select MMC_SDHCI
+ 	help
+ 	  This selects the common helper functions support for Secure Digital
+ 	  Host Controller Interface based platform and OF drivers.
+@@ -106,8 +107,8 @@
+ 
+ config MMC_SDHCI_OF_ARASAN
+ 	tristate "SDHCI OF support for the Arasan SDHCI controllers"
+-	depends on MMC_SDHCI_PLTFM
+-	depends on OF
++	depends on OF && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Arasan Secure Digital Host Controller Interface
+ 	  (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
+@@ -118,9 +119,9 @@
+ 
+ config MMC_SDHCI_OF_ESDHC
+ 	tristate "SDHCI OF support for the Freescale eSDHC controller"
+-	depends on MMC_SDHCI_PLTFM
+-	depends on PPC_OF
++	depends on PPC_OF && HAS_DMA
+ 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Freescale eSDHC controller support.
+ 
+@@ -130,9 +131,9 @@
+ 
+ config MMC_SDHCI_OF_HLWD
+ 	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
+-	depends on MMC_SDHCI_PLTFM
+-	depends on PPC_OF
++	depends on PPC_OF && HAS_DMA
+ 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface (SDHCI)
+ 	  found in the "Hollywood" chipset of the Nintendo Wii video game
+@@ -144,8 +145,8 @@
+ 
+ config MMC_SDHCI_CNS3XXX
+ 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
+-	depends on ARCH_CNS3XXX
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_CNS3XXX && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
+ 
+@@ -155,9 +156,9 @@
+ 
+ config MMC_SDHCI_ESDHC_IMX
+ 	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
+-	depends on ARCH_MXC
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_MXC && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Freescale eSDHC/uSDHC controller support
+ 	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
+@@ -168,9 +169,9 @@
+ 
+ config MMC_SDHCI_DOVE
+ 	tristate "SDHCI support on Marvell's Dove SoC"
+-	depends on ARCH_DOVE || MACH_DOVE
+-	depends on MMC_SDHCI_PLTFM
++	depends on (ARCH_DOVE || MACH_DOVE) && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface in
+ 	  Marvell's Dove SoC.
+@@ -181,9 +182,9 @@
+ 
+ config MMC_SDHCI_TEGRA
+ 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
+-	depends on ARCH_TEGRA
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_TEGRA && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Tegra SD/MMC controller. If you have a Tegra
+ 	  platform with SD or MMC devices, say Y or M here.
+@@ -192,7 +193,8 @@
+ 
+ config MMC_SDHCI_S3C
+ 	tristate "SDHCI support on Samsung S3C SoC"
+-	depends on MMC_SDHCI && PLAT_SAMSUNG
++	depends on PLAT_SAMSUNG && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface (SDHCI)
+ 	  often referrered to as the HSMMC block in some of the Samsung S3C
+@@ -204,8 +206,8 @@
+ 
+ config MMC_SDHCI_SIRF
+ 	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
+-	depends on ARCH_SIRF
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_SIRF && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the SDHCI support for SiRF System-on-Chip devices.
+ 
+@@ -215,8 +217,8 @@
+ 
+ config MMC_SDHCI_PXAV3
+ 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
+-	depends on CLKDEV_LOOKUP
+-	depends on MMC_SDHCI_PLTFM
++	depends on CLKDEV_LOOKUP && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	default CPU_MMP2
+ 	help
+ 	  This selects the Marvell(R) PXAV3 SD Host Controller.
+@@ -227,8 +229,8 @@
+ 
+ config MMC_SDHCI_PXAV2
+ 	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
+-	depends on CLKDEV_LOOKUP
+-	depends on MMC_SDHCI_PLTFM
++	depends on CLKDEV_LOOKUP && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	default CPU_PXA910
+ 	help
+ 	  This selects the Marvell(R) PXAV2 SD Host Controller.
+@@ -239,7 +241,8 @@
+ 
+ config MMC_SDHCI_SPEAR
+ 	tristate "SDHCI support on ST SPEAr platform"
+-	depends on MMC_SDHCI && PLAT_SPEAR
++	depends on PLAT_SPEAR && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface (SDHCI)
+ 	  often referrered to as the HSMMC block in some of the ST SPEAR range
+@@ -261,8 +264,8 @@
+ 
+ config MMC_SDHCI_BCM_KONA
+ 	tristate "SDHCI support on Broadcom KONA platform"
+-	depends on ARCH_BCM_MOBILE
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_BCM_MOBILE && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Broadcom Kona Secure Digital Host Controller
+ 	  Interface(SDHCI) support.
+@@ -272,9 +275,9 @@
+ 
+ config MMC_SDHCI_BCM2835
+ 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
+-	depends on ARCH_BCM2835
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_BCM2835 && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
+ 	  platform with SD or MMC devices, say Y or M here.
+diff -Nur linux-3.16.6.orig/drivers/mmc/host/sdhci.c linux-3.16.6/drivers/mmc/host/sdhci.c
+--- linux-3.16.6.orig/drivers/mmc/host/sdhci.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/mmc/host/sdhci.c	2014-10-23 12:34:10.650220104 -0500
+@@ -1530,7 +1530,6 @@
+ 			host->ops->set_clock(host, host->clock);
+ 		}
+ 
+-
+ 		/* Reset SD Clock Enable */
+ 		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ 		clk &= ~SDHCI_CLOCK_CARD_EN;
+@@ -1763,9 +1762,6 @@
+ 		ctrl |= SDHCI_CTRL_VDD_180;
+ 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ 
+-		/* Wait for 5ms */
+-		usleep_range(5000, 5500);
+-
+ 		/* 1.8V regulator output should be stable within 5 ms */
+ 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ 		if (ctrl & SDHCI_CTRL_VDD_180)
+diff -Nur linux-3.16.6.orig/drivers/regulator/anatop-regulator.c linux-3.16.6/drivers/regulator/anatop-regulator.c
+--- linux-3.16.6.orig/drivers/regulator/anatop-regulator.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/regulator/anatop-regulator.c	2014-10-23 12:36:22.798219997 -0500
+@@ -267,6 +267,7 @@
+ 	config.driver_data = sreg;
+ 	config.of_node = pdev->dev.of_node;
+ 	config.regmap = sreg->anatop;
++	config.ena_gpio = -EINVAL;
+ 
+ 	/* Only core regulators have the ramp up delay configuration. */
+ 	if (sreg->control_reg && sreg->delay_bit_width) {
+diff -Nur linux-3.16.6.orig/drivers/regulator/core.c linux-3.16.6/drivers/regulator/core.c
+--- linux-3.16.6.orig/drivers/regulator/core.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/regulator/core.c	2014-10-23 12:36:22.802220004 -0500
+@@ -24,6 +24,7 @@
+ #include <linux/suspend.h>
+ #include <linux/delay.h>
+ #include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/of.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/of_regulator.h>
+@@ -77,7 +78,7 @@
+  */
+ struct regulator_enable_gpio {
+ 	struct list_head list;
+-	int gpio;
++	struct gpio_desc *gpiod;
+ 	u32 enable_count;	/* a number of enabled shared GPIO */
+ 	u32 request_count;	/* a number of requested shared GPIO */
+ 	unsigned int ena_gpio_invert:1;
+@@ -1660,10 +1661,13 @@
+ 				const struct regulator_config *config)
+ {
+ 	struct regulator_enable_gpio *pin;
++	struct gpio_desc *gpiod;
+ 	int ret;
+ 
++	gpiod = gpio_to_desc(config->ena_gpio);
++
+ 	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
+-		if (pin->gpio == config->ena_gpio) {
++		if (pin->gpiod == gpiod) {
+ 			rdev_dbg(rdev, "GPIO %d is already used\n",
+ 				config->ena_gpio);
+ 			goto update_ena_gpio_to_rdev;
+@@ -1682,7 +1686,7 @@
+ 		return -ENOMEM;
+ 	}
+ 
+-	pin->gpio = config->ena_gpio;
++	pin->gpiod = gpiod;
+ 	pin->ena_gpio_invert = config->ena_gpio_invert;
+ 	list_add(&pin->list, &regulator_ena_gpio_list);
+ 
+@@ -1701,10 +1705,10 @@
+ 
+ 	/* Free the GPIO only in case of no use */
+ 	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
+-		if (pin->gpio == rdev->ena_pin->gpio) {
++		if (pin->gpiod == rdev->ena_pin->gpiod) {
+ 			if (pin->request_count <= 1) {
+ 				pin->request_count = 0;
+-				gpio_free(pin->gpio);
++				gpiod_put(pin->gpiod);
+ 				list_del(&pin->list);
+ 				kfree(pin);
+ 			} else {
+@@ -1732,8 +1736,8 @@
+ 	if (enable) {
+ 		/* Enable GPIO at initial use */
+ 		if (pin->enable_count == 0)
+-			gpio_set_value_cansleep(pin->gpio,
+-						!pin->ena_gpio_invert);
++			gpiod_set_value_cansleep(pin->gpiod,
++						 !pin->ena_gpio_invert);
+ 
+ 		pin->enable_count++;
+ 	} else {
+@@ -1744,8 +1748,8 @@
+ 
+ 		/* Disable GPIO if not used */
+ 		if (pin->enable_count <= 1) {
+-			gpio_set_value_cansleep(pin->gpio,
+-						pin->ena_gpio_invert);
++			gpiod_set_value_cansleep(pin->gpiod,
++						 pin->ena_gpio_invert);
+ 			pin->enable_count = 0;
+ 		}
+ 	}
+@@ -3470,7 +3474,7 @@
+ 
+ 	dev_set_drvdata(&rdev->dev, rdev);
+ 
+-	if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
++	if (gpio_is_valid(config->ena_gpio)) {
+ 		ret = regulator_ena_gpio_request(rdev, config);
+ 		if (ret != 0) {
+ 			rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
+diff -Nur linux-3.16.6.orig/drivers/regulator/dummy.c linux-3.16.6/drivers/regulator/dummy.c
+--- linux-3.16.6.orig/drivers/regulator/dummy.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/regulator/dummy.c	2014-10-23 12:36:22.810220006 -0500
+@@ -48,6 +48,7 @@
+ 
+ 	config.dev = &pdev->dev;
+ 	config.init_data = &dummy_initdata;
++	config.ena_gpio = -EINVAL;
+ 
+ 	dummy_regulator_rdev = regulator_register(&dummy_desc, &config);
+ 	if (IS_ERR(dummy_regulator_rdev)) {
+diff -Nur linux-3.16.6.orig/drivers/regulator/fixed.c linux-3.16.6/drivers/regulator/fixed.c
+--- linux-3.16.6.orig/drivers/regulator/fixed.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/regulator/fixed.c	2014-10-23 12:36:22.810220006 -0500
+@@ -156,9 +156,7 @@
+ 		drvdata->desc.n_voltages = 1;
+ 
+ 	drvdata->desc.fixed_uV = config->microvolts;
+-
+-	if (config->gpio >= 0)
+-		cfg.ena_gpio = config->gpio;
++	cfg.ena_gpio = config->gpio;
+ 	cfg.ena_gpio_invert = !config->enable_high;
+ 	if (config->enabled_at_boot) {
+ 		if (config->enable_high)
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/drm-ddc-connector.c linux-3.16.6/drivers/staging/imx-drm/drm-ddc-connector.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/drm-ddc-connector.c	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/drm-ddc-connector.c	2014-10-23 12:37:30.178219970 -0500
+@@ -0,0 +1,88 @@
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <drm/drmP.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_edid.h>
++
++#include "drm-ddc-connector.h"
++
++enum drm_connector_status
++drm_ddc_connector_always_connected(struct drm_connector *connector, bool force)
++{
++	return connector_status_connected;
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_always_connected);
++
++int drm_ddc_connector_get_modes(struct drm_connector *connector)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++	struct edid *edid;
++	int ret = 0;
++
++	if (!ddc_conn->ddc)
++		return 0;
++
++	edid = drm_get_edid(connector, ddc_conn->ddc);
++	if (edid) {
++		drm_mode_connector_update_edid_property(connector, edid);
++		ret = drm_add_edid_modes(connector, edid);
++		/* Store the ELD */
++		drm_edid_to_eld(connector, edid);
++		kfree(edid);
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_get_modes);
++
++void drm_ddc_connector_destroy(struct drm_connector *connector)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++
++	pr_info("%s: %p\n", __func__, ddc_conn);
++
++	drm_sysfs_connector_remove(connector);
++	drm_connector_cleanup(connector);
++	if (ddc_conn->ddc)
++		i2c_put_adapter(ddc_conn->ddc);
++	kfree(ddc_conn);
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_destroy);
++
++void drm_ddc_connector_add(struct drm_device *drm,
++	struct drm_ddc_connector *ddc_conn,
++	struct drm_connector_funcs *funcs, int connector_type)
++{
++	drm_connector_init(drm, &ddc_conn->connector, funcs, connector_type);
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_add);
++
++struct drm_ddc_connector *drm_ddc_connector_create(struct drm_device *drm,
++	struct device_node *np, void *private)
++{
++	struct drm_ddc_connector *ddc_conn;
++	struct device_node *ddc_node;
++
++	ddc_conn = kzalloc(sizeof(*ddc_conn), GFP_KERNEL);
++	if (!ddc_conn)
++		return ERR_PTR(-ENOMEM);
++
++	ddc_conn->private = private;
++
++	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
++	if (ddc_node) {
++		ddc_conn->ddc = of_find_i2c_adapter_by_node(ddc_node);
++		of_node_put(ddc_node);
++		if (!ddc_conn->ddc) {
++			kfree(ddc_conn);
++			return ERR_PTR(-EPROBE_DEFER);
++		}
++	}
++
++	return ddc_conn;
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_create);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_DESCRIPTION("Generic DRM DDC connector module");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/drm-ddc-connector.h linux-3.16.6/drivers/staging/imx-drm/drm-ddc-connector.h
+--- linux-3.16.6.orig/drivers/staging/imx-drm/drm-ddc-connector.h	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/drm-ddc-connector.h	2014-10-23 12:37:30.178219970 -0500
+@@ -0,0 +1,31 @@
++#ifndef DRM_DDC_CONNECTOR_H
++#define DRM_DDC_CONNECTOR_H
++
++#include <drm/drm_crtc.h>
++
++struct drm_ddc_connector {
++	struct i2c_adapter *ddc;
++	struct drm_connector connector;
++	void *private;
++};
++
++#define to_ddc_conn(c) container_of(c, struct drm_ddc_connector, connector)
++
++enum drm_connector_status drm_ddc_connector_always_connected(
++	struct drm_connector *connector, bool force);
++int drm_ddc_connector_get_modes(struct drm_connector *connector);
++void drm_ddc_connector_add(struct drm_device *drm,
++	struct drm_ddc_connector *ddc_conn,
++	struct drm_connector_funcs *funcs, int connector_type);
++void drm_ddc_connector_destroy(struct drm_connector *connector);
++struct drm_ddc_connector *drm_ddc_connector_create(struct drm_device *drm,
++	struct device_node *np, void *private);
++
++static inline void *drm_ddc_private(struct drm_connector *connector)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++
++	return ddc_conn->private;
++}
++
++#endif
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-audio.c linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-audio.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-audio.c	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-audio.c	2014-10-23 12:37:11.394219951 -0500
+@@ -0,0 +1,654 @@
++/*
++ * DesignWare HDMI audio driver
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Written and tested against the (alleged) DW HDMI Tx found in iMX6S.
++ */
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/asoundef.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++
++#include "dw-hdmi-audio.h"
++
++#define DRIVER_NAME "dw-hdmi-audio"
++
++/* Provide some bits rather than bit offsets */
++enum {
++	HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7),
++	HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3),
++	HDMI_AHB_DMA_START_START = BIT(0),
++	HDMI_AHB_DMA_STOP_STOP = BIT(0),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL =
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY,
++	HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5),
++	HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4),
++	HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3),
++	HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2),
++	HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
++	HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
++	HDMI_IH_AHBDMAAUD_STAT0_ALL =
++		HDMI_IH_AHBDMAAUD_STAT0_ERROR |
++		HDMI_IH_AHBDMAAUD_STAT0_LOST |
++		HDMI_IH_AHBDMAAUD_STAT0_RETRY |
++		HDMI_IH_AHBDMAAUD_STAT0_DONE |
++		HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL |
++		HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY,
++	HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1,
++	HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1,
++	HDMI_AHB_DMA_CONF0_INCR4 = 0,
++	HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0),
++	HDMI_AHB_DMA_MASK_DONE = BIT(7),
++	HDMI_REVISION_ID = 0x0001,
++	HDMI_IH_AHBDMAAUD_STAT0 = 0x0109,
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189,
++	HDMI_AUD_N1 = 0x3200,
++	HDMI_AUD_CTS1 = 0x3203,
++	HDMI_AHB_DMA_CONF0 = 0x3600,
++	HDMI_AHB_DMA_START = 0x3601,
++	HDMI_AHB_DMA_STOP = 0x3602,
++	HDMI_AHB_DMA_THRSLD = 0x3603,
++	HDMI_AHB_DMA_STRADDR0 = 0x3604,
++	HDMI_AHB_DMA_STPADDR0 = 0x3608,
++	HDMI_AHB_DMA_STAT = 0x3612,
++	HDMI_AHB_DMA_STAT_FULL = BIT(1),
++	HDMI_AHB_DMA_MASK = 0x3614,
++	HDMI_AHB_DMA_POL = 0x3615,
++	HDMI_AHB_DMA_CONF1 = 0x3616,
++	HDMI_AHB_DMA_BUFFPOL = 0x361a,
++};
++
++struct snd_dw_hdmi {
++	struct snd_card *card;
++	struct snd_pcm *pcm;
++	struct dw_hdmi_audio_data data;
++	struct snd_pcm_substream *substream;
++	void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
++	void *buf_src;
++	void *buf_dst;
++	dma_addr_t buf_addr;
++	unsigned buf_offset;
++	unsigned buf_period;
++	unsigned buf_size;
++	unsigned channels;
++	uint8_t revision;
++	uint8_t iec_offset;
++	uint8_t cs[192][8];
++};
++
++static void dw_hdmi_writel(unsigned long val, void __iomem *ptr)
++{
++	writeb_relaxed(val, ptr);
++	writeb_relaxed(val >> 8, ptr + 1);
++	writeb_relaxed(val >> 16, ptr + 2);
++	writeb_relaxed(val >> 24, ptr + 3);
++}
++
++/*
++ * Convert to hardware format: The userspace buffer contains IEC958 samples,
++ * with the PCUV bits in bits 31..28 and audio samples in bits 27..4.  We
++ * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
++ * samples in 23..0.
++ *
++ * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
++ *
++ * Ideally, we could do with having the data properly formatted in userspace.
++ */
++static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
++	size_t offset, size_t bytes)
++{
++	uint32_t *src = dw->buf_src + offset;
++	uint32_t *dst = dw->buf_dst + offset;
++	uint32_t *end = dw->buf_src + offset + bytes;
++
++	do {
++		uint32_t b, sample = *src++;
++
++		b = (sample & 8) << (28 - 3);
++
++		sample >>= 4;
++
++		*dst++ = sample | b;
++	} while (src < end);
++}
++
++static uint32_t parity(uint32_t sample)
++{
++	sample ^= sample >> 16;
++	sample ^= sample >> 8;
++	sample ^= sample >> 4;
++	sample ^= sample >> 2;
++	sample ^= sample >> 1;
++	return (sample & 1) << 27;
++}
++
++static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw,
++	size_t offset, size_t bytes)
++{
++	uint32_t *src = dw->buf_src + offset;
++	uint32_t *dst = dw->buf_dst + offset;
++	uint32_t *end = dw->buf_src + offset + bytes;
++
++	do {
++		unsigned i;
++		uint8_t *cs;
++
++		cs = dw->cs[dw->iec_offset++];
++		if (dw->iec_offset >= 192)
++			dw->iec_offset = 0;
++
++		i = dw->channels;
++		do {
++			uint32_t sample = *src++;
++
++			sample &= ~0xff000000;
++			sample |= *cs++ << 24;
++			sample |= parity(sample & ~0xf8000000);
++
++			*dst++ = sample;
++		} while (--i);
++	} while (src < end);
++}
++
++static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
++	struct snd_pcm_runtime *runtime)
++{
++	uint8_t cs[4];
++	unsigned ch, i, j;
++
++	cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
++	cs[1] = IEC958_AES1_CON_GENERAL;
++	cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC;
++	cs[3] = IEC958_AES3_CON_CLOCK_1000PPM;
++
++	switch (runtime->rate) {
++	case 32000:
++		cs[3] |= IEC958_AES3_CON_FS_32000;
++		break;
++	case 44100:
++		cs[3] |= IEC958_AES3_CON_FS_44100;
++		break;
++	case 48000:
++		cs[3] |= IEC958_AES3_CON_FS_48000;
++		break;
++	case 88200:
++		cs[3] |= IEC958_AES3_CON_FS_88200;
++		break;
++	case 96000:
++		cs[3] |= IEC958_AES3_CON_FS_96000;
++		break;
++	case 176400:
++		cs[3] |= IEC958_AES3_CON_FS_176400;
++		break;
++	case 192000:
++		cs[3] |= IEC958_AES3_CON_FS_192000;
++		break;
++	}
++
++	memset(dw->cs, 0, sizeof(dw->cs));
++
++	for (ch = 0; ch < 8; ch++) {
++		cs[2] &= ~IEC958_AES2_CON_CHANNEL;
++		cs[2] |= (ch + 1) << 4;
++
++		for (i = 0; i < ARRAY_SIZE(cs); i++) {
++			unsigned c = cs[i];
++
++			for (j = 0; j < 8; j++, c >>= 1)
++				dw->cs[i * 8 + j][ch] = (c & 1) << 2;
++		}
++	}
++	dw->cs[0][0] |= BIT(4);
++}
++
++static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw)
++{
++	void __iomem *base = dw->data.base;
++	unsigned offset = dw->buf_offset;
++	unsigned period = dw->buf_period;
++	u32 start, stop;
++
++	dw->reformat(dw, offset, period);
++
++	/* Clear all irqs before enabling irqs and starting DMA */
++	writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL,
++		       base + HDMI_IH_AHBDMAAUD_STAT0);
++
++	start = dw->buf_addr + offset;
++	stop = start + period - 1;
++
++	/* Setup the hardware start/stop addresses */
++	dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0);
++	dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0);
++
++	writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK);
++	writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START);
++
++	offset += period;
++	if (offset >= dw->buf_size)
++		offset = 0;
++	dw->buf_offset = offset;
++}
++
++static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw)
++{
++	dw->substream = NULL;
++
++	/* Disable interrupts before disabling DMA */
++	writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK);
++	writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP);
++	synchronize_irq(dw->data.irq);
++}
++
++static irqreturn_t snd_dw_hdmi_irq(int irq, void *data)
++{
++	struct snd_dw_hdmi *dw = data;
++	struct snd_pcm_substream *substream;
++	unsigned stat;
++
++	stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
++	if (!stat)
++		return IRQ_NONE;
++
++	writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
++
++	substream = dw->substream;
++	if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) {
++		snd_pcm_period_elapsed(substream);
++		if (dw->substream)
++			dw_hdmi_start_dma(dw);
++	}
++
++	return IRQ_HANDLED;
++}
++
++static struct snd_pcm_hardware dw_hdmi_hw = {
++	.info = SNDRV_PCM_INFO_INTERLEAVED |
++		SNDRV_PCM_INFO_BLOCK_TRANSFER |
++		SNDRV_PCM_INFO_MMAP |
++		SNDRV_PCM_INFO_MMAP_VALID,
++	.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
++		   SNDRV_PCM_FMTBIT_S24_LE,
++	.rates = SNDRV_PCM_RATE_32000 |
++		 SNDRV_PCM_RATE_44100 |
++		 SNDRV_PCM_RATE_48000 |
++		 SNDRV_PCM_RATE_88200 |
++		 SNDRV_PCM_RATE_96000 |
++		 SNDRV_PCM_RATE_176400 |
++		 SNDRV_PCM_RATE_192000,
++	.channels_min = 2,
++	.channels_max = 8,
++	.buffer_bytes_max = 64 * 1024,
++	.period_bytes_min = 256,
++	.period_bytes_max = 8192,	/* ERR004323: must limit to 8k */
++	.periods_min = 2,
++	.periods_max = 16,
++	.fifo_size = 0,
++};
++
++static unsigned rates_mask[] = {
++	SNDRV_PCM_RATE_32000,
++	SNDRV_PCM_RATE_44100,
++	SNDRV_PCM_RATE_48000,
++	SNDRV_PCM_RATE_88200,
++	SNDRV_PCM_RATE_96000,
++	SNDRV_PCM_RATE_176400,
++	SNDRV_PCM_RATE_192000,
++};
++
++static void dw_hdmi_parse_eld(struct snd_dw_hdmi *dw,
++	struct snd_pcm_runtime *runtime)
++{
++	u8 *sad, *eld = dw->data.eld;
++	unsigned eld_ver,  mnl, sad_count, rates, rate_mask, i;
++	unsigned max_channels;
++
++	eld_ver = eld[0] >> 3;
++	if (eld_ver != 2 && eld_ver != 31)
++		return;
++
++	mnl = eld[4] & 0x1f;
++	if (mnl > 16)
++		return;
++
++	sad_count = eld[5] >> 4;
++	sad = eld + 20 + mnl;
++
++	/* Start from the basic audio settings */
++	max_channels = 2;
++	rates = 7;
++	while (sad_count > 0) {
++		switch (sad[0] & 0x78) {
++		case 0x08: /* PCM */
++			max_channels = max(max_channels, (sad[0] & 7) + 1u);
++			rates |= sad[1];
++			break;
++		}
++		sad += 3;
++		sad_count -= 1;
++	}
++
++	for (rate_mask = i = 0; i < ARRAY_SIZE(rates_mask); i++)
++		if (rates & 1 << i)
++			rate_mask |= rates_mask[i];
++
++	runtime->hw.rates &= rate_mask;
++	runtime->hw.channels_max = min(runtime->hw.channels_max, max_channels);
++}
++
++static int dw_hdmi_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_dw_hdmi *dw = substream->private_data;
++	void __iomem *base = dw->data.base;
++	int ret;
++
++	/* Clear FIFO */
++	writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST,
++		       base + HDMI_AHB_DMA_CONF0);
++
++	/* Configure interrupt polarities */
++	writeb_relaxed(~0, base + HDMI_AHB_DMA_POL);
++	writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL);
++
++	/* Keep interrupts masked, and clear any pending */
++	writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK);
++	writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0);
++
++	ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
++			  "dw-hdmi-audio", dw);
++	if (ret)
++		return ret;
++
++	/* Un-mute done interrupt */
++	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL &
++		       ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE,
++		       base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
++
++	runtime->hw = dw_hdmi_hw;
++	dw_hdmi_parse_eld(dw, runtime);
++	snd_pcm_limit_hw_rates(runtime);
++	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
++
++	return 0;
++}
++
++static int dw_hdmi_close(struct snd_pcm_substream *substream)
++{
++	struct snd_dw_hdmi *dw = substream->private_data;
++
++	/* Mute all interrupts */
++	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
++		       dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
++
++	free_irq(dw->data.irq, dw);
++
++	return 0;
++}
++
++static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
++{
++	return snd_pcm_lib_free_vmalloc_buffer(substream);
++}
++
++static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
++						params_buffer_bytes(params));
++}
++
++static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_dw_hdmi *dw = substream->private_data;
++	uint8_t threshold, conf0, conf1;
++
++	/* Setup as per 3.0.5 FSL 4.1.0 BSP */
++	switch (dw->revision) {
++	case 0x0a:
++		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
++			HDMI_AHB_DMA_CONF0_INCR4;
++		if (runtime->channels == 2)
++			threshold = 126;
++		else
++			threshold = 124;
++		break;
++	case 0x1a:
++		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
++			HDMI_AHB_DMA_CONF0_INCR8;
++		threshold = 128;
++		break;
++	default:
++		/* NOTREACHED */
++		return -EINVAL;
++	}
++
++	dw->data.set_sample_rate(dw->data.hdmi, runtime->rate);
++
++	/* Minimum number of bytes in the fifo. */
++	runtime->hw.fifo_size = threshold * 32;
++
++	conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK;
++	conf1 = (1 << runtime->channels) - 1;
++
++	writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD);
++	writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0);
++	writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1);
++
++	switch (runtime->format) {
++	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
++		dw->reformat = dw_hdmi_reformat_iec958;
++		break;
++	case SNDRV_PCM_FORMAT_S24_LE:
++		dw_hdmi_create_cs(dw, runtime);
++		dw->reformat = dw_hdmi_reformat_s24;
++		break;
++	}
++	dw->iec_offset = 0;
++	dw->channels = runtime->channels;
++	dw->buf_src  = runtime->dma_area;
++	dw->buf_dst  = substream->dma_buffer.area;
++	dw->buf_addr = substream->dma_buffer.addr;
++	dw->buf_period = snd_pcm_lib_period_bytes(substream);
++	dw->buf_size = snd_pcm_lib_buffer_bytes(substream);
++
++	return 0;
++}
++
++static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct snd_dw_hdmi *dw = substream->private_data;
++	void __iomem *base = dw->data.base;
++	unsigned n[3], cts[3];
++	int ret = 0, i;
++	bool err005174;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		err005174 = dw->revision == 0x0a;
++		if (err005174) {
++			for (i = 2; i >= 1; i--) {
++				n[i] = readb_relaxed(base + HDMI_AUD_N1 + i);
++				cts[i] = readb_relaxed(base + HDMI_AUD_CTS1 + i);
++				writeb_relaxed(0, base + HDMI_AUD_N1 + i);
++				writeb_relaxed(0, base + HDMI_AUD_CTS1 + i);
++			}
++		}
++
++		dw->buf_offset = 0;
++		dw->substream = substream;
++		dw_hdmi_start_dma(dw);
++
++		if (err005174) {
++			for (i = 2; i >= 1; i--)
++				writeb_relaxed(cts[i], base + HDMI_AUD_CTS1 + i);
++			for (i = 2; i >= 1; i--)
++				writeb_relaxed(n[i], base + HDMI_AUD_N1 + i);
++		}
++
++		substream->runtime->delay = substream->runtime->period_size;
++		break;
++
++	case SNDRV_PCM_TRIGGER_STOP:
++		dw_hdmi_stop_dma(dw);
++		break;
++
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_dw_hdmi *dw = substream->private_data;
++
++	return bytes_to_frames(runtime, dw->buf_offset);
++}
++
++static struct snd_pcm_ops snd_dw_hdmi_ops = {
++	.open = dw_hdmi_open,
++	.close = dw_hdmi_close,
++	.ioctl = snd_pcm_lib_ioctl,
++	.hw_params = dw_hdmi_hw_params,
++	.hw_free = dw_hdmi_hw_free,
++	.prepare = dw_hdmi_prepare,
++	.trigger = dw_hdmi_trigger,
++	.pointer = dw_hdmi_pointer,
++	.page = snd_pcm_lib_get_vmalloc_page,
++};
++
++static int snd_dw_hdmi_probe(struct platform_device *pdev)
++{
++	const struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
++	struct device *dev = pdev->dev.parent;
++	struct snd_dw_hdmi *dw;
++	struct snd_card *card;
++	struct snd_pcm *pcm;
++	unsigned revision;
++	int ret;
++
++	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
++		       data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
++	revision = readb_relaxed(data->base + HDMI_REVISION_ID);
++	if (revision != 0x0a && revision != 0x1a) {
++		dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n",
++			revision);
++		return -ENXIO;
++	}
++
++	ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
++			      THIS_MODULE, sizeof(struct snd_dw_hdmi), &card);
++	if (ret < 0)
++		return ret;
++
++	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
++	strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname));
++	snprintf(card->longname, sizeof(card->longname),
++		 "%s rev 0x%02x, irq %d", card->shortname, revision,
++		 data->irq);
++
++	dw = card->private_data;
++	dw->card = card;
++	dw->data = *data;
++	dw->revision = revision;
++
++	ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm);
++	if (ret < 0)
++		goto err;
++
++	dw->pcm = pcm;
++	pcm->private_data = dw;
++	strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
++	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops);
++
++	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++			dev, 64 * 1024, 64 * 1024);
++
++	ret = snd_card_register(card);
++	if (ret < 0)
++		goto err;
++
++	platform_set_drvdata(pdev, dw);
++
++	return 0;
++
++err:
++	snd_card_free(card);
++	return ret;
++}
++
++static int snd_dw_hdmi_remove(struct platform_device *pdev)
++{
++	struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
++
++	snd_card_free(dw->card);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int snd_dw_hdmi_suspend(struct device *dev)
++{
++	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
++
++	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
++	snd_pcm_suspend_all(dw->pcm);
++
++	return 0;
++}
++
++static int snd_dw_hdmi_resume(struct device *dev)
++{
++	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
++
++	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0);
++
++	return 0;
++}
++
++static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
++			 snd_dw_hdmi_resume);
++#define PM_OPS &snd_dw_hdmi_pm
++#else
++#define PM_OPS NULL
++#endif
++
++static struct platform_driver snd_dw_hdmi_driver = {
++	.probe	= snd_dw_hdmi_probe,
++	.remove	= snd_dw_hdmi_remove,
++	.driver	= {
++		.name = "dw-hdmi-audio",
++		.owner = THIS_MODULE,
++		.pm = PM_OPS,
++	},
++};
++
++module_platform_driver(snd_dw_hdmi_driver);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-audio.h linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-audio.h
+--- linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-audio.h	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-audio.h	2014-10-23 12:36:44.258220010 -0500
+@@ -0,0 +1,15 @@
++#ifndef DW_HDMI_AUDIO_H
++#define DW_HDMI_AUDIO_H
++
++struct imx_hdmi;
++
++struct dw_hdmi_audio_data {
++	phys_addr_t phys;
++	void __iomem *base;
++	int irq;
++	struct imx_hdmi *hdmi;
++	u8 *eld;
++	void (*set_sample_rate)(struct imx_hdmi *, unsigned);
++};
++
++#endif
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-cec.c linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-cec.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-cec.c	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-cec.c	2014-10-23 12:37:23.890220362 -0500
+@@ -0,0 +1,207 @@
++/* http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c?h=imx_3.0.35_4.1.0 */
++#include <linux/cec-dev.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++
++#include "imx-hdmi.h"
++#include "dw-hdmi-cec.h"
++
++#define DEV_NAME "mxc_hdmi_cec"
++
++enum {
++	CEC_STAT_DONE		= BIT(0),
++	CEC_STAT_EOM		= BIT(1),
++	CEC_STAT_NACK		= BIT(2),
++	CEC_STAT_ARBLOST	= BIT(3),
++	CEC_STAT_ERROR_INIT	= BIT(4),
++	CEC_STAT_ERROR_FOLL	= BIT(5),
++	CEC_STAT_WAKEUP		= BIT(6),
++
++	CEC_CTRL_START		= BIT(0),
++	CEC_CTRL_NORMAL		= 1 << 1,
++};
++
++struct dw_hdmi_cec {
++	struct cec_dev cec;
++
++	struct device *dev;
++	void __iomem *base;
++	const struct dw_hdmi_cec_ops *ops;
++	void *ops_data;
++	int irq;
++};
++
++static void dw_hdmi_set_address(struct cec_dev *cec_dev, unsigned addresses)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++
++	writeb(addresses & 255, cec->base + HDMI_CEC_ADDR_L);
++	writeb(addresses >> 8, cec->base + HDMI_CEC_ADDR_H);
++}
++
++static void dw_hdmi_send_message(struct cec_dev *cec_dev, u8 *msg,
++	size_t count)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++	unsigned i;
++
++	for (i = 0; i < count; i++)
++		writeb(msg[i], cec->base + HDMI_CEC_TX_DATA0 + i);
++
++	writeb(count, cec->base + HDMI_CEC_TX_CNT);
++	writeb(CEC_CTRL_NORMAL | CEC_CTRL_START, cec->base + HDMI_CEC_CTRL);
++}
++
++static irqreturn_t dw_hdmi_cec_irq(int irq, void *data)
++{
++	struct dw_hdmi_cec *cec = data;
++	struct cec_dev *cec_dev = &cec->cec;
++	unsigned stat = readb(cec->base + HDMI_IH_CEC_STAT0);
++
++	if (stat == 0)
++		return IRQ_NONE;
++
++	writeb(stat, cec->base + HDMI_IH_CEC_STAT0);
++
++	if (stat & CEC_STAT_ERROR_INIT) {
++		if (cec->cec.retries) {
++			unsigned v = readb(cec->base + HDMI_CEC_CTRL);
++			writeb(v | CEC_CTRL_START, cec->base + HDMI_CEC_CTRL);
++			cec->cec.retries -= 1;
++		} else {
++			cec->cec.write_busy = 0;
++			cec_dev_event(cec_dev, MESSAGE_TYPE_SEND_ERROR, NULL, 0);
++		}
++	} else if (stat & (CEC_STAT_DONE | CEC_STAT_NACK))
++		cec_dev_send_complete(cec_dev, stat & CEC_STAT_DONE);
++
++	if (stat & CEC_STAT_EOM) {
++		unsigned len, i;
++		u8 msg[MAX_MESSAGE_LEN];
++
++		len = readb(cec->base + HDMI_CEC_RX_CNT);
++		if (len > sizeof(msg))
++			len = sizeof(msg);
++
++		for (i = 0; i < len; i++)
++			msg[i] = readb(cec->base + HDMI_CEC_RX_DATA0 + i);
++
++		writeb(0, cec->base + HDMI_CEC_LOCK);
++
++		cec_dev_receive(cec_dev, msg, len);
++	}
++
++	return IRQ_HANDLED;
++}
++EXPORT_SYMBOL(dw_hdmi_cec_irq);
++
++static void dw_hdmi_cec_release(struct cec_dev *cec_dev)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++
++	writeb(~0, cec->base + HDMI_CEC_MASK);
++	writeb(~0, cec->base + HDMI_IH_MUTE_CEC_STAT0);
++	writeb(0, cec->base + HDMI_CEC_POLARITY);
++
++	free_irq(cec->irq, cec);
++
++	cec->ops->disable(cec->ops_data);
++}
++
++static int dw_hdmi_cec_open(struct cec_dev *cec_dev)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++	unsigned irqs;
++	int ret;
++
++	writeb(0, cec->base + HDMI_CEC_CTRL);
++	writeb(~0, cec->base + HDMI_IH_CEC_STAT0);
++	writeb(0, cec->base + HDMI_CEC_LOCK);
++
++	ret = request_irq(cec->irq, dw_hdmi_cec_irq, IRQF_SHARED,
++			  DEV_NAME, cec);
++	if (ret < 0)
++		return ret;
++
++	dw_hdmi_set_address(cec_dev, cec_dev->addresses);
++
++	cec->ops->enable(cec->ops_data);
++
++	irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM |
++	       CEC_STAT_DONE;
++	writeb(irqs, cec->base + HDMI_CEC_POLARITY);
++	writeb(~irqs, cec->base + HDMI_CEC_MASK);
++	writeb(~irqs, cec->base + HDMI_IH_MUTE_CEC_STAT0);
++
++	return 0;
++}
++
++static int dw_hdmi_cec_probe(struct platform_device *pdev)
++{
++	struct dw_hdmi_cec_data *data = dev_get_platdata(&pdev->dev);
++	struct dw_hdmi_cec *cec;
++
++	if (!data)
++		return -ENXIO;
++
++	cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
++	if (!cec)
++		return -ENOMEM;
++
++	cec->dev = &pdev->dev;
++	cec->base = data->base;
++	cec->irq = data->irq;
++	cec->ops = data->ops;
++	cec->ops_data = data->ops_data;
++	cec->cec.open = dw_hdmi_cec_open;
++	cec->cec.release = dw_hdmi_cec_release;
++	cec->cec.send_message = dw_hdmi_send_message;
++	cec->cec.set_address = dw_hdmi_set_address;
++
++	cec_dev_init(&cec->cec, THIS_MODULE);
++
++	/* FIXME: soft-reset the CEC interface */
++
++	dw_hdmi_set_address(&cec->cec, cec->cec.addresses);
++	writeb(0, cec->base + HDMI_CEC_TX_CNT);
++	writeb(~0, cec->base + HDMI_CEC_MASK);
++	writeb(~0, cec->base + HDMI_IH_MUTE_CEC_STAT0);
++	writeb(0, cec->base + HDMI_CEC_POLARITY);
++
++	platform_set_drvdata(pdev, cec);
++
++	/*
++	 * Our device is just a convenience - we want to link to the real
++	 * hardware device here, so that userspace can see the association
++	 * between the HDMI hardware and its associated CEC chardev.
++	 */
++	return cec_dev_add(&cec->cec, cec->dev->parent, DEV_NAME);
++}
++
++static int dw_hdmi_cec_remove(struct platform_device *pdev)
++{
++	struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
++
++	cec_dev_remove(&cec->cec);
++
++	return 0;
++}
++
++static struct platform_driver dw_hdmi_cec_driver = {
++	.probe	= dw_hdmi_cec_probe,
++	.remove	= dw_hdmi_cec_remove,
++	.driver = {
++		.name = "dw-hdmi-cec",
++		.owner = THIS_MODULE,
++	},
++};
++module_platform_driver(dw_hdmi_cec_driver);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_DESCRIPTION("Synopsis Designware HDMI CEC driver for i.MX");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS(PLATFORM_MODULE_PREFIX "dw-hdmi-cec");
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-cec.h linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-cec.h
+--- linux-3.16.6.orig/drivers/staging/imx-drm/dw-hdmi-cec.h	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/dw-hdmi-cec.h	2014-10-23 12:37:23.890220362 -0500
+@@ -0,0 +1,16 @@
++#ifndef DW_HDMI_CEC_H
++#define DW_HDMI_CEC_H
++
++struct dw_hdmi_cec_ops {
++	void (*enable)(void *);
++	void (*disable)(void *);
++};
++
++struct dw_hdmi_cec_data {
++	void __iomem *base;
++	int irq;
++	const struct dw_hdmi_cec_ops *ops;
++	void *ops_data;
++};
++
++#endif
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/imx-drm-core.c linux-3.16.6/drivers/staging/imx-drm/imx-drm-core.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/imx-drm-core.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/imx-drm-core.c	2014-10-23 12:37:37.690220197 -0500
+@@ -115,8 +115,7 @@
+ 	helper = &imx_crtc->imx_drm_helper_funcs;
+ 	if (helper->set_interface_pix_fmt)
+ 		return helper->set_interface_pix_fmt(encoder->crtc,
+-				encoder->encoder_type, interface_pix_fmt,
+-				hsync_pin, vsync_pin);
++				interface_pix_fmt, hsync_pin, vsync_pin);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/imx-drm.h linux-3.16.6/drivers/staging/imx-drm/imx-drm.h
+--- linux-3.16.6.orig/drivers/staging/imx-drm/imx-drm.h	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/imx-drm.h	2014-10-23 12:37:37.690220197 -0500
+@@ -17,7 +17,7 @@
+ struct imx_drm_crtc_helper_funcs {
+ 	int (*enable_vblank)(struct drm_crtc *crtc);
+ 	void (*disable_vblank)(struct drm_crtc *crtc);
+-	int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
++	int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
+ 			u32 pix_fmt, int hsync_pin, int vsync_pin);
+ 	const struct drm_crtc_helper_funcs *crtc_helper_funcs;
+ 	const struct drm_crtc_funcs *crtc_funcs;
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/imx-hdmi.c linux-3.16.6/drivers/staging/imx-drm/imx-hdmi.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/imx-hdmi.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/imx-hdmi.c	2014-10-23 12:37:30.178219970 -0500
+@@ -29,6 +29,9 @@
+ #include <drm/drm_encoder_slave.h>
+ #include <video/imx-ipu-v3.h>
+ 
++#include "drm-ddc-connector.h"
++#include "dw-hdmi-audio.h"
++#include "dw-hdmi-cec.h"
+ #include "imx-hdmi.h"
+ #include "imx-drm.h"
+ 
+@@ -112,9 +115,11 @@
+ };
+ 
+ struct imx_hdmi {
+-	struct drm_connector connector;
++	struct drm_ddc_connector *ddc_conn;
+ 	struct drm_encoder encoder;
+ 
++	struct platform_device *audio;
++	struct platform_device *cec;
+ 	enum imx_hdmi_devtype dev_type;
+ 	struct device *dev;
+ 	struct clk *isfr_clk;
+@@ -124,13 +129,13 @@
+ 	int vic;
+ 
+ 	u8 edid[HDMI_EDID_LEN];
++	u8 mc_clkdis;
+ 	bool cable_plugin;
+ 
+ 	bool phy_enabled;
+ 	struct drm_display_mode previous_mode;
+ 
+ 	struct regmap *regmap;
+-	struct i2c_adapter *ddc;
+ 	void __iomem *regs;
+ 
+ 	unsigned int sample_rate;
+@@ -361,6 +366,12 @@
+ 	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
+ }
+ 
++static void imx_hdmi_set_sample_rate(struct imx_hdmi *hdmi, unsigned rate)
++{
++	hdmi->sample_rate = rate;
++	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
++}
++
+ /*
+  * this submodule is responsible for the video data synchronization.
+  * for example, for RGB 4:4:4 input, the data map is defined as
+@@ -1144,8 +1155,6 @@
+ /* 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);
+@@ -1157,23 +1166,28 @@
+ 	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);
++	hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE |
++			   HDMI_MC_CLKDIS_CSCCLK_DISABLE |
++			   HDMI_MC_CLKDIS_AUDCLK_DISABLE |
++			   HDMI_MC_CLKDIS_PREPCLK_DISABLE |
++			   HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ 
+-	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+-	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_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);
++		hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
++		hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ 	}
+ }
+ 
+ static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
+ {
+-	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ }
+ 
+ /* Workaround to clear the overflow condition */
+@@ -1376,43 +1390,16 @@
+ static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
+ 							*connector, bool force)
+ {
+-	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+-					     connector);
++	struct imx_hdmi *hdmi = drm_ddc_private(connector);
+ 
+ 	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
+ 		connector_status_connected : connector_status_disconnected;
+ }
+ 
+-static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
+-{
+-	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+-					     connector);
+-	struct edid *edid;
+-	int ret;
+-
+-	if (!hdmi->ddc)
+-		return 0;
+-
+-	edid = drm_get_edid(connector, hdmi->ddc);
+-	if (edid) {
+-		dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
+-			edid->width_cm, edid->height_cm);
+-
+-		drm_mode_connector_update_edid_property(connector, edid);
+-		ret = drm_add_edid_modes(connector, edid);
+-		kfree(edid);
+-	} else {
+-		dev_dbg(hdmi->dev, "failed to get edid\n");
+-	}
+-
+-	return 0;
+-}
+-
+ static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
+ 							   *connector)
+ {
+-	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+-					     connector);
++	struct imx_hdmi *hdmi = drm_ddc_private(connector);
+ 
+ 	return &hdmi->encoder;
+ }
+@@ -1485,11 +1472,11 @@
+ 	.dpms = drm_helper_connector_dpms,
+ 	.fill_modes = drm_helper_probe_single_connector_modes,
+ 	.detect = imx_hdmi_connector_detect,
+-	.destroy = imx_drm_connector_destroy,
++	.destroy = drm_ddc_connector_destroy,
+ };
+ 
+ static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
+-	.get_modes = imx_hdmi_connector_get_modes,
++	.get_modes = drm_ddc_connector_get_modes,
+ 	.best_encoder = imx_hdmi_connector_best_encoder,
+ };
+ 
+@@ -1530,7 +1517,7 @@
+ 
+ 			imx_hdmi_poweroff(hdmi);
+ 		}
+-		drm_helper_hpd_irq_event(hdmi->connector.dev);
++		drm_helper_hpd_irq_event(hdmi->ddc_conn->connector.dev);
+ 	}
+ 
+ 	hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
+@@ -1548,24 +1535,43 @@
+ 	if (ret)
+ 		return ret;
+ 
+-	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
++	hdmi->ddc_conn->connector.polled = DRM_CONNECTOR_POLL_HPD;
+ 
+ 	drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
+ 	drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
+ 			 DRM_MODE_ENCODER_TMDS);
+ 
+-	drm_connector_helper_add(&hdmi->connector,
++	drm_connector_helper_add(&hdmi->ddc_conn->connector,
+ 			&imx_hdmi_connector_helper_funcs);
+-	drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
+-			   DRM_MODE_CONNECTOR_HDMIA);
++	drm_ddc_connector_add(drm, hdmi->ddc_conn, &imx_hdmi_connector_funcs,
++			      DRM_MODE_CONNECTOR_HDMIA);
+ 
+-	hdmi->connector.encoder = &hdmi->encoder;
+-
+-	drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
++	drm_mode_connector_attach_encoder(&hdmi->ddc_conn->connector, &hdmi->encoder);
+ 
+ 	return 0;
+ }
+ 
++static void imx_hdmi_cec_enable(void *data)
++{
++	struct imx_hdmi *hdmi = data;
++
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
++}
++
++static void imx_hdmi_cec_disable(void *data)
++{
++	struct imx_hdmi *hdmi = data;
++
++	hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
++}
++
++static const struct dw_hdmi_cec_ops imx_hdmi_cec_ops = {
++	.enable = imx_hdmi_cec_enable,
++	.disable = imx_hdmi_cec_disable,
++};
++
+ static struct platform_device_id imx_hdmi_devtype[] = {
+ 	{
+ 		.name = "imx6q-hdmi",
+@@ -1587,11 +1593,13 @@
+ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
+ {
+ 	struct platform_device *pdev = to_platform_device(dev);
++	struct platform_device_info pdevinfo;
+ 	const struct of_device_id *of_id =
+ 				of_match_device(imx_hdmi_dt_ids, dev);
+ 	struct drm_device *drm = data;
+ 	struct device_node *np = dev->of_node;
+-	struct device_node *ddc_node;
++	struct dw_hdmi_audio_data audio;
++	struct dw_hdmi_cec_data cec;
+ 	struct imx_hdmi *hdmi;
+ 	struct resource *iores;
+ 	int ret, irq;
+@@ -1600,9 +1608,14 @@
+ 	if (!hdmi)
+ 		return -ENOMEM;
+ 
++	hdmi->ddc_conn = drm_ddc_connector_create(drm, np, hdmi);
++	if (IS_ERR(hdmi->ddc_conn))
++		return PTR_ERR(hdmi->ddc_conn);
++
+ 	hdmi->dev = dev;
+ 	hdmi->sample_rate = 48000;
+ 	hdmi->ratio = 100;
++	hdmi->mc_clkdis = 0x7f;
+ 
+ 	if (of_id) {
+ 		const struct platform_device_id *device_id = of_id->data;
+@@ -1610,17 +1623,6 @@
+ 		hdmi->dev_type = device_id->driver_data;
+ 	}
+ 
+-	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");
+-
+-		of_node_put(ddc_node);
+-	} else {
+-		dev_dbg(hdmi->dev, "no ddc property found\n");
+-	}
+-
+ 	irq = platform_get_irq(pdev, 0);
+ 	if (irq < 0)
+ 		return irq;
+@@ -1706,6 +1708,35 @@
+ 	/* Unmute interrupts */
+ 	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ 
++	memset(&pdevinfo, 0, sizeof(pdevinfo));
++	pdevinfo.parent = dev;
++	pdevinfo.id = PLATFORM_DEVID_AUTO;
++
++	audio.phys = iores->start;
++	audio.base = hdmi->regs;
++	audio.irq = irq;
++	audio.hdmi = hdmi;
++	audio.eld = hdmi->ddc_conn->connector.eld;
++	audio.set_sample_rate = imx_hdmi_set_sample_rate;
++
++	pdevinfo.name = "dw-hdmi-audio";
++	pdevinfo.data = &audio;
++	pdevinfo.size_data = sizeof(audio);
++	pdevinfo.dma_mask = DMA_BIT_MASK(32);
++	hdmi->audio = platform_device_register_full(&pdevinfo);
++
++	cec.base = hdmi->regs;
++	cec.irq = irq;
++	cec.ops = &imx_hdmi_cec_ops;
++	cec.ops_data = hdmi;
++
++	pdevinfo.name = "dw-hdmi-cec";
++	pdevinfo.data = &cec;
++	pdevinfo.size_data = sizeof(cec);
++	pdevinfo.dma_mask = 0;
++
++	hdmi->cec = platform_device_register_full(&pdevinfo);
++
+ 	dev_set_drvdata(dev, hdmi);
+ 
+ 	return 0;
+@@ -1723,15 +1754,18 @@
+ {
+ 	struct imx_hdmi *hdmi = dev_get_drvdata(dev);
+ 
++	if (!IS_ERR(hdmi->audio))
++		platform_device_unregister(hdmi->audio);
++	if (!IS_ERR(hdmi->cec))
++		platform_device_unregister(hdmi->cec);
++
+ 	/* Disable all interrupts */
+ 	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+ 
+-	hdmi->connector.funcs->destroy(&hdmi->connector);
+ 	hdmi->encoder.funcs->destroy(&hdmi->encoder);
+ 
+ 	clk_disable_unprepare(hdmi->iahb_clk);
+ 	clk_disable_unprepare(hdmi->isfr_clk);
+-	i2c_put_adapter(hdmi->ddc);
+ }
+ 
+ static const struct component_ops hdmi_ops = {
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/imx-ldb.c linux-3.16.6/drivers/staging/imx-drm/imx-ldb.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/imx-ldb.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/imx-ldb.c	2014-10-23 12:35:16.922220006 -0500
+@@ -24,6 +24,7 @@
+ #include <drm/drmP.h>
+ #include <drm/drm_fb_helper.h>
+ #include <drm/drm_crtc_helper.h>
++#include <drm/drm_panel.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+ #include <linux/of_address.h>
+@@ -60,6 +61,7 @@
+ 	struct imx_ldb *ldb;
+ 	struct drm_connector connector;
+ 	struct drm_encoder encoder;
++	struct drm_panel *panel;
+ 	struct device_node *child;
+ 	int chno;
+ 	void *edid;
+@@ -96,6 +98,13 @@
+ 	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
+ 	int num_modes = 0;
+ 
++	if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs &&
++	    imx_ldb_ch->panel->funcs->get_modes) {
++		num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel);
++		if (num_modes > 0)
++			return num_modes;
++	}
++
+ 	if (imx_ldb_ch->edid) {
+ 		drm_mode_connector_update_edid_property(connector,
+ 							imx_ldb_ch->edid);
+@@ -243,6 +252,8 @@
+ 	}
+ 
+ 	regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
++
++	drm_panel_enable(imx_ldb_ch->panel);
+ }
+ 
+ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
+@@ -294,6 +305,8 @@
+ 		 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
+ 		return;
+ 
++	drm_panel_disable(imx_ldb_ch->panel);
++
+ 	if (imx_ldb_ch == &ldb->channel[0])
+ 		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
+ 	else if (imx_ldb_ch == &ldb->channel[1])
+@@ -378,6 +391,9 @@
+ 	drm_connector_init(drm, &imx_ldb_ch->connector,
+ 			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
+ 
++	if (imx_ldb_ch->panel)
++		drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector);
++
+ 	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
+ 			&imx_ldb_ch->encoder);
+ 
+@@ -492,6 +508,7 @@
+ 
+ 	for_each_child_of_node(np, child) {
+ 		struct imx_ldb_channel *channel;
++		struct device_node *panel_node;
+ 
+ 		ret = of_property_read_u32(child, "reg", &i);
+ 		if (ret || i < 0 || i > 1)
+@@ -555,6 +572,10 @@
+ 			return -EINVAL;
+ 		}
+ 
++		panel_node = of_parse_phandle(child, "fsl,panel", 0);
++		if (panel_node)
++			channel->panel = of_drm_find_panel(panel_node);
++
+ 		ret = imx_ldb_register(drm, channel);
+ 		if (ret)
+ 			return ret;
+@@ -574,9 +595,6 @@
+ 	for (i = 0; i < 2; i++) {
+ 		struct imx_ldb_channel *channel = &imx_ldb->channel[i];
+ 
+-		if (!channel->connector.funcs)
+-			continue;
+-
+ 		channel->connector.funcs->destroy(&channel->connector);
+ 		channel->encoder.funcs->destroy(&channel->encoder);
+ 	}
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/imx-ldb.c.orig linux-3.16.6/drivers/staging/imx-drm/imx-ldb.c.orig
+--- linux-3.16.6.orig/drivers/staging/imx-drm/imx-ldb.c.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/imx-ldb.c.orig	2014-10-15 05:05:43.000000000 -0500
+@@ -0,0 +1,616 @@
++/*
++ * i.MX drm driver - LVDS display bridge
++ *
++ * 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 <linux/module.h>
++#include <linux/clk.h>
++#include <linux/component.h>
++#include <drm/drmP.h>
++#include <drm/drm_fb_helper.h>
++#include <drm/drm_crtc_helper.h>
++#include <linux/mfd/syscon.h>
++#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <video/of_videomode.h>
++#include <linux/regmap.h>
++#include <linux/videodev2.h>
++
++#include "imx-drm.h"
++
++#define DRIVER_NAME "imx-ldb"
++
++#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)
++
++#define con_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, connector)
++#define enc_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, encoder)
++
++struct imx_ldb;
++
++struct imx_ldb_channel {
++	struct imx_ldb *ldb;
++	struct drm_connector connector;
++	struct drm_encoder encoder;
++	struct device_node *child;
++	int chno;
++	void *edid;
++	int edid_len;
++	struct drm_display_mode mode;
++	int mode_valid;
++};
++
++struct bus_mux {
++	int reg;
++	int shift;
++	int mask;
++};
++
++struct imx_ldb {
++	struct regmap *regmap;
++	struct device *dev;
++	struct imx_ldb_channel channel[2];
++	struct clk *clk[2]; /* our own clock */
++	struct clk *clk_sel[4]; /* parent of display clock */
++	struct clk *clk_pll[2]; /* upstream clock we can adjust */
++	u32 ldb_ctrl;
++	const struct bus_mux *lvds_mux;
++};
++
++static enum drm_connector_status imx_ldb_connector_detect(
++		struct drm_connector *connector, bool force)
++{
++	return connector_status_connected;
++}
++
++static int imx_ldb_connector_get_modes(struct drm_connector *connector)
++{
++	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
++	int num_modes = 0;
++
++	if (imx_ldb_ch->edid) {
++		drm_mode_connector_update_edid_property(connector,
++							imx_ldb_ch->edid);
++		num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid);
++	}
++
++	if (imx_ldb_ch->mode_valid) {
++		struct drm_display_mode *mode;
++
++		mode = drm_mode_create(connector->dev);
++		if (!mode)
++			return -EINVAL;
++		drm_mode_copy(mode, &imx_ldb_ch->mode);
++		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
++		drm_mode_probed_add(connector, mode);
++		num_modes++;
++	}
++
++	return num_modes;
++}
++
++static struct drm_encoder *imx_ldb_connector_best_encoder(
++		struct drm_connector *connector)
++{
++	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
++
++	return &imx_ldb_ch->encoder;
++}
++
++static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode)
++{
++}
++
++static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder,
++			   const struct drm_display_mode *mode,
++			   struct drm_display_mode *adjusted_mode)
++{
++	return true;
++}
++
++static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
++		unsigned long serial_clk, unsigned long di_clk)
++{
++	int ret;
++
++	dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
++			clk_get_rate(ldb->clk_pll[chno]), serial_clk);
++	clk_set_rate(ldb->clk_pll[chno], serial_clk);
++
++	dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
++			clk_get_rate(ldb->clk_pll[chno]));
++
++	dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
++			clk_get_rate(ldb->clk[chno]),
++			(long int)di_clk);
++	clk_set_rate(ldb->clk[chno], di_clk);
++
++	dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
++			clk_get_rate(ldb->clk[chno]));
++
++	/* set display clock mux to LDB input clock */
++	ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]);
++	if (ret)
++		dev_err(ldb->dev,
++			"unable to set di%d parent clock to ldb_di%d\n", mux,
++			chno);
++}
++
++static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
++{
++	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
++	struct imx_ldb *ldb = imx_ldb_ch->ldb;
++	struct drm_display_mode *mode = &encoder->crtc->mode;
++	u32 pixel_fmt;
++	unsigned long serial_clk;
++	unsigned long di_clk = mode->clock * 1000;
++	int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
++
++	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
++		/* dual channel LVDS mode */
++		serial_clk = 3500UL * mode->clock;
++		imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
++		imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk);
++	} else {
++		serial_clk = 7000UL * mode->clock;
++		imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk,
++				di_clk);
++	}
++
++	switch (imx_ldb_ch->chno) {
++	case 0:
++		pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ?
++			V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
++		break;
++	case 1:
++		pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ?
++			V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
++		break;
++	default:
++		dev_err(ldb->dev, "unable to config di%d panel format\n",
++			imx_ldb_ch->chno);
++		pixel_fmt = V4L2_PIX_FMT_RGB24;
++	}
++
++	imx_drm_panel_format(encoder, pixel_fmt);
++}
++
++static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
++{
++	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
++	struct imx_ldb *ldb = imx_ldb_ch->ldb;
++	int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
++	int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
++
++	if (dual) {
++		clk_prepare_enable(ldb->clk[0]);
++		clk_prepare_enable(ldb->clk[1]);
++	}
++
++	if (imx_ldb_ch == &ldb->channel[0] || dual) {
++		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
++		if (mux == 0 || ldb->lvds_mux)
++			ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
++		else if (mux == 1)
++			ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1;
++	}
++	if (imx_ldb_ch == &ldb->channel[1] || dual) {
++		ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
++		if (mux == 1 || ldb->lvds_mux)
++			ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1;
++		else if (mux == 0)
++			ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0;
++	}
++
++	if (ldb->lvds_mux) {
++		const struct bus_mux *lvds_mux = NULL;
++
++		if (imx_ldb_ch == &ldb->channel[0])
++			lvds_mux = &ldb->lvds_mux[0];
++		else if (imx_ldb_ch == &ldb->channel[1])
++			lvds_mux = &ldb->lvds_mux[1];
++
++		regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask,
++				   mux << lvds_mux->shift);
++	}
++
++	regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
++}
++
++static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
++			 struct drm_display_mode *mode,
++			 struct drm_display_mode *adjusted_mode)
++{
++	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
++	struct imx_ldb *ldb = imx_ldb_ch->ldb;
++	int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
++
++	if (mode->clock > 170000) {
++		dev_warn(ldb->dev,
++			 "%s: mode exceeds 170 MHz pixel clock\n", __func__);
++	}
++	if (mode->clock > 85000 && !dual) {
++		dev_warn(ldb->dev,
++			 "%s: mode exceeds 85 MHz pixel clock\n", __func__);
++	}
++
++	/* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
++	if (imx_ldb_ch == &ldb->channel[0]) {
++		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
++			ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW;
++		else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
++			ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW;
++	}
++	if (imx_ldb_ch == &ldb->channel[1]) {
++		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
++			ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW;
++		else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
++			ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW;
++	}
++}
++
++static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
++{
++	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
++	struct imx_ldb *ldb = imx_ldb_ch->ldb;
++
++	/*
++	 * imx_ldb_encoder_disable is called by
++	 * drm_helper_disable_unused_functions without
++	 * the encoder being enabled before.
++	 */
++	if (imx_ldb_ch == &ldb->channel[0] &&
++	    (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0)
++		return;
++	else if (imx_ldb_ch == &ldb->channel[1] &&
++		 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
++		return;
++
++	if (imx_ldb_ch == &ldb->channel[0])
++		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
++	else if (imx_ldb_ch == &ldb->channel[1])
++		ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
++
++	regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
++
++	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
++		clk_disable_unprepare(ldb->clk[0]);
++		clk_disable_unprepare(ldb->clk[1]);
++	}
++}
++
++static struct drm_connector_funcs imx_ldb_connector_funcs = {
++	.dpms = drm_helper_connector_dpms,
++	.fill_modes = drm_helper_probe_single_connector_modes,
++	.detect = imx_ldb_connector_detect,
++	.destroy = imx_drm_connector_destroy,
++};
++
++static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
++	.get_modes = imx_ldb_connector_get_modes,
++	.best_encoder = imx_ldb_connector_best_encoder,
++};
++
++static struct drm_encoder_funcs imx_ldb_encoder_funcs = {
++	.destroy = imx_drm_encoder_destroy,
++};
++
++static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
++	.dpms = imx_ldb_encoder_dpms,
++	.mode_fixup = imx_ldb_encoder_mode_fixup,
++	.prepare = imx_ldb_encoder_prepare,
++	.commit = imx_ldb_encoder_commit,
++	.mode_set = imx_ldb_encoder_mode_set,
++	.disable = imx_ldb_encoder_disable,
++};
++
++static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno)
++{
++	char clkname[16];
++
++	snprintf(clkname, sizeof(clkname), "di%d", chno);
++	ldb->clk[chno] = devm_clk_get(ldb->dev, clkname);
++	if (IS_ERR(ldb->clk[chno]))
++		return PTR_ERR(ldb->clk[chno]);
++
++	snprintf(clkname, sizeof(clkname), "di%d_pll", chno);
++	ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
++
++	return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
++}
++
++static int imx_ldb_register(struct drm_device *drm,
++	struct imx_ldb_channel *imx_ldb_ch)
++{
++	struct imx_ldb *ldb = imx_ldb_ch->ldb;
++	int ret;
++
++	ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder,
++				       imx_ldb_ch->child);
++	if (ret)
++		return ret;
++
++	ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno);
++	if (ret)
++		return ret;
++
++	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
++		ret = imx_ldb_get_clk(ldb, 1);
++		if (ret)
++			return ret;
++	}
++
++	drm_encoder_helper_add(&imx_ldb_ch->encoder,
++			&imx_ldb_encoder_helper_funcs);
++	drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
++			 DRM_MODE_ENCODER_LVDS);
++
++	drm_connector_helper_add(&imx_ldb_ch->connector,
++			&imx_ldb_connector_helper_funcs);
++	drm_connector_init(drm, &imx_ldb_ch->connector,
++			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
++
++	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
++			&imx_ldb_ch->encoder);
++
++	return 0;
++}
++
++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 struct bus_mux imx6q_lvds_mux[2] = {
++	{
++		.reg = IOMUXC_GPR3,
++		.shift = 6,
++		.mask = IMX6Q_GPR3_LVDS0_MUX_CTL_MASK,
++	}, {
++		.reg = IOMUXC_GPR3,
++		.shift = 8,
++		.mask = IMX6Q_GPR3_LVDS1_MUX_CTL_MASK,
++	}
++};
++
++/*
++ * For a device declaring compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb",
++ * of_match_device will walk through this list and take the first entry
++ * matching any of its compatible values. Therefore, the more generic
++ * entries (in this case fsl,imx53-ldb) need to be ordered last.
++ */
++static const struct of_device_id imx_ldb_dt_ids[] = {
++	{ .compatible = "fsl,imx6q-ldb", .data = imx6q_lvds_mux, },
++	{ .compatible = "fsl,imx53-ldb", .data = NULL, },
++	{ }
++};
++MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
++
++static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
++{
++	struct drm_device *drm = data;
++	struct device_node *np = dev->of_node;
++	const struct of_device_id *of_id =
++			of_match_device(imx_ldb_dt_ids, dev);
++	struct device_node *child;
++	const u8 *edidp;
++	struct imx_ldb *imx_ldb;
++	int datawidth;
++	int mapping;
++	int dual;
++	int ret;
++	int i;
++
++	imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
++	if (!imx_ldb)
++		return -ENOMEM;
++
++	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
++	if (IS_ERR(imx_ldb->regmap)) {
++		dev_err(dev, "failed to get parent regmap\n");
++		return PTR_ERR(imx_ldb->regmap);
++	}
++
++	imx_ldb->dev = dev;
++
++	if (of_id)
++		imx_ldb->lvds_mux = of_id->data;
++
++	dual = of_property_read_bool(np, "fsl,dual-channel");
++	if (dual)
++		imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
++
++	/*
++	 * There are three different possible clock mux configurations:
++	 * i.MX53:  ipu1_di0_sel, ipu1_di1_sel
++	 * i.MX6q:  ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel
++	 * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel
++	 * Map them all to di0_sel...di3_sel.
++	 */
++	for (i = 0; i < 4; i++) {
++		char clkname[16];
++
++		sprintf(clkname, "di%d_sel", i);
++		imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname);
++		if (IS_ERR(imx_ldb->clk_sel[i])) {
++			ret = PTR_ERR(imx_ldb->clk_sel[i]);
++			imx_ldb->clk_sel[i] = NULL;
++			break;
++		}
++	}
++	if (i == 0)
++		return ret;
++
++	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;
++		channel->child = child;
++
++		edidp = of_get_property(child, "edid", &channel->edid_len);
++		if (edidp) {
++			channel->edid = kmemdup(edidp, channel->edid_len,
++						GFP_KERNEL);
++		} else {
++			ret = of_get_drm_display_mode(child, &channel->mode, 0);
++			if (!ret)
++				channel->mode_valid = 1;
++		}
++
++		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;
++		}
++
++		ret = imx_ldb_register(drm, channel);
++		if (ret)
++			return ret;
++	}
++
++	dev_set_drvdata(dev, imx_ldb);
++
++	return 0;
++}
++
++static void imx_ldb_unbind(struct device *dev, struct device *master,
++	void *data)
++{
++	struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
++	int i;
++
++	for (i = 0; i < 2; i++) {
++		struct imx_ldb_channel *channel = &imx_ldb->channel[i];
++
++		if (!channel->connector.funcs)
++			continue;
++
++		channel->connector.funcs->destroy(&channel->connector);
++		channel->encoder.funcs->destroy(&channel->encoder);
++	}
++}
++
++static const struct component_ops imx_ldb_ops = {
++	.bind	= imx_ldb_bind,
++	.unbind	= imx_ldb_unbind,
++};
++
++static int imx_ldb_probe(struct platform_device *pdev)
++{
++	return component_add(&pdev->dev, &imx_ldb_ops);
++}
++
++static int imx_ldb_remove(struct platform_device *pdev)
++{
++	component_del(&pdev->dev, &imx_ldb_ops);
++	return 0;
++}
++
++static struct platform_driver imx_ldb_driver = {
++	.probe		= imx_ldb_probe,
++	.remove		= imx_ldb_remove,
++	.driver		= {
++		.of_match_table = imx_ldb_dt_ids,
++		.name	= DRIVER_NAME,
++		.owner	= THIS_MODULE,
++	},
++};
++
++module_platform_driver(imx_ldb_driver);
++
++MODULE_DESCRIPTION("i.MX LVDS driver");
++MODULE_AUTHOR("Sascha Hauer, Pengutronix");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" DRIVER_NAME);
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/imx-tve.c linux-3.16.6/drivers/staging/imx-drm/imx-tve.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/imx-tve.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/imx-tve.c	2014-10-23 12:37:30.182220005 -0500
+@@ -22,7 +22,6 @@
+ #include <linux/clk-provider.h>
+ #include <linux/component.h>
+ #include <linux/module.h>
+-#include <linux/i2c.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/spinlock.h>
+@@ -32,6 +31,7 @@
+ #include <drm/drm_crtc_helper.h>
+ #include <video/imx-ipu-v3.h>
+ 
++#include "drm-ddc-connector.h"
+ #include "imx-drm.h"
+ 
+ #define TVE_COM_CONF_REG	0x00
+@@ -111,7 +111,7 @@
+ };
+ 
+ struct imx_tve {
+-	struct drm_connector connector;
++	struct drm_ddc_connector *ddc_conn;
+ 	struct drm_encoder encoder;
+ 	struct device *dev;
+ 	spinlock_t lock;	/* register lock */
+@@ -120,7 +120,6 @@
+ 
+ 	struct regmap *regmap;
+ 	struct regulator *dac_reg;
+-	struct i2c_adapter *ddc;
+ 	struct clk *clk;
+ 	struct clk *di_sel_clk;
+ 	struct clk_hw clk_hw_di;
+@@ -219,35 +218,10 @@
+ 	return 0;
+ }
+ 
+-static enum drm_connector_status imx_tve_connector_detect(
+-				struct drm_connector *connector, bool force)
+-{
+-	return connector_status_connected;
+-}
+-
+-static int imx_tve_connector_get_modes(struct drm_connector *connector)
+-{
+-	struct imx_tve *tve = con_to_tve(connector);
+-	struct edid *edid;
+-	int ret = 0;
+-
+-	if (!tve->ddc)
+-		return 0;
+-
+-	edid = drm_get_edid(connector, tve->ddc);
+-	if (edid) {
+-		drm_mode_connector_update_edid_property(connector, edid);
+-		ret = drm_add_edid_modes(connector, edid);
+-		kfree(edid);
+-	}
+-
+-	return ret;
+-}
+-
+ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
+ 					struct drm_display_mode *mode)
+ {
+-	struct imx_tve *tve = con_to_tve(connector);
++	struct imx_tve *tve = to_ddc_conn(connector)->private;
+ 	unsigned long rate;
+ 
+ 	/* pixel clock with 2x oversampling */
+@@ -269,7 +243,7 @@
+ static struct drm_encoder *imx_tve_connector_best_encoder(
+ 		struct drm_connector *connector)
+ {
+-	struct imx_tve *tve = con_to_tve(connector);
++	struct imx_tve *tve = drm_ddc_private(connector);
+ 
+ 	return &tve->encoder;
+ }
+@@ -360,12 +334,12 @@
+ static struct drm_connector_funcs imx_tve_connector_funcs = {
+ 	.dpms = drm_helper_connector_dpms,
+ 	.fill_modes = drm_helper_probe_single_connector_modes,
+-	.detect = imx_tve_connector_detect,
+-	.destroy = imx_drm_connector_destroy,
++	.detect = drm_ddc_connector_always_connected,
++	.destroy = drm_ddc_connector_destroy,
+ };
+ 
+ static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
+-	.get_modes = imx_tve_connector_get_modes,
++	.get_modes = drm_ddc_connector_get_modes,
+ 	.best_encoder = imx_tve_connector_best_encoder,
+ 	.mode_valid = imx_tve_connector_mode_valid,
+ };
+@@ -508,12 +482,13 @@
+ 	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
+ 			 encoder_type);
+ 
+-	drm_connector_helper_add(&tve->connector,
++	drm_connector_helper_add(&tve->ddc_conn->connector,
+ 			&imx_tve_connector_helper_funcs);
+-	drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
+-			   DRM_MODE_CONNECTOR_VGA);
++	drm_ddc_connector_add(drm, tve->ddc_conn, &imx_tve_connector_funcs,
++			      DRM_MODE_CONNECTOR_VGA);
+ 
+-	drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
++	drm_mode_connector_attach_encoder(&tve->ddc_conn->connector,
++					  &tve->encoder);
+ 
+ 	return 0;
+ }
+@@ -562,7 +537,6 @@
+ 	struct platform_device *pdev = to_platform_device(dev);
+ 	struct drm_device *drm = data;
+ 	struct device_node *np = dev->of_node;
+-	struct device_node *ddc_node;
+ 	struct imx_tve *tve;
+ 	struct resource *res;
+ 	void __iomem *base;
+@@ -574,15 +548,13 @@
+ 	if (!tve)
+ 		return -ENOMEM;
+ 
++	tve->ddc_conn = drm_ddc_connector_create(drm, np, tve);
++	if (IS_ERR(tve->ddc_conn))
++		return PTR_ERR(tve->ddc_conn);
++
+ 	tve->dev = dev;
+ 	spin_lock_init(&tve->lock);
+ 
+-	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
+-	if (ddc_node) {
+-		tve->ddc = of_find_i2c_adapter_by_node(ddc_node);
+-		of_node_put(ddc_node);
+-	}
+-
+ 	tve->mode = of_get_tve_mode(np);
+ 	if (tve->mode != TVE_MODE_VGA) {
+ 		dev_err(dev, "only VGA mode supported, currently\n");
+@@ -689,7 +661,6 @@
+ {
+ 	struct imx_tve *tve = dev_get_drvdata(dev);
+ 
+-	tve->connector.funcs->destroy(&tve->connector);
+ 	tve->encoder.funcs->destroy(&tve->encoder);
+ 
+ 	if (!IS_ERR(tve->dac_reg))
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/ipuv3-crtc.c linux-3.16.6/drivers/staging/imx-drm/ipuv3-crtc.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/ipuv3-crtc.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/ipuv3-crtc.c	2014-10-23 12:37:37.690220197 -0500
+@@ -51,7 +51,6 @@
+ 	struct drm_framebuffer	*newfb;
+ 	int			irq;
+ 	u32			interface_pix_fmt;
+-	unsigned long		di_clkflags;
+ 	int			di_hsync_pin;
+ 	int			di_vsync_pin;
+ };
+@@ -146,10 +145,13 @@
+ 			       int x, int y,
+ 			       struct drm_framebuffer *old_fb)
+ {
++	struct drm_device *dev = crtc->dev;
++	struct drm_encoder *encoder;
+ 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+-	int ret;
+ 	struct ipu_di_signal_cfg sig_cfg = {};
++	unsigned long encoder_types = 0;
+ 	u32 out_pixel_fmt;
++	int ret;
+ 
+ 	dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
+ 			mode->hdisplay);
+@@ -165,8 +167,26 @@
+ 	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+ 		sig_cfg.Vsync_pol = 1;
+ 
+-	sig_cfg.enable_pol = 1;
+-	sig_cfg.clk_pol = 0;
++	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
++		if (encoder->crtc == crtc)
++			encoder_types |= BIT(encoder->encoder_type);
++
++	dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
++		__func__, encoder_types);
++
++	/*
++	 * If we have DAC, TVDAC or LDB, then we need the IPU DI clock
++	 * to be the same as the LDB DI clock.
++	 */
++	if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) | 
++			     BIT(DRM_MODE_ENCODER_TVDAC) |
++			     BIT(DRM_MODE_ENCODER_LVDS)))
++		sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT;
++	else
++		sig_cfg.clkflags = 0;
++
++	sig_cfg.enable_pol = ENABLE_POL_HIGH;
++	sig_cfg.clk_pol = CLK_POL_NEGEDGE;
+ 	sig_cfg.width = mode->hdisplay;
+ 	sig_cfg.height = mode->vdisplay;
+ 	sig_cfg.pixel_fmt = out_pixel_fmt;
+@@ -178,7 +198,6 @@
+ 	sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start;
+ 	sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay;
+ 	sig_cfg.pixelclock = mode->clock * 1000;
+-	sig_cfg.clkflags = ipu_crtc->di_clkflags;
+ 
+ 	sig_cfg.v_to_h_sync = 0;
+ 
+@@ -277,7 +296,7 @@
+ 	ipu_crtc->newfb = NULL;
+ }
+ 
+-static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
++static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
+ 		u32 pixfmt, int hsync_pin, int vsync_pin)
+ {
+ 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+@@ -286,19 +305,6 @@
+ 	ipu_crtc->di_hsync_pin = hsync_pin;
+ 	ipu_crtc->di_vsync_pin = vsync_pin;
+ 
+-	switch (encoder_type) {
+-	case DRM_MODE_ENCODER_DAC:
+-	case DRM_MODE_ENCODER_TVDAC:
+-	case DRM_MODE_ENCODER_LVDS:
+-		ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
+-			IPU_DI_CLKMODE_EXT;
+-		break;
+-	case DRM_MODE_ENCODER_TMDS:
+-	case DRM_MODE_ENCODER_NONE:
+-		ipu_crtc->di_clkflags = 0;
+-		break;
+-	}
+-
+ 	return 0;
+ }
+ 
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/ipuv3-plane.c linux-3.16.6/drivers/staging/imx-drm/ipuv3-plane.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/ipuv3-plane.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/ipuv3-plane.c	2014-10-23 12:35:00.842220709 -0500
+@@ -281,8 +281,7 @@
+ 
+ 		ipu_idmac_put(ipu_plane->ipu_ch);
+ 		ipu_dmfc_put(ipu_plane->dmfc);
+-		if (ipu_plane->dp)
+-			ipu_dp_put(ipu_plane->dp);
++		ipu_dp_put(ipu_plane->dp);
+ 	}
+ }
+ 
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/ipuv3-plane.c.orig linux-3.16.6/drivers/staging/imx-drm/ipuv3-plane.c.orig
+--- linux-3.16.6.orig/drivers/staging/imx-drm/ipuv3-plane.c.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/ipuv3-plane.c.orig	2014-10-15 05:05:43.000000000 -0500
+@@ -0,0 +1,388 @@
++/*
++ * i.MX IPUv3 DP Overlay Planes
++ *
++ * Copyright (C) 2013 Philipp Zabel, 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 <drm/drmP.h>
++#include <drm/drm_fb_cma_helper.h>
++#include <drm/drm_gem_cma_helper.h>
++
++#include "video/imx-ipu-v3.h"
++#include "ipuv3-plane.h"
++
++#define to_ipu_plane(x)	container_of(x, struct ipu_plane, base)
++
++static const uint32_t ipu_plane_formats[] = {
++	DRM_FORMAT_XRGB1555,
++	DRM_FORMAT_XBGR1555,
++	DRM_FORMAT_ARGB8888,
++	DRM_FORMAT_XRGB8888,
++	DRM_FORMAT_ABGR8888,
++	DRM_FORMAT_XBGR8888,
++	DRM_FORMAT_YUYV,
++	DRM_FORMAT_YVYU,
++	DRM_FORMAT_YUV420,
++	DRM_FORMAT_YVU420,
++};
++
++int ipu_plane_irq(struct ipu_plane *ipu_plane)
++{
++	return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
++				     IPU_IRQ_EOF);
++}
++
++static int calc_vref(struct drm_display_mode *mode)
++{
++	unsigned long htotal, vtotal;
++
++	htotal = mode->htotal;
++	vtotal = mode->vtotal;
++
++	if (!htotal || !vtotal)
++		return 60;
++
++	return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
++}
++
++static inline int calc_bandwidth(int width, int height, unsigned int vref)
++{
++	return width * height * vref;
++}
++
++int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
++		       int x, int y)
++{
++	struct ipu_ch_param __iomem *cpmem;
++	struct drm_gem_cma_object *cma_obj;
++	unsigned long eba;
++
++	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
++	if (!cma_obj) {
++		DRM_DEBUG_KMS("entry is null.\n");
++		return -EFAULT;
++	}
++
++	dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
++		&cma_obj->paddr, x, y);
++
++	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
++	ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
++
++	eba = cma_obj->paddr + fb->offsets[0] +
++	      fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
++	ipu_cpmem_set_buffer(cpmem, 0, eba);
++	ipu_cpmem_set_buffer(cpmem, 1, eba);
++
++	/* cache offsets for subsequent pageflips */
++	ipu_plane->x = x;
++	ipu_plane->y = y;
++
++	return 0;
++}
++
++int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
++		       struct drm_display_mode *mode,
++		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
++		       unsigned int crtc_w, unsigned int crtc_h,
++		       uint32_t src_x, uint32_t src_y,
++		       uint32_t src_w, uint32_t src_h)
++{
++	struct ipu_ch_param __iomem *cpmem;
++	struct device *dev = ipu_plane->base.dev->dev;
++	int ret;
++
++	/* no scaling */
++	if (src_w != crtc_w || src_h != crtc_h)
++		return -EINVAL;
++
++	/* clip to crtc bounds */
++	if (crtc_x < 0) {
++		if (-crtc_x > crtc_w)
++			return -EINVAL;
++		src_x += -crtc_x;
++		src_w -= -crtc_x;
++		crtc_w -= -crtc_x;
++		crtc_x = 0;
++	}
++	if (crtc_y < 0) {
++		if (-crtc_y > crtc_h)
++			return -EINVAL;
++		src_y += -crtc_y;
++		src_h -= -crtc_y;
++		crtc_h -= -crtc_y;
++		crtc_y = 0;
++	}
++	if (crtc_x + crtc_w > mode->hdisplay) {
++		if (crtc_x > mode->hdisplay)
++			return -EINVAL;
++		crtc_w = mode->hdisplay - crtc_x;
++		src_w = crtc_w;
++	}
++	if (crtc_y + crtc_h > mode->vdisplay) {
++		if (crtc_y > mode->vdisplay)
++			return -EINVAL;
++		crtc_h = mode->vdisplay - crtc_y;
++		src_h = crtc_h;
++	}
++	/* full plane minimum width is 13 pixels */
++	if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
++		return -EINVAL;
++	if (crtc_h < 2)
++		return -EINVAL;
++
++	switch (ipu_plane->dp_flow) {
++	case IPU_DP_FLOW_SYNC_BG:
++		ret = ipu_dp_setup_channel(ipu_plane->dp,
++				IPUV3_COLORSPACE_RGB,
++				IPUV3_COLORSPACE_RGB);
++		if (ret) {
++			dev_err(dev,
++				"initializing display processor failed with %d\n",
++				ret);
++			return ret;
++		}
++		ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1);
++		break;
++	case IPU_DP_FLOW_SYNC_FG:
++		ipu_dp_setup_channel(ipu_plane->dp,
++				ipu_drm_fourcc_to_colorspace(fb->pixel_format),
++				IPUV3_COLORSPACE_UNKNOWN);
++		ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
++		break;
++	}
++
++	ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
++	if (ret) {
++		dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
++		return ret;
++	}
++
++	ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
++			calc_bandwidth(crtc_w, crtc_h,
++				       calc_vref(mode)), 64);
++	if (ret) {
++		dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
++		return ret;
++	}
++
++	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
++	ipu_ch_param_zero(cpmem);
++	ipu_cpmem_set_resolution(cpmem, src_w, src_h);
++	ret = ipu_cpmem_set_fmt(cpmem, fb->pixel_format);
++	if (ret < 0) {
++		dev_err(dev, "unsupported pixel format 0x%08x\n",
++			fb->pixel_format);
++		return ret;
++	}
++	ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
++
++	ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
++	if (ret < 0)
++		return ret;
++
++	return 0;
++}
++
++void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
++{
++	if (!IS_ERR_OR_NULL(ipu_plane->dp))
++		ipu_dp_put(ipu_plane->dp);
++	if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
++		ipu_dmfc_put(ipu_plane->dmfc);
++	if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
++		ipu_idmac_put(ipu_plane->ipu_ch);
++}
++
++int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
++{
++	int ret;
++
++	ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
++	if (IS_ERR(ipu_plane->ipu_ch)) {
++		ret = PTR_ERR(ipu_plane->ipu_ch);
++		DRM_ERROR("failed to get idmac channel: %d\n", ret);
++		return ret;
++	}
++
++	ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
++	if (IS_ERR(ipu_plane->dmfc)) {
++		ret = PTR_ERR(ipu_plane->dmfc);
++		DRM_ERROR("failed to get dmfc: ret %d\n", ret);
++		goto err_out;
++	}
++
++	if (ipu_plane->dp_flow >= 0) {
++		ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
++		if (IS_ERR(ipu_plane->dp)) {
++			ret = PTR_ERR(ipu_plane->dp);
++			DRM_ERROR("failed to get dp flow: %d\n", ret);
++			goto err_out;
++		}
++	}
++
++	return 0;
++err_out:
++	ipu_plane_put_resources(ipu_plane);
++
++	return ret;
++}
++
++void ipu_plane_enable(struct ipu_plane *ipu_plane)
++{
++	if (ipu_plane->dp)
++		ipu_dp_enable(ipu_plane->ipu);
++	ipu_dmfc_enable_channel(ipu_plane->dmfc);
++	ipu_idmac_enable_channel(ipu_plane->ipu_ch);
++	if (ipu_plane->dp)
++		ipu_dp_enable_channel(ipu_plane->dp);
++
++	ipu_plane->enabled = true;
++}
++
++void ipu_plane_disable(struct ipu_plane *ipu_plane)
++{
++	ipu_plane->enabled = false;
++
++	ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
++
++	if (ipu_plane->dp)
++		ipu_dp_disable_channel(ipu_plane->dp);
++	ipu_idmac_disable_channel(ipu_plane->ipu_ch);
++	ipu_dmfc_disable_channel(ipu_plane->dmfc);
++	if (ipu_plane->dp)
++		ipu_dp_disable(ipu_plane->ipu);
++}
++
++static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)
++{
++	bool enable;
++
++	DRM_DEBUG_KMS("mode = %d", mode);
++
++	enable = (mode == DRM_MODE_DPMS_ON);
++
++	if (enable == ipu_plane->enabled)
++		return;
++
++	if (enable) {
++		ipu_plane_enable(ipu_plane);
++	} else {
++		ipu_plane_disable(ipu_plane);
++
++		ipu_idmac_put(ipu_plane->ipu_ch);
++		ipu_dmfc_put(ipu_plane->dmfc);
++		if (ipu_plane->dp)
++			ipu_dp_put(ipu_plane->dp);
++	}
++}
++
++/*
++ * drm_plane API
++ */
++
++static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
++			    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
++			    unsigned int crtc_w, unsigned int crtc_h,
++			    uint32_t src_x, uint32_t src_y,
++			    uint32_t src_w, uint32_t src_h)
++{
++	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
++	int ret = 0;
++
++	DRM_DEBUG_KMS("plane - %p\n", plane);
++
++	if (!ipu_plane->enabled)
++		ret = ipu_plane_get_resources(ipu_plane);
++	if (ret < 0)
++		return ret;
++
++	ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb,
++			crtc_x, crtc_y, crtc_w, crtc_h,
++			src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16);
++	if (ret < 0) {
++		ipu_plane_put_resources(ipu_plane);
++		return ret;
++	}
++
++	if (crtc != plane->crtc)
++		dev_info(plane->dev->dev, "crtc change: %p -> %p\n",
++				plane->crtc, crtc);
++	plane->crtc = crtc;
++
++	ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_ON);
++
++	return 0;
++}
++
++static int ipu_disable_plane(struct drm_plane *plane)
++{
++	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
++
++	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
++
++	ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_OFF);
++
++	ipu_plane_put_resources(ipu_plane);
++
++	return 0;
++}
++
++static void ipu_plane_destroy(struct drm_plane *plane)
++{
++	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
++
++	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
++
++	ipu_disable_plane(plane);
++	drm_plane_cleanup(plane);
++	kfree(ipu_plane);
++}
++
++static struct drm_plane_funcs ipu_plane_funcs = {
++	.update_plane	= ipu_update_plane,
++	.disable_plane	= ipu_disable_plane,
++	.destroy	= ipu_plane_destroy,
++};
++
++struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
++				 int dma, int dp, unsigned int possible_crtcs,
++				 bool priv)
++{
++	struct ipu_plane *ipu_plane;
++	int ret;
++
++	DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
++		      dma, dp, possible_crtcs);
++
++	ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
++	if (!ipu_plane) {
++		DRM_ERROR("failed to allocate plane\n");
++		return ERR_PTR(-ENOMEM);
++	}
++
++	ipu_plane->ipu = ipu;
++	ipu_plane->dma = dma;
++	ipu_plane->dp_flow = dp;
++
++	ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs,
++			     &ipu_plane_funcs, ipu_plane_formats,
++			     ARRAY_SIZE(ipu_plane_formats),
++			     priv);
++	if (ret) {
++		DRM_ERROR("failed to initialize plane\n");
++		kfree(ipu_plane);
++		return ERR_PTR(ret);
++	}
++
++	return ipu_plane;
++}
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/Kconfig linux-3.16.6/drivers/staging/imx-drm/Kconfig
+--- linux-3.16.6.orig/drivers/staging/imx-drm/Kconfig	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/Kconfig	2014-10-23 12:37:23.890220362 -0500
+@@ -35,6 +35,7 @@
+ config DRM_IMX_LDB
+ 	tristate "Support for LVDS displays"
+ 	depends on DRM_IMX && MFD_SYSCON
++	select DRM_PANEL
+ 	help
+ 	  Choose this to enable the internal LVDS Display Bridge (LDB)
+ 	  found on i.MX53 and i.MX6 processors.
+@@ -51,3 +52,20 @@
+ 	depends on DRM_IMX
+ 	help
+ 	  Choose this if you want to use HDMI on i.MX6.
++
++config DRM_DW_HDMI_AUDIO
++	tristate "Synopsis Designware Audio interface"
++	depends on DRM_IMX_HDMI != n
++	help
++	  Support the Audio interface which is part of the Synopsis
++	  Designware HDMI block.  This is used in conjunction with
++	  the i.MX HDMI driver.
++
++config DRM_DW_HDMI_CEC
++	tristate "Synopsis Designware CEC interface"
++	depends on DRM_IMX_HDMI != n
++	select HDMI_CEC_CORE
++	help
++	  Support the CEC interface which is part of the Synposis
++	  Designware HDMI block.  This is used in conjunction with
++	  the i.MX HDMI driver.
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/Kconfig.orig linux-3.16.6/drivers/staging/imx-drm/Kconfig.orig
+--- linux-3.16.6.orig/drivers/staging/imx-drm/Kconfig.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/drivers/staging/imx-drm/Kconfig.orig	2014-10-23 12:35:45.310219999 -0500
+@@ -0,0 +1,62 @@
++config DRM_IMX
++	tristate "DRM Support for Freescale i.MX"
++	select DRM_KMS_HELPER
++	select DRM_KMS_FB_HELPER
++	select VIDEOMODE_HELPERS
++	select DRM_GEM_CMA_HELPER
++	select DRM_KMS_CMA_HELPER
++	depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM)
++	help
++	  enable i.MX graphics support
++
++config DRM_IMX_FB_HELPER
++	tristate "provide legacy framebuffer /dev/fb0"
++	select DRM_KMS_CMA_HELPER
++	depends on DRM_IMX
++	help
++	  The DRM framework can provide a legacy /dev/fb0 framebuffer
++	  for your device. This is necessary to get a framebuffer console
++	  and also for applications using the legacy framebuffer API
++
++config DRM_IMX_PARALLEL_DISPLAY
++	tristate "Support for parallel displays"
++	select DRM_PANEL
++	depends on DRM_IMX
++	select VIDEOMODE_HELPERS
++
++config DRM_IMX_TVE
++	tristate "Support for TV and VGA displays"
++	depends on DRM_IMX
++	select REGMAP_MMIO
++	help
++	  Choose this to enable the internal Television Encoder (TVe)
++	  found on i.MX53 processors.
++
++config DRM_IMX_LDB
++	tristate "Support for LVDS displays"
++	depends on DRM_IMX && MFD_SYSCON
++	select DRM_PANEL
++	help
++	  Choose this to enable the internal LVDS Display Bridge (LDB)
++	  found on i.MX53 and i.MX6 processors.
++
++config DRM_IMX_IPUV3
++	tristate "DRM Support for i.MX IPUv3"
++	depends on DRM_IMX
++	depends on IMX_IPUV3_CORE
++	help
++	  Choose this if you have a i.MX5 or i.MX6 processor.
++
++config DRM_IMX_HDMI
++	tristate "Freescale i.MX DRM HDMI"
++	depends on DRM_IMX
++	help
++	  Choose this if you want to use HDMI on i.MX6.
++
++config DRM_DW_HDMI_AUDIO
++	tristate "Synopsis Designware Audio interface"
++	depends on DRM_IMX_HDMI != n
++	help
++	  Support the Audio interface which is part of the Synopsis
++	  Designware HDMI block.  This is used in conjunction with
++	  the i.MX HDMI driver.
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/Makefile linux-3.16.6/drivers/staging/imx-drm/Makefile
+--- linux-3.16.6.orig/drivers/staging/imx-drm/Makefile	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/Makefile	2014-10-23 12:37:30.178219970 -0500
+@@ -3,6 +3,7 @@
+ 
+ obj-$(CONFIG_DRM_IMX) += imxdrm.o
+ 
++obj-$(CONFIG_DRM_IMX) += drm-ddc-connector.o
+ obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
+ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
+ obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
+@@ -10,3 +11,5 @@
+ imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
+ obj-$(CONFIG_DRM_IMX_IPUV3)	+= imx-ipuv3-crtc.o
+ obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o
++obj-$(CONFIG_DRM_DW_HDMI_AUDIO) += dw-hdmi-audio.o
++obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o
+diff -Nur linux-3.16.6.orig/drivers/staging/imx-drm/parallel-display.c linux-3.16.6/drivers/staging/imx-drm/parallel-display.c
+--- linux-3.16.6.orig/drivers/staging/imx-drm/parallel-display.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/drivers/staging/imx-drm/parallel-display.c	2014-10-23 12:35:30.986219995 -0500
+@@ -225,6 +225,8 @@
+ 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565;
+ 		else if (!strcmp(fmt, "bgr666"))
+ 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
++		else if (!strcmp(fmt, "rgb666"))
++			imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB666;
+ 		else if (!strcmp(fmt, "lvds666"))
+ 			imxpd->interface_pix_fmt = v4l2_fourcc('L', 'V', 'D', '6');
+ 	}
+diff -Nur linux-3.16.6.orig/include/linux/cec-dev.h linux-3.16.6/include/linux/cec-dev.h
+--- linux-3.16.6.orig/include/linux/cec-dev.h	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/include/linux/cec-dev.h	2014-10-23 12:37:18.374219998 -0500
+@@ -0,0 +1,69 @@
++#ifndef _LINUX_CEC_DEV_H
++#define _LINUX_CEC_DEV_H
++
++#include <linux/cdev.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
++
++#include <uapi/linux/cec-dev.h>
++
++struct device;
++
++struct cec_dev {
++	struct cdev cdev;
++	dev_t devn;
++
++	struct mutex mutex;
++	unsigned users;
++
++	spinlock_t lock;
++	wait_queue_head_t waitq;
++	struct list_head events;
++	u8 write_busy;
++
++	u8 retries;
++	u16 addresses;
++	u16 physical;
++
++	int (*open)(struct cec_dev *);
++	void (*release)(struct cec_dev *);
++	void (*send_message)(struct cec_dev *, u8 *, size_t);
++	void (*set_address)(struct cec_dev *, unsigned);
++};
++
++void cec_dev_event(struct cec_dev *cec_dev, int type, u8 *msg, size_t len);
++
++static inline void cec_dev_receive(struct cec_dev *cec_dev, u8 *msg,
++	unsigned len)
++{
++	cec_dev_event(cec_dev, MESSAGE_TYPE_RECEIVE_SUCCESS, msg, len);
++}
++
++static inline void cec_dev_send_complete(struct cec_dev *cec_dev, int ack)
++{
++	cec_dev->retries = 0;
++	cec_dev->write_busy = 0;
++
++	cec_dev_event(cec_dev, ack ? MESSAGE_TYPE_SEND_SUCCESS :
++		      MESSAGE_TYPE_NOACK, NULL, 0);
++}
++
++static inline void cec_dev_disconnect(struct cec_dev *cec_dev)
++{
++	cec_dev->physical = 0;
++	cec_dev_event(cec_dev, MESSAGE_TYPE_DISCONNECTED, NULL, 0);
++}
++
++static inline void cec_dev_connect(struct cec_dev *cec_dev, u32 phys)
++{
++	cec_dev->physical = phys;
++	cec_dev_event(cec_dev, MESSAGE_TYPE_CONNECTED, NULL, 0);
++}
++
++void cec_dev_init(struct cec_dev *cec_dev, struct module *);
++int cec_dev_add(struct cec_dev *cec_dev, struct device *, const char *name);
++void cec_dev_remove(struct cec_dev *cec_dev);
++
++#endif
+diff -Nur linux-3.16.6.orig/include/linux/mmc/host.h linux-3.16.6/include/linux/mmc/host.h
+--- linux-3.16.6.orig/include/linux/mmc/host.h	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/include/linux/mmc/host.h	2014-10-23 12:34:18.742220000 -0500
+@@ -298,6 +298,11 @@
+ 	unsigned long           clkgate_delay;
+ #endif
+ 
++	/* card specific properties to deal with power and reset */
++	struct regulator	*card_regulator; /* External VCC needed by the card */
++	struct gpio_desc	*card_reset_gpios[2]; /* External resets, active low */
++	struct clk		*card_clk;	/* External clock needed by the card */
++
+ 	/* host specific block data */
+ 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
+ 	unsigned short		max_segs;	/* see blk_queue_max_segments */
+diff -Nur linux-3.16.6.orig/include/uapi/linux/cec-dev.h linux-3.16.6/include/uapi/linux/cec-dev.h
+--- linux-3.16.6.orig/include/uapi/linux/cec-dev.h	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/include/uapi/linux/cec-dev.h	2014-10-23 12:37:18.374219998 -0500
+@@ -0,0 +1,34 @@
++#ifndef _UAPI_LINUX_CEC_DEV_H
++#define _UAPI_LINUX_CEC_DEV_H
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++
++#define MAX_MESSAGE_LEN 16
++
++enum {
++	HDMICEC_IOC_MAGIC = 'H',
++	/* This is wrong: we pass the argument as a number, not a pointer */
++	HDMICEC_IOC_O_SETLOGICALADDRESS	= _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char),
++	HDMICEC_IOC_SETLOGICALADDRESS	= _IO(HDMICEC_IOC_MAGIC, 1),
++	HDMICEC_IOC_STARTDEVICE		= _IO(HDMICEC_IOC_MAGIC, 2),
++	HDMICEC_IOC_STOPDEVICE		= _IO(HDMICEC_IOC_MAGIC, 3),
++	HDMICEC_IOC_GETPHYADDRESS	= _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4]),
++};
++
++enum {
++	MESSAGE_TYPE_RECEIVE_SUCCESS = 1,
++	MESSAGE_TYPE_NOACK,
++	MESSAGE_TYPE_DISCONNECTED,
++	MESSAGE_TYPE_CONNECTED,
++	MESSAGE_TYPE_SEND_SUCCESS,
++	MESSAGE_TYPE_SEND_ERROR,
++};
++
++struct cec_user_event {
++	__u32 event_type;
++	__u32 msg_len;
++	__u8 msg[MAX_MESSAGE_LEN];
++};
++
++#endif
+diff -Nur linux-3.16.6.orig/include/uapi/linux/videodev2.h linux-3.16.6/include/uapi/linux/videodev2.h
+--- linux-3.16.6.orig/include/uapi/linux/videodev2.h	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/include/uapi/linux/videodev2.h	2014-10-23 12:35:23.722220002 -0500
+@@ -299,6 +299,7 @@
+ #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_RGB666  v4l2_fourcc('R', 'G', 'B', 'H') /* 18  RGB-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   */
+diff -Nur linux-3.16.6.orig/include/video/imx-ipu-v3.h linux-3.16.6/include/video/imx-ipu-v3.h
+--- linux-3.16.6.orig/include/video/imx-ipu-v3.h	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/include/video/imx-ipu-v3.h	2014-10-23 12:35:38.090219994 -0500
+@@ -27,6 +27,12 @@
+ 
+ #define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
+ 
++#define CLK_POL_NEGEDGE		0
++#define CLK_POL_POSEDGE		1
++
++#define ENABLE_POL_LOW		0
++#define ENABLE_POL_HIGH		1
++
+ /*
+  * Bitfield of Display Interface signal polarities.
+  */
+@@ -37,7 +43,7 @@
+ 	unsigned clksel_en:1;
+ 	unsigned clkidle_en:1;
+ 	unsigned data_pol:1;	/* true = inverted */
+-	unsigned clk_pol:1;	/* true = rising edge */
++	unsigned clk_pol:1;
+ 	unsigned enable_pol:1;
+ 	unsigned Hsync_pol:1;	/* true = active high */
+ 	unsigned Vsync_pol:1;
+diff -Nur linux-3.16.6.orig/sound/soc/codecs/sgtl5000.c linux-3.16.6/sound/soc/codecs/sgtl5000.c
+--- linux-3.16.6.orig/sound/soc/codecs/sgtl5000.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/sound/soc/codecs/sgtl5000.c	2014-10-23 12:37:45.114220003 -0500
+@@ -773,7 +773,7 @@
+ 	struct ldo_regulator *ldo = rdev_get_drvdata(dev);
+ 	struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data;
+ 	int reg;
+-
++dev_info(codec->dev, "%s(): enabled %u\n", __func__, ldo->enabled);
+ 	if (ldo_regulator_is_enabled(dev))
+ 		return 0;
+ 
+@@ -805,10 +805,16 @@
+ {
+ 	struct ldo_regulator *ldo = rdev_get_drvdata(dev);
+ 	struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data;
++dev_info(codec->dev, "%s(): enabled %u\n", __func__, ldo->enabled);
++
++	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
++				SGTL5000_LINREG_SIMPLE_POWERUP,
++				SGTL5000_LINREG_SIMPLE_POWERUP);
+ 
+ 	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+ 				SGTL5000_LINEREG_D_POWERUP,
+ 				0);
++dev_info(codec->dev, "%s: ANA_POWER = 0x%04x\n", __func__, snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER));
+ 
+ 	/* clear voltage info */
+ 	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
+@@ -866,6 +872,7 @@
+ 	config.dev = codec->dev;
+ 	config.driver_data = ldo;
+ 	config.init_data = init_data;
++	config.ena_gpio = -EINVAL;
+ 
+ 	ldo->dev = regulator_register(&ldo->desc, &config);
+ 	if (IS_ERR(ldo->dev)) {
+@@ -1159,8 +1166,11 @@
+ 		 * if vddio and vddd > 3.1v,
+ 		 * charge pump should be clean before set ana_pwr
+ 		 */
+-		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+-				SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
++// FIXME: this is total crap - we have read this register above into
++// ana_pwr, which we then modify (above), and then write back to the
++// register below.  This modification just gets completely overwritten.
++//		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
++//				SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
+ 
+ 		/* VDDC use VDDIO rail */
+ 		lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
+@@ -1304,6 +1314,9 @@
+ 	int ret;
+ 	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+ 
++	if (!devres_open_group(codec->dev, NULL, GFP_KERNEL))
++		return -ENOMEM;
++
+ 	ret = sgtl5000_enable_regulators(codec);
+ 	if (ret)
+ 		return ret;
+@@ -1361,6 +1374,9 @@
+ err:
+ 	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+ 						sgtl5000->supplies);
++
++	devres_release_group(codec->dev, NULL);
++
+ 	ldo_regulator_remove(codec);
+ 
+ 	return ret;
+@@ -1374,6 +1390,9 @@
+ 
+ 	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+ 						sgtl5000->supplies);
++
++	devres_release_group(codec->dev, NULL);
++
+ 	ldo_regulator_remove(codec);
+ 
+ 	return 0;
+diff -Nur linux-3.16.6.orig/sound/soc/fsl/imx-pcm-dma.c linux-3.16.6/sound/soc/fsl/imx-pcm-dma.c
+--- linux-3.16.6.orig/sound/soc/fsl/imx-pcm-dma.c	2014-10-15 05:05:43.000000000 -0500
++++ linux-3.16.6/sound/soc/fsl/imx-pcm-dma.c	2014-10-23 12:35:54.206220260 -0500
+@@ -43,7 +43,7 @@
+ 	.buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
+ 	.period_bytes_min = 128,
+ 	.period_bytes_max = 65535, /* Limited by SDMA engine */
+-	.periods_min = 2,
++	.periods_min = 4,
+ 	.periods_max = 255,
+ 	.fifo_size = 0,
+ };
+@@ -59,6 +59,7 @@
+ {
+ 	return devm_snd_dmaengine_pcm_register(&pdev->dev,
+ 		&imx_dmaengine_pcm_config,
++		SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
+ 		SND_DMAENGINE_PCM_FLAG_COMPAT);
+ }
+ EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
+diff -Nur linux-3.16.6.orig/sound/soc/fsl/imx-pcm-dma.c.orig linux-3.16.6/sound/soc/fsl/imx-pcm-dma.c.orig
+--- linux-3.16.6.orig/sound/soc/fsl/imx-pcm-dma.c.orig	1969-12-31 18:00:00.000000000 -0600
++++ linux-3.16.6/sound/soc/fsl/imx-pcm-dma.c.orig	2014-10-23 12:26:49.542220041 -0500
+@@ -0,0 +1,66 @@
++/*
++ * imx-pcm-dma-mx2.c  --  ALSA Soc Audio Layer
++ *
++ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
++ *
++ * This code is based on code copyrighted by Freescale,
++ * Liam Girdwood, Javier Martin and probably others.
++ *
++ *  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.
++ */
++#include <linux/platform_device.h>
++#include <linux/dmaengine.h>
++#include <linux/types.h>
++#include <linux/module.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/dmaengine_pcm.h>
++
++#include "imx-pcm.h"
++
++static bool filter(struct dma_chan *chan, void *param)
++{
++	if (!imx_dma_is_general_purpose(chan))
++		return false;
++
++	chan->private = param;
++
++	return true;
++}
++
++static const struct snd_pcm_hardware imx_pcm_hardware = {
++	.info = SNDRV_PCM_INFO_INTERLEAVED |
++		SNDRV_PCM_INFO_BLOCK_TRANSFER |
++		SNDRV_PCM_INFO_MMAP |
++		SNDRV_PCM_INFO_MMAP_VALID |
++		SNDRV_PCM_INFO_PAUSE |
++		SNDRV_PCM_INFO_RESUME,
++	.buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
++	.period_bytes_min = 128,
++	.period_bytes_max = 65535, /* Limited by SDMA engine */
++	.periods_min = 4,
++	.periods_max = 255,
++	.fifo_size = 0,
++};
++
++static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
++	.pcm_hardware = &imx_pcm_hardware,
++	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
++	.compat_filter_fn = filter,
++	.prealloc_buffer_size = IMX_SSI_DMABUF_SIZE,
++};
++
++int imx_pcm_dma_init(struct platform_device *pdev)
++{
++	return devm_snd_dmaengine_pcm_register(&pdev->dev,
++		&imx_dmaengine_pcm_config,
++		SND_DMAENGINE_PCM_FLAG_COMPAT);
++}
++EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
++
++MODULE_LICENSE("GPL");

+ 6 - 6
target/config/Config.in.kernelversion.choice

@@ -4,17 +4,17 @@
 choice
 prompt "Kernel Version"
 depends on !ADK_CHOOSE_TARGET_ARCH && !ADK_CHOOSE_TARGET_SYSTEM && ADK_TARGET_KERNEL_CUSTOMISING
-default ADK_KERNEL_VERSION_3_14_17 if ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
-default ADK_KERNEL_VERSION_3_16_4
+default ADK_KERNEL_VERSION_3_14_22 if ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
+default ADK_KERNEL_VERSION_3_16_6
 
-config ADK_KERNEL_VERSION_3_16_4
-	prompt "3.16.4"
+config ADK_KERNEL_VERSION_3_16_6
+	prompt "3.16.6"
 	depends on !ADK_TARGET_SYSTEM_MIKROTIK_RB4XX
 	boolean
 	select ADK_KERNEL_VERSION_3_16
 
-config ADK_KERNEL_VERSION_3_14_17
-	prompt "3.14.17"
+config ADK_KERNEL_VERSION_3_14_22
+	prompt "3.14.22"
 	boolean
 	select ADK_KERNEL_VERSION_3_14
 

+ 2 - 2
target/config/Config.in.kernelversion.default

@@ -18,8 +18,8 @@ config ADK_KERNEL_VERSION_3_4
 
 config ADK_KERNEL_VERSION
 	string
-	default "3.16.4" if ADK_KERNEL_VERSION_3_16_4
-	default "3.14.17" if ADK_KERNEL_VERSION_3_14_17
+	default "3.16.6" if ADK_KERNEL_VERSION_3_16_6
+	default "3.14.22" if ADK_KERNEL_VERSION_3_14_22
 	default "3.12.27" if ADK_KERNEL_VERSION_3_12_27
 	default "3.10.53" if ADK_KERNEL_VERSION_3_10_53
 	default "3.4.103" if ADK_KERNEL_VERSION_3_4_103

+ 0 - 3
target/linux/config/Config.in.gpio

@@ -1,6 +1,3 @@
-config ADK_KERNEL_RESET_CONTROLLER
-	boolean
-
 config ADK_KERNEL_RESET_GPIO
 	boolean
 

+ 3 - 6
target/linux/config/Config.in.graphics

@@ -131,7 +131,7 @@ config ADK_KERNEL_DRM_IMX_LDB
 config ADK_KERNEL_DRM_IMX_TVE
 	boolean
 
-config ADK_KERNEL_DRM_IMX_IPUV3_CORE
+config ADK_KERNEL_IMX_IPUV3_CORE
 	boolean
 
 config ADK_KERNEL_DRM_IMX_IPUV3
@@ -140,9 +140,6 @@ config ADK_KERNEL_DRM_IMX_IPUV3
 config ADK_KERNEL_DRM_IMX_HDMI
 	boolean
 
-config ADK_KERNEL_RESET_CONTROLLER
-	boolean
-
 config ADK_KERNEL_AGP
 	boolean
 
@@ -202,8 +199,8 @@ config ADK_KERNEL_DRM_IMX
 	select ADK_KERNEL_DRM_IMX_LDB
 	select ADK_KERNEL_DRM_IMX_TVE
 	select ADK_KERNEL_DRM_IMX_PARALLEL_DISPLAY
+	select ADK_KERNEL_IMX_IPUV3_CORE
 	select ADK_KERNEL_DRM_IMX_IPUV3
-	select ADK_KERNEL_DRM_IMX_IPUV3_CORE
 	select ADK_KERNEL_DRM_IMX_HDMI
 	select ADK_KERNEL_FB
 	select ADK_KERNEL_STAGING
@@ -215,7 +212,7 @@ config ADK_KERNEL_DRM_IMX
 	default y if ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
  	default n
  	help
-	 Framebuffer support for Cubox-i/Hummingboard
+	  Framebuffer support for Cubox-i/Hummingboard
 
 config ADK_KERNEL_DRM_VIVANTE
 	prompt "Framebuffer support for Cubox-i/Hummingboard (Vivante)"

+ 3 - 0
target/linux/config/Config.in.kernel

@@ -4,6 +4,9 @@ config ADK_KERNEL_STAGING
 config ADK_KERNEL_EXPERIMENTAL
 	boolean
 
+config ADK_KERNEL_RESET_CONTROLLER
+        boolean
+
 config ADK_KERNEL_BLK_DEV_INITRD
 	boolean
 

+ 0 - 0
target/linux/patches/3.14.17/bsd-compatibility.patch → target/linux/patches/3.14.22/bsd-compatibility.patch


+ 0 - 0
target/linux/patches/3.14.17/cleankernel.patch → target/linux/patches/3.14.22/cleankernel.patch


+ 0 - 0
target/linux/patches/3.14.17/defaults.patch → target/linux/patches/3.14.22/defaults.patch


+ 0 - 0
target/linux/patches/3.14.17/disable-netfilter.patch → target/linux/patches/3.14.22/disable-netfilter.patch


+ 0 - 0
target/linux/patches/3.14.17/export-symbol-for-exmap.patch → target/linux/patches/3.14.22/export-symbol-for-exmap.patch


+ 0 - 0
target/linux/patches/3.14.17/gemalto.patch → target/linux/patches/3.14.22/gemalto.patch


+ 0 - 0
target/linux/patches/3.14.17/initramfs-nosizelimit.patch → target/linux/patches/3.14.22/initramfs-nosizelimit.patch


+ 0 - 0
target/linux/patches/3.14.17/lemote-rfkill.patch → target/linux/patches/3.14.22/lemote-rfkill.patch


+ 0 - 0
target/linux/patches/3.14.17/microblaze-axi.patch → target/linux/patches/3.14.22/microblaze-axi.patch


+ 0 - 0
target/linux/patches/3.14.17/microblaze-ethernet.patch → target/linux/patches/3.14.22/microblaze-ethernet.patch


+ 0 - 0
target/linux/patches/3.14.17/mkpiggy.patch → target/linux/patches/3.14.22/mkpiggy.patch


+ 0 - 0
target/linux/patches/3.14.17/mtd-rootfs.patch → target/linux/patches/3.14.22/mtd-rootfs.patch


+ 0 - 0
target/linux/patches/3.14.17/nfsv3-tcp.patch → target/linux/patches/3.14.22/nfsv3-tcp.patch


+ 0 - 0
target/linux/patches/3.14.17/non-static.patch → target/linux/patches/3.14.22/non-static.patch


+ 0 - 0
target/linux/patches/3.14.17/patch-fblogo → target/linux/patches/3.14.22/patch-fblogo


+ 0 - 0
target/linux/patches/3.14.17/patch-grsec → target/linux/patches/3.14.22/patch-grsec


+ 0 - 0
target/linux/patches/3.14.17/patch-mptcp → target/linux/patches/3.14.22/patch-mptcp


+ 0 - 0
target/linux/patches/3.14.17/patch-yaffs2 → target/linux/patches/3.14.22/patch-yaffs2


+ 0 - 0
target/linux/patches/3.14.17/ppc64-missing-zlib.patch → target/linux/patches/3.14.22/ppc64-missing-zlib.patch


+ 0 - 0
target/linux/patches/3.14.17/regmap-boolean.patch → target/linux/patches/3.14.22/regmap-boolean.patch


+ 0 - 0
target/linux/patches/3.14.17/relocs.patch → target/linux/patches/3.14.22/relocs.patch


+ 0 - 0
target/linux/patches/3.14.17/sgidefs.patch → target/linux/patches/3.14.22/sgidefs.patch


+ 0 - 0
target/linux/patches/3.14.17/sortext.patch → target/linux/patches/3.14.22/sortext.patch


+ 0 - 0
target/linux/patches/3.14.17/startup.patch → target/linux/patches/3.14.22/startup.patch


+ 0 - 0
target/linux/patches/3.14.17/tcp-fastopen.patch → target/linux/patches/3.14.22/tcp-fastopen.patch


+ 0 - 0
target/linux/patches/3.14.17/wlan-cf.patch → target/linux/patches/3.14.22/wlan-cf.patch


+ 0 - 0
target/linux/patches/3.14.17/xargs.patch → target/linux/patches/3.14.22/xargs.patch


+ 0 - 0
target/linux/patches/3.14.17/zlib-inflate.patch → target/linux/patches/3.14.22/zlib-inflate.patch


+ 0 - 0
target/linux/patches/3.16.4/bsd-compatibility.patch → target/linux/patches/3.16.6/bsd-compatibility.patch


+ 0 - 0
target/linux/patches/3.16.4/cleankernel.patch → target/linux/patches/3.16.6/cleankernel.patch


+ 0 - 0
target/linux/patches/3.16.4/cris-header.patch → target/linux/patches/3.16.6/cris-header.patch


+ 0 - 0
target/linux/patches/3.16.4/defaults.patch → target/linux/patches/3.16.6/defaults.patch


+ 0 - 0
target/linux/patches/3.16.4/disable-netfilter.patch → target/linux/patches/3.16.6/disable-netfilter.patch


+ 0 - 0
target/linux/patches/3.16.4/export-symbol-for-exmap.patch → target/linux/patches/3.16.6/export-symbol-for-exmap.patch


+ 0 - 0
target/linux/patches/3.16.4/gemalto.patch → target/linux/patches/3.16.6/gemalto.patch


+ 0 - 0
target/linux/patches/3.16.4/initramfs-nosizelimit.patch → target/linux/patches/3.16.6/initramfs-nosizelimit.patch


+ 0 - 0
target/linux/patches/3.16.4/lemote-rfkill.patch → target/linux/patches/3.16.6/lemote-rfkill.patch


+ 0 - 0
target/linux/patches/3.16.4/microblaze-axi.patch → target/linux/patches/3.16.6/microblaze-axi.patch


+ 0 - 0
target/linux/patches/3.16.4/microblaze-ethernet.patch → target/linux/patches/3.16.6/microblaze-ethernet.patch


+ 0 - 0
target/linux/patches/3.16.4/mkpiggy.patch → target/linux/patches/3.16.6/mkpiggy.patch


+ 0 - 0
target/linux/patches/3.16.4/mtd-rootfs.patch → target/linux/patches/3.16.6/mtd-rootfs.patch


+ 0 - 0
target/linux/patches/3.16.4/nfsv3-tcp.patch → target/linux/patches/3.16.6/nfsv3-tcp.patch


+ 0 - 0
target/linux/patches/3.16.4/non-static.patch → target/linux/patches/3.16.6/non-static.patch


+ 0 - 0
target/linux/patches/3.16.4/patch-fblogo → target/linux/patches/3.16.6/patch-fblogo


+ 0 - 0
target/linux/patches/3.16.4/patch-yaffs2 → target/linux/patches/3.16.6/patch-yaffs2


+ 0 - 0
target/linux/patches/3.16.4/ppc64-missing-zlib.patch → target/linux/patches/3.16.6/ppc64-missing-zlib.patch


+ 0 - 0
target/linux/patches/3.16.4/regmap-boolean.patch → target/linux/patches/3.16.6/regmap-boolean.patch


+ 0 - 0
target/linux/patches/3.16.4/relocs.patch → target/linux/patches/3.16.6/relocs.patch


+ 0 - 0
target/linux/patches/3.16.4/sgidefs.patch → target/linux/patches/3.16.6/sgidefs.patch


+ 0 - 0
target/linux/patches/3.16.4/sortext.patch → target/linux/patches/3.16.6/sortext.patch


+ 0 - 0
target/linux/patches/3.16.4/sparc-memset.patch → target/linux/patches/3.16.6/sparc-memset.patch


+ 0 - 0
target/linux/patches/3.16.4/startup.patch → target/linux/patches/3.16.6/startup.patch


+ 0 - 0
target/linux/patches/3.16.4/wlan-cf.patch → target/linux/patches/3.16.6/wlan-cf.patch


+ 0 - 0
target/linux/patches/3.16.4/xargs.patch → target/linux/patches/3.16.6/xargs.patch


+ 0 - 0
target/m68k/qemu-m68k/patches/3.16.4/m68k-coldfire-fec.patch → target/m68k/qemu-m68k/patches/3.16.6/m68k-coldfire-fec.patch


+ 0 - 0
target/m68k/qemu-m68k/patches/3.16.4/qemu-coldfire.patch → target/m68k/qemu-m68k/patches/3.16.6/qemu-coldfire.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0001-mtd-add-rb4xx-nand-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0001-mtd-add-rb4xx-nand-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0003-net-add-ag71xx-mac-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0003-net-add-ag71xx-mac-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0004-drivers-link-SPI-drivers-before-MTD-drivers.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0004-drivers-link-SPI-drivers-before-MTD-drivers.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0005-spi-add-various-flags-to-spi_transfer-and-spi_messag.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0005-spi-add-various-flags-to-spi_transfer-and-spi_messag.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0006-spi-add-rb4xx-SPI-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0006-spi-add-rb4xx-SPI-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0007-spi-add-rb4xx-cpld-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0007-spi-add-rb4xx-cpld-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0008-gpio-add-GPIO-latch-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0008-gpio-add-GPIO-latch-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0009-spi-export-spi_bitbang_bufs-function.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0009-spi-export-spi_bitbang_bufs-function.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0010-spi-add-type-field-to-spi_transfer-struct.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0010-spi-add-type-field-to-spi_transfer-struct.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0011-mtd-m25p80-set-SPI-transfer-type.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0011-mtd-m25p80-set-SPI-transfer-type.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0012-mips-ath79-swizzle-PCI-address-for-ar71xx.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0012-mips-ath79-swizzle-PCI-address-for-ar71xx.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0013-net-add-swconfig-support.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0013-net-add-swconfig-support.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0014-phy-add-detach-callback-to-struct-phy_driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0014-phy-add-detach-callback-to-struct-phy_driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0015-phy-add-ar8216-PHY-support.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0015-phy-add-ar8216-PHY-support.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0016-phy-mdio-bitbang-ignore-TA-value.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0016-phy-mdio-bitbang-ignore-TA-value.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0017-MIPS-ath79-fix-maximum-timeout.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0017-MIPS-ath79-fix-maximum-timeout.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0018-net-allow-PHY-drivers-to-insert-packet-mangle-hooks.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0018-net-allow-PHY-drivers-to-insert-packet-mangle-hooks.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0019-MIPS-ath79-process-board-cmdline-option.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0019-MIPS-ath79-process-board-cmdline-option.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0020-spi-ath79-add-fast-flash-read-support.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0020-spi-ath79-add-fast-flash-read-support.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0021-phy-add-mdio-boardinfo.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0021-phy-add-mdio-boardinfo.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0022-mips-ath79-add-ath79-ethernet-driver.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0022-mips-ath79-add-ath79-ethernet-driver.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0023-MIPS-ath79-add-Mikrotik-rb4xx-device-support.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0023-MIPS-ath79-add-Mikrotik-rb4xx-device-support.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0024-various-fixups-for-Werror.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0024-various-fixups-for-Werror.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0025-rb4xx_nand-add-partition-for-cfgfs.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0025-rb4xx_nand-add-partition-for-cfgfs.patch


+ 0 - 0
target/mips/mikrotik-rb4xx/patches/3.14.17/0026-various-fixups-for-ath5k-fixing-system-freezes.patch → target/mips/mikrotik-rb4xx/patches/3.14.22/0026-various-fixups-for-ath5k-fixing-system-freezes.patch


+ 0 - 0
target/mips/mikrotik-rb532/patches/3.14.17/rb532-cfgfs.patch → target/mips/mikrotik-rb532/patches/3.14.22/rb532-cfgfs.patch


+ 0 - 0
target/mips/mikrotik-rb532/patches/3.14.17/rb532-pci.patch → target/mips/mikrotik-rb532/patches/3.14.22/rb532-pci.patch


+ 0 - 0
target/mips64/lemote-yeelong/patches/3.16.4/sm7xx-fb.patch → target/mips64/lemote-yeelong/patches/3.16.6/sm7xx-fb.patch


Some files were not shown because too many files changed in this diff