Merge tag 'drm-misc-next-2017-03-12' of git://anongit.freedesktop.org/git/drm-misc...
authorDave Airlie <airlied@redhat.com>
Wed, 15 Mar 2017 01:32:01 +0000 (11:32 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 15 Mar 2017 01:32:01 +0000 (11:32 +1000)
More drm-misc stuff for 4.12:

- drm_platform removal from Laurent
- more dw-hdmi bridge driver updates (Laurent, Kieran, Neil)
- more header cleanup and documentation
- more drm_debugs_remove_files removal (Noralf)
- minor qxl updates (Gerd)
- edp crc support in helper + analogix_dp (Tomeu) for more igt
  testing!
- old/new iterator roll-out (Maarten)
- new bridge drivers: lvds (Laurent), megachips-something (Peter
  Senna)

* tag 'drm-misc-next-2017-03-12' of git://anongit.freedesktop.org/git/drm-misc: (51 commits)
  drm: bridge: dw-hdmi: Move the driver to a separate directory.
  drm: bridge: dw-hdmi: Switch to regmap for register access
  drm: bridge: dw-hdmi: Remove device type from platform data
  drm: bridge: dw-hdmi: Add support for custom PHY configuration
  drm: bridge: dw-hdmi: Create PHY operations
  drm: bridge: dw-hdmi: Fix the PHY power up sequence
  drm: bridge: dw-hdmi: Fix the PHY power down sequence
  drm: bridge: dw-hdmi: Enable CSC even for DVI
  drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
  drm: bridge: dw-hdmi: Remove unused functions
  drm: Extract drm_file.h
  drm: Remove DRM_MINOR_CNT
  drm: rename drm_fops.c to drm_file.c
  drm/doc: document fallback behaviour for atomic events
  drm: Remove drmP.h include from drm_kms_helper_common.c
  drm: Extract drm_pci.h
  drm: Move drm_lock_data out of drmP.h
  drm: Extract drm_prime.h
  drm/doc: Add todo about connector_list_iter
  drm/qxl: Remove qxl_debugfs_remove_files()
  ...

87 files changed:
Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/gpu/drm-internals.rst
Documentation/gpu/drm-mm.rst
Documentation/gpu/todo.rst
MAINTAINERS
drivers/gpu/drm/Makefile
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/Makefile
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/dumb-vga-dac.c
drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c [deleted file]
drivers/gpu/drm/bridge/dw-hdmi-audio.h [deleted file]
drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c [deleted file]
drivers/gpu/drm/bridge/dw-hdmi.c [deleted file]
drivers/gpu/drm/bridge/dw-hdmi.h [deleted file]
drivers/gpu/drm/bridge/lvds-encoder.c [new file with mode: 0644]
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/Kconfig [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/Makefile [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c [new file with mode: 0644]
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h [new file with mode: 0644]
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_blend.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_file.c [new file with mode: 0644]
drivers/gpu/drm/drm_fops.c [deleted file]
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_kms_helper_common.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/drm_platform.c [deleted file]
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/exynos/exynos_dp.c
drivers/gpu/drm/exynos/exynos_drm_dpi.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/imx/dw_hdmi-imx.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c
drivers/gpu/drm/msm/msm_debugfs.c
drivers/gpu/drm/msm/msm_debugfs.h
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_kms.h
drivers/gpu/drm/msm/msm_perf.c
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/qxl/qxl_debugfs.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_kms.c
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_vq.c
include/drm/bridge/analogix_dp.h
include/drm/bridge/dw_hdmi.h
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_atomic_helper.h
include/drm/drm_auth.h
include/drm/drm_crtc.h
include/drm/drm_dp_helper.h
include/drm/drm_drv.h
include/drm/drm_file.h [new file with mode: 0644]
include/drm/drm_gem.h
include/drm/drm_pci.h [new file with mode: 0644]
include/drm/drm_prime.h [new file with mode: 0644]
include/drm/drm_vma_manager.h

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
new file mode 100644 (file)
index 0000000..fd39ad3
--- /dev/null
@@ -0,0 +1,64 @@
+Parallel to LVDS Encoder
+------------------------
+
+This binding supports the parallel to LVDS encoders that don't require any
+configuration.
+
+LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
+incompatible data link layers have been used over time to transmit image data
+to LVDS panels. This binding targets devices compatible with the following
+specifications only.
+
+[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
+1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
+[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
+Semiconductor
+[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
+Electronics Standards Association (VESA)
+
+Those devices have been marketed under the FPD-Link and FlatLink brand names
+among others.
+
+
+Required properties:
+
+- compatible: Must be "lvds-encoder"
+
+Required nodes:
+
+This device has two video ports. Their connections are modeled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for parallel input
+- Video port 1 for LVDS output
+
+
+Example
+-------
+
+lvds-encoder {
+       compatible = "lvds-encoder";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               port@0 {
+                       reg = <0>;
+
+                       lvds_enc_in: endpoint {
+                               remote-endpoint = <&display_out_rgb>;
+                       };
+               };
+
+               port@1 {
+                       reg = <1>;
+
+                       lvds_enc_out: endpoint {
+                               remote-endpoint = <&lvds_panel_in>;
+                       };
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt b/Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
new file mode 100644 (file)
index 0000000..7baa658
--- /dev/null
@@ -0,0 +1,94 @@
+Drivers for the second video output of the GE B850v3:
+   STDP4028-ge-b850v3-fw bridges (LVDS-DP)
+   STDP2690-ge-b850v3-fw bridges (DP-DP++)
+
+The video processing pipeline on the second output on the GE B850v3:
+
+   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
+
+Each bridge has a dedicated flash containing firmware for supporting the custom
+design. The result is that, in this design, neither the STDP4028 nor the
+STDP2690 behave as the stock bridges would. The compatible strings include the
+suffix "-ge-b850v3-fw" to make it clear that the driver is for the bridges with
+the firmware specific for the GE B850v3.
+
+The hardware do not provide control over the video processing pipeline, as the
+two bridges behaves as a single one. The only interfaces exposed by the
+hardware are EDID, HPD, and interrupts.
+
+stdp4028-ge-b850v3-fw required properties:
+  - compatible : "megachips,stdp4028-ge-b850v3-fw"
+  - reg : I2C bus address
+  - interrupt-parent : phandle of the interrupt controller that services
+    interrupts to the device
+  - interrupts : one interrupt should be described here, as in
+    <0 IRQ_TYPE_LEVEL_HIGH>
+  - ports : One input port(reg = <0>) and one output port(reg = <1>)
+
+stdp2690-ge-b850v3-fw required properties:
+    compatible : "megachips,stdp2690-ge-b850v3-fw"
+  - reg : I2C bus address
+  - ports : One input port(reg = <0>) and one output port(reg = <1>)
+
+Example:
+
+&mux2_i2c2 {
+       status = "okay";
+       clock-frequency = <100000>;
+
+       stdp4028@73 {
+               compatible = "megachips,stdp4028-ge-b850v3-fw";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg = <0x73>;
+
+               interrupt-parent = <&gpio2>;
+               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               stdp4028_in: endpoint {
+                                       remote-endpoint = <&lvds0_out>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               stdp4028_out: endpoint {
+                                       remote-endpoint = <&stdp2690_in>;
+                               };
+                       };
+               };
+       };
+
+       stdp2690@72 {
+               compatible = "megachips,stdp2690-ge-b850v3-fw";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg = <0x72>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               stdp2690_in: endpoint {
+                                       remote-endpoint = <&stdp4028_out>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               stdp2690_out: endpoint {
+                                       /* Connector for external display */
+                               };
+                       };
+               };
+       };
+};
index ec0bfb9..4686f4b 100644 (file)
@@ -178,6 +178,7 @@ maxim       Maxim Integrated Products
 mcube  mCube
 meas   Measurement Specialties
 mediatek       MediaTek Inc.
+megachips      MegaChips
 melexis        Melexis N.V.
 melfas MELFAS Inc.
 memsic MEMSIC Inc.
index e35920d..3bb4d93 100644 (file)
@@ -240,9 +240,6 @@ drivers.
 .. kernel-doc:: drivers/gpu/drm/drm_pci.c
    :export:
 
-.. kernel-doc:: drivers/gpu/drm/drm_platform.c
-   :export:
-
 Open/Close, File Operations and IOCTLs
 ======================================
 
@@ -298,10 +295,10 @@ over.
 File Operations
 ---------------
 
-.. kernel-doc:: drivers/gpu/drm/drm_fops.c
+.. kernel-doc:: drivers/gpu/drm/drm_file.c
    :doc: file operations
 
-.. kernel-doc:: drivers/gpu/drm/drm_fops.c
+.. kernel-doc:: drivers/gpu/drm/drm_file.c
    :export:
 
 IOCTLs
index fd35998..d7a29d4 100644 (file)
@@ -449,6 +449,9 @@ PRIME Helper Functions
 PRIME Function References
 -------------------------
 
+.. kernel-doc:: include/drm/drm_prime.h
+   :internal:
+
 .. kernel-doc:: drivers/gpu/drm/drm_prime.c
    :export:
 
index ce0f1a5..64e9d16 100644 (file)
@@ -153,6 +153,19 @@ following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
 
 Contact: Daniel Vetter
 
+Switch to drm_connector_list_iter for any connector_list walking
+----------------------------------------------------------------
+
+Connectors can be hotplugged, and we now have a special list of helpers to walk
+the connector_list in a race-free fashion, without incurring deadlocks on
+mutexes and other fun stuff.
+
+Unfortunately most drivers are not converted yet. At least all those supporting
+DP MST hotplug should be converted, since for those drivers the difference
+matters. See drm_for_each_connector_iter() vs. drm_for_each_connector().
+
+Contact: Daniel Vetter
+
 Core refactorings
 =================
 
index 4084e2f..e88154f 100644 (file)
@@ -8123,6 +8123,14 @@ L:       linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/mediatek/mt7601u/
 
+MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
+M:     Peter Senna Tschudin <peter.senna@collabora.com>
+M:     Martin Donnelly <martin.donnelly@ge.com>
+M:     Martyn Welch <martyn.welch@collabora.co.uk>
+S:     Maintained
+F:     drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+F:     Documentation/devicetree/bindings/video/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
+
 MEGARAID SCSI/SAS DRIVERS
 M:     Kashyap Desai <kashyap.desai@broadcom.com>
 M:     Sumit Saxena <sumit.saxena@broadcom.com>
index 3ee9579..59aae43 100644 (file)
@@ -4,10 +4,10 @@
 
 drm-y       := drm_auth.o drm_bufs.o drm_cache.o \
                drm_context.o drm_dma.o \
-               drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
+               drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \
                drm_lock.o drm_memory.o drm_drv.o \
                drm_scatter.o drm_pci.o \
-               drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
+               drm_sysfs.o drm_hashtab.o drm_mm.o \
                drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
                drm_info.o drm_encoder_slave.o \
                drm_trace_points.o drm_global.o drm_prime.o \
index 1952e87..408e00b 100644 (file)
@@ -137,10 +137,9 @@ static int armada_drm_bind(struct device *dev)
                return ret;
        }
 
-       priv->drm.platformdev = to_platform_device(dev);
        priv->drm.dev_private = priv;
 
-       platform_set_drvdata(priv->drm.platformdev, &priv->drm);
+       dev_set_drvdata(dev, &priv->drm);
 
        INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
        INIT_KFIFO(priv->fb_unref);
index eb8688e..f6968d3 100644 (file)
@@ -24,29 +24,25 @@ config DRM_DUMB_VGA_DAC
        help
          Support for RGB to VGA DAC based bridges
 
-config DRM_DW_HDMI
-       tristate
+config DRM_LVDS_ENCODER
+       tristate "Transparent parallel to LVDS encoder support"
+       depends on OF
        select DRM_KMS_HELPER
-
-config DRM_DW_HDMI_AHB_AUDIO
-       tristate "Synopsis Designware AHB Audio interface"
-       depends on DRM_DW_HDMI && SND
-       select SND_PCM
-       select SND_PCM_ELD
-       select SND_PCM_IEC958
+       select DRM_PANEL
        help
-         Support the AHB Audio interface which is part of the Synopsis
-         Designware HDMI block.  This is used in conjunction with
-         the i.MX6 HDMI driver.
+         Support for transparent parallel to LVDS encoders that don't require
+         any configuration.
 
-config DRM_DW_HDMI_I2S_AUDIO
-       tristate "Synopsis Designware I2S Audio interface"
-       depends on SND_SOC
-       depends on DRM_DW_HDMI
-       select SND_SOC_HDMI_CODEC
-       help
-         Support the I2S Audio interface which is part of the Synopsis
-         Designware HDMI block.
+config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW
+       tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw"
+       depends on OF
+       select DRM_KMS_HELPER
+       select DRM_PANEL
+       ---help---
+          This is a driver for the display bridges of
+          GE B850v3 that convert dual channel LVDS
+          to DP++. This is used with the i.MX6 imx-ldb
+          driver. You are likely to say N here.
 
 config DRM_NXP_PTN3460
        tristate "NXP PTN3460 DP/LVDS bridge"
@@ -101,4 +97,6 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
 
+source "drivers/gpu/drm/bridge/synopsys/Kconfig"
+
 endmenu
index 2e83a78..3fe2226 100644 (file)
@@ -2,9 +2,8 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
-obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
-obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
-obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
+obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
+obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
@@ -13,3 +12,4 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-y += synopsys/
index e7cd105..c26997a 100644 (file)
@@ -1488,6 +1488,28 @@ int analogix_dp_resume(struct device *dev)
 EXPORT_SYMBOL_GPL(analogix_dp_resume);
 #endif
 
+int analogix_dp_start_crc(struct drm_connector *connector)
+{
+       struct analogix_dp_device *dp = to_dp(connector);
+
+       if (!connector->state->crtc) {
+               DRM_ERROR("Connector %s doesn't currently have a CRTC.\n",
+                         connector->name);
+               return -EINVAL;
+       }
+
+       return drm_dp_start_crc(&dp->aux, connector->state->crtc);
+}
+EXPORT_SYMBOL_GPL(analogix_dp_start_crc);
+
+int analogix_dp_stop_crc(struct drm_connector *connector)
+{
+       struct analogix_dp_device *dp = to_dp(connector);
+
+       return drm_dp_stop_crc(&dp->aux);
+}
+EXPORT_SYMBOL_GPL(analogix_dp_stop_crc);
+
 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
 MODULE_DESCRIPTION("Analogix DP Core Driver");
 MODULE_LICENSE("GPL v2");
index 86e9f9c..63e113b 100644 (file)
@@ -237,6 +237,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
 
 static const struct of_device_id dumb_vga_match[] = {
        { .compatible = "dumb-vga-dac" },
+       { .compatible = "adi,adv7123" },
        { .compatible = "ti,ths8135" },
        {},
 };
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
deleted file mode 100644 (file)
index 8f2d137..0000000
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
- * 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 Designware HDMI Tx found in iMX6.
- */
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <drm/bridge/dw_hdmi.h>
-#include <drm/drm_edid.h>
-
-#include <sound/asoundef.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/pcm_drm_eld.h>
-#include <sound/pcm_iec958.h>
-
-#include "dw-hdmi-audio.h"
-
-#define DRIVER_NAME "dw-hdmi-ahb-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_FC_AUDICONF2 = 0x1027,
-       HDMI_FC_AUDSCONF = 0x1063,
-       HDMI_FC_AUDSCONF_LAYOUT1 = 1 << 0,
-       HDMI_FC_AUDSCONF_LAYOUT0 = 0 << 0,
-       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_MASK = 0x3614,
-       HDMI_AHB_DMA_POL = 0x3615,
-       HDMI_AHB_DMA_CONF1 = 0x3616,
-       HDMI_AHB_DMA_BUFFPOL = 0x361a,
-};
-
-struct dw_hdmi_channel_conf {
-       u8 conf1;
-       u8 ca;
-};
-
-/*
- * The default mapping of ALSA channels to HDMI channels and speaker
- * allocation bits.  Note that we can't do channel remapping here -
- * channels must be in the same order.
- *
- * Mappings for alsa-lib pcm/surround*.conf files:
- *
- *             Front   Sur4.0  Sur4.1  Sur5.0  Sur5.1  Sur7.1
- * Channels    2       4       6       6       6       8
- *
- * Our mapping from ALSA channel to CEA686D speaker name and HDMI channel:
- *
- *                             Number of ALSA channels
- * ALSA Channel        2       3       4       5       6       7       8
- * 0           FL:0    =       =       =       =       =       =
- * 1           FR:1    =       =       =       =       =       =
- * 2                   FC:3    RL:4    LFE:2   =       =       =
- * 3                           RR:5    RL:4    FC:3    =       =
- * 4                                   RR:5    RL:4    =       =
- * 5                                           RR:5    =       =
- * 6                                                   RC:6    =
- * 7                                                   RLC/FRC RLC/FRC
- */
-static struct dw_hdmi_channel_conf default_hdmi_channel_config[7] = {
-       { 0x03, 0x00 }, /* FL,FR */
-       { 0x0b, 0x02 }, /* FL,FR,FC */
-       { 0x33, 0x08 }, /* FL,FR,RL,RR */
-       { 0x37, 0x09 }, /* FL,FR,LFE,RL,RR */
-       { 0x3f, 0x0b }, /* FL,FR,LFE,FC,RL,RR */
-       { 0x7f, 0x0f }, /* FL,FR,LFE,FC,RL,RR,RC */
-       { 0xff, 0x13 }, /* FL,FR,LFE,FC,RL,RR,[FR]RC,[FR]LC */
-};
-
-struct snd_dw_hdmi {
-       struct snd_card *card;
-       struct snd_pcm *pcm;
-       spinlock_t lock;
-       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;
-       u8 revision;
-       u8 iec_offset;
-       u8 cs[192][8];
-};
-
-static void dw_hdmi_writel(u32 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)
-{
-       u32 *src = dw->buf_src + offset;
-       u32 *dst = dw->buf_dst + offset;
-       u32 *end = dw->buf_src + offset + bytes;
-
-       do {
-               u32 b, sample = *src++;
-
-               b = (sample & 8) << (28 - 3);
-
-               sample >>= 4;
-
-               *dst++ = sample | b;
-       } while (src < end);
-}
-
-static u32 parity(u32 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)
-{
-       u32 *src = dw->buf_src + offset;
-       u32 *dst = dw->buf_dst + offset;
-       u32 *end = dw->buf_src + offset + bytes;
-
-       do {
-               unsigned i;
-               u8 *cs;
-
-               cs = dw->cs[dw->iec_offset++];
-               if (dw->iec_offset >= 192)
-                       dw->iec_offset = 0;
-
-               i = dw->channels;
-               do {
-                       u32 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)
-{
-       u8 cs[4];
-       unsigned ch, i, j;
-
-       snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs));
-
-       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)
-{
-       /* 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);
-}
-
-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);
-
-               spin_lock(&dw->lock);
-               if (dw->substream)
-                       dw_hdmi_start_dma(dw);
-               spin_unlock(&dw->lock);
-       }
-
-       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 = 1024 * 1024,
-       .period_bytes_min = 256,
-       .period_bytes_max = 8192,       /* ERR004323: must limit to 8k */
-       .periods_min = 2,
-       .periods_max = 16,
-       .fifo_size = 0,
-};
-
-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;
-
-       runtime->hw = dw_hdmi_hw;
-
-       ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
-       if (ret < 0)
-               return ret;
-
-       ret = snd_pcm_limit_hw_rates(runtime);
-       if (ret < 0)
-               return ret;
-
-       ret = snd_pcm_hw_constraint_integer(runtime,
-                                           SNDRV_PCM_HW_PARAM_PERIODS);
-       if (ret < 0)
-               return ret;
-
-       /* Limit the buffer size to the size of the preallocated buffer */
-       ret = snd_pcm_hw_constraint_minmax(runtime,
-                                          SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
-                                          0, substream->dma_buffer.bytes);
-       if (ret < 0)
-               return 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);
-
-       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)
-{
-       /* Allocate the PCM runtime buffer, which is exposed to userspace. */
-       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;
-       u8 threshold, conf0, conf1, layout, ca;
-
-       /* 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_hdmi_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 = default_hdmi_channel_config[runtime->channels - 2].conf1;
-       ca = default_hdmi_channel_config[runtime->channels - 2].ca;
-
-       /*
-        * For >2 channel PCM audio, we need to select layout 1
-        * and set an appropriate channel map.
-        */
-       if (runtime->channels > 2)
-               layout = HDMI_FC_AUDSCONF_LAYOUT1;
-       else
-               layout = HDMI_FC_AUDSCONF_LAYOUT0;
-
-       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);
-       writeb_relaxed(layout, dw->data.base + HDMI_FC_AUDSCONF);
-       writeb_relaxed(ca, dw->data.base + HDMI_FC_AUDICONF2);
-
-       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;
-       unsigned long flags;
-       int ret = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               spin_lock_irqsave(&dw->lock, flags);
-               dw->buf_offset = 0;
-               dw->substream = substream;
-               dw_hdmi_start_dma(dw);
-               dw_hdmi_audio_enable(dw->data.hdmi);
-               spin_unlock_irqrestore(&dw->lock, flags);
-               substream->runtime->delay = substream->runtime->period_size;
-               break;
-
-       case SNDRV_PCM_TRIGGER_STOP:
-               spin_lock_irqsave(&dw->lock, flags);
-               dw->substream = NULL;
-               dw_hdmi_stop_dma(dw);
-               dw_hdmi_audio_disable(dw->data.hdmi);
-               spin_unlock_irqrestore(&dw->lock, flags);
-               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;
-
-       /*
-        * We are unable to report the exact hardware position as
-        * reading the 32-bit DMA position using 8-bit reads is racy.
-        */
-       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;
-
-       spin_lock_init(&dw->lock);
-
-       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);
-
-       /*
-        * To support 8-channel 96kHz audio reliably, we need 512k
-        * to satisfy alsa with our restricted period (ERR004323).
-        */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                       dev, 128 * 1024, 1024 * 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;
-}
-
-#if defined(CONFIG_PM_SLEEP) && defined(IS_NOT_BROKEN)
-/*
- * This code is fine, but requires implementation in the dw_hdmi_trigger()
- * method which is currently missing as I have no way to test this.
- */
-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 = DRIVER_NAME,
-               .pm = PM_OPS,
-       },
-};
-
-module_platform_driver(snd_dw_hdmi_driver);
-
-MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
-MODULE_DESCRIPTION("Synopsis Designware HDMI AHB ALSA interface");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/dw-hdmi-audio.h
deleted file mode 100644 (file)
index fd1f745..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef DW_HDMI_AUDIO_H
-#define DW_HDMI_AUDIO_H
-
-struct dw_hdmi;
-
-struct dw_hdmi_audio_data {
-       phys_addr_t phys;
-       void __iomem *base;
-       int irq;
-       struct dw_hdmi *hdmi;
-       u8 *eld;
-};
-
-struct dw_hdmi_i2s_audio_data {
-       struct dw_hdmi *hdmi;
-
-       void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
-       u8 (*read)(struct dw_hdmi *hdmi, int offset);
-};
-
-#endif
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
deleted file mode 100644 (file)
index aaf287d..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * dw-hdmi-i2s-audio.c
- *
- * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * 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 <drm/bridge/dw_hdmi.h>
-
-#include <sound/hdmi-codec.h>
-
-#include "dw-hdmi.h"
-#include "dw-hdmi-audio.h"
-
-#define DRIVER_NAME "dw-hdmi-i2s-audio"
-
-static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio,
-                             u8 val, int offset)
-{
-       struct dw_hdmi *hdmi = audio->hdmi;
-
-       audio->write(hdmi, val, offset);
-}
-
-static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
-{
-       struct dw_hdmi *hdmi = audio->hdmi;
-
-       return audio->read(hdmi, offset);
-}
-
-static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
-                                struct hdmi_codec_daifmt *fmt,
-                                struct hdmi_codec_params *hparms)
-{
-       struct dw_hdmi_i2s_audio_data *audio = data;
-       struct dw_hdmi *hdmi = audio->hdmi;
-       u8 conf0 = 0;
-       u8 conf1 = 0;
-       u8 inputclkfs = 0;
-
-       /* it cares I2S only */
-       if ((fmt->fmt != HDMI_I2S) ||
-           (fmt->bit_clk_master | fmt->frame_clk_master)) {
-               dev_err(dev, "unsupported format/settings\n");
-               return -EINVAL;
-       }
-
-       inputclkfs      = HDMI_AUD_INPUTCLKFS_64FS;
-       conf0           = HDMI_AUD_CONF0_I2S_ALL_ENABLE;
-
-       switch (hparms->sample_width) {
-       case 16:
-               conf1 = HDMI_AUD_CONF1_WIDTH_16;
-               break;
-       case 24:
-       case 32:
-               conf1 = HDMI_AUD_CONF1_WIDTH_24;
-               break;
-       }
-
-       dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
-
-       hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
-       hdmi_write(audio, conf0, HDMI_AUD_CONF0);
-       hdmi_write(audio, conf1, HDMI_AUD_CONF1);
-
-       dw_hdmi_audio_enable(hdmi);
-
-       return 0;
-}
-
-static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
-{
-       struct dw_hdmi_i2s_audio_data *audio = data;
-       struct dw_hdmi *hdmi = audio->hdmi;
-
-       dw_hdmi_audio_disable(hdmi);
-
-       hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
-}
-
-static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
-       .hw_params      = dw_hdmi_i2s_hw_params,
-       .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
-};
-
-static int snd_dw_hdmi_probe(struct platform_device *pdev)
-{
-       struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data;
-       struct platform_device_info pdevinfo;
-       struct hdmi_codec_pdata pdata;
-       struct platform_device *platform;
-
-       pdata.ops               = &dw_hdmi_i2s_ops;
-       pdata.i2s               = 1;
-       pdata.max_i2s_channels  = 6;
-       pdata.data              = audio;
-
-       memset(&pdevinfo, 0, sizeof(pdevinfo));
-       pdevinfo.parent         = pdev->dev.parent;
-       pdevinfo.id             = PLATFORM_DEVID_AUTO;
-       pdevinfo.name           = HDMI_CODEC_DRV_NAME;
-       pdevinfo.data           = &pdata;
-       pdevinfo.size_data      = sizeof(pdata);
-       pdevinfo.dma_mask       = DMA_BIT_MASK(32);
-
-       platform = platform_device_register_full(&pdevinfo);
-       if (IS_ERR(platform))
-               return PTR_ERR(platform);
-
-       dev_set_drvdata(&pdev->dev, platform);
-
-       return 0;
-}
-
-static int snd_dw_hdmi_remove(struct platform_device *pdev)
-{
-       struct platform_device *platform = dev_get_drvdata(&pdev->dev);
-
-       platform_device_unregister(platform);
-
-       return 0;
-}
-
-static struct platform_driver snd_dw_hdmi_driver = {
-       .probe  = snd_dw_hdmi_probe,
-       .remove = snd_dw_hdmi_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .owner = THIS_MODULE,
-       },
-};
-module_platform_driver(snd_dw_hdmi_driver);
-
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
deleted file mode 100644 (file)
index 9a9ec27..0000000
+++ /dev/null
@@ -1,2221 +0,0 @@
-/*
- * DesignWare High-Definition Multimedia Interface (HDMI) driver
- *
- * Copyright (C) 2013-2015 Mentor Graphics Inc.
- * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
- * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/hdmi.h>
-#include <linux/mutex.h>
-#include <linux/of_device.h>
-#include <linux/spinlock.h>
-
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_encoder_slave.h>
-#include <drm/bridge/dw_hdmi.h>
-
-#include "dw-hdmi.h"
-#include "dw-hdmi-audio.h"
-
-#define HDMI_EDID_LEN          512
-
-#define RGB                    0
-#define YCBCR444               1
-#define YCBCR422_16BITS                2
-#define YCBCR422_8BITS         3
-#define XVYCC444               4
-
-enum hdmi_datamap {
-       RGB444_8B = 0x01,
-       RGB444_10B = 0x03,
-       RGB444_12B = 0x05,
-       RGB444_16B = 0x07,
-       YCbCr444_8B = 0x09,
-       YCbCr444_10B = 0x0B,
-       YCbCr444_12B = 0x0D,
-       YCbCr444_16B = 0x0F,
-       YCbCr422_8B = 0x16,
-       YCbCr422_10B = 0x14,
-       YCbCr422_12B = 0x12,
-};
-
-static const u16 csc_coeff_default[3][4] = {
-       { 0x2000, 0x0000, 0x0000, 0x0000 },
-       { 0x0000, 0x2000, 0x0000, 0x0000 },
-       { 0x0000, 0x0000, 0x2000, 0x0000 }
-};
-
-static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
-       { 0x2000, 0x6926, 0x74fd, 0x010e },
-       { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
-       { 0x2000, 0x0000, 0x38b4, 0x7e3b }
-};
-
-static const u16 csc_coeff_rgb_out_eitu709[3][4] = {
-       { 0x2000, 0x7106, 0x7a02, 0x00a7 },
-       { 0x2000, 0x3264, 0x0000, 0x7e6d },
-       { 0x2000, 0x0000, 0x3b61, 0x7e25 }
-};
-
-static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
-       { 0x2591, 0x1322, 0x074b, 0x0000 },
-       { 0x6535, 0x2000, 0x7acc, 0x0200 },
-       { 0x6acd, 0x7534, 0x2000, 0x0200 }
-};
-
-static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
-       { 0x2dc5, 0x0d9b, 0x049e, 0x0000 },
-       { 0x62f0, 0x2000, 0x7d11, 0x0200 },
-       { 0x6756, 0x78ab, 0x2000, 0x0200 }
-};
-
-struct hdmi_vmode {
-       bool mdataenablepolarity;
-
-       unsigned int mpixelclock;
-       unsigned int mpixelrepetitioninput;
-       unsigned int mpixelrepetitionoutput;
-};
-
-struct hdmi_data_info {
-       unsigned int enc_in_format;
-       unsigned int enc_out_format;
-       unsigned int enc_color_depth;
-       unsigned int colorimetry;
-       unsigned int pix_repet_factor;
-       unsigned int hdcp_enable;
-       struct hdmi_vmode video_mode;
-};
-
-struct dw_hdmi_i2c {
-       struct i2c_adapter      adap;
-
-       struct mutex            lock;   /* used to serialize data transfers */
-       struct completion       cmp;
-       u8                      stat;
-
-       u8                      slave_reg;
-       bool                    is_regaddr;
-};
-
-struct dw_hdmi_phy_data {
-       enum dw_hdmi_phy_type type;
-       const char *name;
-       bool has_svsret;
-};
-
-struct dw_hdmi {
-       struct drm_connector connector;
-       struct drm_bridge bridge;
-
-       enum dw_hdmi_devtype dev_type;
-       unsigned int version;
-
-       struct platform_device *audio;
-       struct device *dev;
-       struct clk *isfr_clk;
-       struct clk *iahb_clk;
-       struct dw_hdmi_i2c *i2c;
-
-       struct hdmi_data_info hdmi_data;
-       const struct dw_hdmi_plat_data *plat_data;
-
-       int vic;
-
-       u8 edid[HDMI_EDID_LEN];
-       bool cable_plugin;
-
-       const struct dw_hdmi_phy_data *phy;
-       bool phy_enabled;
-
-       struct drm_display_mode previous_mode;
-
-       struct i2c_adapter *ddc;
-       void __iomem *regs;
-       bool sink_is_hdmi;
-       bool sink_has_audio;
-
-       struct mutex mutex;             /* for state below and previous_mode */
-       enum drm_connector_force force; /* mutex-protected force state */
-       bool disabled;                  /* DRM has disabled our bridge */
-       bool bridge_is_on;              /* indicates the bridge is on */
-       bool rxsense;                   /* rxsense state */
-       u8 phy_mask;                    /* desired phy int mask settings */
-
-       spinlock_t audio_lock;
-       struct mutex audio_mutex;
-       unsigned int sample_rate;
-       unsigned int audio_cts;
-       unsigned int audio_n;
-       bool audio_enable;
-
-       void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
-       u8 (*read)(struct dw_hdmi *hdmi, int offset);
-};
-
-#define HDMI_IH_PHY_STAT0_RX_SENSE \
-       (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \
-        HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3)
-
-#define HDMI_PHY_RX_SENSE \
-       (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
-        HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
-
-static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-       writel(val, hdmi->regs + (offset << 2));
-}
-
-static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
-{
-       return readl(hdmi->regs + (offset << 2));
-}
-
-static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-       writeb(val, hdmi->regs + offset);
-}
-
-static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
-{
-       return readb(hdmi->regs + offset);
-}
-
-static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-       hdmi->write(hdmi, val, offset);
-}
-
-static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
-{
-       return hdmi->read(hdmi, offset);
-}
-
-static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
-{
-       u8 val = hdmi_readb(hdmi, reg) & ~mask;
-
-       val |= data & mask;
-       hdmi_writeb(hdmi, val, reg);
-}
-
-static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
-                            u8 shift, u8 mask)
-{
-       hdmi_modb(hdmi, data << shift, mask, reg);
-}
-
-static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi)
-{
-       /* Software reset */
-       hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ);
-
-       /* Set Standard Mode speed (determined to be 100KHz on iMX6) */
-       hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV);
-
-       /* Set done, not acknowledged and arbitration interrupt polarities */
-       hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT);
-       hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL,
-                   HDMI_I2CM_CTLINT);
-
-       /* Clear DONE and ERROR interrupts */
-       hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
-                   HDMI_IH_I2CM_STAT0);
-
-       /* Mute DONE and ERROR interrupts */
-       hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
-                   HDMI_IH_MUTE_I2CM_STAT0);
-}
-
-static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
-                           unsigned char *buf, unsigned int length)
-{
-       struct dw_hdmi_i2c *i2c = hdmi->i2c;
-       int stat;
-
-       if (!i2c->is_regaddr) {
-               dev_dbg(hdmi->dev, "set read register address to 0\n");
-               i2c->slave_reg = 0x00;
-               i2c->is_regaddr = true;
-       }
-
-       while (length--) {
-               reinit_completion(&i2c->cmp);
-
-               hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
-               hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
-                           HDMI_I2CM_OPERATION);
-
-               stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
-               if (!stat)
-                       return -EAGAIN;
-
-               /* Check for error condition on the bus */
-               if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
-                       return -EIO;
-
-               *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
-       }
-
-       return 0;
-}
-
-static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi,
-                            unsigned char *buf, unsigned int length)
-{
-       struct dw_hdmi_i2c *i2c = hdmi->i2c;
-       int stat;
-
-       if (!i2c->is_regaddr) {
-               /* Use the first write byte as register address */
-               i2c->slave_reg = buf[0];
-               length--;
-               buf++;
-               i2c->is_regaddr = true;
-       }
-
-       while (length--) {
-               reinit_completion(&i2c->cmp);
-
-               hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO);
-               hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
-               hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE,
-                           HDMI_I2CM_OPERATION);
-
-               stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
-               if (!stat)
-                       return -EAGAIN;
-
-               /* Check for error condition on the bus */
-               if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
-                       return -EIO;
-       }
-
-       return 0;
-}
-
-static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
-                           struct i2c_msg *msgs, int num)
-{
-       struct dw_hdmi *hdmi = i2c_get_adapdata(adap);
-       struct dw_hdmi_i2c *i2c = hdmi->i2c;
-       u8 addr = msgs[0].addr;
-       int i, ret = 0;
-
-       dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
-
-       for (i = 0; i < num; i++) {
-               if (msgs[i].addr != addr) {
-                       dev_warn(hdmi->dev,
-                                "unsupported transfer, changed slave address\n");
-                       return -EOPNOTSUPP;
-               }
-
-               if (msgs[i].len == 0) {
-                       dev_dbg(hdmi->dev,
-                               "unsupported transfer %d/%d, no data\n",
-                               i + 1, num);
-                       return -EOPNOTSUPP;
-               }
-       }
-
-       mutex_lock(&i2c->lock);
-
-       /* Unmute DONE and ERROR interrupts */
-       hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0);
-
-       /* Set slave device address taken from the first I2C message */
-       hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE);
-
-       /* Set slave device register address on transfer */
-       i2c->is_regaddr = false;
-
-       for (i = 0; i < num; i++) {
-               dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
-                       i + 1, num, msgs[i].len, msgs[i].flags);
-
-               if (msgs[i].flags & I2C_M_RD)
-                       ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
-               else
-                       ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
-
-               if (ret < 0)
-                       break;
-       }
-
-       if (!ret)
-               ret = num;
-
-       /* Mute DONE and ERROR interrupts */
-       hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
-                   HDMI_IH_MUTE_I2CM_STAT0);
-
-       mutex_unlock(&i2c->lock);
-
-       return ret;
-}
-
-static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm dw_hdmi_algorithm = {
-       .master_xfer    = dw_hdmi_i2c_xfer,
-       .functionality  = dw_hdmi_i2c_func,
-};
-
-static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
-{
-       struct i2c_adapter *adap;
-       struct dw_hdmi_i2c *i2c;
-       int ret;
-
-       i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
-       if (!i2c)
-               return ERR_PTR(-ENOMEM);
-
-       mutex_init(&i2c->lock);
-       init_completion(&i2c->cmp);
-
-       adap = &i2c->adap;
-       adap->class = I2C_CLASS_DDC;
-       adap->owner = THIS_MODULE;
-       adap->dev.parent = hdmi->dev;
-       adap->algo = &dw_hdmi_algorithm;
-       strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
-       i2c_set_adapdata(adap, hdmi);
-
-       ret = i2c_add_adapter(adap);
-       if (ret) {
-               dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
-               devm_kfree(hdmi->dev, i2c);
-               return ERR_PTR(ret);
-       }
-
-       hdmi->i2c = i2c;
-
-       dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
-
-       return adap;
-}
-
-static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
-                          unsigned int n)
-{
-       /* Must be set/cleared first */
-       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
-
-       /* nshift factor = 0 */
-       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
-
-       hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
-                   HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
-       hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
-       hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
-
-       hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
-       hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
-       hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
-}
-
-static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
-{
-       unsigned int n = (128 * freq) / 1000;
-       unsigned int mult = 1;
-
-       while (freq > 48000) {
-               mult *= 2;
-               freq /= 2;
-       }
-
-       switch (freq) {
-       case 32000:
-               if (pixel_clk == 25175000)
-                       n = 4576;
-               else if (pixel_clk == 27027000)
-                       n = 4096;
-               else if (pixel_clk == 74176000 || pixel_clk == 148352000)
-                       n = 11648;
-               else
-                       n = 4096;
-               n *= mult;
-               break;
-
-       case 44100:
-               if (pixel_clk == 25175000)
-                       n = 7007;
-               else if (pixel_clk == 74176000)
-                       n = 17836;
-               else if (pixel_clk == 148352000)
-                       n = 8918;
-               else
-                       n = 6272;
-               n *= mult;
-               break;
-
-       case 48000:
-               if (pixel_clk == 25175000)
-                       n = 6864;
-               else if (pixel_clk == 27027000)
-                       n = 6144;
-               else if (pixel_clk == 74176000)
-                       n = 11648;
-               else if (pixel_clk == 148352000)
-                       n = 5824;
-               else
-                       n = 6144;
-               n *= mult;
-               break;
-
-       default:
-               break;
-       }
-
-       return n;
-}
-
-static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
-       unsigned long pixel_clk, unsigned int sample_rate)
-{
-       unsigned long ftdms = pixel_clk;
-       unsigned int n, cts;
-       u64 tmp;
-
-       n = hdmi_compute_n(sample_rate, pixel_clk);
-
-       /*
-        * Compute the CTS value from the N value.  Note that CTS and N
-        * can be up to 20 bits in total, so we need 64-bit math.  Also
-        * note that our TDMS clock is not fully accurate; it is accurate
-        * to kHz.  This can introduce an unnecessary remainder in the
-        * calculation below, so we don't try to warn about that.
-        */
-       tmp = (u64)ftdms * n;
-       do_div(tmp, 128 * sample_rate);
-       cts = tmp;
-
-       dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
-               __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
-               n, cts);
-
-       spin_lock_irq(&hdmi->audio_lock);
-       hdmi->audio_n = n;
-       hdmi->audio_cts = cts;
-       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
-       spin_unlock_irq(&hdmi->audio_lock);
-}
-
-static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
-{
-       mutex_lock(&hdmi->audio_mutex);
-       hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate);
-       mutex_unlock(&hdmi->audio_mutex);
-}
-
-static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
-{
-       mutex_lock(&hdmi->audio_mutex);
-       hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
-                                hdmi->sample_rate);
-       mutex_unlock(&hdmi->audio_mutex);
-}
-
-void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
-{
-       mutex_lock(&hdmi->audio_mutex);
-       hdmi->sample_rate = rate;
-       hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
-                                hdmi->sample_rate);
-       mutex_unlock(&hdmi->audio_mutex);
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
-
-void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&hdmi->audio_lock, flags);
-       hdmi->audio_enable = true;
-       hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
-       spin_unlock_irqrestore(&hdmi->audio_lock, flags);
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
-
-void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&hdmi->audio_lock, flags);
-       hdmi->audio_enable = false;
-       hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
-       spin_unlock_irqrestore(&hdmi->audio_lock, flags);
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
-
-/*
- * this submodule is responsible for the video data synchronization.
- * for example, for RGB 4:4:4 input, the data map is defined as
- *                     pin{47~40} <==> R[7:0]
- *                     pin{31~24} <==> G[7:0]
- *                     pin{15~8}  <==> B[7:0]
- */
-static void hdmi_video_sample(struct dw_hdmi *hdmi)
-{
-       int color_format = 0;
-       u8 val;
-
-       if (hdmi->hdmi_data.enc_in_format == RGB) {
-               if (hdmi->hdmi_data.enc_color_depth == 8)
-                       color_format = 0x01;
-               else if (hdmi->hdmi_data.enc_color_depth == 10)
-                       color_format = 0x03;
-               else if (hdmi->hdmi_data.enc_color_depth == 12)
-                       color_format = 0x05;
-               else if (hdmi->hdmi_data.enc_color_depth == 16)
-                       color_format = 0x07;
-               else
-                       return;
-       } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
-               if (hdmi->hdmi_data.enc_color_depth == 8)
-                       color_format = 0x09;
-               else if (hdmi->hdmi_data.enc_color_depth == 10)
-                       color_format = 0x0B;
-               else if (hdmi->hdmi_data.enc_color_depth == 12)
-                       color_format = 0x0D;
-               else if (hdmi->hdmi_data.enc_color_depth == 16)
-                       color_format = 0x0F;
-               else
-                       return;
-       } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
-               if (hdmi->hdmi_data.enc_color_depth == 8)
-                       color_format = 0x16;
-               else if (hdmi->hdmi_data.enc_color_depth == 10)
-                       color_format = 0x14;
-               else if (hdmi->hdmi_data.enc_color_depth == 12)
-                       color_format = 0x12;
-               else
-                       return;
-       }
-
-       val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
-               ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
-               HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
-       hdmi_writeb(hdmi, val, HDMI_TX_INVID0);
-
-       /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
-       val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
-               HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
-               HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
-       hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING);
-       hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0);
-       hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1);
-       hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0);
-       hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1);
-       hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0);
-       hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
-}
-
-static int is_color_space_conversion(struct dw_hdmi *hdmi)
-{
-       return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
-}
-
-static int is_color_space_decimation(struct dw_hdmi *hdmi)
-{
-       if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
-               return 0;
-       if (hdmi->hdmi_data.enc_in_format == RGB ||
-           hdmi->hdmi_data.enc_in_format == YCBCR444)
-               return 1;
-       return 0;
-}
-
-static int is_color_space_interpolation(struct dw_hdmi *hdmi)
-{
-       if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
-               return 0;
-       if (hdmi->hdmi_data.enc_out_format == RGB ||
-           hdmi->hdmi_data.enc_out_format == YCBCR444)
-               return 1;
-       return 0;
-}
-
-static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
-{
-       const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
-       unsigned i;
-       u32 csc_scale = 1;
-
-       if (is_color_space_conversion(hdmi)) {
-               if (hdmi->hdmi_data.enc_out_format == RGB) {
-                       if (hdmi->hdmi_data.colorimetry ==
-                                       HDMI_COLORIMETRY_ITU_601)
-                               csc_coeff = &csc_coeff_rgb_out_eitu601;
-                       else
-                               csc_coeff = &csc_coeff_rgb_out_eitu709;
-               } else if (hdmi->hdmi_data.enc_in_format == RGB) {
-                       if (hdmi->hdmi_data.colorimetry ==
-                                       HDMI_COLORIMETRY_ITU_601)
-                               csc_coeff = &csc_coeff_rgb_in_eitu601;
-                       else
-                               csc_coeff = &csc_coeff_rgb_in_eitu709;
-                       csc_scale = 0;
-               }
-       }
-
-       /* The CSC registers are sequential, alternating MSB then LSB */
-       for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
-               u16 coeff_a = (*csc_coeff)[0][i];
-               u16 coeff_b = (*csc_coeff)[1][i];
-               u16 coeff_c = (*csc_coeff)[2][i];
-
-               hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
-               hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
-               hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
-               hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
-               hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
-               hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
-       }
-
-       hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
-                 HDMI_CSC_SCALE);
-}
-
-static void hdmi_video_csc(struct dw_hdmi *hdmi)
-{
-       int color_depth = 0;
-       int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
-       int decimation = 0;
-
-       /* YCC422 interpolation to 444 mode */
-       if (is_color_space_interpolation(hdmi))
-               interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
-       else if (is_color_space_decimation(hdmi))
-               decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
-
-       if (hdmi->hdmi_data.enc_color_depth == 8)
-               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
-       else if (hdmi->hdmi_data.enc_color_depth == 10)
-               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
-       else if (hdmi->hdmi_data.enc_color_depth == 12)
-               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
-       else if (hdmi->hdmi_data.enc_color_depth == 16)
-               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
-       else
-               return;
-
-       /* Configure the CSC registers */
-       hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
-       hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
-                 HDMI_CSC_SCALE);
-
-       dw_hdmi_update_csc_coeffs(hdmi);
-}
-
-/*
- * HDMI video packetizer is used to packetize the data.
- * for example, if input is YCC422 mode or repeater is used,
- * data should be repacked this module can be bypassed.
- */
-static void hdmi_video_packetize(struct dw_hdmi *hdmi)
-{
-       unsigned int color_depth = 0;
-       unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
-       unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
-       struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
-       u8 val, vp_conf;
-
-       if (hdmi_data->enc_out_format == RGB ||
-           hdmi_data->enc_out_format == YCBCR444) {
-               if (!hdmi_data->enc_color_depth) {
-                       output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-               } else if (hdmi_data->enc_color_depth == 8) {
-                       color_depth = 4;
-                       output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-               } else if (hdmi_data->enc_color_depth == 10) {
-                       color_depth = 5;
-               } else if (hdmi_data->enc_color_depth == 12) {
-                       color_depth = 6;
-               } else if (hdmi_data->enc_color_depth == 16) {
-                       color_depth = 7;
-               } else {
-                       return;
-               }
-       } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
-               if (!hdmi_data->enc_color_depth ||
-                   hdmi_data->enc_color_depth == 8)
-                       remap_size = HDMI_VP_REMAP_YCC422_16bit;
-               else if (hdmi_data->enc_color_depth == 10)
-                       remap_size = HDMI_VP_REMAP_YCC422_20bit;
-               else if (hdmi_data->enc_color_depth == 12)
-                       remap_size = HDMI_VP_REMAP_YCC422_24bit;
-               else
-                       return;
-               output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
-       } else {
-               return;
-       }
-
-       /* set the packetizer registers */
-       val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
-               HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
-               ((hdmi_data->pix_repet_factor <<
-               HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
-               HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
-       hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
-
-       hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
-                 HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
-
-       /* Data from pixel repeater block */
-       if (hdmi_data->pix_repet_factor > 1) {
-               vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
-                         HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
-       } else { /* data from packetizer block */
-               vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
-                         HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
-       }
-
-       hdmi_modb(hdmi, vp_conf,
-                 HDMI_VP_CONF_PR_EN_MASK |
-                 HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
-
-       hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
-                 HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
-
-       hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
-
-       if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
-               vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
-                         HDMI_VP_CONF_PP_EN_ENABLE |
-                         HDMI_VP_CONF_YCC422_EN_DISABLE;
-       } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
-               vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
-                         HDMI_VP_CONF_PP_EN_DISABLE |
-                         HDMI_VP_CONF_YCC422_EN_ENABLE;
-       } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
-               vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
-                         HDMI_VP_CONF_PP_EN_DISABLE |
-                         HDMI_VP_CONF_YCC422_EN_DISABLE;
-       } else {
-               return;
-       }
-
-       hdmi_modb(hdmi, vp_conf,
-                 HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
-                 HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
-
-       hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
-                       HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
-                 HDMI_VP_STUFF_PP_STUFFING_MASK |
-                 HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
-
-       hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
-                 HDMI_VP_CONF);
-}
-
-static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
-                                      unsigned char bit)
-{
-       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
-                 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
-}
-
-static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi,
-                                       unsigned char bit)
-{
-       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
-                 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
-}
-
-static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi,
-                                      unsigned char bit)
-{
-       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
-                 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
-}
-
-static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi,
-                                    unsigned char bit)
-{
-       hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
-}
-
-static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi,
-                                     unsigned char bit)
-{
-       hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
-}
-
-static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
-{
-       u32 val;
-
-       while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
-               if (msec-- == 0)
-                       return false;
-               udelay(1000);
-       }
-       hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
-
-       return true;
-}
-
-static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
-                                unsigned char addr)
-{
-       hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
-       hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
-       hdmi_writeb(hdmi, (unsigned char)(data >> 8),
-                   HDMI_PHY_I2CM_DATAO_1_ADDR);
-       hdmi_writeb(hdmi, (unsigned char)(data >> 0),
-                   HDMI_PHY_I2CM_DATAO_0_ADDR);
-       hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
-                   HDMI_PHY_I2CM_OPERATION_ADDR);
-       hdmi_phy_wait_i2c_done(hdmi, 1000);
-}
-
-static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
-{
-       hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_PDZ_OFFSET,
-                        HDMI_PHY_CONF0_PDZ_MASK);
-}
-
-static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
-{
-       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_ENTMDS_OFFSET,
-                        HDMI_PHY_CONF0_ENTMDS_MASK);
-}
-
-static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable)
-{
-       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_SVSRET_OFFSET,
-                        HDMI_PHY_CONF0_SVSRET_MASK);
-}
-
-static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
-{
-       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
-                        HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
-}
-
-static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable)
-{
-       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
-                        HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
-}
-
-static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable)
-{
-       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
-                        HDMI_PHY_CONF0_SELDATAENPOL_MASK);
-}
-
-static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
-{
-       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
-                        HDMI_PHY_CONF0_SELDIPIF_OFFSET,
-                        HDMI_PHY_CONF0_SELDIPIF_MASK);
-}
-
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
-{
-       u8 val, msec;
-       const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
-       const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
-       const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
-       const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
-
-       /* PLL/MPLL Cfg - always match on final entry */
-       for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
-               if (hdmi->hdmi_data.video_mode.mpixelclock <=
-                   mpll_config->mpixelclock)
-                       break;
-
-       for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
-               if (hdmi->hdmi_data.video_mode.mpixelclock <=
-                   curr_ctrl->mpixelclock)
-                       break;
-
-       for (; phy_config->mpixelclock != ~0UL; phy_config++)
-               if (hdmi->hdmi_data.video_mode.mpixelclock <=
-                   phy_config->mpixelclock)
-                       break;
-
-       if (mpll_config->mpixelclock == ~0UL ||
-           curr_ctrl->mpixelclock == ~0UL ||
-           phy_config->mpixelclock == ~0UL) {
-               dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
-                       hdmi->hdmi_data.video_mode.mpixelclock);
-               return -EINVAL;
-       }
-
-       /* Enable csc path */
-       if (cscon)
-               val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
-       else
-               val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
-
-       hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
-
-       /* gen2 tx power off */
-       dw_hdmi_phy_gen2_txpwron(hdmi, 0);
-
-       /* gen2 pddq */
-       dw_hdmi_phy_gen2_pddq(hdmi, 1);
-
-       /* Leave low power consumption mode by asserting SVSRET. */
-       if (hdmi->phy->has_svsret)
-               dw_hdmi_phy_enable_svsret(hdmi, 1);
-
-       /* PHY reset. The reset signal is active high on Gen2 PHYs. */
-       hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
-       hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
-
-       hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
-
-       hdmi_phy_test_clear(hdmi, 1);
-       hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
-                   HDMI_PHY_I2CM_SLAVE_ADDR);
-       hdmi_phy_test_clear(hdmi, 0);
-
-       hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
-                          HDMI_3D_TX_PHY_CPCE_CTRL);
-       hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
-                          HDMI_3D_TX_PHY_GMPCTRL);
-       hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
-                          HDMI_3D_TX_PHY_CURRCTRL);
-
-       hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
-       hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
-                          HDMI_3D_TX_PHY_MSM_CTRL);
-
-       hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
-       hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
-                          HDMI_3D_TX_PHY_CKSYMTXCTRL);
-       hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
-                          HDMI_3D_TX_PHY_VLEVCTRL);
-
-       /* Override and disable clock termination. */
-       hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
-                          HDMI_3D_TX_PHY_CKCALCTRL);
-
-       dw_hdmi_phy_enable_powerdown(hdmi, false);
-
-       /* toggle TMDS enable */
-       dw_hdmi_phy_enable_tmds(hdmi, 0);
-       dw_hdmi_phy_enable_tmds(hdmi, 1);
-
-       /* gen2 tx power on */
-       dw_hdmi_phy_gen2_txpwron(hdmi, 1);
-       dw_hdmi_phy_gen2_pddq(hdmi, 0);
-
-       /* Wait for PHY PLL lock */
-       msec = 5;
-       do {
-               val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
-               if (!val)
-                       break;
-
-               if (msec == 0) {
-                       dev_err(hdmi->dev, "PHY PLL not locked\n");
-                       return -ETIMEDOUT;
-               }
-
-               udelay(1000);
-               msec--;
-       } while (1);
-
-       return 0;
-}
-
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
-{
-       int i, ret;
-       bool cscon;
-
-       /*check csc whether needed activated in HDMI mode */
-       cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
-
-       /* HDMI Phy spec says to do the phy initialization sequence twice */
-       for (i = 0; i < 2; i++) {
-               dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
-               dw_hdmi_phy_sel_interface_control(hdmi, 0);
-               dw_hdmi_phy_enable_tmds(hdmi, 0);
-               dw_hdmi_phy_enable_powerdown(hdmi, true);
-
-               /* Enable CSC */
-               ret = hdmi_phy_configure(hdmi, cscon);
-               if (ret)
-                       return ret;
-       }
-
-       hdmi->phy_enabled = true;
-       return 0;
-}
-
-static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
-{
-       u8 de;
-
-       if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
-               de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
-       else
-               de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
-
-       /* disable rx detect */
-       hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
-                 HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
-
-       hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
-
-       hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
-                 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
-}
-
-static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
-{
-       struct hdmi_avi_infoframe frame;
-       u8 val;
-
-       /* Initialise info frame from DRM mode */
-       drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
-
-       if (hdmi->hdmi_data.enc_out_format == YCBCR444)
-               frame.colorspace = HDMI_COLORSPACE_YUV444;
-       else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
-               frame.colorspace = HDMI_COLORSPACE_YUV422;
-       else
-               frame.colorspace = HDMI_COLORSPACE_RGB;
-
-       /* Set up colorimetry */
-       if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
-               frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-               if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-                       frame.extended_colorimetry =
-                               HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-               else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-                       frame.extended_colorimetry =
-                               HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
-       } else if (hdmi->hdmi_data.enc_out_format != RGB) {
-               frame.colorimetry = hdmi->hdmi_data.colorimetry;
-               frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-       } else { /* Carries no data */
-               frame.colorimetry = HDMI_COLORIMETRY_NONE;
-               frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-       }
-
-       frame.scan_mode = HDMI_SCAN_MODE_NONE;
-
-       /*
-        * The Designware IP uses a different byte format from standard
-        * AVI info frames, though generally the bits are in the correct
-        * bytes.
-        */
-
-       /*
-        * AVI data byte 1 differences: Colorspace in bits 0,1 rather than 5,6,
-        * scan info in bits 4,5 rather than 0,1 and active aspect present in
-        * bit 6 rather than 4.
-        */
-       val = (frame.scan_mode & 3) << 4 | (frame.colorspace & 3);
-       if (frame.active_aspect & 15)
-               val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT;
-       if (frame.top_bar || frame.bottom_bar)
-               val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR;
-       if (frame.left_bar || frame.right_bar)
-               val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR;
-       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
-
-       /* AVI data byte 2 differences: none */
-       val = ((frame.colorimetry & 0x3) << 6) |
-             ((frame.picture_aspect & 0x3) << 4) |
-             (frame.active_aspect & 0xf);
-       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
-
-       /* AVI data byte 3 differences: none */
-       val = ((frame.extended_colorimetry & 0x7) << 4) |
-             ((frame.quantization_range & 0x3) << 2) |
-             (frame.nups & 0x3);
-       if (frame.itc)
-               val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID;
-       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
-
-       /* AVI data byte 4 differences: none */
-       val = frame.video_code & 0x7f;
-       hdmi_writeb(hdmi, val, HDMI_FC_AVIVID);
-
-       /* AVI Data Byte 5- set up input and output pixel repetition */
-       val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
-               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
-               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
-               ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput <<
-               HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
-               HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
-       hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
-
-       /*
-        * AVI data byte 5 differences: content type in 0,1 rather than 4,5,
-        * ycc range in bits 2,3 rather than 6,7
-        */
-       val = ((frame.ycc_quantization_range & 0x3) << 2) |
-             (frame.content_type & 0x3);
-       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
-
-       /* AVI Data Bytes 6-13 */
-       hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0);
-       hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1);
-       hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0);
-       hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1);
-       hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0);
-       hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1);
-       hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0);
-       hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
-}
-
-static void hdmi_av_composer(struct dw_hdmi *hdmi,
-                            const struct drm_display_mode *mode)
-{
-       u8 inv_val;
-       struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
-       int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
-       unsigned int vdisplay;
-
-       vmode->mpixelclock = mode->clock * 1000;
-
-       dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
-
-       /* Set up HDMI_FC_INVIDCONF */
-       inv_val = (hdmi->hdmi_data.hdcp_enable ?
-               HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
-               HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
-
-       inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
-               HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
-               HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW;
-
-       inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
-               HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
-               HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW;
-
-       inv_val |= (vmode->mdataenablepolarity ?
-               HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
-               HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
-
-       if (hdmi->vic == 39)
-               inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
-       else
-               inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
-                       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
-                       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
-
-       inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
-               HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
-               HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
-
-       inv_val |= hdmi->sink_is_hdmi ?
-               HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
-               HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE;
-
-       hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
-
-       vdisplay = mode->vdisplay;
-       vblank = mode->vtotal - mode->vdisplay;
-       v_de_vs = mode->vsync_start - mode->vdisplay;
-       vsync_len = mode->vsync_end - mode->vsync_start;
-
-       /*
-        * When we're setting an interlaced mode, we need
-        * to adjust the vertical timing to suit.
-        */
-       if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
-               vdisplay /= 2;
-               vblank /= 2;
-               v_de_vs /= 2;
-               vsync_len /= 2;
-       }
-
-       /* Set up horizontal active pixel width */
-       hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
-       hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
-
-       /* Set up vertical active lines */
-       hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1);
-       hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
-
-       /* Set up horizontal blanking pixel region width */
-       hblank = mode->htotal - mode->hdisplay;
-       hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
-       hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
-
-       /* Set up vertical blanking pixel region width */
-       hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
-
-       /* Set up HSYNC active edge delay width (in pixel clks) */
-       h_de_hs = mode->hsync_start - mode->hdisplay;
-       hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1);
-       hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
-
-       /* Set up VSYNC active edge delay (in lines) */
-       hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
-
-       /* Set up HSYNC active pulse width (in pixel clks) */
-       hsync_len = mode->hsync_end - mode->hsync_start;
-       hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
-       hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
-
-       /* Set up VSYNC active edge delay (in lines) */
-       hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
-}
-
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
-{
-       if (!hdmi->phy_enabled)
-               return;
-
-       dw_hdmi_phy_enable_tmds(hdmi, 0);
-       dw_hdmi_phy_enable_powerdown(hdmi, true);
-
-       hdmi->phy_enabled = false;
-}
-
-/* HDMI Initialization Step B.4 */
-static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
-{
-       u8 clkdis;
-
-       /* control period minimum duration */
-       hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
-       hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
-       hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC);
-
-       /* Set to fill TMDS data channels */
-       hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM);
-       hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM);
-       hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
-
-       /* Enable pixel clock and tmds data path */
-       clkdis = 0x7F;
-       clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
-       hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
-
-       clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
-       hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
-
-       /* Enable csc path */
-       if (is_color_space_conversion(hdmi)) {
-               clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
-               hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
-       }
-}
-
-static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
-{
-       hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
-}
-
-/* Workaround to clear the overflow condition */
-static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
-{
-       unsigned int count;
-       unsigned int i;
-       u8 val;
-
-       /*
-        * Under some circumstances the Frame Composer arithmetic unit can miss
-        * an FC register write due to being busy processing the previous one.
-        * The issue can be worked around by issuing a TMDS software reset and
-        * then write one of the FC registers several times.
-        *
-        * The number of iterations matters and depends on the HDMI TX revision
-        * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
-        * i.MX6DL (v1.31a) have been identified as needing the workaround, with
-        * 4 and 1 iterations respectively.
-        */
-
-       switch (hdmi->version) {
-       case 0x130a:
-               count = 4;
-               break;
-       case 0x131a:
-               count = 1;
-               break;
-       default:
-               return;
-       }
-
-       /* TMDS software reset */
-       hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
-
-       val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
-       for (i = 0; i < count; i++)
-               hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
-}
-
-static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi)
-{
-       hdmi_writeb(hdmi, 0, HDMI_FC_MASK2);
-       hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2);
-}
-
-static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
-{
-       hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
-                   HDMI_IH_MUTE_FC_STAT2);
-}
-
-static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
-{
-       int ret;
-
-       hdmi_disable_overflow_interrupts(hdmi);
-
-       hdmi->vic = drm_match_cea_mode(mode);
-
-       if (!hdmi->vic) {
-               dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
-       } else {
-               dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
-       }
-
-       if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
-           (hdmi->vic == 21) || (hdmi->vic == 22) ||
-           (hdmi->vic == 2) || (hdmi->vic == 3) ||
-           (hdmi->vic == 17) || (hdmi->vic == 18))
-               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
-       else
-               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
-
-       hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
-       hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
-
-       /* TODO: Get input format from IPU (via FB driver interface) */
-       hdmi->hdmi_data.enc_in_format = RGB;
-
-       hdmi->hdmi_data.enc_out_format = RGB;
-
-       hdmi->hdmi_data.enc_color_depth = 8;
-       hdmi->hdmi_data.pix_repet_factor = 0;
-       hdmi->hdmi_data.hdcp_enable = 0;
-       hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
-
-       /* HDMI Initialization Step B.1 */
-       hdmi_av_composer(hdmi, mode);
-
-       /* HDMI Initializateion Step B.2 */
-       ret = dw_hdmi_phy_init(hdmi);
-       if (ret)
-               return ret;
-
-       /* HDMI Initialization Step B.3 */
-       dw_hdmi_enable_video_path(hdmi);
-
-       if (hdmi->sink_has_audio) {
-               dev_dbg(hdmi->dev, "sink has audio support\n");
-
-               /* HDMI Initialization Step E - Configure audio */
-               hdmi_clk_regenerator_update_pixel_clock(hdmi);
-               hdmi_enable_audio_clk(hdmi);
-       }
-
-       /* not for DVI mode */
-       if (hdmi->sink_is_hdmi) {
-               dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__);
-
-               /* HDMI Initialization Step F - Configure AVI InfoFrame */
-               hdmi_config_AVI(hdmi, mode);
-       } else {
-               dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
-       }
-
-       hdmi_video_packetize(hdmi);
-       hdmi_video_csc(hdmi);
-       hdmi_video_sample(hdmi);
-       hdmi_tx_hdcp_config(hdmi);
-
-       dw_hdmi_clear_overflow(hdmi);
-       if (hdmi->cable_plugin && hdmi->sink_is_hdmi)
-               hdmi_enable_overflow_interrupts(hdmi);
-
-       return 0;
-}
-
-/* Wait until we are registered to enable interrupts */
-static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
-{
-       hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
-                   HDMI_PHY_I2CM_INT_ADDR);
-
-       hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
-                   HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
-                   HDMI_PHY_I2CM_CTLINT_ADDR);
-
-       /* enable cable hot plug irq */
-       hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
-
-       /* Clear Hotplug interrupts */
-       hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
-                   HDMI_IH_PHY_STAT0);
-
-       return 0;
-}
-
-static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
-{
-       u8 ih_mute;
-
-       /*
-        * Boot up defaults are:
-        * HDMI_IH_MUTE   = 0x03 (disabled)
-        * HDMI_IH_MUTE_* = 0x00 (enabled)
-        *
-        * Disable top level interrupt bits in HDMI block
-        */
-       ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
-                 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
-                 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
-
-       hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
-
-       /* by default mask all interrupts */
-       hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK);
-       hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0);
-       hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1);
-       hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2);
-       hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0);
-       hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR);
-       hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
-       hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT);
-       hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT);
-       hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
-       hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
-       hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
-       hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
-       hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
-       hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
-
-       /* Disable interrupts in the IH_MUTE_* registers */
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
-       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
-
-       /* Enable top level interrupt bits in HDMI block */
-       ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
-                   HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
-       hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
-}
-
-static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
-{
-       hdmi->bridge_is_on = true;
-       dw_hdmi_setup(hdmi, &hdmi->previous_mode);
-}
-
-static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
-{
-       dw_hdmi_phy_disable(hdmi);
-       hdmi->bridge_is_on = false;
-}
-
-static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
-{
-       int force = hdmi->force;
-
-       if (hdmi->disabled) {
-               force = DRM_FORCE_OFF;
-       } else if (force == DRM_FORCE_UNSPECIFIED) {
-               if (hdmi->rxsense)
-                       force = DRM_FORCE_ON;
-               else
-                       force = DRM_FORCE_OFF;
-       }
-
-       if (force == DRM_FORCE_OFF) {
-               if (hdmi->bridge_is_on)
-                       dw_hdmi_poweroff(hdmi);
-       } else {
-               if (!hdmi->bridge_is_on)
-                       dw_hdmi_poweron(hdmi);
-       }
-}
-
-/*
- * Adjust the detection of RXSENSE according to whether we have a forced
- * connection mode enabled, or whether we have been disabled.  There is
- * no point processing RXSENSE interrupts if we have a forced connection
- * state, or DRM has us disabled.
- *
- * We also disable rxsense interrupts when we think we're disconnected
- * to avoid floating TDMS signals giving false rxsense interrupts.
- *
- * Note: we still need to listen for HPD interrupts even when DRM has us
- * disabled so that we can detect a connect event.
- */
-static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
-{
-       u8 old_mask = hdmi->phy_mask;
-
-       if (hdmi->force || hdmi->disabled || !hdmi->rxsense)
-               hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
-       else
-               hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
-
-       if (old_mask != hdmi->phy_mask)
-               hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
-}
-
-static enum drm_connector_status
-dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
-{
-       struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
-                                            connector);
-
-       mutex_lock(&hdmi->mutex);
-       hdmi->force = DRM_FORCE_UNSPECIFIED;
-       dw_hdmi_update_power(hdmi);
-       dw_hdmi_update_phy_mask(hdmi);
-       mutex_unlock(&hdmi->mutex);
-
-       return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
-               connector_status_connected : connector_status_disconnected;
-}
-
-static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
-{
-       struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
-                                            connector);
-       struct edid *edid;
-       int ret = 0;
-
-       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);
-
-               hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
-               hdmi->sink_has_audio = drm_detect_monitor_audio(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);
-       } else {
-               dev_dbg(hdmi->dev, "failed to get edid\n");
-       }
-
-       return ret;
-}
-
-static enum drm_mode_status
-dw_hdmi_connector_mode_valid(struct drm_connector *connector,
-                            struct drm_display_mode *mode)
-{
-       struct dw_hdmi *hdmi = container_of(connector,
-                                          struct dw_hdmi, connector);
-       enum drm_mode_status mode_status = MODE_OK;
-
-       /* We don't support double-clocked modes */
-       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
-               return MODE_BAD;
-
-       if (hdmi->plat_data->mode_valid)
-               mode_status = hdmi->plat_data->mode_valid(connector, mode);
-
-       return mode_status;
-}
-
-static void dw_hdmi_connector_force(struct drm_connector *connector)
-{
-       struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
-                                            connector);
-
-       mutex_lock(&hdmi->mutex);
-       hdmi->force = connector->force;
-       dw_hdmi_update_power(hdmi);
-       dw_hdmi_update_phy_mask(hdmi);
-       mutex_unlock(&hdmi->mutex);
-}
-
-static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
-       .dpms = drm_atomic_helper_connector_dpms,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .detect = dw_hdmi_connector_detect,
-       .destroy = drm_connector_cleanup,
-       .force = dw_hdmi_connector_force,
-       .reset = drm_atomic_helper_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
-       .get_modes = dw_hdmi_connector_get_modes,
-       .mode_valid = dw_hdmi_connector_mode_valid,
-       .best_encoder = drm_atomic_helper_best_encoder,
-};
-
-static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
-{
-       struct dw_hdmi *hdmi = bridge->driver_private;
-       struct drm_encoder *encoder = bridge->encoder;
-       struct drm_connector *connector = &hdmi->connector;
-
-       connector->interlace_allowed = 1;
-       connector->polled = DRM_CONNECTOR_POLL_HPD;
-
-       drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
-
-       drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
-                          DRM_MODE_CONNECTOR_HDMIA);
-
-       drm_mode_connector_attach_encoder(connector, encoder);
-
-       return 0;
-}
-
-static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
-                                   struct drm_display_mode *orig_mode,
-                                   struct drm_display_mode *mode)
-{
-       struct dw_hdmi *hdmi = bridge->driver_private;
-
-       mutex_lock(&hdmi->mutex);
-
-       /* Store the display mode for plugin/DKMS poweron events */
-       memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
-
-       mutex_unlock(&hdmi->mutex);
-}
-
-static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
-{
-       struct dw_hdmi *hdmi = bridge->driver_private;
-
-       mutex_lock(&hdmi->mutex);
-       hdmi->disabled = true;
-       dw_hdmi_update_power(hdmi);
-       dw_hdmi_update_phy_mask(hdmi);
-       mutex_unlock(&hdmi->mutex);
-}
-
-static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
-{
-       struct dw_hdmi *hdmi = bridge->driver_private;
-
-       mutex_lock(&hdmi->mutex);
-       hdmi->disabled = false;
-       dw_hdmi_update_power(hdmi);
-       dw_hdmi_update_phy_mask(hdmi);
-       mutex_unlock(&hdmi->mutex);
-}
-
-static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
-       .attach = dw_hdmi_bridge_attach,
-       .enable = dw_hdmi_bridge_enable,
-       .disable = dw_hdmi_bridge_disable,
-       .mode_set = dw_hdmi_bridge_mode_set,
-};
-
-static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
-{
-       struct dw_hdmi_i2c *i2c = hdmi->i2c;
-       unsigned int stat;
-
-       stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0);
-       if (!stat)
-               return IRQ_NONE;
-
-       hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0);
-
-       i2c->stat = stat;
-
-       complete(&i2c->cmp);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
-{
-       struct dw_hdmi *hdmi = dev_id;
-       u8 intr_stat;
-       irqreturn_t ret = IRQ_NONE;
-
-       if (hdmi->i2c)
-               ret = dw_hdmi_i2c_irq(hdmi);
-
-       intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
-       if (intr_stat) {
-               hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
-               return IRQ_WAKE_THREAD;
-       }
-
-       return ret;
-}
-
-static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
-{
-       struct dw_hdmi *hdmi = dev_id;
-       u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat;
-
-       intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
-       phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
-       phy_stat = hdmi_readb(hdmi, HDMI_PHY_STAT0);
-
-       phy_pol_mask = 0;
-       if (intr_stat & HDMI_IH_PHY_STAT0_HPD)
-               phy_pol_mask |= HDMI_PHY_HPD;
-       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0)
-               phy_pol_mask |= HDMI_PHY_RX_SENSE0;
-       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE1)
-               phy_pol_mask |= HDMI_PHY_RX_SENSE1;
-       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE2)
-               phy_pol_mask |= HDMI_PHY_RX_SENSE2;
-       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE3)
-               phy_pol_mask |= HDMI_PHY_RX_SENSE3;
-
-       if (phy_pol_mask)
-               hdmi_modb(hdmi, ~phy_int_pol, phy_pol_mask, HDMI_PHY_POL0);
-
-       /*
-        * RX sense tells us whether the TDMS transmitters are detecting
-        * load - in other words, there's something listening on the
-        * other end of the link.  Use this to decide whether we should
-        * power on the phy as HPD may be toggled by the sink to merely
-        * ask the source to re-read the EDID.
-        */
-       if (intr_stat &
-           (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
-               mutex_lock(&hdmi->mutex);
-               if (!hdmi->disabled && !hdmi->force) {
-                       /*
-                        * If the RX sense status indicates we're disconnected,
-                        * clear the software rxsense status.
-                        */
-                       if (!(phy_stat & HDMI_PHY_RX_SENSE))
-                               hdmi->rxsense = false;
-
-                       /*
-                        * Only set the software rxsense status when both
-                        * rxsense and hpd indicates we're connected.
-                        * This avoids what seems to be bad behaviour in
-                        * at least iMX6S versions of the phy.
-                        */
-                       if (phy_stat & HDMI_PHY_HPD)
-                               hdmi->rxsense = true;
-
-                       dw_hdmi_update_power(hdmi);
-                       dw_hdmi_update_phy_mask(hdmi);
-               }
-               mutex_unlock(&hdmi->mutex);
-       }
-
-       if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
-               dev_dbg(hdmi->dev, "EVENT=%s\n",
-                       phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
-               if (hdmi->bridge.dev)
-                       drm_helper_hpd_irq_event(hdmi->bridge.dev);
-       }
-
-       hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
-       hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
-                   HDMI_IH_MUTE_PHY_STAT0);
-
-       return IRQ_HANDLED;
-}
-
-static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
-       {
-               .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
-               .name = "DWC HDMI TX PHY",
-       }, {
-               .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
-               .name = "DWC MHL PHY + HEAC PHY",
-               .has_svsret = true,
-       }, {
-               .type = DW_HDMI_PHY_DWC_MHL_PHY,
-               .name = "DWC MHL PHY",
-               .has_svsret = true,
-       }, {
-               .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
-               .name = "DWC HDMI 3D TX PHY + HEAC PHY",
-       }, {
-               .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
-               .name = "DWC HDMI 3D TX PHY",
-       }, {
-               .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
-               .name = "DWC HDMI 2.0 TX PHY",
-               .has_svsret = true,
-       }
-};
-
-static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
-{
-       unsigned int i;
-       u8 phy_type;
-
-       phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
-
-       for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
-               if (dw_hdmi_phys[i].type == phy_type) {
-                       hdmi->phy = &dw_hdmi_phys[i];
-                       return 0;
-               }
-       }
-
-       if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
-               dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
-       else
-               dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
-                       phy_type);
-
-       return -ENODEV;
-}
-
-static struct dw_hdmi *
-__dw_hdmi_probe(struct platform_device *pdev,
-               const struct dw_hdmi_plat_data *plat_data)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct platform_device_info pdevinfo;
-       struct device_node *ddc_node;
-       struct dw_hdmi *hdmi;
-       struct resource *iores;
-       int irq;
-       int ret;
-       u32 val = 1;
-       u8 prod_id0;
-       u8 prod_id1;
-       u8 config0;
-       u8 config3;
-
-       hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
-       if (!hdmi)
-               return ERR_PTR(-ENOMEM);
-
-       hdmi->plat_data = plat_data;
-       hdmi->dev = dev;
-       hdmi->dev_type = plat_data->dev_type;
-       hdmi->sample_rate = 48000;
-       hdmi->disabled = true;
-       hdmi->rxsense = true;
-       hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
-
-       mutex_init(&hdmi->mutex);
-       mutex_init(&hdmi->audio_mutex);
-       spin_lock_init(&hdmi->audio_lock);
-
-       of_property_read_u32(np, "reg-io-width", &val);
-
-       switch (val) {
-       case 4:
-               hdmi->write = dw_hdmi_writel;
-               hdmi->read = dw_hdmi_readl;
-               break;
-       case 1:
-               hdmi->write = dw_hdmi_writeb;
-               hdmi->read = dw_hdmi_readb;
-               break;
-       default:
-               dev_err(dev, "reg-io-width must be 1 or 4\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
-       if (ddc_node) {
-               hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
-               of_node_put(ddc_node);
-               if (!hdmi->ddc) {
-                       dev_dbg(hdmi->dev, "failed to read ddc node\n");
-                       return ERR_PTR(-EPROBE_DEFER);
-               }
-
-       } else {
-               dev_dbg(hdmi->dev, "no ddc property found\n");
-       }
-
-       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hdmi->regs = devm_ioremap_resource(dev, iores);
-       if (IS_ERR(hdmi->regs)) {
-               ret = PTR_ERR(hdmi->regs);
-               goto err_res;
-       }
-
-       hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
-       if (IS_ERR(hdmi->isfr_clk)) {
-               ret = PTR_ERR(hdmi->isfr_clk);
-               dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
-               goto err_res;
-       }
-
-       ret = clk_prepare_enable(hdmi->isfr_clk);
-       if (ret) {
-               dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
-               goto err_res;
-       }
-
-       hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
-       if (IS_ERR(hdmi->iahb_clk)) {
-               ret = PTR_ERR(hdmi->iahb_clk);
-               dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
-               goto err_isfr;
-       }
-
-       ret = clk_prepare_enable(hdmi->iahb_clk);
-       if (ret) {
-               dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret);
-               goto err_isfr;
-       }
-
-       /* Product and revision IDs */
-       hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
-                     | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
-       prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
-       prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
-
-       if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
-           (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
-               dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
-                       hdmi->version, prod_id0, prod_id1);
-               ret = -ENODEV;
-               goto err_iahb;
-       }
-
-       ret = dw_hdmi_detect_phy(hdmi);
-       if (ret < 0)
-               goto err_iahb;
-
-       dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
-                hdmi->version >> 12, hdmi->version & 0xfff,
-                prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
-                hdmi->phy->name);
-
-       initialize_hdmi_ih_mutes(hdmi);
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto err_iahb;
-       }
-
-       ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
-                                       dw_hdmi_irq, IRQF_SHARED,
-                                       dev_name(dev), hdmi);
-       if (ret)
-               goto err_iahb;
-
-       /*
-        * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
-        * N and cts values before enabling phy
-        */
-       hdmi_init_clk_regenerator(hdmi);
-
-       /* If DDC bus is not specified, try to register HDMI I2C bus */
-       if (!hdmi->ddc) {
-               hdmi->ddc = dw_hdmi_i2c_adapter(hdmi);
-               if (IS_ERR(hdmi->ddc))
-                       hdmi->ddc = NULL;
-       }
-
-       /*
-        * Configure registers related to HDMI interrupt
-        * generation before registering IRQ.
-        */
-       hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
-
-       /* Clear Hotplug interrupts */
-       hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
-                   HDMI_IH_PHY_STAT0);
-
-       hdmi->bridge.driver_private = hdmi;
-       hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
-#ifdef CONFIG_OF
-       hdmi->bridge.of_node = pdev->dev.of_node;
-#endif
-
-       ret = dw_hdmi_fb_registered(hdmi);
-       if (ret)
-               goto err_iahb;
-
-       /* Unmute interrupts */
-       hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
-                   HDMI_IH_MUTE_PHY_STAT0);
-
-       memset(&pdevinfo, 0, sizeof(pdevinfo));
-       pdevinfo.parent = dev;
-       pdevinfo.id = PLATFORM_DEVID_AUTO;
-
-       config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
-       config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
-
-       if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
-               struct dw_hdmi_audio_data audio;
-
-               audio.phys = iores->start;
-               audio.base = hdmi->regs;
-               audio.irq = irq;
-               audio.hdmi = hdmi;
-               audio.eld = hdmi->connector.eld;
-
-               pdevinfo.name = "dw-hdmi-ahb-audio";
-               pdevinfo.data = &audio;
-               pdevinfo.size_data = sizeof(audio);
-               pdevinfo.dma_mask = DMA_BIT_MASK(32);
-               hdmi->audio = platform_device_register_full(&pdevinfo);
-       } else if (config0 & HDMI_CONFIG0_I2S) {
-               struct dw_hdmi_i2s_audio_data audio;
-
-               audio.hdmi      = hdmi;
-               audio.write     = hdmi_writeb;
-               audio.read      = hdmi_readb;
-
-               pdevinfo.name = "dw-hdmi-i2s-audio";
-               pdevinfo.data = &audio;
-               pdevinfo.size_data = sizeof(audio);
-               pdevinfo.dma_mask = DMA_BIT_MASK(32);
-               hdmi->audio = platform_device_register_full(&pdevinfo);
-       }
-
-       /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
-       if (hdmi->i2c)
-               dw_hdmi_i2c_init(hdmi);
-
-       platform_set_drvdata(pdev, hdmi);
-
-       return hdmi;
-
-err_iahb:
-       if (hdmi->i2c) {
-               i2c_del_adapter(&hdmi->i2c->adap);
-               hdmi->ddc = NULL;
-       }
-
-       clk_disable_unprepare(hdmi->iahb_clk);
-err_isfr:
-       clk_disable_unprepare(hdmi->isfr_clk);
-err_res:
-       i2c_put_adapter(hdmi->ddc);
-
-       return ERR_PTR(ret);
-}
-
-static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
-{
-       if (hdmi->audio && !IS_ERR(hdmi->audio))
-               platform_device_unregister(hdmi->audio);
-
-       /* Disable all interrupts */
-       hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
-
-       clk_disable_unprepare(hdmi->iahb_clk);
-       clk_disable_unprepare(hdmi->isfr_clk);
-
-       if (hdmi->i2c)
-               i2c_del_adapter(&hdmi->i2c->adap);
-       else
-               i2c_put_adapter(hdmi->ddc);
-}
-
-/* -----------------------------------------------------------------------------
- * Probe/remove API, used from platforms based on the DRM bridge API.
- */
-int dw_hdmi_probe(struct platform_device *pdev,
-                 const struct dw_hdmi_plat_data *plat_data)
-{
-       struct dw_hdmi *hdmi;
-       int ret;
-
-       hdmi = __dw_hdmi_probe(pdev, plat_data);
-       if (IS_ERR(hdmi))
-               return PTR_ERR(hdmi);
-
-       ret = drm_bridge_add(&hdmi->bridge);
-       if (ret < 0) {
-               __dw_hdmi_remove(hdmi);
-               return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_probe);
-
-void dw_hdmi_remove(struct platform_device *pdev)
-{
-       struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
-
-       drm_bridge_remove(&hdmi->bridge);
-
-       __dw_hdmi_remove(hdmi);
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_remove);
-
-/* -----------------------------------------------------------------------------
- * Bind/unbind API, used from platforms based on the component framework.
- */
-int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
-                const struct dw_hdmi_plat_data *plat_data)
-{
-       struct dw_hdmi *hdmi;
-       int ret;
-
-       hdmi = __dw_hdmi_probe(pdev, plat_data);
-       if (IS_ERR(hdmi))
-               return PTR_ERR(hdmi);
-
-       ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
-       if (ret) {
-               dw_hdmi_remove(pdev);
-               DRM_ERROR("Failed to initialize bridge with drm\n");
-               return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_bind);
-
-void dw_hdmi_unbind(struct device *dev)
-{
-       struct dw_hdmi *hdmi = dev_get_drvdata(dev);
-
-       __dw_hdmi_remove(hdmi);
-}
-EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
-
-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
-MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
-MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
-MODULE_DESCRIPTION("DW HDMI transmitter driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:dw-hdmi");
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
deleted file mode 100644 (file)
index 325b0b8..0000000
+++ /dev/null
@@ -1,1153 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __DW_HDMI_H__
-#define __DW_HDMI_H__
-
-/* Identification Registers */
-#define HDMI_DESIGN_ID                          0x0000
-#define HDMI_REVISION_ID                        0x0001
-#define HDMI_PRODUCT_ID0                        0x0002
-#define HDMI_PRODUCT_ID1                        0x0003
-#define HDMI_CONFIG0_ID                         0x0004
-#define HDMI_CONFIG1_ID                         0x0005
-#define HDMI_CONFIG2_ID                         0x0006
-#define HDMI_CONFIG3_ID                         0x0007
-
-/* Interrupt Registers */
-#define HDMI_IH_FC_STAT0                        0x0100
-#define HDMI_IH_FC_STAT1                        0x0101
-#define HDMI_IH_FC_STAT2                        0x0102
-#define HDMI_IH_AS_STAT0                        0x0103
-#define HDMI_IH_PHY_STAT0                       0x0104
-#define HDMI_IH_I2CM_STAT0                      0x0105
-#define HDMI_IH_CEC_STAT0                       0x0106
-#define HDMI_IH_VP_STAT0                        0x0107
-#define HDMI_IH_I2CMPHY_STAT0                   0x0108
-#define HDMI_IH_AHBDMAAUD_STAT0                 0x0109
-
-#define HDMI_IH_MUTE_FC_STAT0                   0x0180
-#define HDMI_IH_MUTE_FC_STAT1                   0x0181
-#define HDMI_IH_MUTE_FC_STAT2                   0x0182
-#define HDMI_IH_MUTE_AS_STAT0                   0x0183
-#define HDMI_IH_MUTE_PHY_STAT0                  0x0184
-#define HDMI_IH_MUTE_I2CM_STAT0                 0x0185
-#define HDMI_IH_MUTE_CEC_STAT0                  0x0186
-#define HDMI_IH_MUTE_VP_STAT0                   0x0187
-#define HDMI_IH_MUTE_I2CMPHY_STAT0              0x0188
-#define HDMI_IH_MUTE_AHBDMAAUD_STAT0            0x0189
-#define HDMI_IH_MUTE                            0x01FF
-
-/* Video Sample Registers */
-#define HDMI_TX_INVID0                          0x0200
-#define HDMI_TX_INSTUFFING                      0x0201
-#define HDMI_TX_GYDATA0                         0x0202
-#define HDMI_TX_GYDATA1                         0x0203
-#define HDMI_TX_RCRDATA0                        0x0204
-#define HDMI_TX_RCRDATA1                        0x0205
-#define HDMI_TX_BCBDATA0                        0x0206
-#define HDMI_TX_BCBDATA1                        0x0207
-
-/* Video Packetizer Registers */
-#define HDMI_VP_STATUS                          0x0800
-#define HDMI_VP_PR_CD                           0x0801
-#define HDMI_VP_STUFF                           0x0802
-#define HDMI_VP_REMAP                           0x0803
-#define HDMI_VP_CONF                            0x0804
-#define HDMI_VP_STAT                            0x0805
-#define HDMI_VP_INT                             0x0806
-#define HDMI_VP_MASK                            0x0807
-#define HDMI_VP_POL                             0x0808
-
-/* Frame Composer Registers */
-#define HDMI_FC_INVIDCONF                       0x1000
-#define HDMI_FC_INHACTV0                        0x1001
-#define HDMI_FC_INHACTV1                        0x1002
-#define HDMI_FC_INHBLANK0                       0x1003
-#define HDMI_FC_INHBLANK1                       0x1004
-#define HDMI_FC_INVACTV0                        0x1005
-#define HDMI_FC_INVACTV1                        0x1006
-#define HDMI_FC_INVBLANK                        0x1007
-#define HDMI_FC_HSYNCINDELAY0                   0x1008
-#define HDMI_FC_HSYNCINDELAY1                   0x1009
-#define HDMI_FC_HSYNCINWIDTH0                   0x100A
-#define HDMI_FC_HSYNCINWIDTH1                   0x100B
-#define HDMI_FC_VSYNCINDELAY                    0x100C
-#define HDMI_FC_VSYNCINWIDTH                    0x100D
-#define HDMI_FC_INFREQ0                         0x100E
-#define HDMI_FC_INFREQ1                         0x100F
-#define HDMI_FC_INFREQ2                         0x1010
-#define HDMI_FC_CTRLDUR                         0x1011
-#define HDMI_FC_EXCTRLDUR                       0x1012
-#define HDMI_FC_EXCTRLSPAC                      0x1013
-#define HDMI_FC_CH0PREAM                        0x1014
-#define HDMI_FC_CH1PREAM                        0x1015
-#define HDMI_FC_CH2PREAM                        0x1016
-#define HDMI_FC_AVICONF3                        0x1017
-#define HDMI_FC_GCP                             0x1018
-#define HDMI_FC_AVICONF0                        0x1019
-#define HDMI_FC_AVICONF1                        0x101A
-#define HDMI_FC_AVICONF2                        0x101B
-#define HDMI_FC_AVIVID                          0x101C
-#define HDMI_FC_AVIETB0                         0x101D
-#define HDMI_FC_AVIETB1                         0x101E
-#define HDMI_FC_AVISBB0                         0x101F
-#define HDMI_FC_AVISBB1                         0x1020
-#define HDMI_FC_AVIELB0                         0x1021
-#define HDMI_FC_AVIELB1                         0x1022
-#define HDMI_FC_AVISRB0                         0x1023
-#define HDMI_FC_AVISRB1                         0x1024
-#define HDMI_FC_AUDICONF0                       0x1025
-#define HDMI_FC_AUDICONF1                       0x1026
-#define HDMI_FC_AUDICONF2                       0x1027
-#define HDMI_FC_AUDICONF3                       0x1028
-#define HDMI_FC_VSDIEEEID0                      0x1029
-#define HDMI_FC_VSDSIZE                         0x102A
-#define HDMI_FC_VSDIEEEID1                      0x1030
-#define HDMI_FC_VSDIEEEID2                      0x1031
-#define HDMI_FC_VSDPAYLOAD0                     0x1032
-#define HDMI_FC_VSDPAYLOAD1                     0x1033
-#define HDMI_FC_VSDPAYLOAD2                     0x1034
-#define HDMI_FC_VSDPAYLOAD3                     0x1035
-#define HDMI_FC_VSDPAYLOAD4                     0x1036
-#define HDMI_FC_VSDPAYLOAD5                     0x1037
-#define HDMI_FC_VSDPAYLOAD6                     0x1038
-#define HDMI_FC_VSDPAYLOAD7                     0x1039
-#define HDMI_FC_VSDPAYLOAD8                     0x103A
-#define HDMI_FC_VSDPAYLOAD9                     0x103B
-#define HDMI_FC_VSDPAYLOAD10                    0x103C
-#define HDMI_FC_VSDPAYLOAD11                    0x103D
-#define HDMI_FC_VSDPAYLOAD12                    0x103E
-#define HDMI_FC_VSDPAYLOAD13                    0x103F
-#define HDMI_FC_VSDPAYLOAD14                    0x1040
-#define HDMI_FC_VSDPAYLOAD15                    0x1041
-#define HDMI_FC_VSDPAYLOAD16                    0x1042
-#define HDMI_FC_VSDPAYLOAD17                    0x1043
-#define HDMI_FC_VSDPAYLOAD18                    0x1044
-#define HDMI_FC_VSDPAYLOAD19                    0x1045
-#define HDMI_FC_VSDPAYLOAD20                    0x1046
-#define HDMI_FC_VSDPAYLOAD21                    0x1047
-#define HDMI_FC_VSDPAYLOAD22                    0x1048
-#define HDMI_FC_VSDPAYLOAD23                    0x1049
-#define HDMI_FC_SPDVENDORNAME0                  0x104A
-#define HDMI_FC_SPDVENDORNAME1                  0x104B
-#define HDMI_FC_SPDVENDORNAME2                  0x104C
-#define HDMI_FC_SPDVENDORNAME3                  0x104D
-#define HDMI_FC_SPDVENDORNAME4                  0x104E
-#define HDMI_FC_SPDVENDORNAME5                  0x104F
-#define HDMI_FC_SPDVENDORNAME6                  0x1050
-#define HDMI_FC_SPDVENDORNAME7                  0x1051
-#define HDMI_FC_SDPPRODUCTNAME0                 0x1052
-#define HDMI_FC_SDPPRODUCTNAME1                 0x1053
-#define HDMI_FC_SDPPRODUCTNAME2                 0x1054
-#define HDMI_FC_SDPPRODUCTNAME3                 0x1055
-#define HDMI_FC_SDPPRODUCTNAME4                 0x1056
-#define HDMI_FC_SDPPRODUCTNAME5                 0x1057
-#define HDMI_FC_SDPPRODUCTNAME6                 0x1058
-#define HDMI_FC_SDPPRODUCTNAME7                 0x1059
-#define HDMI_FC_SDPPRODUCTNAME8                 0x105A
-#define HDMI_FC_SDPPRODUCTNAME9                 0x105B
-#define HDMI_FC_SDPPRODUCTNAME10                0x105C
-#define HDMI_FC_SDPPRODUCTNAME11                0x105D
-#define HDMI_FC_SDPPRODUCTNAME12                0x105E
-#define HDMI_FC_SDPPRODUCTNAME13                0x105F
-#define HDMI_FC_SDPPRODUCTNAME14                0x1060
-#define HDMI_FC_SPDPRODUCTNAME15                0x1061
-#define HDMI_FC_SPDDEVICEINF                    0x1062
-#define HDMI_FC_AUDSCONF                        0x1063
-#define HDMI_FC_AUDSSTAT                        0x1064
-#define HDMI_FC_DATACH0FILL                     0x1070
-#define HDMI_FC_DATACH1FILL                     0x1071
-#define HDMI_FC_DATACH2FILL                     0x1072
-#define HDMI_FC_CTRLQHIGH                       0x1073
-#define HDMI_FC_CTRLQLOW                        0x1074
-#define HDMI_FC_ACP0                            0x1075
-#define HDMI_FC_ACP28                           0x1076
-#define HDMI_FC_ACP27                           0x1077
-#define HDMI_FC_ACP26                           0x1078
-#define HDMI_FC_ACP25                           0x1079
-#define HDMI_FC_ACP24                           0x107A
-#define HDMI_FC_ACP23                           0x107B
-#define HDMI_FC_ACP22                           0x107C
-#define HDMI_FC_ACP21                           0x107D
-#define HDMI_FC_ACP20                           0x107E
-#define HDMI_FC_ACP19                           0x107F
-#define HDMI_FC_ACP18                           0x1080
-#define HDMI_FC_ACP17                           0x1081
-#define HDMI_FC_ACP16                           0x1082
-#define HDMI_FC_ACP15                           0x1083
-#define HDMI_FC_ACP14                           0x1084
-#define HDMI_FC_ACP13                           0x1085
-#define HDMI_FC_ACP12                           0x1086
-#define HDMI_FC_ACP11                           0x1087
-#define HDMI_FC_ACP10                           0x1088
-#define HDMI_FC_ACP9                            0x1089
-#define HDMI_FC_ACP8                            0x108A
-#define HDMI_FC_ACP7                            0x108B
-#define HDMI_FC_ACP6                            0x108C
-#define HDMI_FC_ACP5                            0x108D
-#define HDMI_FC_ACP4                            0x108E
-#define HDMI_FC_ACP3                            0x108F
-#define HDMI_FC_ACP2                            0x1090
-#define HDMI_FC_ACP1                            0x1091
-#define HDMI_FC_ISCR1_0                         0x1092
-#define HDMI_FC_ISCR1_16                        0x1093
-#define HDMI_FC_ISCR1_15                        0x1094
-#define HDMI_FC_ISCR1_14                        0x1095
-#define HDMI_FC_ISCR1_13                        0x1096
-#define HDMI_FC_ISCR1_12                        0x1097
-#define HDMI_FC_ISCR1_11                        0x1098
-#define HDMI_FC_ISCR1_10                        0x1099
-#define HDMI_FC_ISCR1_9                         0x109A
-#define HDMI_FC_ISCR1_8                         0x109B
-#define HDMI_FC_ISCR1_7                         0x109C
-#define HDMI_FC_ISCR1_6                         0x109D
-#define HDMI_FC_ISCR1_5                         0x109E
-#define HDMI_FC_ISCR1_4                         0x109F
-#define HDMI_FC_ISCR1_3                         0x10A0
-#define HDMI_FC_ISCR1_2                         0x10A1
-#define HDMI_FC_ISCR1_1                         0x10A2
-#define HDMI_FC_ISCR2_15                        0x10A3
-#define HDMI_FC_ISCR2_14                        0x10A4
-#define HDMI_FC_ISCR2_13                        0x10A5
-#define HDMI_FC_ISCR2_12                        0x10A6
-#define HDMI_FC_ISCR2_11                        0x10A7
-#define HDMI_FC_ISCR2_10                        0x10A8
-#define HDMI_FC_ISCR2_9                         0x10A9
-#define HDMI_FC_ISCR2_8                         0x10AA
-#define HDMI_FC_ISCR2_7                         0x10AB
-#define HDMI_FC_ISCR2_6                         0x10AC
-#define HDMI_FC_ISCR2_5                         0x10AD
-#define HDMI_FC_ISCR2_4                         0x10AE
-#define HDMI_FC_ISCR2_3                         0x10AF
-#define HDMI_FC_ISCR2_2                         0x10B0
-#define HDMI_FC_ISCR2_1                         0x10B1
-#define HDMI_FC_ISCR2_0                         0x10B2
-#define HDMI_FC_DATAUTO0                        0x10B3
-#define HDMI_FC_DATAUTO1                        0x10B4
-#define HDMI_FC_DATAUTO2                        0x10B5
-#define HDMI_FC_DATMAN                          0x10B6
-#define HDMI_FC_DATAUTO3                        0x10B7
-#define HDMI_FC_RDRB0                           0x10B8
-#define HDMI_FC_RDRB1                           0x10B9
-#define HDMI_FC_RDRB2                           0x10BA
-#define HDMI_FC_RDRB3                           0x10BB
-#define HDMI_FC_RDRB4                           0x10BC
-#define HDMI_FC_RDRB5                           0x10BD
-#define HDMI_FC_RDRB6                           0x10BE
-#define HDMI_FC_RDRB7                           0x10BF
-#define HDMI_FC_STAT0                           0x10D0
-#define HDMI_FC_INT0                            0x10D1
-#define HDMI_FC_MASK0                           0x10D2
-#define HDMI_FC_POL0                            0x10D3
-#define HDMI_FC_STAT1                           0x10D4
-#define HDMI_FC_INT1                            0x10D5
-#define HDMI_FC_MASK1                           0x10D6
-#define HDMI_FC_POL1                            0x10D7
-#define HDMI_FC_STAT2                           0x10D8
-#define HDMI_FC_INT2                            0x10D9
-#define HDMI_FC_MASK2                           0x10DA
-#define HDMI_FC_POL2                            0x10DB
-#define HDMI_FC_PRCONF                          0x10E0
-
-#define HDMI_FC_GMD_STAT                        0x1100
-#define HDMI_FC_GMD_EN                          0x1101
-#define HDMI_FC_GMD_UP                          0x1102
-#define HDMI_FC_GMD_CONF                        0x1103
-#define HDMI_FC_GMD_HB                          0x1104
-#define HDMI_FC_GMD_PB0                         0x1105
-#define HDMI_FC_GMD_PB1                         0x1106
-#define HDMI_FC_GMD_PB2                         0x1107
-#define HDMI_FC_GMD_PB3                         0x1108
-#define HDMI_FC_GMD_PB4                         0x1109
-#define HDMI_FC_GMD_PB5                         0x110A
-#define HDMI_FC_GMD_PB6                         0x110B
-#define HDMI_FC_GMD_PB7                         0x110C
-#define HDMI_FC_GMD_PB8                         0x110D
-#define HDMI_FC_GMD_PB9                         0x110E
-#define HDMI_FC_GMD_PB10                        0x110F
-#define HDMI_FC_GMD_PB11                        0x1110
-#define HDMI_FC_GMD_PB12                        0x1111
-#define HDMI_FC_GMD_PB13                        0x1112
-#define HDMI_FC_GMD_PB14                        0x1113
-#define HDMI_FC_GMD_PB15                        0x1114
-#define HDMI_FC_GMD_PB16                        0x1115
-#define HDMI_FC_GMD_PB17                        0x1116
-#define HDMI_FC_GMD_PB18                        0x1117
-#define HDMI_FC_GMD_PB19                        0x1118
-#define HDMI_FC_GMD_PB20                        0x1119
-#define HDMI_FC_GMD_PB21                        0x111A
-#define HDMI_FC_GMD_PB22                        0x111B
-#define HDMI_FC_GMD_PB23                        0x111C
-#define HDMI_FC_GMD_PB24                        0x111D
-#define HDMI_FC_GMD_PB25                        0x111E
-#define HDMI_FC_GMD_PB26                        0x111F
-#define HDMI_FC_GMD_PB27                        0x1120
-
-#define HDMI_FC_DBGFORCE                        0x1200
-#define HDMI_FC_DBGAUD0CH0                      0x1201
-#define HDMI_FC_DBGAUD1CH0                      0x1202
-#define HDMI_FC_DBGAUD2CH0                      0x1203
-#define HDMI_FC_DBGAUD0CH1                      0x1204
-#define HDMI_FC_DBGAUD1CH1                      0x1205
-#define HDMI_FC_DBGAUD2CH1                      0x1206
-#define HDMI_FC_DBGAUD0CH2                      0x1207
-#define HDMI_FC_DBGAUD1CH2                      0x1208
-#define HDMI_FC_DBGAUD2CH2                      0x1209
-#define HDMI_FC_DBGAUD0CH3                      0x120A
-#define HDMI_FC_DBGAUD1CH3                      0x120B
-#define HDMI_FC_DBGAUD2CH3                      0x120C
-#define HDMI_FC_DBGAUD0CH4                      0x120D
-#define HDMI_FC_DBGAUD1CH4                      0x120E
-#define HDMI_FC_DBGAUD2CH4                      0x120F
-#define HDMI_FC_DBGAUD0CH5                      0x1210
-#define HDMI_FC_DBGAUD1CH5                      0x1211
-#define HDMI_FC_DBGAUD2CH5                      0x1212
-#define HDMI_FC_DBGAUD0CH6                      0x1213
-#define HDMI_FC_DBGAUD1CH6                      0x1214
-#define HDMI_FC_DBGAUD2CH6                      0x1215
-#define HDMI_FC_DBGAUD0CH7                      0x1216
-#define HDMI_FC_DBGAUD1CH7                      0x1217
-#define HDMI_FC_DBGAUD2CH7                      0x1218
-#define HDMI_FC_DBGTMDS0                        0x1219
-#define HDMI_FC_DBGTMDS1                        0x121A
-#define HDMI_FC_DBGTMDS2                        0x121B
-
-/* HDMI Source PHY Registers */
-#define HDMI_PHY_CONF0                          0x3000
-#define HDMI_PHY_TST0                           0x3001
-#define HDMI_PHY_TST1                           0x3002
-#define HDMI_PHY_TST2                           0x3003
-#define HDMI_PHY_STAT0                          0x3004
-#define HDMI_PHY_INT0                           0x3005
-#define HDMI_PHY_MASK0                          0x3006
-#define HDMI_PHY_POL0                           0x3007
-
-/* HDMI Master PHY Registers */
-#define HDMI_PHY_I2CM_SLAVE_ADDR                0x3020
-#define HDMI_PHY_I2CM_ADDRESS_ADDR              0x3021
-#define HDMI_PHY_I2CM_DATAO_1_ADDR              0x3022
-#define HDMI_PHY_I2CM_DATAO_0_ADDR              0x3023
-#define HDMI_PHY_I2CM_DATAI_1_ADDR              0x3024
-#define HDMI_PHY_I2CM_DATAI_0_ADDR              0x3025
-#define HDMI_PHY_I2CM_OPERATION_ADDR            0x3026
-#define HDMI_PHY_I2CM_INT_ADDR                  0x3027
-#define HDMI_PHY_I2CM_CTLINT_ADDR               0x3028
-#define HDMI_PHY_I2CM_DIV_ADDR                  0x3029
-#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR             0x302a
-#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR        0x302b
-#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR        0x302c
-#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR        0x302d
-#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR        0x302e
-#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR        0x302f
-#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR        0x3030
-#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR        0x3031
-#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR        0x3032
-
-/* Audio Sampler Registers */
-#define HDMI_AUD_CONF0                          0x3100
-#define HDMI_AUD_CONF1                          0x3101
-#define HDMI_AUD_INT                            0x3102
-#define HDMI_AUD_CONF2                          0x3103
-#define HDMI_AUD_N1                             0x3200
-#define HDMI_AUD_N2                             0x3201
-#define HDMI_AUD_N3                             0x3202
-#define HDMI_AUD_CTS1                           0x3203
-#define HDMI_AUD_CTS2                           0x3204
-#define HDMI_AUD_CTS3                           0x3205
-#define HDMI_AUD_INPUTCLKFS                     0x3206
-#define HDMI_AUD_SPDIFINT                      0x3302
-#define HDMI_AUD_CONF0_HBR                      0x3400
-#define HDMI_AUD_HBR_STATUS                     0x3401
-#define HDMI_AUD_HBR_INT                        0x3402
-#define HDMI_AUD_HBR_POL                        0x3403
-#define HDMI_AUD_HBR_MASK                       0x3404
-
-/*
- * Generic Parallel Audio Interface Registers
- * Not used as GPAUD interface is not enabled in hw
- */
-#define HDMI_GP_CONF0                           0x3500
-#define HDMI_GP_CONF1                           0x3501
-#define HDMI_GP_CONF2                           0x3502
-#define HDMI_GP_STAT                            0x3503
-#define HDMI_GP_INT                             0x3504
-#define HDMI_GP_MASK                            0x3505
-#define HDMI_GP_POL                             0x3506
-
-/* Audio DMA Registers */
-#define HDMI_AHB_DMA_CONF0                      0x3600
-#define HDMI_AHB_DMA_START                      0x3601
-#define HDMI_AHB_DMA_STOP                       0x3602
-#define HDMI_AHB_DMA_THRSLD                     0x3603
-#define HDMI_AHB_DMA_STRADDR0                   0x3604
-#define HDMI_AHB_DMA_STRADDR1                   0x3605
-#define HDMI_AHB_DMA_STRADDR2                   0x3606
-#define HDMI_AHB_DMA_STRADDR3                   0x3607
-#define HDMI_AHB_DMA_STPADDR0                   0x3608
-#define HDMI_AHB_DMA_STPADDR1                   0x3609
-#define HDMI_AHB_DMA_STPADDR2                   0x360a
-#define HDMI_AHB_DMA_STPADDR3                   0x360b
-#define HDMI_AHB_DMA_BSTADDR0                   0x360c
-#define HDMI_AHB_DMA_BSTADDR1                   0x360d
-#define HDMI_AHB_DMA_BSTADDR2                   0x360e
-#define HDMI_AHB_DMA_BSTADDR3                   0x360f
-#define HDMI_AHB_DMA_MBLENGTH0                  0x3610
-#define HDMI_AHB_DMA_MBLENGTH1                  0x3611
-#define HDMI_AHB_DMA_STAT                       0x3612
-#define HDMI_AHB_DMA_INT                        0x3613
-#define HDMI_AHB_DMA_MASK                       0x3614
-#define HDMI_AHB_DMA_POL                        0x3615
-#define HDMI_AHB_DMA_CONF1                      0x3616
-#define HDMI_AHB_DMA_BUFFSTAT                   0x3617
-#define HDMI_AHB_DMA_BUFFINT                    0x3618
-#define HDMI_AHB_DMA_BUFFMASK                   0x3619
-#define HDMI_AHB_DMA_BUFFPOL                    0x361a
-
-/* Main Controller Registers */
-#define HDMI_MC_SFRDIV                          0x4000
-#define HDMI_MC_CLKDIS                          0x4001
-#define HDMI_MC_SWRSTZ                          0x4002
-#define HDMI_MC_OPCTRL                          0x4003
-#define HDMI_MC_FLOWCTRL                        0x4004
-#define HDMI_MC_PHYRSTZ                         0x4005
-#define HDMI_MC_LOCKONCLOCK                     0x4006
-#define HDMI_MC_HEACPHY_RST                     0x4007
-
-/* Color Space  Converter Registers */
-#define HDMI_CSC_CFG                            0x4100
-#define HDMI_CSC_SCALE                          0x4101
-#define HDMI_CSC_COEF_A1_MSB                    0x4102
-#define HDMI_CSC_COEF_A1_LSB                    0x4103
-#define HDMI_CSC_COEF_A2_MSB                    0x4104
-#define HDMI_CSC_COEF_A2_LSB                    0x4105
-#define HDMI_CSC_COEF_A3_MSB                    0x4106
-#define HDMI_CSC_COEF_A3_LSB                    0x4107
-#define HDMI_CSC_COEF_A4_MSB                    0x4108
-#define HDMI_CSC_COEF_A4_LSB                    0x4109
-#define HDMI_CSC_COEF_B1_MSB                    0x410A
-#define HDMI_CSC_COEF_B1_LSB                    0x410B
-#define HDMI_CSC_COEF_B2_MSB                    0x410C
-#define HDMI_CSC_COEF_B2_LSB                    0x410D
-#define HDMI_CSC_COEF_B3_MSB                    0x410E
-#define HDMI_CSC_COEF_B3_LSB                    0x410F
-#define HDMI_CSC_COEF_B4_MSB                    0x4110
-#define HDMI_CSC_COEF_B4_LSB                    0x4111
-#define HDMI_CSC_COEF_C1_MSB                    0x4112
-#define HDMI_CSC_COEF_C1_LSB                    0x4113
-#define HDMI_CSC_COEF_C2_MSB                    0x4114
-#define HDMI_CSC_COEF_C2_LSB                    0x4115
-#define HDMI_CSC_COEF_C3_MSB                    0x4116
-#define HDMI_CSC_COEF_C3_LSB                    0x4117
-#define HDMI_CSC_COEF_C4_MSB                    0x4118
-#define HDMI_CSC_COEF_C4_LSB                    0x4119
-
-/* HDCP Encryption Engine Registers */
-#define HDMI_A_HDCPCFG0                         0x5000
-#define HDMI_A_HDCPCFG1                         0x5001
-#define HDMI_A_HDCPOBS0                         0x5002
-#define HDMI_A_HDCPOBS1                         0x5003
-#define HDMI_A_HDCPOBS2                         0x5004
-#define HDMI_A_HDCPOBS3                         0x5005
-#define HDMI_A_APIINTCLR                        0x5006
-#define HDMI_A_APIINTSTAT                       0x5007
-#define HDMI_A_APIINTMSK                        0x5008
-#define HDMI_A_VIDPOLCFG                        0x5009
-#define HDMI_A_OESSWCFG                         0x500A
-#define HDMI_A_TIMER1SETUP0                     0x500B
-#define HDMI_A_TIMER1SETUP1                     0x500C
-#define HDMI_A_TIMER2SETUP0                     0x500D
-#define HDMI_A_TIMER2SETUP1                     0x500E
-#define HDMI_A_100MSCFG                         0x500F
-#define HDMI_A_2SCFG0                           0x5010
-#define HDMI_A_2SCFG1                           0x5011
-#define HDMI_A_5SCFG0                           0x5012
-#define HDMI_A_5SCFG1                           0x5013
-#define HDMI_A_SRMVERLSB                        0x5014
-#define HDMI_A_SRMVERMSB                        0x5015
-#define HDMI_A_SRMCTRL                          0x5016
-#define HDMI_A_SFRSETUP                         0x5017
-#define HDMI_A_I2CHSETUP                        0x5018
-#define HDMI_A_INTSETUP                         0x5019
-#define HDMI_A_PRESETUP                         0x501A
-#define HDMI_A_SRM_BASE                         0x5020
-
-/* CEC Engine Registers */
-#define HDMI_CEC_CTRL                           0x7D00
-#define HDMI_CEC_STAT                           0x7D01
-#define HDMI_CEC_MASK                           0x7D02
-#define HDMI_CEC_POLARITY                       0x7D03
-#define HDMI_CEC_INT                            0x7D04
-#define HDMI_CEC_ADDR_L                         0x7D05
-#define HDMI_CEC_ADDR_H                         0x7D06
-#define HDMI_CEC_TX_CNT                         0x7D07
-#define HDMI_CEC_RX_CNT                         0x7D08
-#define HDMI_CEC_TX_DATA0                       0x7D10
-#define HDMI_CEC_TX_DATA1                       0x7D11
-#define HDMI_CEC_TX_DATA2                       0x7D12
-#define HDMI_CEC_TX_DATA3                       0x7D13
-#define HDMI_CEC_TX_DATA4                       0x7D14
-#define HDMI_CEC_TX_DATA5                       0x7D15
-#define HDMI_CEC_TX_DATA6                       0x7D16
-#define HDMI_CEC_TX_DATA7                       0x7D17
-#define HDMI_CEC_TX_DATA8                       0x7D18
-#define HDMI_CEC_TX_DATA9                       0x7D19
-#define HDMI_CEC_TX_DATA10                      0x7D1a
-#define HDMI_CEC_TX_DATA11                      0x7D1b
-#define HDMI_CEC_TX_DATA12                      0x7D1c
-#define HDMI_CEC_TX_DATA13                      0x7D1d
-#define HDMI_CEC_TX_DATA14                      0x7D1e
-#define HDMI_CEC_TX_DATA15                      0x7D1f
-#define HDMI_CEC_RX_DATA0                       0x7D20
-#define HDMI_CEC_RX_DATA1                       0x7D21
-#define HDMI_CEC_RX_DATA2                       0x7D22
-#define HDMI_CEC_RX_DATA3                       0x7D23
-#define HDMI_CEC_RX_DATA4                       0x7D24
-#define HDMI_CEC_RX_DATA5                       0x7D25
-#define HDMI_CEC_RX_DATA6                       0x7D26
-#define HDMI_CEC_RX_DATA7                       0x7D27
-#define HDMI_CEC_RX_DATA8                       0x7D28
-#define HDMI_CEC_RX_DATA9                       0x7D29
-#define HDMI_CEC_RX_DATA10                      0x7D2a
-#define HDMI_CEC_RX_DATA11                      0x7D2b
-#define HDMI_CEC_RX_DATA12                      0x7D2c
-#define HDMI_CEC_RX_DATA13                      0x7D2d
-#define HDMI_CEC_RX_DATA14                      0x7D2e
-#define HDMI_CEC_RX_DATA15                      0x7D2f
-#define HDMI_CEC_LOCK                           0x7D30
-#define HDMI_CEC_WKUPCTRL                       0x7D31
-
-/* I2C Master Registers (E-DDC) */
-#define HDMI_I2CM_SLAVE                         0x7E00
-#define HDMI_I2CM_ADDRESS                       0x7E01
-#define HDMI_I2CM_DATAO                         0x7E02
-#define HDMI_I2CM_DATAI                         0x7E03
-#define HDMI_I2CM_OPERATION                     0x7E04
-#define HDMI_I2CM_INT                           0x7E05
-#define HDMI_I2CM_CTLINT                        0x7E06
-#define HDMI_I2CM_DIV                           0x7E07
-#define HDMI_I2CM_SEGADDR                       0x7E08
-#define HDMI_I2CM_SOFTRSTZ                      0x7E09
-#define HDMI_I2CM_SEGPTR                        0x7E0A
-#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR            0x7E0B
-#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR            0x7E0C
-#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR            0x7E0D
-#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR            0x7E0E
-#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR            0x7E0F
-#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR            0x7E10
-#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR            0x7E11
-#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
-
-enum {
-/* PRODUCT_ID0 field values */
-       HDMI_PRODUCT_ID0_HDMI_TX = 0xa0,
-
-/* PRODUCT_ID1 field values */
-       HDMI_PRODUCT_ID1_HDCP = 0xc0,
-       HDMI_PRODUCT_ID1_HDMI_RX = 0x02,
-       HDMI_PRODUCT_ID1_HDMI_TX = 0x01,
-
-/* CONFIG0_ID field values */
-       HDMI_CONFIG0_I2S = 0x10,
-
-/* CONFIG1_ID field values */
-       HDMI_CONFIG1_AHB = 0x01,
-
-/* CONFIG3_ID field values */
-       HDMI_CONFIG3_AHBAUDDMA = 0x02,
-       HDMI_CONFIG3_GPAUD = 0x01,
-
-/* IH_FC_INT2 field values */
-       HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
-       HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
-       HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
-
-/* IH_FC_STAT2 field values */
-       HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
-       HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
-       HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
-
-/* IH_PHY_STAT0 field values */
-       HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
-       HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
-       HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
-       HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
-       HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
-       HDMI_IH_PHY_STAT0_HPD = 0x1,
-
-/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */
-       HDMI_IH_I2CM_STAT0_DONE = 0x2,
-       HDMI_IH_I2CM_STAT0_ERROR = 0x1,
-
-/* IH_MUTE_I2CMPHY_STAT0 field values */
-       HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
-       HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
-
-/* IH_AHBDMAAUD_STAT0 field values */
-       HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
-       HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
-       HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
-       HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
-       HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
-       HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
-
-/* IH_MUTE_FC_STAT2 field values */
-       HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
-       HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
-       HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
-
-/* IH_MUTE_AHBDMAAUD_STAT0 field values */
-       HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
-       HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
-       HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
-       HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
-       HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
-       HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
-
-/* IH_MUTE field values */
-       HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
-       HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
-
-/* TX_INVID0 field values */
-       HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80,
-       HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
-       HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
-       HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F,
-       HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
-
-/* TX_INSTUFFING field values */
-       HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4,
-       HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
-       HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
-       HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
-       HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
-       HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
-       HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
-       HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
-       HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
-
-/* VP_PR_CD field values */
-       HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0,
-       HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
-       HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F,
-       HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
-
-/* VP_STUFF field values */
-       HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
-       HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
-       HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10,
-       HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
-       HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
-       HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
-       HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
-       HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
-       HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
-       HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
-       HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
-       HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
-       HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
-       HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
-       HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
-
-/* VP_CONF field values */
-       HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
-       HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
-       HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
-       HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
-       HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
-       HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
-       HDMI_VP_CONF_PR_EN_MASK = 0x10,
-       HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
-       HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
-       HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
-       HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8,
-       HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
-       HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
-       HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
-       HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0,
-       HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
-       HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
-       HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
-       HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
-
-/* VP_REMAP field values */
-       HDMI_VP_REMAP_MASK = 0x3,
-       HDMI_VP_REMAP_YCC422_24bit = 0x2,
-       HDMI_VP_REMAP_YCC422_20bit = 0x1,
-       HDMI_VP_REMAP_YCC422_16bit = 0x0,
-
-/* FC_INVIDCONF field values */
-       HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80,
-       HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80,
-       HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00,
-       HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
-       HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
-       HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
-       HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
-       HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
-       HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
-       HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
-       HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
-       HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
-       HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
-       HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
-       HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
-       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
-       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
-       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
-       HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
-       HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
-       HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
-
-/* FC_AUDICONF0 field values */
-       HDMI_FC_AUDICONF0_CC_OFFSET = 4,
-       HDMI_FC_AUDICONF0_CC_MASK = 0x70,
-       HDMI_FC_AUDICONF0_CT_OFFSET = 0,
-       HDMI_FC_AUDICONF0_CT_MASK = 0xF,
-
-/* FC_AUDICONF1 field values */
-       HDMI_FC_AUDICONF1_SS_OFFSET = 3,
-       HDMI_FC_AUDICONF1_SS_MASK = 0x18,
-       HDMI_FC_AUDICONF1_SF_OFFSET = 0,
-       HDMI_FC_AUDICONF1_SF_MASK = 0x7,
-
-/* FC_AUDICONF3 field values */
-       HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
-       HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
-       HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
-       HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
-       HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
-       HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
-
-/* FC_AUDSCHNLS0 field values */
-       HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
-       HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
-       HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
-
-/* FC_AUDSCHNLS3-6 field values */
-       HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
-       HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
-       HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
-       HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
-       HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
-       HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
-
-       HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
-       HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
-       HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
-       HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
-       HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
-       HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
-
-/* HDMI_FC_AUDSCHNLS7 field values */
-       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
-
-/* HDMI_FC_AUDSCHNLS8 field values */
-       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
-       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
-       HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
-       HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
-
-/* FC_AUDSCONF field values */
-       HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
-       HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
-       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
-       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
-       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
-       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
-
-/* FC_STAT2 field values */
-       HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
-       HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
-       HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
-
-/* FC_INT2 field values */
-       HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
-       HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
-       HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
-
-/* FC_MASK2 field values */
-       HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
-       HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
-       HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
-
-/* FC_PRCONF field values */
-       HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
-       HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
-       HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
-       HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
-
-/* FC_AVICONF0-FC_AVICONF3 field values */
-       HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
-       HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
-       HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
-       HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
-       HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
-       HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
-       HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
-       HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C,
-       HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
-       HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
-       HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
-       HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C,
-       HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
-       HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
-       HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
-       HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
-
-       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F,
-       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
-       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
-       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A,
-       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B,
-       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
-       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
-       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
-       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
-       HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0,
-       HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
-       HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
-       HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
-       HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0,
-
-       HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
-       HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
-       HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
-       HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
-       HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03,
-       HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C,
-       HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
-       HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
-       HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
-       HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
-       HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
-       HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
-       HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
-       HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
-       HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
-       HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
-       HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
-       HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
-
-       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
-       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
-       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
-       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
-       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
-       HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C,
-       HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
-       HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
-
-/* FC_DBGFORCE field values */
-       HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
-       HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
-
-/* PHY_CONF0 field values */
-       HDMI_PHY_CONF0_PDZ_MASK = 0x80,
-       HDMI_PHY_CONF0_PDZ_OFFSET = 7,
-       HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
-       HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
-       HDMI_PHY_CONF0_SVSRET_MASK = 0x20,
-       HDMI_PHY_CONF0_SVSRET_OFFSET = 5,
-       HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
-       HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
-       HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
-       HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
-       HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4,
-       HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
-       HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
-       HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
-       HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
-       HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
-
-/* PHY_TST0 field values */
-       HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
-       HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
-       HDMI_PHY_TST0_TSTEN_MASK = 0x10,
-       HDMI_PHY_TST0_TSTEN_OFFSET = 4,
-       HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
-       HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
-
-/* PHY_STAT0 field values */
-       HDMI_PHY_RX_SENSE3 = 0x80,
-       HDMI_PHY_RX_SENSE2 = 0x40,
-       HDMI_PHY_RX_SENSE1 = 0x20,
-       HDMI_PHY_RX_SENSE0 = 0x10,
-       HDMI_PHY_HPD = 0x02,
-       HDMI_PHY_TX_PHY_LOCK = 0x01,
-
-/* PHY_I2CM_SLAVE_ADDR field values */
-       HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
-       HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
-
-/* PHY_I2CM_OPERATION_ADDR field values */
-       HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
-       HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
-
-/* HDMI_PHY_I2CM_INT_ADDR */
-       HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
-       HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
-
-/* HDMI_PHY_I2CM_CTLINT_ADDR */
-       HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
-       HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
-       HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
-       HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
-
-/* AUD_CONF0 field values */
-       HDMI_AUD_CONF0_SW_RESET = 0x80,
-       HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F,
-
-/* AUD_CONF1 field values */
-       HDMI_AUD_CONF1_MODE_I2S = 0x00,
-       HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02,
-       HDMI_AUD_CONF1_MODE_LEFT_J = 0x04,
-       HDMI_AUD_CONF1_WIDTH_16 = 0x10,
-       HDMI_AUD_CONF1_WIDTH_24 = 0x18,
-
-/* AUD_CTS3 field values */
-       HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
-       HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
-       HDMI_AUD_CTS3_N_SHIFT_1 = 0,
-       HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
-       HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
-       HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
-       HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
-       HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
-       /* note that the CTS3 MANUAL bit has been removed
-          from our part. Can't set it, will read as 0. */
-       HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
-       HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
-
-/* HDMI_AUD_INPUTCLKFS field values */
-       HDMI_AUD_INPUTCLKFS_128FS = 0,
-       HDMI_AUD_INPUTCLKFS_256FS = 1,
-       HDMI_AUD_INPUTCLKFS_512FS = 2,
-       HDMI_AUD_INPUTCLKFS_64FS = 4,
-
-/* AHB_DMA_CONF0 field values */
-       HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
-       HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
-       HDMI_AHB_DMA_CONF0_HBR = 0x10,
-       HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
-       HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
-       HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
-       HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
-       HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
-       HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
-       HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
-       HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
-
-/* HDMI_AHB_DMA_START field values */
-       HDMI_AHB_DMA_START_START_OFFSET = 0,
-       HDMI_AHB_DMA_START_START_MASK = 0x01,
-
-/* HDMI_AHB_DMA_STOP field values */
-       HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
-       HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
-
-/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
-       HDMI_AHB_DMA_DONE = 0x80,
-       HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
-       HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
-       HDMI_AHB_DMA_ERROR = 0x10,
-       HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
-       HDMI_AHB_DMA_FIFO_FULL = 0x02,
-       HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
-
-/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */
-       HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
-       HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
-
-/* MC_CLKDIS field values */
-       HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
-       HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
-       HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
-       HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
-       HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
-       HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
-       HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
-
-/* MC_SWRSTZ field values */
-       HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
-
-/* MC_FLOWCTRL field values */
-       HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
-       HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
-       HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
-
-/* MC_PHYRSTZ field values */
-       HDMI_MC_PHYRSTZ_PHYRSTZ = 0x01,
-
-/* MC_HEACPHY_RST field values */
-       HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
-       HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
-
-/* CSC_CFG field values */
-       HDMI_CSC_CFG_INTMODE_MASK = 0x30,
-       HDMI_CSC_CFG_INTMODE_OFFSET = 4,
-       HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
-       HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
-       HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
-       HDMI_CSC_CFG_DECMODE_MASK = 0x3,
-       HDMI_CSC_CFG_DECMODE_OFFSET = 0,
-       HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
-       HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
-       HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
-       HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
-
-/* CSC_SCALE field values */
-       HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0,
-       HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
-       HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
-       HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
-       HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
-       HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
-
-/* A_HDCPCFG0 field values */
-       HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80,
-       HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80,
-       HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00,
-       HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40,
-       HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40,
-       HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00,
-       HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20,
-       HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20,
-       HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00,
-       HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10,
-       HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10,
-       HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00,
-       HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8,
-       HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8,
-       HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0,
-       HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4,
-       HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4,
-       HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0,
-       HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2,
-       HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2,
-       HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0,
-       HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1,
-       HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1,
-       HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0,
-
-/* A_HDCPCFG1 field values */
-       HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8,
-       HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8,
-       HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0,
-       HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4,
-       HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4,
-       HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0,
-       HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2,
-       HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2,
-       HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0,
-       HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1,
-       HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0,
-
-/* A_VIDPOLCFG field values */
-       HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60,
-       HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5,
-       HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10,
-       HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10,
-       HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0,
-       HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8,
-       HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8,
-       HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0,
-       HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
-       HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
-       HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
-
-/* I2CM_OPERATION field values */
-       HDMI_I2CM_OPERATION_WRITE = 0x10,
-       HDMI_I2CM_OPERATION_READ_EXT = 0x2,
-       HDMI_I2CM_OPERATION_READ = 0x1,
-
-/* I2CM_INT field values */
-       HDMI_I2CM_INT_DONE_POL = 0x8,
-       HDMI_I2CM_INT_DONE_MASK = 0x4,
-
-/* I2CM_CTLINT field values */
-       HDMI_I2CM_CTLINT_NAC_POL = 0x80,
-       HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
-       HDMI_I2CM_CTLINT_ARB_POL = 0x8,
-       HDMI_I2CM_CTLINT_ARB_MASK = 0x4,
-};
-
-/*
- * HDMI 3D TX PHY registers
- */
-#define HDMI_3D_TX_PHY_PWRCTRL                 0x00
-#define HDMI_3D_TX_PHY_SERDIVCTRL              0x01
-#define HDMI_3D_TX_PHY_SERCKCTRL               0x02
-#define HDMI_3D_TX_PHY_SERCKKILLCTRL           0x03
-#define HDMI_3D_TX_PHY_TXRESCTRL               0x04
-#define HDMI_3D_TX_PHY_CKCALCTRL               0x05
-#define HDMI_3D_TX_PHY_CPCE_CTRL               0x06
-#define HDMI_3D_TX_PHY_TXCLKMEASCTRL           0x07
-#define HDMI_3D_TX_PHY_TXMEASCTRL              0x08
-#define HDMI_3D_TX_PHY_CKSYMTXCTRL             0x09
-#define HDMI_3D_TX_PHY_CMPSEQCTRL              0x0a
-#define HDMI_3D_TX_PHY_CMPPWRCTRL              0x0b
-#define HDMI_3D_TX_PHY_CMPMODECTRL             0x0c
-#define HDMI_3D_TX_PHY_MEASCTRL                        0x0d
-#define HDMI_3D_TX_PHY_VLEVCTRL                        0x0e
-#define HDMI_3D_TX_PHY_D2ACTRL                 0x0f
-#define HDMI_3D_TX_PHY_CURRCTRL                        0x10
-#define HDMI_3D_TX_PHY_DRVANACTRL              0x11
-#define HDMI_3D_TX_PHY_PLLMEASCTRL             0x12
-#define HDMI_3D_TX_PHY_PLLPHBYCTRL             0x13
-#define HDMI_3D_TX_PHY_GRP_CTRL                        0x14
-#define HDMI_3D_TX_PHY_GMPCTRL                 0x15
-#define HDMI_3D_TX_PHY_MPLLMEASCTRL            0x16
-#define HDMI_3D_TX_PHY_MSM_CTRL                        0x17
-#define HDMI_3D_TX_PHY_SCRPB_STATUS            0x18
-#define HDMI_3D_TX_PHY_TXTERM                  0x19
-#define HDMI_3D_TX_PHY_PTRPT_ENBL              0x1a
-#define HDMI_3D_TX_PHY_PATTERNGEN              0x1b
-#define HDMI_3D_TX_PHY_SDCAP_MODE              0x1c
-#define HDMI_3D_TX_PHY_SCOPEMODE               0x1d
-#define HDMI_3D_TX_PHY_DIGTXMODE               0x1e
-#define HDMI_3D_TX_PHY_STR_STATUS              0x1f
-#define HDMI_3D_TX_PHY_SCOPECNT0               0x20
-#define HDMI_3D_TX_PHY_SCOPECNT1               0x21
-#define HDMI_3D_TX_PHY_SCOPECNT2               0x22
-#define HDMI_3D_TX_PHY_SCOPECNTCLK             0x23
-#define HDMI_3D_TX_PHY_SCOPESAMPLE             0x24
-#define HDMI_3D_TX_PHY_SCOPECNTMSB01           0x25
-#define HDMI_3D_TX_PHY_SCOPECNTMSB2CK          0x26
-
-/* HDMI_3D_TX_PHY_CKCALCTRL values */
-#define HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE              BIT(15)
-
-/* HDMI_3D_TX_PHY_MSM_CTRL values */
-#define HDMI_3D_TX_PHY_MSM_CTRL_MPLL_PH_SEL_CK         BIT(13)
-#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_CLK_REF_MPLL   (0 << 1)
-#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_OFF            (1 << 1)
-#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_PCLK           (2 << 1)
-#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK         (3 << 1)
-#define HDMI_3D_TX_PHY_MSM_CTRL_SCOPE_CK_SEL           BIT(0)
-
-/* HDMI_3D_TX_PHY_PTRPT_ENBL values */
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_OVERRIDE             BIT(15)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT2         BIT(8)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT1         BIT(7)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT0         BIT(6)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_CK_REF_ENB           BIT(5)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_RCAL_ENB             BIT(4)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_CLK_ALIGN_ENB     BIT(3)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_READY             BIT(2)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_CKO_WORD_ENB         BIT(1)
-#define HDMI_3D_TX_PHY_PTRPT_ENBL_REFCLK_ENB           BIT(0)
-
-#endif /* __DW_HDMI_H__ */
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
new file mode 100644 (file)
index 0000000..f1f67a2
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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 <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_panel.h>
+
+#include <linux/of_graph.h>
+
+struct lvds_encoder {
+       struct device *dev;
+
+       struct drm_bridge bridge;
+       struct drm_connector connector;
+       struct drm_panel *panel;
+};
+
+static inline struct lvds_encoder *
+drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
+{
+       return container_of(bridge, struct lvds_encoder, bridge);
+}
+
+static inline struct lvds_encoder *
+drm_connector_to_lvds_encoder(struct drm_connector *connector)
+{
+       return container_of(connector, struct lvds_encoder, connector);
+}
+
+static int lvds_connector_get_modes(struct drm_connector *connector)
+{
+       struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
+
+       return drm_panel_get_modes(lvds->panel);
+}
+
+static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = {
+       .get_modes = lvds_connector_get_modes,
+};
+
+static const struct drm_connector_funcs lvds_connector_funcs = {
+       .dpms = drm_atomic_helper_connector_dpms,
+       .reset = drm_atomic_helper_connector_reset,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int lvds_encoder_attach(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+       struct drm_connector *connector = &lvds->connector;
+       int ret;
+
+       if (!bridge->encoder) {
+               DRM_ERROR("Missing encoder\n");
+               return -ENODEV;
+       }
+
+       drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
+
+       ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs,
+                                DRM_MODE_CONNECTOR_LVDS);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector\n");
+               return ret;
+       }
+
+       drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
+
+       ret = drm_panel_attach(lvds->panel, &lvds->connector);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static void lvds_encoder_detach(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+       drm_panel_detach(lvds->panel);
+}
+
+static void lvds_encoder_pre_enable(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+       drm_panel_prepare(lvds->panel);
+}
+
+static void lvds_encoder_enable(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+       drm_panel_enable(lvds->panel);
+}
+
+static void lvds_encoder_disable(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+       drm_panel_disable(lvds->panel);
+}
+
+static void lvds_encoder_post_disable(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+       drm_panel_unprepare(lvds->panel);
+}
+
+static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
+       .attach = lvds_encoder_attach,
+       .detach = lvds_encoder_detach,
+       .pre_enable = lvds_encoder_pre_enable,
+       .enable = lvds_encoder_enable,
+       .disable = lvds_encoder_disable,
+       .post_disable = lvds_encoder_post_disable,
+};
+
+static int lvds_encoder_probe(struct platform_device *pdev)
+{
+       struct lvds_encoder *lvds;
+       struct device_node *port;
+       struct device_node *endpoint;
+       struct device_node *panel;
+
+       lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
+       if (!lvds)
+               return -ENOMEM;
+
+       lvds->dev = &pdev->dev;
+       platform_set_drvdata(pdev, lvds);
+
+       lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
+       lvds->bridge.of_node = pdev->dev.of_node;
+
+       /* Locate the panel DT node. */
+       port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
+       if (!port) {
+               dev_dbg(&pdev->dev, "port 1 not found\n");
+               return -ENXIO;
+       }
+
+       endpoint = of_get_child_by_name(port, "endpoint");
+       of_node_put(port);
+       if (!endpoint) {
+               dev_dbg(&pdev->dev, "no endpoint for port 1\n");
+               return -ENXIO;
+       }
+
+       panel = of_graph_get_remote_port_parent(endpoint);
+       of_node_put(endpoint);
+       if (!panel) {
+               dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
+               return -ENXIO;
+       }
+
+       lvds->panel = of_drm_find_panel(panel);
+       of_node_put(panel);
+       if (!lvds->panel) {
+               dev_dbg(&pdev->dev, "panel not found, deferring probe\n");
+               return -EPROBE_DEFER;
+       }
+
+       /* Register the bridge. */
+       return drm_bridge_add(&lvds->bridge);
+}
+
+static int lvds_encoder_remove(struct platform_device *pdev)
+{
+       struct lvds_encoder *encoder = platform_get_drvdata(pdev);
+
+       drm_bridge_remove(&encoder->bridge);
+
+       return 0;
+}
+
+static const struct of_device_id lvds_encoder_match[] = {
+       { .compatible = "lvds-encoder" },
+       { .compatible = "thine,thc63lvdm83d" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, lvds_encoder_match);
+
+static struct platform_driver lvds_encoder_driver = {
+       .probe  = lvds_encoder_probe,
+       .remove = lvds_encoder_remove,
+       .driver         = {
+               .name           = "lvds-encoder",
+               .of_match_table = lvds_encoder_match,
+       },
+};
+module_platform_driver(lvds_encoder_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
new file mode 100644 (file)
index 0000000..cfc606a
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * Driver for MegaChips STDP4028 with GE B850v3 firmware (LVDS-DP)
+ * Driver for MegaChips STDP2690 with GE B850v3 firmware (DP-DP++)
+
+ * Copyright (c) 2017, Collabora Ltd.
+ * Copyright (c) 2017, General Electric Company
+
+ * 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/>.
+
+ * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
+ * display bridge of the GE B850v3. There are two physical bridges on the video
+ * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). The
+ * physical bridges are automatically configured by the input video signal, and
+ * the driver has no access to the video processing pipeline. The driver is
+ * only needed to read EDID from the STDP2690 and to handle HPD events from the
+ * STDP4028. The driver communicates with both bridges over i2c. The video
+ * signal pipeline is as follows:
+ *
+ *   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drmP.h>
+
+#define EDID_EXT_BLOCK_CNT 0x7E
+
+#define STDP4028_IRQ_OUT_CONF_REG 0x02
+#define STDP4028_DPTX_IRQ_EN_REG 0x3C
+#define STDP4028_DPTX_IRQ_STS_REG 0x3D
+#define STDP4028_DPTX_STS_REG 0x3E
+
+#define STDP4028_DPTX_DP_IRQ_EN 0x1000
+
+#define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400
+#define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000
+#define STDP4028_DPTX_IRQ_CONFIG \
+               (STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN)
+
+#define STDP4028_DPTX_HOTPLUG_STS 0x0200
+#define STDP4028_DPTX_LINK_STS 0x1000
+#define STDP4028_CON_STATE_CONNECTED \
+               (STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS)
+
+#define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400
+#define STDP4028_DPTX_LINK_CH_STS 0x2000
+#define STDP4028_DPTX_IRQ_CLEAR \
+               (STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS)
+
+static DEFINE_MUTEX(ge_b850v3_lvds_dev_mutex);
+
+struct ge_b850v3_lvds {
+       struct drm_connector connector;
+       struct drm_bridge bridge;
+       struct i2c_client *stdp4028_i2c;
+       struct i2c_client *stdp2690_i2c;
+       struct edid *edid;
+};
+
+static struct ge_b850v3_lvds *ge_b850v3_lvds_ptr;
+
+static u8 *stdp2690_get_edid(struct i2c_client *client)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       unsigned char start = 0x00;
+       unsigned int total_size;
+       u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL);
+
+       struct i2c_msg msgs[] = {
+               {
+                       .addr   = client->addr,
+                       .flags  = 0,
+                       .len    = 1,
+                       .buf    = &start,
+               }, {
+                       .addr   = client->addr,
+                       .flags  = I2C_M_RD,
+                       .len    = EDID_LENGTH,
+                       .buf    = block,
+               }
+       };
+
+       if (!block)
+               return NULL;
+
+       if (i2c_transfer(adapter, msgs, 2) != 2) {
+               DRM_ERROR("Unable to read EDID.\n");
+               goto err;
+       }
+
+       if (!drm_edid_block_valid(block, 0, false, NULL)) {
+               DRM_ERROR("Invalid EDID data\n");
+               goto err;
+       }
+
+       total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH;
+       if (total_size > EDID_LENGTH) {
+               kfree(block);
+               block = kmalloc(total_size, GFP_KERNEL);
+               if (!block)
+                       return NULL;
+
+               /* Yes, read the entire buffer, and do not skip the first
+                * EDID_LENGTH bytes.
+                */
+               start = 0x00;
+               msgs[1].len = total_size;
+               msgs[1].buf = block;
+
+               if (i2c_transfer(adapter, msgs, 2) != 2) {
+                       DRM_ERROR("Unable to read EDID extension blocks.\n");
+                       goto err;
+               }
+               if (!drm_edid_block_valid(block, 1, false, NULL)) {
+                       DRM_ERROR("Invalid EDID data\n");
+                       goto err;
+               }
+       }
+
+       return block;
+
+err:
+       kfree(block);
+       return NULL;
+}
+
+static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
+{
+       struct i2c_client *client;
+       int num_modes = 0;
+
+       client = ge_b850v3_lvds_ptr->stdp2690_i2c;
+
+       kfree(ge_b850v3_lvds_ptr->edid);
+       ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client);
+
+       if (ge_b850v3_lvds_ptr->edid) {
+               drm_mode_connector_update_edid_property(connector,
+                                                     ge_b850v3_lvds_ptr->edid);
+               num_modes = drm_add_edid_modes(connector,
+                                              ge_b850v3_lvds_ptr->edid);
+       }
+
+       return num_modes;
+}
+
+static enum drm_mode_status ge_b850v3_lvds_mode_valid(
+               struct drm_connector *connector, struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+static const struct
+drm_connector_helper_funcs ge_b850v3_lvds_connector_helper_funcs = {
+       .get_modes = ge_b850v3_lvds_get_modes,
+       .mode_valid = ge_b850v3_lvds_mode_valid,
+};
+
+static enum drm_connector_status ge_b850v3_lvds_detect(
+               struct drm_connector *connector, bool force)
+{
+       struct i2c_client *stdp4028_i2c =
+                       ge_b850v3_lvds_ptr->stdp4028_i2c;
+       s32 link_state;
+
+       link_state = i2c_smbus_read_word_data(stdp4028_i2c,
+                                             STDP4028_DPTX_STS_REG);
+
+       if (link_state == STDP4028_CON_STATE_CONNECTED)
+               return connector_status_connected;
+
+       if (link_state == 0)
+               return connector_status_disconnected;
+
+       return connector_status_unknown;
+}
+
+static const struct drm_connector_funcs ge_b850v3_lvds_connector_funcs = {
+       .dpms = drm_atomic_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = ge_b850v3_lvds_detect,
+       .destroy = drm_connector_cleanup,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id)
+{
+       struct i2c_client *stdp4028_i2c
+                       = ge_b850v3_lvds_ptr->stdp4028_i2c;
+
+       i2c_smbus_write_word_data(stdp4028_i2c,
+                                 STDP4028_DPTX_IRQ_STS_REG,
+                                 STDP4028_DPTX_IRQ_CLEAR);
+
+       if (ge_b850v3_lvds_ptr->connector.dev)
+               drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->connector.dev);
+
+       return IRQ_HANDLED;
+}
+
+static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
+{
+       struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
+       struct i2c_client *stdp4028_i2c
+                       = ge_b850v3_lvds_ptr->stdp4028_i2c;
+       int ret;
+
+       if (!bridge->encoder) {
+               DRM_ERROR("Parent encoder object not found");
+               return -ENODEV;
+       }
+
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       drm_connector_helper_add(connector,
+                                &ge_b850v3_lvds_connector_helper_funcs);
+
+       ret = drm_connector_init(bridge->dev, connector,
+                                &ge_b850v3_lvds_connector_funcs,
+                                DRM_MODE_CONNECTOR_DisplayPort);
+       if (ret) {
+               DRM_ERROR("Failed to initialize connector with drm\n");
+               return ret;
+       }
+
+       ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
+       if (ret)
+               return ret;
+
+       /* Configures the bridge to re-enable interrupts after each ack. */
+       i2c_smbus_write_word_data(stdp4028_i2c,
+                                 STDP4028_IRQ_OUT_CONF_REG,
+                                 STDP4028_DPTX_DP_IRQ_EN);
+
+       /* Enable interrupts */
+       i2c_smbus_write_word_data(stdp4028_i2c,
+                                 STDP4028_DPTX_IRQ_EN_REG,
+                                 STDP4028_DPTX_IRQ_CONFIG);
+
+       return 0;
+}
+
+static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = {
+       .attach = ge_b850v3_lvds_attach,
+};
+
+static int ge_b850v3_lvds_init(struct device *dev)
+{
+       mutex_lock(&ge_b850v3_lvds_dev_mutex);
+
+       if (ge_b850v3_lvds_ptr)
+               goto success;
+
+       ge_b850v3_lvds_ptr = devm_kzalloc(dev,
+                                         sizeof(*ge_b850v3_lvds_ptr),
+                                         GFP_KERNEL);
+
+       if (!ge_b850v3_lvds_ptr) {
+               mutex_unlock(&ge_b850v3_lvds_dev_mutex);
+               return -ENOMEM;
+       }
+
+       ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
+       ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node;
+       drm_bridge_add(&ge_b850v3_lvds_ptr->bridge);
+
+success:
+       mutex_unlock(&ge_b850v3_lvds_dev_mutex);
+       return 0;
+}
+
+static void ge_b850v3_lvds_remove(void)
+{
+       mutex_lock(&ge_b850v3_lvds_dev_mutex);
+       /*
+        * This check is to avoid both the drivers
+        * removing the bridge in their remove() function
+        */
+       if (!ge_b850v3_lvds_ptr)
+               goto out;
+
+       drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge);
+
+       kfree(ge_b850v3_lvds_ptr->edid);
+
+       ge_b850v3_lvds_ptr = NULL;
+out:
+       mutex_unlock(&ge_b850v3_lvds_dev_mutex);
+}
+
+static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c,
+                                      const struct i2c_device_id *id)
+{
+       struct device *dev = &stdp4028_i2c->dev;
+
+       ge_b850v3_lvds_init(dev);
+
+       ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;
+       i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr);
+
+       /* Clear pending interrupts since power up. */
+       i2c_smbus_write_word_data(stdp4028_i2c,
+                                 STDP4028_DPTX_IRQ_STS_REG,
+                                 STDP4028_DPTX_IRQ_CLEAR);
+
+       if (!stdp4028_i2c->irq)
+               return 0;
+
+       return devm_request_threaded_irq(&stdp4028_i2c->dev,
+                       stdp4028_i2c->irq, NULL,
+                       ge_b850v3_lvds_irq_handler,
+                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                       "ge-b850v3-lvds-dp", ge_b850v3_lvds_ptr);
+}
+
+static int stdp4028_ge_b850v3_fw_remove(struct i2c_client *stdp4028_i2c)
+{
+       ge_b850v3_lvds_remove();
+
+       return 0;
+}
+
+static const struct i2c_device_id stdp4028_ge_b850v3_fw_i2c_table[] = {
+       {"stdp4028_ge_fw", 0},
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, stdp4028_ge_b850v3_fw_i2c_table);
+
+static const struct of_device_id stdp4028_ge_b850v3_fw_match[] = {
+       { .compatible = "megachips,stdp4028-ge-b850v3-fw" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, stdp4028_ge_b850v3_fw_match);
+
+static struct i2c_driver stdp4028_ge_b850v3_fw_driver = {
+       .id_table       = stdp4028_ge_b850v3_fw_i2c_table,
+       .probe          = stdp4028_ge_b850v3_fw_probe,
+       .remove         = stdp4028_ge_b850v3_fw_remove,
+       .driver         = {
+               .name           = "stdp4028-ge-b850v3-fw",
+               .of_match_table = stdp4028_ge_b850v3_fw_match,
+       },
+};
+
+static int stdp2690_ge_b850v3_fw_probe(struct i2c_client *stdp2690_i2c,
+                                      const struct i2c_device_id *id)
+{
+       struct device *dev = &stdp2690_i2c->dev;
+
+       ge_b850v3_lvds_init(dev);
+
+       ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c;
+       i2c_set_clientdata(stdp2690_i2c, ge_b850v3_lvds_ptr);
+
+       return 0;
+}
+
+static int stdp2690_ge_b850v3_fw_remove(struct i2c_client *stdp2690_i2c)
+{
+       ge_b850v3_lvds_remove();
+
+       return 0;
+}
+
+static const struct i2c_device_id stdp2690_ge_b850v3_fw_i2c_table[] = {
+       {"stdp2690_ge_fw", 0},
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, stdp2690_ge_b850v3_fw_i2c_table);
+
+static const struct of_device_id stdp2690_ge_b850v3_fw_match[] = {
+       { .compatible = "megachips,stdp2690-ge-b850v3-fw" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, stdp2690_ge_b850v3_fw_match);
+
+static struct i2c_driver stdp2690_ge_b850v3_fw_driver = {
+       .id_table       = stdp2690_ge_b850v3_fw_i2c_table,
+       .probe          = stdp2690_ge_b850v3_fw_probe,
+       .remove         = stdp2690_ge_b850v3_fw_remove,
+       .driver         = {
+               .name           = "stdp2690-ge-b850v3-fw",
+               .of_match_table = stdp2690_ge_b850v3_fw_match,
+       },
+};
+
+static int __init stdpxxxx_ge_b850v3_init(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&stdp4028_ge_b850v3_fw_driver);
+       if (ret)
+               return ret;
+
+       return i2c_add_driver(&stdp2690_ge_b850v3_fw_driver);
+}
+module_init(stdpxxxx_ge_b850v3_init);
+
+static void __exit stdpxxxx_ge_b850v3_exit(void)
+{
+       i2c_del_driver(&stdp2690_ge_b850v3_fw_driver);
+       i2c_del_driver(&stdp4028_ge_b850v3_fw_driver);
+}
+module_exit(stdpxxxx_ge_b850v3_exit);
+
+MODULE_AUTHOR("Peter Senna Tschudin <peter.senna@collabora.com>");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk>");
+MODULE_DESCRIPTION("GE LVDS to DP++ display bridge)");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
new file mode 100644 (file)
index 0000000..40d2827
--- /dev/null
@@ -0,0 +1,23 @@
+config DRM_DW_HDMI
+       tristate
+       select DRM_KMS_HELPER
+
+config DRM_DW_HDMI_AHB_AUDIO
+       tristate "Synopsys Designware AHB Audio interface"
+       depends on DRM_DW_HDMI && SND
+       select SND_PCM
+       select SND_PCM_ELD
+       select SND_PCM_IEC958
+       help
+         Support the AHB Audio interface which is part of the Synopsys
+         Designware HDMI block.  This is used in conjunction with
+         the i.MX6 HDMI driver.
+
+config DRM_DW_HDMI_I2S_AUDIO
+       tristate "Synopsys Designware I2S Audio interface"
+       depends on SND_SOC
+       depends on DRM_DW_HDMI
+       select SND_SOC_HDMI_CODEC
+       help
+         Support the I2S Audio interface which is part of the Synopsys
+         Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
new file mode 100644 (file)
index 0000000..17aa7a6
--- /dev/null
@@ -0,0 +1,5 @@
+#ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
new file mode 100644 (file)
index 0000000..8f2d137
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * 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 Designware HDMI Tx found in iMX6.
+ */
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_edid.h>
+
+#include <sound/asoundef.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
+#include <sound/pcm_iec958.h>
+
+#include "dw-hdmi-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-ahb-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_FC_AUDICONF2 = 0x1027,
+       HDMI_FC_AUDSCONF = 0x1063,
+       HDMI_FC_AUDSCONF_LAYOUT1 = 1 << 0,
+       HDMI_FC_AUDSCONF_LAYOUT0 = 0 << 0,
+       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_MASK = 0x3614,
+       HDMI_AHB_DMA_POL = 0x3615,
+       HDMI_AHB_DMA_CONF1 = 0x3616,
+       HDMI_AHB_DMA_BUFFPOL = 0x361a,
+};
+
+struct dw_hdmi_channel_conf {
+       u8 conf1;
+       u8 ca;
+};
+
+/*
+ * The default mapping of ALSA channels to HDMI channels and speaker
+ * allocation bits.  Note that we can't do channel remapping here -
+ * channels must be in the same order.
+ *
+ * Mappings for alsa-lib pcm/surround*.conf files:
+ *
+ *             Front   Sur4.0  Sur4.1  Sur5.0  Sur5.1  Sur7.1
+ * Channels    2       4       6       6       6       8
+ *
+ * Our mapping from ALSA channel to CEA686D speaker name and HDMI channel:
+ *
+ *                             Number of ALSA channels
+ * ALSA Channel        2       3       4       5       6       7       8
+ * 0           FL:0    =       =       =       =       =       =
+ * 1           FR:1    =       =       =       =       =       =
+ * 2                   FC:3    RL:4    LFE:2   =       =       =
+ * 3                           RR:5    RL:4    FC:3    =       =
+ * 4                                   RR:5    RL:4    =       =
+ * 5                                           RR:5    =       =
+ * 6                                                   RC:6    =
+ * 7                                                   RLC/FRC RLC/FRC
+ */
+static struct dw_hdmi_channel_conf default_hdmi_channel_config[7] = {
+       { 0x03, 0x00 }, /* FL,FR */
+       { 0x0b, 0x02 }, /* FL,FR,FC */
+       { 0x33, 0x08 }, /* FL,FR,RL,RR */
+       { 0x37, 0x09 }, /* FL,FR,LFE,RL,RR */
+       { 0x3f, 0x0b }, /* FL,FR,LFE,FC,RL,RR */
+       { 0x7f, 0x0f }, /* FL,FR,LFE,FC,RL,RR,RC */
+       { 0xff, 0x13 }, /* FL,FR,LFE,FC,RL,RR,[FR]RC,[FR]LC */
+};
+
+struct snd_dw_hdmi {
+       struct snd_card *card;
+       struct snd_pcm *pcm;
+       spinlock_t lock;
+       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;
+       u8 revision;
+       u8 iec_offset;
+       u8 cs[192][8];
+};
+
+static void dw_hdmi_writel(u32 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)
+{
+       u32 *src = dw->buf_src + offset;
+       u32 *dst = dw->buf_dst + offset;
+       u32 *end = dw->buf_src + offset + bytes;
+
+       do {
+               u32 b, sample = *src++;
+
+               b = (sample & 8) << (28 - 3);
+
+               sample >>= 4;
+
+               *dst++ = sample | b;
+       } while (src < end);
+}
+
+static u32 parity(u32 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)
+{
+       u32 *src = dw->buf_src + offset;
+       u32 *dst = dw->buf_dst + offset;
+       u32 *end = dw->buf_src + offset + bytes;
+
+       do {
+               unsigned i;
+               u8 *cs;
+
+               cs = dw->cs[dw->iec_offset++];
+               if (dw->iec_offset >= 192)
+                       dw->iec_offset = 0;
+
+               i = dw->channels;
+               do {
+                       u32 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)
+{
+       u8 cs[4];
+       unsigned ch, i, j;
+
+       snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs));
+
+       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)
+{
+       /* 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);
+}
+
+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);
+
+               spin_lock(&dw->lock);
+               if (dw->substream)
+                       dw_hdmi_start_dma(dw);
+               spin_unlock(&dw->lock);
+       }
+
+       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 = 1024 * 1024,
+       .period_bytes_min = 256,
+       .period_bytes_max = 8192,       /* ERR004323: must limit to 8k */
+       .periods_min = 2,
+       .periods_max = 16,
+       .fifo_size = 0,
+};
+
+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;
+
+       runtime->hw = dw_hdmi_hw;
+
+       ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_pcm_limit_hw_rates(runtime);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               return ret;
+
+       /* Limit the buffer size to the size of the preallocated buffer */
+       ret = snd_pcm_hw_constraint_minmax(runtime,
+                                          SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+                                          0, substream->dma_buffer.bytes);
+       if (ret < 0)
+               return 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);
+
+       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)
+{
+       /* Allocate the PCM runtime buffer, which is exposed to userspace. */
+       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;
+       u8 threshold, conf0, conf1, layout, ca;
+
+       /* 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_hdmi_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 = default_hdmi_channel_config[runtime->channels - 2].conf1;
+       ca = default_hdmi_channel_config[runtime->channels - 2].ca;
+
+       /*
+        * For >2 channel PCM audio, we need to select layout 1
+        * and set an appropriate channel map.
+        */
+       if (runtime->channels > 2)
+               layout = HDMI_FC_AUDSCONF_LAYOUT1;
+       else
+               layout = HDMI_FC_AUDSCONF_LAYOUT0;
+
+       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);
+       writeb_relaxed(layout, dw->data.base + HDMI_FC_AUDSCONF);
+       writeb_relaxed(ca, dw->data.base + HDMI_FC_AUDICONF2);
+
+       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;
+       unsigned long flags;
+       int ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               spin_lock_irqsave(&dw->lock, flags);
+               dw->buf_offset = 0;
+               dw->substream = substream;
+               dw_hdmi_start_dma(dw);
+               dw_hdmi_audio_enable(dw->data.hdmi);
+               spin_unlock_irqrestore(&dw->lock, flags);
+               substream->runtime->delay = substream->runtime->period_size;
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+               spin_lock_irqsave(&dw->lock, flags);
+               dw->substream = NULL;
+               dw_hdmi_stop_dma(dw);
+               dw_hdmi_audio_disable(dw->data.hdmi);
+               spin_unlock_irqrestore(&dw->lock, flags);
+               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;
+
+       /*
+        * We are unable to report the exact hardware position as
+        * reading the 32-bit DMA position using 8-bit reads is racy.
+        */
+       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;
+
+       spin_lock_init(&dw->lock);
+
+       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);
+
+       /*
+        * To support 8-channel 96kHz audio reliably, we need 512k
+        * to satisfy alsa with our restricted period (ERR004323).
+        */
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                       dev, 128 * 1024, 1024 * 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;
+}
+
+#if defined(CONFIG_PM_SLEEP) && defined(IS_NOT_BROKEN)
+/*
+ * This code is fine, but requires implementation in the dw_hdmi_trigger()
+ * method which is currently missing as I have no way to test this.
+ */
+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 = DRIVER_NAME,
+               .pm = PM_OPS,
+       },
+};
+
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Synopsis Designware HDMI AHB ALSA interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
new file mode 100644 (file)
index 0000000..fd1f745
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef DW_HDMI_AUDIO_H
+#define DW_HDMI_AUDIO_H
+
+struct dw_hdmi;
+
+struct dw_hdmi_audio_data {
+       phys_addr_t phys;
+       void __iomem *base;
+       int irq;
+       struct dw_hdmi *hdmi;
+       u8 *eld;
+};
+
+struct dw_hdmi_i2s_audio_data {
+       struct dw_hdmi *hdmi;
+
+       void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
+       u8 (*read)(struct dw_hdmi *hdmi, int offset);
+};
+
+#endif
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
new file mode 100644 (file)
index 0000000..aaf287d
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * dw-hdmi-i2s-audio.c
+ *
+ * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * 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 <drm/bridge/dw_hdmi.h>
+
+#include <sound/hdmi-codec.h>
+
+#include "dw-hdmi.h"
+#include "dw-hdmi-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-i2s-audio"
+
+static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio,
+                             u8 val, int offset)
+{
+       struct dw_hdmi *hdmi = audio->hdmi;
+
+       audio->write(hdmi, val, offset);
+}
+
+static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
+{
+       struct dw_hdmi *hdmi = audio->hdmi;
+
+       return audio->read(hdmi, offset);
+}
+
+static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
+                                struct hdmi_codec_daifmt *fmt,
+                                struct hdmi_codec_params *hparms)
+{
+       struct dw_hdmi_i2s_audio_data *audio = data;
+       struct dw_hdmi *hdmi = audio->hdmi;
+       u8 conf0 = 0;
+       u8 conf1 = 0;
+       u8 inputclkfs = 0;
+
+       /* it cares I2S only */
+       if ((fmt->fmt != HDMI_I2S) ||
+           (fmt->bit_clk_master | fmt->frame_clk_master)) {
+               dev_err(dev, "unsupported format/settings\n");
+               return -EINVAL;
+       }
+
+       inputclkfs      = HDMI_AUD_INPUTCLKFS_64FS;
+       conf0           = HDMI_AUD_CONF0_I2S_ALL_ENABLE;
+
+       switch (hparms->sample_width) {
+       case 16:
+               conf1 = HDMI_AUD_CONF1_WIDTH_16;
+               break;
+       case 24:
+       case 32:
+               conf1 = HDMI_AUD_CONF1_WIDTH_24;
+               break;
+       }
+
+       dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
+
+       hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
+       hdmi_write(audio, conf0, HDMI_AUD_CONF0);
+       hdmi_write(audio, conf1, HDMI_AUD_CONF1);
+
+       dw_hdmi_audio_enable(hdmi);
+
+       return 0;
+}
+
+static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
+{
+       struct dw_hdmi_i2s_audio_data *audio = data;
+       struct dw_hdmi *hdmi = audio->hdmi;
+
+       dw_hdmi_audio_disable(hdmi);
+
+       hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
+}
+
+static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
+       .hw_params      = dw_hdmi_i2s_hw_params,
+       .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
+};
+
+static int snd_dw_hdmi_probe(struct platform_device *pdev)
+{
+       struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data;
+       struct platform_device_info pdevinfo;
+       struct hdmi_codec_pdata pdata;
+       struct platform_device *platform;
+
+       pdata.ops               = &dw_hdmi_i2s_ops;
+       pdata.i2s               = 1;
+       pdata.max_i2s_channels  = 6;
+       pdata.data              = audio;
+
+       memset(&pdevinfo, 0, sizeof(pdevinfo));
+       pdevinfo.parent         = pdev->dev.parent;
+       pdevinfo.id             = PLATFORM_DEVID_AUTO;
+       pdevinfo.name           = HDMI_CODEC_DRV_NAME;
+       pdevinfo.data           = &pdata;
+       pdevinfo.size_data      = sizeof(pdata);
+       pdevinfo.dma_mask       = DMA_BIT_MASK(32);
+
+       platform = platform_device_register_full(&pdevinfo);
+       if (IS_ERR(platform))
+               return PTR_ERR(platform);
+
+       dev_set_drvdata(&pdev->dev, platform);
+
+       return 0;
+}
+
+static int snd_dw_hdmi_remove(struct platform_device *pdev)
+{
+       struct platform_device *platform = dev_get_drvdata(&pdev->dev);
+
+       platform_device_unregister(platform);
+
+       return 0;
+}
+
+static struct platform_driver snd_dw_hdmi_driver = {
+       .probe  = snd_dw_hdmi_probe,
+       .remove = snd_dw_hdmi_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+       },
+};
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
new file mode 100644 (file)
index 0000000..026a0dc
--- /dev/null
@@ -0,0 +1,2314 @@
+/*
+ * DesignWare High-Definition Multimedia Interface (HDMI) driver
+ *
+ * Copyright (C) 2013-2015 Mentor Graphics Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/hdmi.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include "dw-hdmi.h"
+#include "dw-hdmi-audio.h"
+
+#define HDMI_EDID_LEN          512
+
+#define RGB                    0
+#define YCBCR444               1
+#define YCBCR422_16BITS                2
+#define YCBCR422_8BITS         3
+#define XVYCC444               4
+
+enum hdmi_datamap {
+       RGB444_8B = 0x01,
+       RGB444_10B = 0x03,
+       RGB444_12B = 0x05,
+       RGB444_16B = 0x07,
+       YCbCr444_8B = 0x09,
+       YCbCr444_10B = 0x0B,
+       YCbCr444_12B = 0x0D,
+       YCbCr444_16B = 0x0F,
+       YCbCr422_8B = 0x16,
+       YCbCr422_10B = 0x14,
+       YCbCr422_12B = 0x12,
+};
+
+static const u16 csc_coeff_default[3][4] = {
+       { 0x2000, 0x0000, 0x0000, 0x0000 },
+       { 0x0000, 0x2000, 0x0000, 0x0000 },
+       { 0x0000, 0x0000, 0x2000, 0x0000 }
+};
+
+static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
+       { 0x2000, 0x6926, 0x74fd, 0x010e },
+       { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
+       { 0x2000, 0x0000, 0x38b4, 0x7e3b }
+};
+
+static const u16 csc_coeff_rgb_out_eitu709[3][4] = {
+       { 0x2000, 0x7106, 0x7a02, 0x00a7 },
+       { 0x2000, 0x3264, 0x0000, 0x7e6d },
+       { 0x2000, 0x0000, 0x3b61, 0x7e25 }
+};
+
+static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
+       { 0x2591, 0x1322, 0x074b, 0x0000 },
+       { 0x6535, 0x2000, 0x7acc, 0x0200 },
+       { 0x6acd, 0x7534, 0x2000, 0x0200 }
+};
+
+static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
+       { 0x2dc5, 0x0d9b, 0x049e, 0x0000 },
+       { 0x62f0, 0x2000, 0x7d11, 0x0200 },
+       { 0x6756, 0x78ab, 0x2000, 0x0200 }
+};
+
+struct hdmi_vmode {
+       bool mdataenablepolarity;
+
+       unsigned int mpixelclock;
+       unsigned int mpixelrepetitioninput;
+       unsigned int mpixelrepetitionoutput;
+};
+
+struct hdmi_data_info {
+       unsigned int enc_in_format;
+       unsigned int enc_out_format;
+       unsigned int enc_color_depth;
+       unsigned int colorimetry;
+       unsigned int pix_repet_factor;
+       unsigned int hdcp_enable;
+       struct hdmi_vmode video_mode;
+};
+
+struct dw_hdmi_i2c {
+       struct i2c_adapter      adap;
+
+       struct mutex            lock;   /* used to serialize data transfers */
+       struct completion       cmp;
+       u8                      stat;
+
+       u8                      slave_reg;
+       bool                    is_regaddr;
+};
+
+struct dw_hdmi_phy_data {
+       enum dw_hdmi_phy_type type;
+       const char *name;
+       unsigned int gen;
+       bool has_svsret;
+       int (*configure)(struct dw_hdmi *hdmi,
+                        const struct dw_hdmi_plat_data *pdata,
+                        unsigned long mpixelclock);
+};
+
+struct dw_hdmi {
+       struct drm_connector connector;
+       struct drm_bridge bridge;
+
+       unsigned int version;
+
+       struct platform_device *audio;
+       struct device *dev;
+       struct clk *isfr_clk;
+       struct clk *iahb_clk;
+       struct dw_hdmi_i2c *i2c;
+
+       struct hdmi_data_info hdmi_data;
+       const struct dw_hdmi_plat_data *plat_data;
+
+       int vic;
+
+       u8 edid[HDMI_EDID_LEN];
+       bool cable_plugin;
+
+       struct {
+               const struct dw_hdmi_phy_ops *ops;
+               const char *name;
+               void *data;
+               bool enabled;
+       } phy;
+
+       struct drm_display_mode previous_mode;
+
+       struct i2c_adapter *ddc;
+       void __iomem *regs;
+       bool sink_is_hdmi;
+       bool sink_has_audio;
+
+       struct mutex mutex;             /* for state below and previous_mode */
+       enum drm_connector_force force; /* mutex-protected force state */
+       bool disabled;                  /* DRM has disabled our bridge */
+       bool bridge_is_on;              /* indicates the bridge is on */
+       bool rxsense;                   /* rxsense state */
+       u8 phy_mask;                    /* desired phy int mask settings */
+
+       spinlock_t audio_lock;
+       struct mutex audio_mutex;
+       unsigned int sample_rate;
+       unsigned int audio_cts;
+       unsigned int audio_n;
+       bool audio_enable;
+
+       unsigned int reg_shift;
+       struct regmap *regm;
+};
+
+#define HDMI_IH_PHY_STAT0_RX_SENSE \
+       (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \
+        HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3)
+
+#define HDMI_PHY_RX_SENSE \
+       (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
+        HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
+
+static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
+{
+       regmap_write(hdmi->regm, offset << hdmi->reg_shift, val);
+}
+
+static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
+{
+       unsigned int val = 0;
+
+       regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val);
+
+       return val;
+}
+
+static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+{
+       regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
+}
+
+static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
+                            u8 shift, u8 mask)
+{
+       hdmi_modb(hdmi, data << shift, mask, reg);
+}
+
+static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi)
+{
+       /* Software reset */
+       hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ);
+
+       /* Set Standard Mode speed (determined to be 100KHz on iMX6) */
+       hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV);
+
+       /* Set done, not acknowledged and arbitration interrupt polarities */
+       hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT);
+       hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL,
+                   HDMI_I2CM_CTLINT);
+
+       /* Clear DONE and ERROR interrupts */
+       hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+                   HDMI_IH_I2CM_STAT0);
+
+       /* Mute DONE and ERROR interrupts */
+       hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+                   HDMI_IH_MUTE_I2CM_STAT0);
+}
+
+static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
+                           unsigned char *buf, unsigned int length)
+{
+       struct dw_hdmi_i2c *i2c = hdmi->i2c;
+       int stat;
+
+       if (!i2c->is_regaddr) {
+               dev_dbg(hdmi->dev, "set read register address to 0\n");
+               i2c->slave_reg = 0x00;
+               i2c->is_regaddr = true;
+       }
+
+       while (length--) {
+               reinit_completion(&i2c->cmp);
+
+               hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
+               hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
+                           HDMI_I2CM_OPERATION);
+
+               stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
+               if (!stat)
+                       return -EAGAIN;
+
+               /* Check for error condition on the bus */
+               if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
+                       return -EIO;
+
+               *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
+       }
+
+       return 0;
+}
+
+static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi,
+                            unsigned char *buf, unsigned int length)
+{
+       struct dw_hdmi_i2c *i2c = hdmi->i2c;
+       int stat;
+
+       if (!i2c->is_regaddr) {
+               /* Use the first write byte as register address */
+               i2c->slave_reg = buf[0];
+               length--;
+               buf++;
+               i2c->is_regaddr = true;
+       }
+
+       while (length--) {
+               reinit_completion(&i2c->cmp);
+
+               hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO);
+               hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
+               hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE,
+                           HDMI_I2CM_OPERATION);
+
+               stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
+               if (!stat)
+                       return -EAGAIN;
+
+               /* Check for error condition on the bus */
+               if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
+                       return -EIO;
+       }
+
+       return 0;
+}
+
+static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
+                           struct i2c_msg *msgs, int num)
+{
+       struct dw_hdmi *hdmi = i2c_get_adapdata(adap);
+       struct dw_hdmi_i2c *i2c = hdmi->i2c;
+       u8 addr = msgs[0].addr;
+       int i, ret = 0;
+
+       dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
+
+       for (i = 0; i < num; i++) {
+               if (msgs[i].addr != addr) {
+                       dev_warn(hdmi->dev,
+                                "unsupported transfer, changed slave address\n");
+                       return -EOPNOTSUPP;
+               }
+
+               if (msgs[i].len == 0) {
+                       dev_dbg(hdmi->dev,
+                               "unsupported transfer %d/%d, no data\n",
+                               i + 1, num);
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       mutex_lock(&i2c->lock);
+
+       /* Unmute DONE and ERROR interrupts */
+       hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0);
+
+       /* Set slave device address taken from the first I2C message */
+       hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE);
+
+       /* Set slave device register address on transfer */
+       i2c->is_regaddr = false;
+
+       for (i = 0; i < num; i++) {
+               dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
+                       i + 1, num, msgs[i].len, msgs[i].flags);
+
+               if (msgs[i].flags & I2C_M_RD)
+                       ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
+               else
+                       ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
+
+               if (ret < 0)
+                       break;
+       }
+
+       if (!ret)
+               ret = num;
+
+       /* Mute DONE and ERROR interrupts */
+       hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+                   HDMI_IH_MUTE_I2CM_STAT0);
+
+       mutex_unlock(&i2c->lock);
+
+       return ret;
+}
+
+static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm dw_hdmi_algorithm = {
+       .master_xfer    = dw_hdmi_i2c_xfer,
+       .functionality  = dw_hdmi_i2c_func,
+};
+
+static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
+{
+       struct i2c_adapter *adap;
+       struct dw_hdmi_i2c *i2c;
+       int ret;
+
+       i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_init(&i2c->lock);
+       init_completion(&i2c->cmp);
+
+       adap = &i2c->adap;
+       adap->class = I2C_CLASS_DDC;
+       adap->owner = THIS_MODULE;
+       adap->dev.parent = hdmi->dev;
+       adap->algo = &dw_hdmi_algorithm;
+       strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
+       i2c_set_adapdata(adap, hdmi);
+
+       ret = i2c_add_adapter(adap);
+       if (ret) {
+               dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
+               devm_kfree(hdmi->dev, i2c);
+               return ERR_PTR(ret);
+       }
+
+       hdmi->i2c = i2c;
+
+       dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
+
+       return adap;
+}
+
+static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
+                          unsigned int n)
+{
+       /* Must be set/cleared first */
+       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+
+       /* nshift factor = 0 */
+       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
+
+       hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+                   HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+       hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
+       hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+
+       hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
+       hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
+       hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
+}
+
+static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
+{
+       unsigned int n = (128 * freq) / 1000;
+       unsigned int mult = 1;
+
+       while (freq > 48000) {
+               mult *= 2;
+               freq /= 2;
+       }
+
+       switch (freq) {
+       case 32000:
+               if (pixel_clk == 25175000)
+                       n = 4576;
+               else if (pixel_clk == 27027000)
+                       n = 4096;
+               else if (pixel_clk == 74176000 || pixel_clk == 148352000)
+                       n = 11648;
+               else
+                       n = 4096;
+               n *= mult;
+               break;
+
+       case 44100:
+               if (pixel_clk == 25175000)
+                       n = 7007;
+               else if (pixel_clk == 74176000)
+                       n = 17836;
+               else if (pixel_clk == 148352000)
+                       n = 8918;
+               else
+                       n = 6272;
+               n *= mult;
+               break;
+
+       case 48000:
+               if (pixel_clk == 25175000)
+                       n = 6864;
+               else if (pixel_clk == 27027000)
+                       n = 6144;
+               else if (pixel_clk == 74176000)
+                       n = 11648;
+               else if (pixel_clk == 148352000)
+                       n = 5824;
+               else
+                       n = 6144;
+               n *= mult;
+               break;
+
+       default:
+               break;
+       }
+
+       return n;
+}
+
+static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
+       unsigned long pixel_clk, unsigned int sample_rate)
+{
+       unsigned long ftdms = pixel_clk;
+       unsigned int n, cts;
+       u64 tmp;
+
+       n = hdmi_compute_n(sample_rate, pixel_clk);
+
+       /*
+        * Compute the CTS value from the N value.  Note that CTS and N
+        * can be up to 20 bits in total, so we need 64-bit math.  Also
+        * note that our TDMS clock is not fully accurate; it is accurate
+        * to kHz.  This can introduce an unnecessary remainder in the
+        * calculation below, so we don't try to warn about that.
+        */
+       tmp = (u64)ftdms * n;
+       do_div(tmp, 128 * sample_rate);
+       cts = tmp;
+
+       dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
+               __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
+               n, cts);
+
+       spin_lock_irq(&hdmi->audio_lock);
+       hdmi->audio_n = n;
+       hdmi->audio_cts = cts;
+       hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
+       spin_unlock_irq(&hdmi->audio_lock);
+}
+
+static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
+{
+       mutex_lock(&hdmi->audio_mutex);
+       hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate);
+       mutex_unlock(&hdmi->audio_mutex);
+}
+
+static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
+{
+       mutex_lock(&hdmi->audio_mutex);
+       hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+                                hdmi->sample_rate);
+       mutex_unlock(&hdmi->audio_mutex);
+}
+
+void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
+{
+       mutex_lock(&hdmi->audio_mutex);
+       hdmi->sample_rate = rate;
+       hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+                                hdmi->sample_rate);
+       mutex_unlock(&hdmi->audio_mutex);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
+
+void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hdmi->audio_lock, flags);
+       hdmi->audio_enable = true;
+       hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
+       spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
+
+void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hdmi->audio_lock, flags);
+       hdmi->audio_enable = false;
+       hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
+       spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
+
+/*
+ * this submodule is responsible for the video data synchronization.
+ * for example, for RGB 4:4:4 input, the data map is defined as
+ *                     pin{47~40} <==> R[7:0]
+ *                     pin{31~24} <==> G[7:0]
+ *                     pin{15~8}  <==> B[7:0]
+ */
+static void hdmi_video_sample(struct dw_hdmi *hdmi)
+{
+       int color_format = 0;
+       u8 val;
+
+       if (hdmi->hdmi_data.enc_in_format == RGB) {
+               if (hdmi->hdmi_data.enc_color_depth == 8)
+                       color_format = 0x01;
+               else if (hdmi->hdmi_data.enc_color_depth == 10)
+                       color_format = 0x03;
+               else if (hdmi->hdmi_data.enc_color_depth == 12)
+                       color_format = 0x05;
+               else if (hdmi->hdmi_data.enc_color_depth == 16)
+                       color_format = 0x07;
+               else
+                       return;
+       } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
+               if (hdmi->hdmi_data.enc_color_depth == 8)
+                       color_format = 0x09;
+               else if (hdmi->hdmi_data.enc_color_depth == 10)
+                       color_format = 0x0B;
+               else if (hdmi->hdmi_data.enc_color_depth == 12)
+                       color_format = 0x0D;
+               else if (hdmi->hdmi_data.enc_color_depth == 16)
+                       color_format = 0x0F;
+               else
+                       return;
+       } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
+               if (hdmi->hdmi_data.enc_color_depth == 8)
+                       color_format = 0x16;
+               else if (hdmi->hdmi_data.enc_color_depth == 10)
+                       color_format = 0x14;
+               else if (hdmi->hdmi_data.enc_color_depth == 12)
+                       color_format = 0x12;
+               else
+                       return;
+       }
+
+       val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
+               ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
+               HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
+       hdmi_writeb(hdmi, val, HDMI_TX_INVID0);
+
+       /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
+       val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
+               HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
+               HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
+       hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING);
+       hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0);
+       hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1);
+       hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0);
+       hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1);
+       hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0);
+       hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
+}
+
+static int is_color_space_conversion(struct dw_hdmi *hdmi)
+{
+       return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
+}
+
+static int is_color_space_decimation(struct dw_hdmi *hdmi)
+{
+       if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
+               return 0;
+       if (hdmi->hdmi_data.enc_in_format == RGB ||
+           hdmi->hdmi_data.enc_in_format == YCBCR444)
+               return 1;
+       return 0;
+}
+
+static int is_color_space_interpolation(struct dw_hdmi *hdmi)
+{
+       if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
+               return 0;
+       if (hdmi->hdmi_data.enc_out_format == RGB ||
+           hdmi->hdmi_data.enc_out_format == YCBCR444)
+               return 1;
+       return 0;
+}
+
+static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
+{
+       const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
+       unsigned i;
+       u32 csc_scale = 1;
+
+       if (is_color_space_conversion(hdmi)) {
+               if (hdmi->hdmi_data.enc_out_format == RGB) {
+                       if (hdmi->hdmi_data.colorimetry ==
+                                       HDMI_COLORIMETRY_ITU_601)
+                               csc_coeff = &csc_coeff_rgb_out_eitu601;
+                       else
+                               csc_coeff = &csc_coeff_rgb_out_eitu709;
+               } else if (hdmi->hdmi_data.enc_in_format == RGB) {
+                       if (hdmi->hdmi_data.colorimetry ==
+                                       HDMI_COLORIMETRY_ITU_601)
+                               csc_coeff = &csc_coeff_rgb_in_eitu601;
+                       else
+                               csc_coeff = &csc_coeff_rgb_in_eitu709;
+                       csc_scale = 0;
+               }
+       }
+
+       /* The CSC registers are sequential, alternating MSB then LSB */
+       for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
+               u16 coeff_a = (*csc_coeff)[0][i];
+               u16 coeff_b = (*csc_coeff)[1][i];
+               u16 coeff_c = (*csc_coeff)[2][i];
+
+               hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
+               hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
+               hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
+               hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
+               hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
+               hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
+       }
+
+       hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+                 HDMI_CSC_SCALE);
+}
+
+static void hdmi_video_csc(struct dw_hdmi *hdmi)
+{
+       int color_depth = 0;
+       int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
+       int decimation = 0;
+
+       /* YCC422 interpolation to 444 mode */
+       if (is_color_space_interpolation(hdmi))
+               interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
+       else if (is_color_space_decimation(hdmi))
+               decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
+
+       if (hdmi->hdmi_data.enc_color_depth == 8)
+               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
+       else if (hdmi->hdmi_data.enc_color_depth == 10)
+               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
+       else if (hdmi->hdmi_data.enc_color_depth == 12)
+               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
+       else if (hdmi->hdmi_data.enc_color_depth == 16)
+               color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
+       else
+               return;
+
+       /* Configure the CSC registers */
+       hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
+       hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
+                 HDMI_CSC_SCALE);
+
+       dw_hdmi_update_csc_coeffs(hdmi);
+}
+
+/*
+ * HDMI video packetizer is used to packetize the data.
+ * for example, if input is YCC422 mode or repeater is used,
+ * data should be repacked this module can be bypassed.
+ */
+static void hdmi_video_packetize(struct dw_hdmi *hdmi)
+{
+       unsigned int color_depth = 0;
+       unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
+       unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
+       struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
+       u8 val, vp_conf;
+
+       if (hdmi_data->enc_out_format == RGB ||
+           hdmi_data->enc_out_format == YCBCR444) {
+               if (!hdmi_data->enc_color_depth) {
+                       output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+               } else if (hdmi_data->enc_color_depth == 8) {
+                       color_depth = 4;
+                       output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+               } else if (hdmi_data->enc_color_depth == 10) {
+                       color_depth = 5;
+               } else if (hdmi_data->enc_color_depth == 12) {
+                       color_depth = 6;
+               } else if (hdmi_data->enc_color_depth == 16) {
+                       color_depth = 7;
+               } else {
+                       return;
+               }
+       } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
+               if (!hdmi_data->enc_color_depth ||
+                   hdmi_data->enc_color_depth == 8)
+                       remap_size = HDMI_VP_REMAP_YCC422_16bit;
+               else if (hdmi_data->enc_color_depth == 10)
+                       remap_size = HDMI_VP_REMAP_YCC422_20bit;
+               else if (hdmi_data->enc_color_depth == 12)
+                       remap_size = HDMI_VP_REMAP_YCC422_24bit;
+               else
+                       return;
+               output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
+       } else {
+               return;
+       }
+
+       /* set the packetizer registers */
+       val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
+               HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
+               ((hdmi_data->pix_repet_factor <<
+               HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
+               HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
+       hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
+
+       hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
+                 HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
+
+       /* Data from pixel repeater block */
+       if (hdmi_data->pix_repet_factor > 1) {
+               vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
+                         HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
+       } else { /* data from packetizer block */
+               vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+                         HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
+       }
+
+       hdmi_modb(hdmi, vp_conf,
+                 HDMI_VP_CONF_PR_EN_MASK |
+                 HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
+
+       hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
+                 HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
+
+       hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
+
+       if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
+               vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+                         HDMI_VP_CONF_PP_EN_ENABLE |
+                         HDMI_VP_CONF_YCC422_EN_DISABLE;
+       } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
+               vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+                         HDMI_VP_CONF_PP_EN_DISABLE |
+                         HDMI_VP_CONF_YCC422_EN_ENABLE;
+       } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
+               vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+                         HDMI_VP_CONF_PP_EN_DISABLE |
+                         HDMI_VP_CONF_YCC422_EN_DISABLE;
+       } else {
+               return;
+       }
+
+       hdmi_modb(hdmi, vp_conf,
+                 HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
+                 HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
+
+       hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+                       HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
+                 HDMI_VP_STUFF_PP_STUFFING_MASK |
+                 HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
+
+       hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+                 HDMI_VP_CONF);
+}
+
+/* -----------------------------------------------------------------------------
+ * Synopsys PHY Handling
+ */
+
+static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
+                                      unsigned char bit)
+{
+       hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
+                 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
+}
+
+static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
+{
+       u32 val;
+
+       while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
+               if (msec-- == 0)
+                       return false;
+               udelay(1000);
+       }
+       hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
+
+       return true;
+}
+
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
+                          unsigned char addr)
+{
+       hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
+       hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+       hdmi_writeb(hdmi, (unsigned char)(data >> 8),
+                   HDMI_PHY_I2CM_DATAO_1_ADDR);
+       hdmi_writeb(hdmi, (unsigned char)(data >> 0),
+                   HDMI_PHY_I2CM_DATAO_0_ADDR);
+       hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
+                   HDMI_PHY_I2CM_OPERATION_ADDR);
+       hdmi_phy_wait_i2c_done(hdmi, 1000);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
+
+static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
+{
+       hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_PDZ_OFFSET,
+                        HDMI_PHY_CONF0_PDZ_MASK);
+}
+
+static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
+{
+       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_ENTMDS_OFFSET,
+                        HDMI_PHY_CONF0_ENTMDS_MASK);
+}
+
+static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable)
+{
+       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_SVSRET_OFFSET,
+                        HDMI_PHY_CONF0_SVSRET_MASK);
+}
+
+static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
+{
+       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
+                        HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
+}
+
+static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable)
+{
+       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
+                        HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
+}
+
+static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable)
+{
+       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
+                        HDMI_PHY_CONF0_SELDATAENPOL_MASK);
+}
+
+static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
+{
+       hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+                        HDMI_PHY_CONF0_SELDIPIF_OFFSET,
+                        HDMI_PHY_CONF0_SELDIPIF_MASK);
+}
+
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
+{
+       const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+       unsigned int i;
+       u16 val;
+
+       if (phy->gen == 1) {
+               dw_hdmi_phy_enable_tmds(hdmi, 0);
+               dw_hdmi_phy_enable_powerdown(hdmi, true);
+               return;
+       }
+
+       dw_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+       /*
+        * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
+        * to low power mode.
+        */
+       for (i = 0; i < 5; ++i) {
+               val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+               if (!(val & HDMI_PHY_TX_PHY_LOCK))
+                       break;
+
+               usleep_range(1000, 2000);
+       }
+
+       if (val & HDMI_PHY_TX_PHY_LOCK)
+               dev_warn(hdmi->dev, "PHY failed to power down\n");
+       else
+               dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
+
+       dw_hdmi_phy_gen2_pddq(hdmi, 1);
+}
+
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
+{
+       const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+       unsigned int i;
+       u8 val;
+
+       if (phy->gen == 1) {
+               dw_hdmi_phy_enable_powerdown(hdmi, false);
+
+               /* Toggle TMDS enable. */
+               dw_hdmi_phy_enable_tmds(hdmi, 0);
+               dw_hdmi_phy_enable_tmds(hdmi, 1);
+               return 0;
+       }
+
+       dw_hdmi_phy_gen2_txpwron(hdmi, 1);
+       dw_hdmi_phy_gen2_pddq(hdmi, 0);
+
+       /* Wait for PHY PLL lock */
+       for (i = 0; i < 5; ++i) {
+               val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+               if (val)
+                       break;
+
+               usleep_range(1000, 2000);
+       }
+
+       if (!val) {
+               dev_err(hdmi->dev, "PHY PLL failed to lock\n");
+               return -ETIMEDOUT;
+       }
+
+       dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
+       return 0;
+}
+
+/*
+ * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available
+ * information the DWC MHL PHY has the same register layout and is thus also
+ * supported by this function.
+ */
+static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
+               const struct dw_hdmi_plat_data *pdata,
+               unsigned long mpixelclock)
+{
+       const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
+       const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
+       const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
+
+       /* PLL/MPLL Cfg - always match on final entry */
+       for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
+               if (mpixelclock <= mpll_config->mpixelclock)
+                       break;
+
+       for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
+               if (mpixelclock <= curr_ctrl->mpixelclock)
+                       break;
+
+       for (; phy_config->mpixelclock != ~0UL; phy_config++)
+               if (mpixelclock <= phy_config->mpixelclock)
+                       break;
+
+       if (mpll_config->mpixelclock == ~0UL ||
+           curr_ctrl->mpixelclock == ~0UL ||
+           phy_config->mpixelclock == ~0UL)
+               return -EINVAL;
+
+       dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
+                             HDMI_3D_TX_PHY_CPCE_CTRL);
+       dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
+                             HDMI_3D_TX_PHY_GMPCTRL);
+       dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
+                             HDMI_3D_TX_PHY_CURRCTRL);
+
+       dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
+       dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
+                             HDMI_3D_TX_PHY_MSM_CTRL);
+
+       dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
+       dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
+                             HDMI_3D_TX_PHY_CKSYMTXCTRL);
+       dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
+                             HDMI_3D_TX_PHY_VLEVCTRL);
+
+       /* Override and disable clock termination. */
+       dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
+                             HDMI_3D_TX_PHY_CKCALCTRL);
+
+       return 0;
+}
+
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
+{
+       const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+       const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
+       unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
+       int ret;
+
+       dw_hdmi_phy_power_off(hdmi);
+
+       /* Leave low power consumption mode by asserting SVSRET. */
+       if (phy->has_svsret)
+               dw_hdmi_phy_enable_svsret(hdmi, 1);
+
+       /* PHY reset. The reset signal is active high on Gen2 PHYs. */
+       hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
+       hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
+
+       hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
+
+       hdmi_phy_test_clear(hdmi, 1);
+       hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
+                   HDMI_PHY_I2CM_SLAVE_ADDR);
+       hdmi_phy_test_clear(hdmi, 0);
+
+       /* Write to the PHY as configured by the platform */
+       if (pdata->configure_phy)
+               ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
+       else
+               ret = phy->configure(hdmi, pdata, mpixelclock);
+       if (ret) {
+               dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n",
+                       mpixelclock);
+               return ret;
+       }
+
+       return dw_hdmi_phy_power_on(hdmi);
+}
+
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+                           struct drm_display_mode *mode)
+{
+       int i, ret;
+
+       /* HDMI Phy spec says to do the phy initialization sequence twice */
+       for (i = 0; i < 2; i++) {
+               dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
+               dw_hdmi_phy_sel_interface_control(hdmi, 0);
+
+               ret = hdmi_phy_configure(hdmi);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+       dw_hdmi_phy_power_off(hdmi);
+}
+
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
+                                                     void *data)
+{
+       return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
+               connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+       .init = dw_hdmi_phy_init,
+       .disable = dw_hdmi_phy_disable,
+       .read_hpd = dw_hdmi_phy_read_hpd,
+};
+
+/* -----------------------------------------------------------------------------
+ * HDMI TX Setup
+ */
+
+static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
+{
+       u8 de;
+
+       if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
+               de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
+       else
+               de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
+
+       /* disable rx detect */
+       hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
+                 HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
+
+       hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
+
+       hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
+                 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
+}
+
+static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
+{
+       struct hdmi_avi_infoframe frame;
+       u8 val;
+
+       /* Initialise info frame from DRM mode */
+       drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+
+       if (hdmi->hdmi_data.enc_out_format == YCBCR444)
+               frame.colorspace = HDMI_COLORSPACE_YUV444;
+       else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
+               frame.colorspace = HDMI_COLORSPACE_YUV422;
+       else
+               frame.colorspace = HDMI_COLORSPACE_RGB;
+
+       /* Set up colorimetry */
+       if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
+               frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+               if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
+                       frame.extended_colorimetry =
+                               HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+               else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
+                       frame.extended_colorimetry =
+                               HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
+       } else if (hdmi->hdmi_data.enc_out_format != RGB) {
+               frame.colorimetry = hdmi->hdmi_data.colorimetry;
+               frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+       } else { /* Carries no data */
+               frame.colorimetry = HDMI_COLORIMETRY_NONE;
+               frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+       }
+
+       frame.scan_mode = HDMI_SCAN_MODE_NONE;
+
+       /*
+        * The Designware IP uses a different byte format from standard
+        * AVI info frames, though generally the bits are in the correct
+        * bytes.
+        */
+
+       /*
+        * AVI data byte 1 differences: Colorspace in bits 0,1 rather than 5,6,
+        * scan info in bits 4,5 rather than 0,1 and active aspect present in
+        * bit 6 rather than 4.
+        */
+       val = (frame.scan_mode & 3) << 4 | (frame.colorspace & 3);
+       if (frame.active_aspect & 15)
+               val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT;
+       if (frame.top_bar || frame.bottom_bar)
+               val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR;
+       if (frame.left_bar || frame.right_bar)
+               val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR;
+       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
+
+       /* AVI data byte 2 differences: none */
+       val = ((frame.colorimetry & 0x3) << 6) |
+             ((frame.picture_aspect & 0x3) << 4) |
+             (frame.active_aspect & 0xf);
+       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
+
+       /* AVI data byte 3 differences: none */
+       val = ((frame.extended_colorimetry & 0x7) << 4) |
+             ((frame.quantization_range & 0x3) << 2) |
+             (frame.nups & 0x3);
+       if (frame.itc)
+               val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID;
+       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
+
+       /* AVI data byte 4 differences: none */
+       val = frame.video_code & 0x7f;
+       hdmi_writeb(hdmi, val, HDMI_FC_AVIVID);
+
+       /* AVI Data Byte 5- set up input and output pixel repetition */
+       val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
+               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
+               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
+               ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput <<
+               HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
+               HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
+       hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
+
+       /*
+        * AVI data byte 5 differences: content type in 0,1 rather than 4,5,
+        * ycc range in bits 2,3 rather than 6,7
+        */
+       val = ((frame.ycc_quantization_range & 0x3) << 2) |
+             (frame.content_type & 0x3);
+       hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
+
+       /* AVI Data Bytes 6-13 */
+       hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0);
+       hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1);
+       hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0);
+       hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1);
+       hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0);
+       hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1);
+       hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0);
+       hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
+}
+
+static void hdmi_av_composer(struct dw_hdmi *hdmi,
+                            const struct drm_display_mode *mode)
+{
+       u8 inv_val;
+       struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
+       int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
+       unsigned int vdisplay;
+
+       vmode->mpixelclock = mode->clock * 1000;
+
+       dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
+
+       /* Set up HDMI_FC_INVIDCONF */
+       inv_val = (hdmi->hdmi_data.hdcp_enable ?
+               HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
+               HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
+
+       inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
+               HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
+               HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW;
+
+       inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
+               HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
+               HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW;
+
+       inv_val |= (vmode->mdataenablepolarity ?
+               HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
+               HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
+
+       if (hdmi->vic == 39)
+               inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
+       else
+               inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
+                       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
+                       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
+
+       inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
+               HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
+               HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
+
+       inv_val |= hdmi->sink_is_hdmi ?
+               HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
+               HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE;
+
+       hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
+
+       vdisplay = mode->vdisplay;
+       vblank = mode->vtotal - mode->vdisplay;
+       v_de_vs = mode->vsync_start - mode->vdisplay;
+       vsync_len = mode->vsync_end - mode->vsync_start;
+
+       /*
+        * When we're setting an interlaced mode, we need
+        * to adjust the vertical timing to suit.
+        */
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               vdisplay /= 2;
+               vblank /= 2;
+               v_de_vs /= 2;
+               vsync_len /= 2;
+       }
+
+       /* Set up horizontal active pixel width */
+       hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
+       hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
+
+       /* Set up vertical active lines */
+       hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1);
+       hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
+
+       /* Set up horizontal blanking pixel region width */
+       hblank = mode->htotal - mode->hdisplay;
+       hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
+       hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
+
+       /* Set up vertical blanking pixel region width */
+       hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
+
+       /* Set up HSYNC active edge delay width (in pixel clks) */
+       h_de_hs = mode->hsync_start - mode->hdisplay;
+       hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1);
+       hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
+
+       /* Set up VSYNC active edge delay (in lines) */
+       hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
+
+       /* Set up HSYNC active pulse width (in pixel clks) */
+       hsync_len = mode->hsync_end - mode->hsync_start;
+       hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
+       hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
+
+       /* Set up VSYNC active edge delay (in lines) */
+       hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
+}
+
+/* HDMI Initialization Step B.4 */
+static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
+{
+       u8 clkdis;
+
+       /* control period minimum duration */
+       hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
+       hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
+       hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC);
+
+       /* Set to fill TMDS data channels */
+       hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM);
+       hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM);
+       hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
+
+       /* Enable pixel clock and tmds data path */
+       clkdis = 0x7F;
+       clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+       hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+       clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+       hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+       /* Enable csc path */
+       if (is_color_space_conversion(hdmi)) {
+               clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+               hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+       }
+
+       /* Enable color space conversion if needed */
+       if (is_color_space_conversion(hdmi))
+               hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
+                           HDMI_MC_FLOWCTRL);
+       else
+               hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
+                           HDMI_MC_FLOWCTRL);
+}
+
+static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
+{
+       hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
+}
+
+/* Workaround to clear the overflow condition */
+static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
+{
+       unsigned int count;
+       unsigned int i;
+       u8 val;
+
+       /*
+        * Under some circumstances the Frame Composer arithmetic unit can miss
+        * an FC register write due to being busy processing the previous one.
+        * The issue can be worked around by issuing a TMDS software reset and
+        * then write one of the FC registers several times.
+        *
+        * The number of iterations matters and depends on the HDMI TX revision
+        * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
+        * i.MX6DL (v1.31a) have been identified as needing the workaround, with
+        * 4 and 1 iterations respectively.
+        */
+
+       switch (hdmi->version) {
+       case 0x130a:
+               count = 4;
+               break;
+       case 0x131a:
+               count = 1;
+               break;
+       default:
+               return;
+       }
+
+       /* TMDS software reset */
+       hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
+
+       val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
+       for (i = 0; i < count; i++)
+               hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
+}
+
+static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi)
+{
+       hdmi_writeb(hdmi, 0, HDMI_FC_MASK2);
+       hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2);
+}
+
+static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
+{
+       hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
+                   HDMI_IH_MUTE_FC_STAT2);
+}
+
+static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
+{
+       int ret;
+
+       hdmi_disable_overflow_interrupts(hdmi);
+
+       hdmi->vic = drm_match_cea_mode(mode);
+
+       if (!hdmi->vic) {
+               dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
+       } else {
+               dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
+       }
+
+       if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
+           (hdmi->vic == 21) || (hdmi->vic == 22) ||
+           (hdmi->vic == 2) || (hdmi->vic == 3) ||
+           (hdmi->vic == 17) || (hdmi->vic == 18))
+               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
+       else
+               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
+
+       hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
+       hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
+
+       /* TODO: Get input format from IPU (via FB driver interface) */
+       hdmi->hdmi_data.enc_in_format = RGB;
+
+       hdmi->hdmi_data.enc_out_format = RGB;
+
+       hdmi->hdmi_data.enc_color_depth = 8;
+       hdmi->hdmi_data.pix_repet_factor = 0;
+       hdmi->hdmi_data.hdcp_enable = 0;
+       hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
+
+       /* HDMI Initialization Step B.1 */
+       hdmi_av_composer(hdmi, mode);
+
+       /* HDMI Initializateion Step B.2 */
+       ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
+       if (ret)
+               return ret;
+       hdmi->phy.enabled = true;
+
+       /* HDMI Initialization Step B.3 */
+       dw_hdmi_enable_video_path(hdmi);
+
+       if (hdmi->sink_has_audio) {
+               dev_dbg(hdmi->dev, "sink has audio support\n");
+
+               /* HDMI Initialization Step E - Configure audio */
+               hdmi_clk_regenerator_update_pixel_clock(hdmi);
+               hdmi_enable_audio_clk(hdmi);
+       }
+
+       /* not for DVI mode */
+       if (hdmi->sink_is_hdmi) {
+               dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__);
+
+               /* HDMI Initialization Step F - Configure AVI InfoFrame */
+               hdmi_config_AVI(hdmi, mode);
+       } else {
+               dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
+       }
+
+       hdmi_video_packetize(hdmi);
+       hdmi_video_csc(hdmi);
+       hdmi_video_sample(hdmi);
+       hdmi_tx_hdcp_config(hdmi);
+
+       dw_hdmi_clear_overflow(hdmi);
+       if (hdmi->cable_plugin && hdmi->sink_is_hdmi)
+               hdmi_enable_overflow_interrupts(hdmi);
+
+       return 0;
+}
+
+/* Wait until we are registered to enable interrupts */
+static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
+{
+       hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
+                   HDMI_PHY_I2CM_INT_ADDR);
+
+       hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
+                   HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
+                   HDMI_PHY_I2CM_CTLINT_ADDR);
+
+       /* enable cable hot plug irq */
+       hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
+
+       /* Clear Hotplug interrupts */
+       hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+                   HDMI_IH_PHY_STAT0);
+
+       return 0;
+}
+
+static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
+{
+       u8 ih_mute;
+
+       /*
+        * Boot up defaults are:
+        * HDMI_IH_MUTE   = 0x03 (disabled)
+        * HDMI_IH_MUTE_* = 0x00 (enabled)
+        *
+        * Disable top level interrupt bits in HDMI block
+        */
+       ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
+                 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+                 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+       hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+
+       /* by default mask all interrupts */
+       hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK);
+       hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0);
+       hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1);
+       hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2);
+       hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0);
+       hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR);
+       hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
+       hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT);
+       hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT);
+       hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
+       hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
+       hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
+       hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
+       hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
+       hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
+
+       /* Disable interrupts in the IH_MUTE_* registers */
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
+       hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+       /* Enable top level interrupt bits in HDMI block */
+       ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+                   HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
+       hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+}
+
+static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
+{
+       hdmi->bridge_is_on = true;
+       dw_hdmi_setup(hdmi, &hdmi->previous_mode);
+}
+
+static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
+{
+       if (hdmi->phy.enabled) {
+               hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
+               hdmi->phy.enabled = false;
+       }
+
+       hdmi->bridge_is_on = false;
+}
+
+static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
+{
+       int force = hdmi->force;
+
+       if (hdmi->disabled) {
+               force = DRM_FORCE_OFF;
+       } else if (force == DRM_FORCE_UNSPECIFIED) {
+               if (hdmi->rxsense)
+                       force = DRM_FORCE_ON;
+               else
+                       force = DRM_FORCE_OFF;
+       }
+
+       if (force == DRM_FORCE_OFF) {
+               if (hdmi->bridge_is_on)
+                       dw_hdmi_poweroff(hdmi);
+       } else {
+               if (!hdmi->bridge_is_on)
+                       dw_hdmi_poweron(hdmi);
+       }
+}
+
+/*
+ * Adjust the detection of RXSENSE according to whether we have a forced
+ * connection mode enabled, or whether we have been disabled.  There is
+ * no point processing RXSENSE interrupts if we have a forced connection
+ * state, or DRM has us disabled.
+ *
+ * We also disable rxsense interrupts when we think we're disconnected
+ * to avoid floating TDMS signals giving false rxsense interrupts.
+ *
+ * Note: we still need to listen for HPD interrupts even when DRM has us
+ * disabled so that we can detect a connect event.
+ */
+static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
+{
+       u8 old_mask = hdmi->phy_mask;
+
+       if (hdmi->force || hdmi->disabled || !hdmi->rxsense)
+               hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
+       else
+               hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
+
+       if (old_mask != hdmi->phy_mask)
+               hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
+}
+
+static enum drm_connector_status
+dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+       struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
+                                            connector);
+
+       mutex_lock(&hdmi->mutex);
+       hdmi->force = DRM_FORCE_UNSPECIFIED;
+       dw_hdmi_update_power(hdmi);
+       dw_hdmi_update_phy_mask(hdmi);
+       mutex_unlock(&hdmi->mutex);
+
+       return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+}
+
+static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+       struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
+                                            connector);
+       struct edid *edid;
+       int ret = 0;
+
+       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);
+
+               hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
+               hdmi->sink_has_audio = drm_detect_monitor_audio(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);
+       } else {
+               dev_dbg(hdmi->dev, "failed to get edid\n");
+       }
+
+       return ret;
+}
+
+static enum drm_mode_status
+dw_hdmi_connector_mode_valid(struct drm_connector *connector,
+                            struct drm_display_mode *mode)
+{
+       struct dw_hdmi *hdmi = container_of(connector,
+                                          struct dw_hdmi, connector);
+       enum drm_mode_status mode_status = MODE_OK;
+
+       /* We don't support double-clocked modes */
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               return MODE_BAD;
+
+       if (hdmi->plat_data->mode_valid)
+               mode_status = hdmi->plat_data->mode_valid(connector, mode);
+
+       return mode_status;
+}
+
+static void dw_hdmi_connector_force(struct drm_connector *connector)
+{
+       struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
+                                            connector);
+
+       mutex_lock(&hdmi->mutex);
+       hdmi->force = connector->force;
+       dw_hdmi_update_power(hdmi);
+       dw_hdmi_update_phy_mask(hdmi);
+       mutex_unlock(&hdmi->mutex);
+}
+
+static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
+       .dpms = drm_atomic_helper_connector_dpms,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .detect = dw_hdmi_connector_detect,
+       .destroy = drm_connector_cleanup,
+       .force = dw_hdmi_connector_force,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
+       .get_modes = dw_hdmi_connector_get_modes,
+       .mode_valid = dw_hdmi_connector_mode_valid,
+       .best_encoder = drm_atomic_helper_best_encoder,
+};
+
+static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
+{
+       struct dw_hdmi *hdmi = bridge->driver_private;
+       struct drm_encoder *encoder = bridge->encoder;
+       struct drm_connector *connector = &hdmi->connector;
+
+       connector->interlace_allowed = 1;
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+       drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
+
+       drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
+                          DRM_MODE_CONNECTOR_HDMIA);
+
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       return 0;
+}
+
+static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
+                                   struct drm_display_mode *orig_mode,
+                                   struct drm_display_mode *mode)
+{
+       struct dw_hdmi *hdmi = bridge->driver_private;
+
+       mutex_lock(&hdmi->mutex);
+
+       /* Store the display mode for plugin/DKMS poweron events */
+       memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
+
+       mutex_unlock(&hdmi->mutex);
+}
+
+static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
+{
+       struct dw_hdmi *hdmi = bridge->driver_private;
+
+       mutex_lock(&hdmi->mutex);
+       hdmi->disabled = true;
+       dw_hdmi_update_power(hdmi);
+       dw_hdmi_update_phy_mask(hdmi);
+       mutex_unlock(&hdmi->mutex);
+}
+
+static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
+{
+       struct dw_hdmi *hdmi = bridge->driver_private;
+
+       mutex_lock(&hdmi->mutex);
+       hdmi->disabled = false;
+       dw_hdmi_update_power(hdmi);
+       dw_hdmi_update_phy_mask(hdmi);
+       mutex_unlock(&hdmi->mutex);
+}
+
+static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
+       .attach = dw_hdmi_bridge_attach,
+       .enable = dw_hdmi_bridge_enable,
+       .disable = dw_hdmi_bridge_disable,
+       .mode_set = dw_hdmi_bridge_mode_set,
+};
+
+static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
+{
+       struct dw_hdmi_i2c *i2c = hdmi->i2c;
+       unsigned int stat;
+
+       stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0);
+       if (!stat)
+               return IRQ_NONE;
+
+       hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0);
+
+       i2c->stat = stat;
+
+       complete(&i2c->cmp);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
+{
+       struct dw_hdmi *hdmi = dev_id;
+       u8 intr_stat;
+       irqreturn_t ret = IRQ_NONE;
+
+       if (hdmi->i2c)
+               ret = dw_hdmi_i2c_irq(hdmi);
+
+       intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
+       if (intr_stat) {
+               hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+               return IRQ_WAKE_THREAD;
+       }
+
+       return ret;
+}
+
+static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
+{
+       struct dw_hdmi *hdmi = dev_id;
+       u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat;
+
+       intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
+       phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
+       phy_stat = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+
+       phy_pol_mask = 0;
+       if (intr_stat & HDMI_IH_PHY_STAT0_HPD)
+               phy_pol_mask |= HDMI_PHY_HPD;
+       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0)
+               phy_pol_mask |= HDMI_PHY_RX_SENSE0;
+       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE1)
+               phy_pol_mask |= HDMI_PHY_RX_SENSE1;
+       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE2)
+               phy_pol_mask |= HDMI_PHY_RX_SENSE2;
+       if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE3)
+               phy_pol_mask |= HDMI_PHY_RX_SENSE3;
+
+       if (phy_pol_mask)
+               hdmi_modb(hdmi, ~phy_int_pol, phy_pol_mask, HDMI_PHY_POL0);
+
+       /*
+        * RX sense tells us whether the TDMS transmitters are detecting
+        * load - in other words, there's something listening on the
+        * other end of the link.  Use this to decide whether we should
+        * power on the phy as HPD may be toggled by the sink to merely
+        * ask the source to re-read the EDID.
+        */
+       if (intr_stat &
+           (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
+               mutex_lock(&hdmi->mutex);
+               if (!hdmi->disabled && !hdmi->force) {
+                       /*
+                        * If the RX sense status indicates we're disconnected,
+                        * clear the software rxsense status.
+                        */
+                       if (!(phy_stat & HDMI_PHY_RX_SENSE))
+                               hdmi->rxsense = false;
+
+                       /*
+                        * Only set the software rxsense status when both
+                        * rxsense and hpd indicates we're connected.
+                        * This avoids what seems to be bad behaviour in
+                        * at least iMX6S versions of the phy.
+                        */
+                       if (phy_stat & HDMI_PHY_HPD)
+                               hdmi->rxsense = true;
+
+                       dw_hdmi_update_power(hdmi);
+                       dw_hdmi_update_phy_mask(hdmi);
+               }
+               mutex_unlock(&hdmi->mutex);
+       }
+
+       if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
+               dev_dbg(hdmi->dev, "EVENT=%s\n",
+                       phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
+               if (hdmi->bridge.dev)
+                       drm_helper_hpd_irq_event(hdmi->bridge.dev);
+       }
+
+       hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
+       hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
+                   HDMI_IH_MUTE_PHY_STAT0);
+
+       return IRQ_HANDLED;
+}
+
+static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
+       {
+               .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
+               .name = "DWC HDMI TX PHY",
+               .gen = 1,
+       }, {
+               .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
+               .name = "DWC MHL PHY + HEAC PHY",
+               .gen = 2,
+               .has_svsret = true,
+               .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
+       }, {
+               .type = DW_HDMI_PHY_DWC_MHL_PHY,
+               .name = "DWC MHL PHY",
+               .gen = 2,
+               .has_svsret = true,
+               .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
+       }, {
+               .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
+               .name = "DWC HDMI 3D TX PHY + HEAC PHY",
+               .gen = 2,
+               .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
+       }, {
+               .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
+               .name = "DWC HDMI 3D TX PHY",
+               .gen = 2,
+               .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
+       }, {
+               .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
+               .name = "DWC HDMI 2.0 TX PHY",
+               .gen = 2,
+               .has_svsret = true,
+       }, {
+               .type = DW_HDMI_PHY_VENDOR_PHY,
+               .name = "Vendor PHY",
+       }
+};
+
+static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
+{
+       unsigned int i;
+       u8 phy_type;
+
+       phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
+
+       if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
+               /* Vendor PHYs require support from the glue layer. */
+               if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
+                       dev_err(hdmi->dev,
+                               "Vendor HDMI PHY not supported by glue layer\n");
+                       return -ENODEV;
+               }
+
+               hdmi->phy.ops = hdmi->plat_data->phy_ops;
+               hdmi->phy.data = hdmi->plat_data->phy_data;
+               hdmi->phy.name = hdmi->plat_data->phy_name;
+               return 0;
+       }
+
+       /* Synopsys PHYs are handled internally. */
+       for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
+               if (dw_hdmi_phys[i].type == phy_type) {
+                       hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
+                       hdmi->phy.name = dw_hdmi_phys[i].name;
+                       hdmi->phy.data = (void *)&dw_hdmi_phys[i];
+
+                       if (!dw_hdmi_phys[i].configure &&
+                           !hdmi->plat_data->configure_phy) {
+                               dev_err(hdmi->dev, "%s requires platform support\n",
+                                       hdmi->phy.name);
+                               return -ENODEV;
+                       }
+
+                       return 0;
+               }
+       }
+
+       dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
+       return -ENODEV;
+}
+
+static const struct regmap_config hdmi_regmap_8bit_config = {
+       .reg_bits       = 32,
+       .val_bits       = 8,
+       .reg_stride     = 1,
+       .max_register   = HDMI_I2CM_FS_SCL_LCNT_0_ADDR,
+};
+
+static const struct regmap_config hdmi_regmap_32bit_config = {
+       .reg_bits       = 32,
+       .val_bits       = 32,
+       .reg_stride     = 4,
+       .max_register   = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2,
+};
+
+static struct dw_hdmi *
+__dw_hdmi_probe(struct platform_device *pdev,
+               const struct dw_hdmi_plat_data *plat_data)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct platform_device_info pdevinfo;
+       struct device_node *ddc_node;
+       struct dw_hdmi *hdmi;
+       struct resource *iores = NULL;
+       int irq;
+       int ret;
+       u32 val = 1;
+       u8 prod_id0;
+       u8 prod_id1;
+       u8 config0;
+       u8 config3;
+
+       hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+       if (!hdmi)
+               return ERR_PTR(-ENOMEM);
+
+       hdmi->plat_data = plat_data;
+       hdmi->dev = dev;
+       hdmi->sample_rate = 48000;
+       hdmi->disabled = true;
+       hdmi->rxsense = true;
+       hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
+
+       mutex_init(&hdmi->mutex);
+       mutex_init(&hdmi->audio_mutex);
+       spin_lock_init(&hdmi->audio_lock);
+
+       ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
+       if (ddc_node) {
+               hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
+               of_node_put(ddc_node);
+               if (!hdmi->ddc) {
+                       dev_dbg(hdmi->dev, "failed to read ddc node\n");
+                       return ERR_PTR(-EPROBE_DEFER);
+               }
+
+       } else {
+               dev_dbg(hdmi->dev, "no ddc property found\n");
+       }
+
+       if (!plat_data->regm) {
+               const struct regmap_config *reg_config;
+
+               of_property_read_u32(np, "reg-io-width", &val);
+               switch (val) {
+               case 4:
+                       reg_config = &hdmi_regmap_32bit_config;
+                       hdmi->reg_shift = 2;
+                       break;
+               case 1:
+                       reg_config = &hdmi_regmap_8bit_config;
+                       break;
+               default:
+                       dev_err(dev, "reg-io-width must be 1 or 4\n");
+                       return ERR_PTR(-EINVAL);
+               }
+
+               iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               hdmi->regs = devm_ioremap_resource(dev, iores);
+               if (IS_ERR(hdmi->regs)) {
+                       ret = PTR_ERR(hdmi->regs);
+                       goto err_res;
+               }
+
+               hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
+               if (IS_ERR(hdmi->regm)) {
+                       dev_err(dev, "Failed to configure regmap\n");
+                       ret = PTR_ERR(hdmi->regm);
+                       goto err_res;
+               }
+       } else {
+               hdmi->regm = plat_data->regm;
+       }
+
+       hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
+       if (IS_ERR(hdmi->isfr_clk)) {
+               ret = PTR_ERR(hdmi->isfr_clk);
+               dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
+               goto err_res;
+       }
+
+       ret = clk_prepare_enable(hdmi->isfr_clk);
+       if (ret) {
+               dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
+               goto err_res;
+       }
+
+       hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
+       if (IS_ERR(hdmi->iahb_clk)) {
+               ret = PTR_ERR(hdmi->iahb_clk);
+               dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
+               goto err_isfr;
+       }
+
+       ret = clk_prepare_enable(hdmi->iahb_clk);
+       if (ret) {
+               dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret);
+               goto err_isfr;
+       }
+
+       /* Product and revision IDs */
+       hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
+                     | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
+       prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
+       prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
+
+       if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
+           (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
+               dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
+                       hdmi->version, prod_id0, prod_id1);
+               ret = -ENODEV;
+               goto err_iahb;
+       }
+
+       ret = dw_hdmi_detect_phy(hdmi);
+       if (ret < 0)
+               goto err_iahb;
+
+       dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
+                hdmi->version >> 12, hdmi->version & 0xfff,
+                prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
+                hdmi->phy.name);
+
+       initialize_hdmi_ih_mutes(hdmi);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = irq;
+               goto err_iahb;
+       }
+
+       ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
+                                       dw_hdmi_irq, IRQF_SHARED,
+                                       dev_name(dev), hdmi);
+       if (ret)
+               goto err_iahb;
+
+       /*
+        * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
+        * N and cts values before enabling phy
+        */
+       hdmi_init_clk_regenerator(hdmi);
+
+       /* If DDC bus is not specified, try to register HDMI I2C bus */
+       if (!hdmi->ddc) {
+               hdmi->ddc = dw_hdmi_i2c_adapter(hdmi);
+               if (IS_ERR(hdmi->ddc))
+                       hdmi->ddc = NULL;
+       }
+
+       /*
+        * Configure registers related to HDMI interrupt
+        * generation before registering IRQ.
+        */
+       hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
+
+       /* Clear Hotplug interrupts */
+       hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+                   HDMI_IH_PHY_STAT0);
+
+       hdmi->bridge.driver_private = hdmi;
+       hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
+#ifdef CONFIG_OF
+       hdmi->bridge.of_node = pdev->dev.of_node;
+#endif
+
+       ret = dw_hdmi_fb_registered(hdmi);
+       if (ret)
+               goto err_iahb;
+
+       /* Unmute interrupts */
+       hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
+                   HDMI_IH_MUTE_PHY_STAT0);
+
+       memset(&pdevinfo, 0, sizeof(pdevinfo));
+       pdevinfo.parent = dev;
+       pdevinfo.id = PLATFORM_DEVID_AUTO;
+
+       config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
+       config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
+
+       if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) {
+               struct dw_hdmi_audio_data audio;
+
+               audio.phys = iores->start;
+               audio.base = hdmi->regs;
+               audio.irq = irq;
+               audio.hdmi = hdmi;
+               audio.eld = hdmi->connector.eld;
+
+               pdevinfo.name = "dw-hdmi-ahb-audio";
+               pdevinfo.data = &audio;
+               pdevinfo.size_data = sizeof(audio);
+               pdevinfo.dma_mask = DMA_BIT_MASK(32);
+               hdmi->audio = platform_device_register_full(&pdevinfo);
+       } else if (config0 & HDMI_CONFIG0_I2S) {
+               struct dw_hdmi_i2s_audio_data audio;
+
+               audio.hdmi      = hdmi;
+               audio.write     = hdmi_writeb;
+               audio.read      = hdmi_readb;
+
+               pdevinfo.name = "dw-hdmi-i2s-audio";
+               pdevinfo.data = &audio;
+               pdevinfo.size_data = sizeof(audio);
+               pdevinfo.dma_mask = DMA_BIT_MASK(32);
+               hdmi->audio = platform_device_register_full(&pdevinfo);
+       }
+
+       /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
+       if (hdmi->i2c)
+               dw_hdmi_i2c_init(hdmi);
+
+       platform_set_drvdata(pdev, hdmi);
+
+       return hdmi;
+
+err_iahb:
+       if (hdmi->i2c) {
+               i2c_del_adapter(&hdmi->i2c->adap);
+               hdmi->ddc = NULL;
+       }
+
+       clk_disable_unprepare(hdmi->iahb_clk);
+err_isfr:
+       clk_disable_unprepare(hdmi->isfr_clk);
+err_res:
+       i2c_put_adapter(hdmi->ddc);
+
+       return ERR_PTR(ret);
+}
+
+static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
+{
+       if (hdmi->audio && !IS_ERR(hdmi->audio))
+               platform_device_unregister(hdmi->audio);
+
+       /* Disable all interrupts */
+       hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+       clk_disable_unprepare(hdmi->iahb_clk);
+       clk_disable_unprepare(hdmi->isfr_clk);
+
+       if (hdmi->i2c)
+               i2c_del_adapter(&hdmi->i2c->adap);
+       else
+               i2c_put_adapter(hdmi->ddc);
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove API, used from platforms based on the DRM bridge API.
+ */
+int dw_hdmi_probe(struct platform_device *pdev,
+                 const struct dw_hdmi_plat_data *plat_data)
+{
+       struct dw_hdmi *hdmi;
+       int ret;
+
+       hdmi = __dw_hdmi_probe(pdev, plat_data);
+       if (IS_ERR(hdmi))
+               return PTR_ERR(hdmi);
+
+       ret = drm_bridge_add(&hdmi->bridge);
+       if (ret < 0) {
+               __dw_hdmi_remove(hdmi);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_probe);
+
+void dw_hdmi_remove(struct platform_device *pdev)
+{
+       struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
+
+       drm_bridge_remove(&hdmi->bridge);
+
+       __dw_hdmi_remove(hdmi);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_remove);
+
+/* -----------------------------------------------------------------------------
+ * Bind/unbind API, used from platforms based on the component framework.
+ */
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
+                const struct dw_hdmi_plat_data *plat_data)
+{
+       struct dw_hdmi *hdmi;
+       int ret;
+
+       hdmi = __dw_hdmi_probe(pdev, plat_data);
+       if (IS_ERR(hdmi))
+               return PTR_ERR(hdmi);
+
+       ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
+       if (ret) {
+               dw_hdmi_remove(pdev);
+               DRM_ERROR("Failed to initialize bridge with drm\n");
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_bind);
+
+void dw_hdmi_unbind(struct device *dev)
+{
+       struct dw_hdmi *hdmi = dev_get_drvdata(dev);
+
+       __dw_hdmi_remove(hdmi);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
+MODULE_DESCRIPTION("DW HDMI transmitter driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:dw-hdmi");
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
new file mode 100644 (file)
index 0000000..325b0b8
--- /dev/null
@@ -0,0 +1,1153 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DW_HDMI_H__
+#define __DW_HDMI_H__
+
+/* Identification Registers */
+#define HDMI_DESIGN_ID                          0x0000
+#define HDMI_REVISION_ID                        0x0001
+#define HDMI_PRODUCT_ID0                        0x0002
+#define HDMI_PRODUCT_ID1                        0x0003
+#define HDMI_CONFIG0_ID                         0x0004
+#define HDMI_CONFIG1_ID                         0x0005
+#define HDMI_CONFIG2_ID                         0x0006
+#define HDMI_CONFIG3_ID                         0x0007
+
+/* Interrupt Registers */
+#define HDMI_IH_FC_STAT0                        0x0100
+#define HDMI_IH_FC_STAT1                        0x0101
+#define HDMI_IH_FC_STAT2                        0x0102
+#define HDMI_IH_AS_STAT0                        0x0103
+#define HDMI_IH_PHY_STAT0                       0x0104
+#define HDMI_IH_I2CM_STAT0                      0x0105
+#define HDMI_IH_CEC_STAT0                       0x0106
+#define HDMI_IH_VP_STAT0                        0x0107
+#define HDMI_IH_I2CMPHY_STAT0                   0x0108
+#define HDMI_IH_AHBDMAAUD_STAT0                 0x0109
+
+#define HDMI_IH_MUTE_FC_STAT0                   0x0180
+#define HDMI_IH_MUTE_FC_STAT1                   0x0181
+#define HDMI_IH_MUTE_FC_STAT2                   0x0182
+#define HDMI_IH_MUTE_AS_STAT0                   0x0183
+#define HDMI_IH_MUTE_PHY_STAT0                  0x0184
+#define HDMI_IH_MUTE_I2CM_STAT0                 0x0185
+#define HDMI_IH_MUTE_CEC_STAT0                  0x0186
+#define HDMI_IH_MUTE_VP_STAT0                   0x0187
+#define HDMI_IH_MUTE_I2CMPHY_STAT0              0x0188
+#define HDMI_IH_MUTE_AHBDMAAUD_STAT0            0x0189
+#define HDMI_IH_MUTE                            0x01FF
+
+/* Video Sample Registers */
+#define HDMI_TX_INVID0                          0x0200
+#define HDMI_TX_INSTUFFING                      0x0201
+#define HDMI_TX_GYDATA0                         0x0202
+#define HDMI_TX_GYDATA1                         0x0203
+#define HDMI_TX_RCRDATA0                        0x0204
+#define HDMI_TX_RCRDATA1                        0x0205
+#define HDMI_TX_BCBDATA0                        0x0206
+#define HDMI_TX_BCBDATA1                        0x0207
+
+/* Video Packetizer Registers */
+#define HDMI_VP_STATUS                          0x0800
+#define HDMI_VP_PR_CD                           0x0801
+#define HDMI_VP_STUFF                           0x0802
+#define HDMI_VP_REMAP                           0x0803
+#define HDMI_VP_CONF                            0x0804
+#define HDMI_VP_STAT                            0x0805
+#define HDMI_VP_INT                             0x0806
+#define HDMI_VP_MASK                            0x0807
+#define HDMI_VP_POL                             0x0808
+
+/* Frame Composer Registers */
+#define HDMI_FC_INVIDCONF                       0x1000
+#define HDMI_FC_INHACTV0                        0x1001
+#define HDMI_FC_INHACTV1                        0x1002
+#define HDMI_FC_INHBLANK0                       0x1003
+#define HDMI_FC_INHBLANK1                       0x1004
+#define HDMI_FC_INVACTV0                        0x1005
+#define HDMI_FC_INVACTV1                        0x1006
+#define HDMI_FC_INVBLANK                        0x1007
+#define HDMI_FC_HSYNCINDELAY0                   0x1008
+#define HDMI_FC_HSYNCINDELAY1                   0x1009
+#define HDMI_FC_HSYNCINWIDTH0                   0x100A
+#define HDMI_FC_HSYNCINWIDTH1                   0x100B
+#define HDMI_FC_VSYNCINDELAY                    0x100C
+#define HDMI_FC_VSYNCINWIDTH                    0x100D
+#define HDMI_FC_INFREQ0                         0x100E
+#define HDMI_FC_INFREQ1                         0x100F
+#define HDMI_FC_INFREQ2                         0x1010
+#define HDMI_FC_CTRLDUR                         0x1011
+#define HDMI_FC_EXCTRLDUR                       0x1012
+#define HDMI_FC_EXCTRLSPAC                      0x1013
+#define HDMI_FC_CH0PREAM                        0x1014
+#define HDMI_FC_CH1PREAM                        0x1015
+#define HDMI_FC_CH2PREAM                        0x1016
+#define HDMI_FC_AVICONF3                        0x1017
+#define HDMI_FC_GCP                             0x1018
+#define HDMI_FC_AVICONF0                        0x1019
+#define HDMI_FC_AVICONF1                        0x101A
+#define HDMI_FC_AVICONF2                        0x101B
+#define HDMI_FC_AVIVID                          0x101C
+#define HDMI_FC_AVIETB0                         0x101D
+#define HDMI_FC_AVIETB1                         0x101E
+#define HDMI_FC_AVISBB0                         0x101F
+#define HDMI_FC_AVISBB1                         0x1020
+#define HDMI_FC_AVIELB0                         0x1021
+#define HDMI_FC_AVIELB1                         0x1022
+#define HDMI_FC_AVISRB0                         0x1023
+#define HDMI_FC_AVISRB1                         0x1024
+#define HDMI_FC_AUDICONF0                       0x1025
+#define HDMI_FC_AUDICONF1                       0x1026
+#define HDMI_FC_AUDICONF2                       0x1027
+#define HDMI_FC_AUDICONF3                       0x1028
+#define HDMI_FC_VSDIEEEID0                      0x1029
+#define HDMI_FC_VSDSIZE                         0x102A
+#define HDMI_FC_VSDIEEEID1                      0x1030
+#define HDMI_FC_VSDIEEEID2                      0x1031
+#define HDMI_FC_VSDPAYLOAD0                     0x1032
+#define HDMI_FC_VSDPAYLOAD1                     0x1033
+#define HDMI_FC_VSDPAYLOAD2                     0x1034
+#define HDMI_FC_VSDPAYLOAD3                     0x1035
+#define HDMI_FC_VSDPAYLOAD4                     0x1036
+#define HDMI_FC_VSDPAYLOAD5                     0x1037
+#define HDMI_FC_VSDPAYLOAD6                     0x1038
+#define HDMI_FC_VSDPAYLOAD7                     0x1039
+#define HDMI_FC_VSDPAYLOAD8                     0x103A
+#define HDMI_FC_VSDPAYLOAD9                     0x103B
+#define HDMI_FC_VSDPAYLOAD10                    0x103C
+#define HDMI_FC_VSDPAYLOAD11                    0x103D
+#define HDMI_FC_VSDPAYLOAD12                    0x103E
+#define HDMI_FC_VSDPAYLOAD13                    0x103F
+#define HDMI_FC_VSDPAYLOAD14                    0x1040
+#define HDMI_FC_VSDPAYLOAD15                    0x1041
+#define HDMI_FC_VSDPAYLOAD16                    0x1042
+#define HDMI_FC_VSDPAYLOAD17                    0x1043
+#define HDMI_FC_VSDPAYLOAD18                    0x1044
+#define HDMI_FC_VSDPAYLOAD19                    0x1045
+#define HDMI_FC_VSDPAYLOAD20                    0x1046
+#define HDMI_FC_VSDPAYLOAD21                    0x1047
+#define HDMI_FC_VSDPAYLOAD22                    0x1048
+#define HDMI_FC_VSDPAYLOAD23                    0x1049
+#define HDMI_FC_SPDVENDORNAME0                  0x104A
+#define HDMI_FC_SPDVENDORNAME1                  0x104B
+#define HDMI_FC_SPDVENDORNAME2                  0x104C
+#define HDMI_FC_SPDVENDORNAME3                  0x104D
+#define HDMI_FC_SPDVENDORNAME4                  0x104E
+#define HDMI_FC_SPDVENDORNAME5                  0x104F
+#define HDMI_FC_SPDVENDORNAME6                  0x1050
+#define HDMI_FC_SPDVENDORNAME7                  0x1051
+#define HDMI_FC_SDPPRODUCTNAME0                 0x1052
+#define HDMI_FC_SDPPRODUCTNAME1                 0x1053
+#define HDMI_FC_SDPPRODUCTNAME2                 0x1054
+#define HDMI_FC_SDPPRODUCTNAME3                 0x1055
+#define HDMI_FC_SDPPRODUCTNAME4                 0x1056
+#define HDMI_FC_SDPPRODUCTNAME5                 0x1057
+#define HDMI_FC_SDPPRODUCTNAME6                 0x1058
+#define HDMI_FC_SDPPRODUCTNAME7                 0x1059
+#define HDMI_FC_SDPPRODUCTNAME8                 0x105A
+#define HDMI_FC_SDPPRODUCTNAME9                 0x105B
+#define HDMI_FC_SDPPRODUCTNAME10                0x105C
+#define HDMI_FC_SDPPRODUCTNAME11                0x105D
+#define HDMI_FC_SDPPRODUCTNAME12                0x105E
+#define HDMI_FC_SDPPRODUCTNAME13                0x105F
+#define HDMI_FC_SDPPRODUCTNAME14                0x1060
+#define HDMI_FC_SPDPRODUCTNAME15                0x1061
+#define HDMI_FC_SPDDEVICEINF                    0x1062
+#define HDMI_FC_AUDSCONF                        0x1063
+#define HDMI_FC_AUDSSTAT                        0x1064
+#define HDMI_FC_DATACH0FILL                     0x1070
+#define HDMI_FC_DATACH1FILL                     0x1071
+#define HDMI_FC_DATACH2FILL                     0x1072
+#define HDMI_FC_CTRLQHIGH                       0x1073
+#define HDMI_FC_CTRLQLOW                        0x1074
+#define HDMI_FC_ACP0                            0x1075
+#define HDMI_FC_ACP28                           0x1076
+#define HDMI_FC_ACP27                           0x1077
+#define HDMI_FC_ACP26                           0x1078
+#define HDMI_FC_ACP25                           0x1079
+#define HDMI_FC_ACP24                           0x107A
+#define HDMI_FC_ACP23                           0x107B
+#define HDMI_FC_ACP22                           0x107C
+#define HDMI_FC_ACP21                           0x107D
+#define HDMI_FC_ACP20                           0x107E
+#define HDMI_FC_ACP19                           0x107F
+#define HDMI_FC_ACP18                           0x1080
+#define HDMI_FC_ACP17                           0x1081
+#define HDMI_FC_ACP16                           0x1082
+#define HDMI_FC_ACP15                           0x1083
+#define HDMI_FC_ACP14                           0x1084
+#define HDMI_FC_ACP13                           0x1085
+#define HDMI_FC_ACP12                           0x1086
+#define HDMI_FC_ACP11                           0x1087
+#define HDMI_FC_ACP10                           0x1088
+#define HDMI_FC_ACP9                            0x1089
+#define HDMI_FC_ACP8                            0x108A
+#define HDMI_FC_ACP7                            0x108B
+#define HDMI_FC_ACP6                            0x108C
+#define HDMI_FC_ACP5                            0x108D
+#define HDMI_FC_ACP4                            0x108E
+#define HDMI_FC_ACP3                            0x108F
+#define HDMI_FC_ACP2                            0x1090
+#define HDMI_FC_ACP1                            0x1091
+#define HDMI_FC_ISCR1_0                         0x1092
+#define HDMI_FC_ISCR1_16                        0x1093
+#define HDMI_FC_ISCR1_15                        0x1094
+#define HDMI_FC_ISCR1_14                        0x1095
+#define HDMI_FC_ISCR1_13                        0x1096
+#define HDMI_FC_ISCR1_12                        0x1097
+#define HDMI_FC_ISCR1_11                        0x1098
+#define HDMI_FC_ISCR1_10                        0x1099
+#define HDMI_FC_ISCR1_9                         0x109A
+#define HDMI_FC_ISCR1_8                         0x109B
+#define HDMI_FC_ISCR1_7                         0x109C
+#define HDMI_FC_ISCR1_6                         0x109D
+#define HDMI_FC_ISCR1_5                         0x109E
+#define HDMI_FC_ISCR1_4                         0x109F
+#define HDMI_FC_ISCR1_3                         0x10A0
+#define HDMI_FC_ISCR1_2                         0x10A1
+#define HDMI_FC_ISCR1_1                         0x10A2
+#define HDMI_FC_ISCR2_15                        0x10A3
+#define HDMI_FC_ISCR2_14                        0x10A4
+#define HDMI_FC_ISCR2_13                        0x10A5
+#define HDMI_FC_ISCR2_12                        0x10A6
+#define HDMI_FC_ISCR2_11                        0x10A7
+#define HDMI_FC_ISCR2_10                        0x10A8
+#define HDMI_FC_ISCR2_9                         0x10A9
+#define HDMI_FC_ISCR2_8                         0x10AA
+#define HDMI_FC_ISCR2_7                         0x10AB
+#define HDMI_FC_ISCR2_6                         0x10AC
+#define HDMI_FC_ISCR2_5                         0x10AD
+#define HDMI_FC_ISCR2_4                         0x10AE
+#define HDMI_FC_ISCR2_3                         0x10AF
+#define HDMI_FC_ISCR2_2                         0x10B0
+#define HDMI_FC_ISCR2_1                         0x10B1
+#define HDMI_FC_ISCR2_0                         0x10B2
+#define HDMI_FC_DATAUTO0                        0x10B3
+#define HDMI_FC_DATAUTO1                        0x10B4
+#define HDMI_FC_DATAUTO2                        0x10B5
+#define HDMI_FC_DATMAN                          0x10B6
+#define HDMI_FC_DATAUTO3                        0x10B7
+#define HDMI_FC_RDRB0                           0x10B8
+#define HDMI_FC_RDRB1                           0x10B9
+#define HDMI_FC_RDRB2                           0x10BA
+#define HDMI_FC_RDRB3                           0x10BB
+#define HDMI_FC_RDRB4                           0x10BC
+#define HDMI_FC_RDRB5                           0x10BD
+#define HDMI_FC_RDRB6                           0x10BE
+#define HDMI_FC_RDRB7                           0x10BF
+#define HDMI_FC_STAT0                           0x10D0
+#define HDMI_FC_INT0                            0x10D1
+#define HDMI_FC_MASK0                           0x10D2
+#define HDMI_FC_POL0                            0x10D3
+#define HDMI_FC_STAT1                           0x10D4
+#define HDMI_FC_INT1                            0x10D5
+#define HDMI_FC_MASK1                           0x10D6
+#define HDMI_FC_POL1                            0x10D7
+#define HDMI_FC_STAT2                           0x10D8
+#define HDMI_FC_INT2                            0x10D9
+#define HDMI_FC_MASK2                           0x10DA
+#define HDMI_FC_POL2                            0x10DB
+#define HDMI_FC_PRCONF                          0x10E0
+
+#define HDMI_FC_GMD_STAT                        0x1100
+#define HDMI_FC_GMD_EN                          0x1101
+#define HDMI_FC_GMD_UP                          0x1102
+#define HDMI_FC_GMD_CONF                        0x1103
+#define HDMI_FC_GMD_HB                          0x1104
+#define HDMI_FC_GMD_PB0                         0x1105
+#define HDMI_FC_GMD_PB1                         0x1106
+#define HDMI_FC_GMD_PB2                         0x1107
+#define HDMI_FC_GMD_PB3                         0x1108
+#define HDMI_FC_GMD_PB4                         0x1109
+#define HDMI_FC_GMD_PB5                         0x110A
+#define HDMI_FC_GMD_PB6                         0x110B
+#define HDMI_FC_GMD_PB7                         0x110C
+#define HDMI_FC_GMD_PB8                         0x110D
+#define HDMI_FC_GMD_PB9                         0x110E
+#define HDMI_FC_GMD_PB10                        0x110F
+#define HDMI_FC_GMD_PB11                        0x1110
+#define HDMI_FC_GMD_PB12                        0x1111
+#define HDMI_FC_GMD_PB13                        0x1112
+#define HDMI_FC_GMD_PB14                        0x1113
+#define HDMI_FC_GMD_PB15                        0x1114
+#define HDMI_FC_GMD_PB16                        0x1115
+#define HDMI_FC_GMD_PB17                        0x1116
+#define HDMI_FC_GMD_PB18                        0x1117
+#define HDMI_FC_GMD_PB19                        0x1118
+#define HDMI_FC_GMD_PB20                        0x1119
+#define HDMI_FC_GMD_PB21                        0x111A
+#define HDMI_FC_GMD_PB22                        0x111B
+#define HDMI_FC_GMD_PB23                        0x111C
+#define HDMI_FC_GMD_PB24                        0x111D
+#define HDMI_FC_GMD_PB25                        0x111E
+#define HDMI_FC_GMD_PB26                        0x111F
+#define HDMI_FC_GMD_PB27                        0x1120
+
+#define HDMI_FC_DBGFORCE                        0x1200
+#define HDMI_FC_DBGAUD0CH0                      0x1201
+#define HDMI_FC_DBGAUD1CH0                      0x1202
+#define HDMI_FC_DBGAUD2CH0                      0x1203
+#define HDMI_FC_DBGAUD0CH1                      0x1204
+#define HDMI_FC_DBGAUD1CH1                      0x1205
+#define HDMI_FC_DBGAUD2CH1                      0x1206
+#define HDMI_FC_DBGAUD0CH2                      0x1207
+#define HDMI_FC_DBGAUD1CH2                      0x1208
+#define HDMI_FC_DBGAUD2CH2                      0x1209
+#define HDMI_FC_DBGAUD0CH3                      0x120A
+#define HDMI_FC_DBGAUD1CH3                      0x120B
+#define HDMI_FC_DBGAUD2CH3                      0x120C
+#define HDMI_FC_DBGAUD0CH4                      0x120D
+#define HDMI_FC_DBGAUD1CH4                      0x120E
+#define HDMI_FC_DBGAUD2CH4                      0x120F
+#define HDMI_FC_DBGAUD0CH5                      0x1210
+#define HDMI_FC_DBGAUD1CH5                      0x1211
+#define HDMI_FC_DBGAUD2CH5                      0x1212
+#define HDMI_FC_DBGAUD0CH6                      0x1213
+#define HDMI_FC_DBGAUD1CH6                      0x1214
+#define HDMI_FC_DBGAUD2CH6                      0x1215
+#define HDMI_FC_DBGAUD0CH7                      0x1216
+#define HDMI_FC_DBGAUD1CH7                      0x1217
+#define HDMI_FC_DBGAUD2CH7                      0x1218
+#define HDMI_FC_DBGTMDS0                        0x1219
+#define HDMI_FC_DBGTMDS1                        0x121A
+#define HDMI_FC_DBGTMDS2                        0x121B
+
+/* HDMI Source PHY Registers */
+#define HDMI_PHY_CONF0                          0x3000
+#define HDMI_PHY_TST0                           0x3001
+#define HDMI_PHY_TST1                           0x3002
+#define HDMI_PHY_TST2                           0x3003
+#define HDMI_PHY_STAT0                          0x3004
+#define HDMI_PHY_INT0                           0x3005
+#define HDMI_PHY_MASK0                          0x3006
+#define HDMI_PHY_POL0                           0x3007
+
+/* HDMI Master PHY Registers */
+#define HDMI_PHY_I2CM_SLAVE_ADDR                0x3020
+#define HDMI_PHY_I2CM_ADDRESS_ADDR              0x3021
+#define HDMI_PHY_I2CM_DATAO_1_ADDR              0x3022
+#define HDMI_PHY_I2CM_DATAO_0_ADDR              0x3023
+#define HDMI_PHY_I2CM_DATAI_1_ADDR              0x3024
+#define HDMI_PHY_I2CM_DATAI_0_ADDR              0x3025
+#define HDMI_PHY_I2CM_OPERATION_ADDR            0x3026
+#define HDMI_PHY_I2CM_INT_ADDR                  0x3027
+#define HDMI_PHY_I2CM_CTLINT_ADDR               0x3028
+#define HDMI_PHY_I2CM_DIV_ADDR                  0x3029
+#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR             0x302a
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR        0x302b
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR        0x302c
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR        0x302d
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR        0x302e
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR        0x302f
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR        0x3030
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR        0x3031
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR        0x3032
+
+/* Audio Sampler Registers */
+#define HDMI_AUD_CONF0                          0x3100
+#define HDMI_AUD_CONF1                          0x3101
+#define HDMI_AUD_INT                            0x3102
+#define HDMI_AUD_CONF2                          0x3103
+#define HDMI_AUD_N1                             0x3200
+#define HDMI_AUD_N2                             0x3201
+#define HDMI_AUD_N3                             0x3202
+#define HDMI_AUD_CTS1                           0x3203
+#define HDMI_AUD_CTS2                           0x3204
+#define HDMI_AUD_CTS3                           0x3205
+#define HDMI_AUD_INPUTCLKFS                     0x3206
+#define HDMI_AUD_SPDIFINT                      0x3302
+#define HDMI_AUD_CONF0_HBR                      0x3400
+#define HDMI_AUD_HBR_STATUS                     0x3401
+#define HDMI_AUD_HBR_INT                        0x3402
+#define HDMI_AUD_HBR_POL                        0x3403
+#define HDMI_AUD_HBR_MASK                       0x3404
+
+/*
+ * Generic Parallel Audio Interface Registers
+ * Not used as GPAUD interface is not enabled in hw
+ */
+#define HDMI_GP_CONF0                           0x3500
+#define HDMI_GP_CONF1                           0x3501
+#define HDMI_GP_CONF2                           0x3502
+#define HDMI_GP_STAT                            0x3503
+#define HDMI_GP_INT                             0x3504
+#define HDMI_GP_MASK                            0x3505
+#define HDMI_GP_POL                             0x3506
+
+/* Audio DMA Registers */
+#define HDMI_AHB_DMA_CONF0                      0x3600
+#define HDMI_AHB_DMA_START                      0x3601
+#define HDMI_AHB_DMA_STOP                       0x3602
+#define HDMI_AHB_DMA_THRSLD                     0x3603
+#define HDMI_AHB_DMA_STRADDR0                   0x3604
+#define HDMI_AHB_DMA_STRADDR1                   0x3605
+#define HDMI_AHB_DMA_STRADDR2                   0x3606
+#define HDMI_AHB_DMA_STRADDR3                   0x3607
+#define HDMI_AHB_DMA_STPADDR0                   0x3608
+#define HDMI_AHB_DMA_STPADDR1                   0x3609
+#define HDMI_AHB_DMA_STPADDR2                   0x360a
+#define HDMI_AHB_DMA_STPADDR3                   0x360b
+#define HDMI_AHB_DMA_BSTADDR0                   0x360c
+#define HDMI_AHB_DMA_BSTADDR1                   0x360d
+#define HDMI_AHB_DMA_BSTADDR2                   0x360e
+#define HDMI_AHB_DMA_BSTADDR3                   0x360f
+#define HDMI_AHB_DMA_MBLENGTH0                  0x3610
+#define HDMI_AHB_DMA_MBLENGTH1                  0x3611
+#define HDMI_AHB_DMA_STAT                       0x3612
+#define HDMI_AHB_DMA_INT                        0x3613
+#define HDMI_AHB_DMA_MASK                       0x3614
+#define HDMI_AHB_DMA_POL                        0x3615
+#define HDMI_AHB_DMA_CONF1                      0x3616
+#define HDMI_AHB_DMA_BUFFSTAT                   0x3617
+#define HDMI_AHB_DMA_BUFFINT                    0x3618
+#define HDMI_AHB_DMA_BUFFMASK                   0x3619
+#define HDMI_AHB_DMA_BUFFPOL                    0x361a
+
+/* Main Controller Registers */
+#define HDMI_MC_SFRDIV                          0x4000
+#define HDMI_MC_CLKDIS                          0x4001
+#define HDMI_MC_SWRSTZ                          0x4002
+#define HDMI_MC_OPCTRL                          0x4003
+#define HDMI_MC_FLOWCTRL                        0x4004
+#define HDMI_MC_PHYRSTZ                         0x4005
+#define HDMI_MC_LOCKONCLOCK                     0x4006
+#define HDMI_MC_HEACPHY_RST                     0x4007
+
+/* Color Space  Converter Registers */
+#define HDMI_CSC_CFG                            0x4100
+#define HDMI_CSC_SCALE                          0x4101
+#define HDMI_CSC_COEF_A1_MSB                    0x4102
+#define HDMI_CSC_COEF_A1_LSB                    0x4103
+#define HDMI_CSC_COEF_A2_MSB                    0x4104
+#define HDMI_CSC_COEF_A2_LSB                    0x4105
+#define HDMI_CSC_COEF_A3_MSB                    0x4106
+#define HDMI_CSC_COEF_A3_LSB                    0x4107
+#define HDMI_CSC_COEF_A4_MSB                    0x4108
+#define HDMI_CSC_COEF_A4_LSB                    0x4109
+#define HDMI_CSC_COEF_B1_MSB                    0x410A
+#define HDMI_CSC_COEF_B1_LSB                    0x410B
+#define HDMI_CSC_COEF_B2_MSB                    0x410C
+#define HDMI_CSC_COEF_B2_LSB                    0x410D
+#define HDMI_CSC_COEF_B3_MSB                    0x410E
+#define HDMI_CSC_COEF_B3_LSB                    0x410F
+#define HDMI_CSC_COEF_B4_MSB                    0x4110
+#define HDMI_CSC_COEF_B4_LSB                    0x4111
+#define HDMI_CSC_COEF_C1_MSB                    0x4112
+#define HDMI_CSC_COEF_C1_LSB                    0x4113
+#define HDMI_CSC_COEF_C2_MSB                    0x4114
+#define HDMI_CSC_COEF_C2_LSB                    0x4115
+#define HDMI_CSC_COEF_C3_MSB                    0x4116
+#define HDMI_CSC_COEF_C3_LSB                    0x4117
+#define HDMI_CSC_COEF_C4_MSB                    0x4118
+#define HDMI_CSC_COEF_C4_LSB                    0x4119
+
+/* HDCP Encryption Engine Registers */
+#define HDMI_A_HDCPCFG0                         0x5000
+#define HDMI_A_HDCPCFG1                         0x5001
+#define HDMI_A_HDCPOBS0                         0x5002
+#define HDMI_A_HDCPOBS1                         0x5003
+#define HDMI_A_HDCPOBS2                         0x5004
+#define HDMI_A_HDCPOBS3                         0x5005
+#define HDMI_A_APIINTCLR                        0x5006
+#define HDMI_A_APIINTSTAT                       0x5007
+#define HDMI_A_APIINTMSK                        0x5008
+#define HDMI_A_VIDPOLCFG                        0x5009
+#define HDMI_A_OESSWCFG                         0x500A
+#define HDMI_A_TIMER1SETUP0                     0x500B
+#define HDMI_A_TIMER1SETUP1                     0x500C
+#define HDMI_A_TIMER2SETUP0                     0x500D
+#define HDMI_A_TIMER2SETUP1                     0x500E
+#define HDMI_A_100MSCFG                         0x500F
+#define HDMI_A_2SCFG0                           0x5010
+#define HDMI_A_2SCFG1                           0x5011
+#define HDMI_A_5SCFG0                           0x5012
+#define HDMI_A_5SCFG1                           0x5013
+#define HDMI_A_SRMVERLSB                        0x5014
+#define HDMI_A_SRMVERMSB                        0x5015
+#define HDMI_A_SRMCTRL                          0x5016
+#define HDMI_A_SFRSETUP                         0x5017
+#define HDMI_A_I2CHSETUP                        0x5018
+#define HDMI_A_INTSETUP                         0x5019
+#define HDMI_A_PRESETUP                         0x501A
+#define HDMI_A_SRM_BASE                         0x5020
+
+/* CEC Engine Registers */
+#define HDMI_CEC_CTRL                           0x7D00
+#define HDMI_CEC_STAT                           0x7D01
+#define HDMI_CEC_MASK                           0x7D02
+#define HDMI_CEC_POLARITY                       0x7D03
+#define HDMI_CEC_INT                            0x7D04
+#define HDMI_CEC_ADDR_L                         0x7D05
+#define HDMI_CEC_ADDR_H                         0x7D06
+#define HDMI_CEC_TX_CNT                         0x7D07
+#define HDMI_CEC_RX_CNT                         0x7D08
+#define HDMI_CEC_TX_DATA0                       0x7D10
+#define HDMI_CEC_TX_DATA1                       0x7D11
+#define HDMI_CEC_TX_DATA2                       0x7D12
+#define HDMI_CEC_TX_DATA3                       0x7D13
+#define HDMI_CEC_TX_DATA4                       0x7D14
+#define HDMI_CEC_TX_DATA5                       0x7D15
+#define HDMI_CEC_TX_DATA6                       0x7D16
+#define HDMI_CEC_TX_DATA7                       0x7D17
+#define HDMI_CEC_TX_DATA8                       0x7D18
+#define HDMI_CEC_TX_DATA9                       0x7D19
+#define HDMI_CEC_TX_DATA10                      0x7D1a
+#define HDMI_CEC_TX_DATA11                      0x7D1b
+#define HDMI_CEC_TX_DATA12                      0x7D1c
+#define HDMI_CEC_TX_DATA13                      0x7D1d
+#define HDMI_CEC_TX_DATA14                      0x7D1e
+#define HDMI_CEC_TX_DATA15                      0x7D1f
+#define HDMI_CEC_RX_DATA0                       0x7D20
+#define HDMI_CEC_RX_DATA1                       0x7D21
+#define HDMI_CEC_RX_DATA2                       0x7D22
+#define HDMI_CEC_RX_DATA3                       0x7D23
+#define HDMI_CEC_RX_DATA4                       0x7D24
+#define HDMI_CEC_RX_DATA5                       0x7D25
+#define HDMI_CEC_RX_DATA6                       0x7D26
+#define HDMI_CEC_RX_DATA7                       0x7D27
+#define HDMI_CEC_RX_DATA8                       0x7D28
+#define HDMI_CEC_RX_DATA9                       0x7D29
+#define HDMI_CEC_RX_DATA10                      0x7D2a
+#define HDMI_CEC_RX_DATA11                      0x7D2b
+#define HDMI_CEC_RX_DATA12                      0x7D2c
+#define HDMI_CEC_RX_DATA13                      0x7D2d
+#define HDMI_CEC_RX_DATA14                      0x7D2e
+#define HDMI_CEC_RX_DATA15                      0x7D2f
+#define HDMI_CEC_LOCK                           0x7D30
+#define HDMI_CEC_WKUPCTRL                       0x7D31
+
+/* I2C Master Registers (E-DDC) */
+#define HDMI_I2CM_SLAVE                         0x7E00
+#define HDMI_I2CM_ADDRESS                       0x7E01
+#define HDMI_I2CM_DATAO                         0x7E02
+#define HDMI_I2CM_DATAI                         0x7E03
+#define HDMI_I2CM_OPERATION                     0x7E04
+#define HDMI_I2CM_INT                           0x7E05
+#define HDMI_I2CM_CTLINT                        0x7E06
+#define HDMI_I2CM_DIV                           0x7E07
+#define HDMI_I2CM_SEGADDR                       0x7E08
+#define HDMI_I2CM_SOFTRSTZ                      0x7E09
+#define HDMI_I2CM_SEGPTR                        0x7E0A
+#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR            0x7E0B
+#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR            0x7E0C
+#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR            0x7E0D
+#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR            0x7E0E
+#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR            0x7E0F
+#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR            0x7E10
+#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR            0x7E11
+#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
+
+enum {
+/* PRODUCT_ID0 field values */
+       HDMI_PRODUCT_ID0_HDMI_TX = 0xa0,
+
+/* PRODUCT_ID1 field values */
+       HDMI_PRODUCT_ID1_HDCP = 0xc0,
+       HDMI_PRODUCT_ID1_HDMI_RX = 0x02,
+       HDMI_PRODUCT_ID1_HDMI_TX = 0x01,
+
+/* CONFIG0_ID field values */
+       HDMI_CONFIG0_I2S = 0x10,
+
+/* CONFIG1_ID field values */
+       HDMI_CONFIG1_AHB = 0x01,
+
+/* CONFIG3_ID field values */
+       HDMI_CONFIG3_AHBAUDDMA = 0x02,
+       HDMI_CONFIG3_GPAUD = 0x01,
+
+/* IH_FC_INT2 field values */
+       HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
+       HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+       HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_FC_STAT2 field values */
+       HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
+       HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+       HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_PHY_STAT0 field values */
+       HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
+       HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
+       HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
+       HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
+       HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
+       HDMI_IH_PHY_STAT0_HPD = 0x1,
+
+/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */
+       HDMI_IH_I2CM_STAT0_DONE = 0x2,
+       HDMI_IH_I2CM_STAT0_ERROR = 0x1,
+
+/* IH_MUTE_I2CMPHY_STAT0 field values */
+       HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
+       HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
+
+/* IH_AHBDMAAUD_STAT0 field values */
+       HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
+       HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
+       HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
+       HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
+       HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+       HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE_FC_STAT2 field values */
+       HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
+       HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+       HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_MUTE_AHBDMAAUD_STAT0 field values */
+       HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
+       HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
+       HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
+       HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
+       HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+       HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE field values */
+       HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
+       HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
+
+/* TX_INVID0 field values */
+       HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80,
+       HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
+       HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
+       HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F,
+       HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
+
+/* TX_INSTUFFING field values */
+       HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4,
+       HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
+       HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
+       HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
+       HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
+       HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
+       HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
+       HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
+       HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
+
+/* VP_PR_CD field values */
+       HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0,
+       HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
+       HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F,
+       HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
+
+/* VP_STUFF field values */
+       HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
+       HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
+       HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10,
+       HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
+       HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
+       HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
+       HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
+       HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
+       HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
+       HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
+       HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
+       HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
+       HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
+       HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
+       HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
+
+/* VP_CONF field values */
+       HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
+       HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
+       HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
+       HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
+       HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
+       HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
+       HDMI_VP_CONF_PR_EN_MASK = 0x10,
+       HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
+       HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
+       HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
+       HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8,
+       HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
+       HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
+       HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
+       HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0,
+       HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
+       HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
+       HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
+       HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
+
+/* VP_REMAP field values */
+       HDMI_VP_REMAP_MASK = 0x3,
+       HDMI_VP_REMAP_YCC422_24bit = 0x2,
+       HDMI_VP_REMAP_YCC422_20bit = 0x1,
+       HDMI_VP_REMAP_YCC422_16bit = 0x0,
+
+/* FC_INVIDCONF field values */
+       HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80,
+       HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80,
+       HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00,
+       HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
+       HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
+       HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+       HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
+       HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
+       HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+       HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
+       HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
+       HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
+       HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
+       HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
+       HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
+       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
+       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
+       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
+       HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
+       HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
+       HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
+
+/* FC_AUDICONF0 field values */
+       HDMI_FC_AUDICONF0_CC_OFFSET = 4,
+       HDMI_FC_AUDICONF0_CC_MASK = 0x70,
+       HDMI_FC_AUDICONF0_CT_OFFSET = 0,
+       HDMI_FC_AUDICONF0_CT_MASK = 0xF,
+
+/* FC_AUDICONF1 field values */
+       HDMI_FC_AUDICONF1_SS_OFFSET = 3,
+       HDMI_FC_AUDICONF1_SS_MASK = 0x18,
+       HDMI_FC_AUDICONF1_SF_OFFSET = 0,
+       HDMI_FC_AUDICONF1_SF_MASK = 0x7,
+
+/* FC_AUDICONF3 field values */
+       HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
+       HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
+       HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
+       HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
+       HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
+       HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
+
+/* FC_AUDSCHNLS0 field values */
+       HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
+       HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
+       HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
+
+/* FC_AUDSCHNLS3-6 field values */
+       HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
+       HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
+       HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
+       HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
+       HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
+       HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
+
+       HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
+       HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
+       HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
+       HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
+       HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
+       HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
+
+/* HDMI_FC_AUDSCHNLS7 field values */
+       HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
+
+/* HDMI_FC_AUDSCHNLS8 field values */
+       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
+       HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
+       HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
+       HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
+
+/* FC_AUDSCONF field values */
+       HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
+       HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
+       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
+       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
+       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
+       HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
+
+/* FC_STAT2 field values */
+       HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
+       HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+       HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_INT2 field values */
+       HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
+       HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+       HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_MASK2 field values */
+       HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
+       HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
+       HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_PRCONF field values */
+       HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
+       HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
+       HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
+       HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
+
+/* FC_AVICONF0-FC_AVICONF3 field values */
+       HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
+       HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
+       HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
+       HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
+       HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
+       HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
+       HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
+       HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C,
+       HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
+       HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
+       HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
+       HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C,
+       HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
+       HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
+       HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
+       HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
+
+       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F,
+       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
+       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
+       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A,
+       HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B,
+       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
+       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
+       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
+       HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
+       HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0,
+       HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
+       HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
+       HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
+       HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0,
+
+       HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
+       HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
+       HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
+       HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
+       HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03,
+       HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C,
+       HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
+       HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
+       HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
+       HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
+       HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
+       HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
+       HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
+       HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
+       HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
+       HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
+       HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
+       HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
+
+       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
+       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
+       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
+       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
+       HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
+       HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C,
+       HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
+       HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
+
+/* FC_DBGFORCE field values */
+       HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
+       HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
+
+/* PHY_CONF0 field values */
+       HDMI_PHY_CONF0_PDZ_MASK = 0x80,
+       HDMI_PHY_CONF0_PDZ_OFFSET = 7,
+       HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
+       HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
+       HDMI_PHY_CONF0_SVSRET_MASK = 0x20,
+       HDMI_PHY_CONF0_SVSRET_OFFSET = 5,
+       HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
+       HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
+       HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
+       HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
+       HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4,
+       HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
+       HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
+       HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
+       HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
+       HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
+
+/* PHY_TST0 field values */
+       HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
+       HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
+       HDMI_PHY_TST0_TSTEN_MASK = 0x10,
+       HDMI_PHY_TST0_TSTEN_OFFSET = 4,
+       HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
+       HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
+
+/* PHY_STAT0 field values */
+       HDMI_PHY_RX_SENSE3 = 0x80,
+       HDMI_PHY_RX_SENSE2 = 0x40,
+       HDMI_PHY_RX_SENSE1 = 0x20,
+       HDMI_PHY_RX_SENSE0 = 0x10,
+       HDMI_PHY_HPD = 0x02,
+       HDMI_PHY_TX_PHY_LOCK = 0x01,
+
+/* PHY_I2CM_SLAVE_ADDR field values */
+       HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
+       HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
+
+/* PHY_I2CM_OPERATION_ADDR field values */
+       HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
+       HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
+
+/* HDMI_PHY_I2CM_INT_ADDR */
+       HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
+       HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
+
+/* HDMI_PHY_I2CM_CTLINT_ADDR */
+       HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
+       HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
+       HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
+       HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
+
+/* AUD_CONF0 field values */
+       HDMI_AUD_CONF0_SW_RESET = 0x80,
+       HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F,
+
+/* AUD_CONF1 field values */
+       HDMI_AUD_CONF1_MODE_I2S = 0x00,
+       HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02,
+       HDMI_AUD_CONF1_MODE_LEFT_J = 0x04,
+       HDMI_AUD_CONF1_WIDTH_16 = 0x10,
+       HDMI_AUD_CONF1_WIDTH_24 = 0x18,
+
+/* AUD_CTS3 field values */
+       HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
+       HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
+       HDMI_AUD_CTS3_N_SHIFT_1 = 0,
+       HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
+       HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
+       HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
+       HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
+       HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
+       /* note that the CTS3 MANUAL bit has been removed
+          from our part. Can't set it, will read as 0. */
+       HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
+       HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
+
+/* HDMI_AUD_INPUTCLKFS field values */
+       HDMI_AUD_INPUTCLKFS_128FS = 0,
+       HDMI_AUD_INPUTCLKFS_256FS = 1,
+       HDMI_AUD_INPUTCLKFS_512FS = 2,
+       HDMI_AUD_INPUTCLKFS_64FS = 4,
+
+/* AHB_DMA_CONF0 field values */
+       HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
+       HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
+       HDMI_AHB_DMA_CONF0_HBR = 0x10,
+       HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
+       HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
+       HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
+       HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
+       HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
+       HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
+       HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
+       HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
+
+/* HDMI_AHB_DMA_START field values */
+       HDMI_AHB_DMA_START_START_OFFSET = 0,
+       HDMI_AHB_DMA_START_START_MASK = 0x01,
+
+/* HDMI_AHB_DMA_STOP field values */
+       HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
+       HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
+
+/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
+       HDMI_AHB_DMA_DONE = 0x80,
+       HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
+       HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
+       HDMI_AHB_DMA_ERROR = 0x10,
+       HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
+       HDMI_AHB_DMA_FIFO_FULL = 0x02,
+       HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
+
+/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */
+       HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
+       HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
+
+/* MC_CLKDIS field values */
+       HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
+       HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
+       HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
+       HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
+       HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
+       HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
+       HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
+
+/* MC_SWRSTZ field values */
+       HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
+
+/* MC_FLOWCTRL field values */
+       HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
+       HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
+       HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
+
+/* MC_PHYRSTZ field values */
+       HDMI_MC_PHYRSTZ_PHYRSTZ = 0x01,
+
+/* MC_HEACPHY_RST field values */
+       HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
+       HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
+
+/* CSC_CFG field values */
+       HDMI_CSC_CFG_INTMODE_MASK = 0x30,
+       HDMI_CSC_CFG_INTMODE_OFFSET = 4,
+       HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
+       HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
+       HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
+       HDMI_CSC_CFG_DECMODE_MASK = 0x3,
+       HDMI_CSC_CFG_DECMODE_OFFSET = 0,
+       HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
+       HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
+       HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
+       HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
+
+/* CSC_SCALE field values */
+       HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0,
+       HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
+       HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
+       HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
+       HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
+       HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
+
+/* A_HDCPCFG0 field values */
+       HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80,
+       HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80,
+       HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00,
+       HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40,
+       HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40,
+       HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00,
+       HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20,
+       HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20,
+       HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00,
+       HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10,
+       HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10,
+       HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00,
+       HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8,
+       HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8,
+       HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0,
+       HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4,
+       HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4,
+       HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0,
+       HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2,
+       HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2,
+       HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0,
+       HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1,
+       HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1,
+       HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0,
+
+/* A_HDCPCFG1 field values */
+       HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8,
+       HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8,
+       HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0,
+       HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4,
+       HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4,
+       HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0,
+       HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2,
+       HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2,
+       HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0,
+       HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1,
+       HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0,
+
+/* A_VIDPOLCFG field values */
+       HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60,
+       HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5,
+       HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10,
+       HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10,
+       HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0,
+       HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8,
+       HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8,
+       HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0,
+       HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
+       HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
+       HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
+
+/* I2CM_OPERATION field values */
+       HDMI_I2CM_OPERATION_WRITE = 0x10,
+       HDMI_I2CM_OPERATION_READ_EXT = 0x2,
+       HDMI_I2CM_OPERATION_READ = 0x1,
+
+/* I2CM_INT field values */
+       HDMI_I2CM_INT_DONE_POL = 0x8,
+       HDMI_I2CM_INT_DONE_MASK = 0x4,
+
+/* I2CM_CTLINT field values */
+       HDMI_I2CM_CTLINT_NAC_POL = 0x80,
+       HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
+       HDMI_I2CM_CTLINT_ARB_POL = 0x8,
+       HDMI_I2CM_CTLINT_ARB_MASK = 0x4,
+};
+
+/*
+ * HDMI 3D TX PHY registers
+ */
+#define HDMI_3D_TX_PHY_PWRCTRL                 0x00
+#define HDMI_3D_TX_PHY_SERDIVCTRL              0x01
+#define HDMI_3D_TX_PHY_SERCKCTRL               0x02
+#define HDMI_3D_TX_PHY_SERCKKILLCTRL           0x03
+#define HDMI_3D_TX_PHY_TXRESCTRL               0x04
+#define HDMI_3D_TX_PHY_CKCALCTRL               0x05
+#define HDMI_3D_TX_PHY_CPCE_CTRL               0x06
+#define HDMI_3D_TX_PHY_TXCLKMEASCTRL           0x07
+#define HDMI_3D_TX_PHY_TXMEASCTRL              0x08
+#define HDMI_3D_TX_PHY_CKSYMTXCTRL             0x09
+#define HDMI_3D_TX_PHY_CMPSEQCTRL              0x0a
+#define HDMI_3D_TX_PHY_CMPPWRCTRL              0x0b
+#define HDMI_3D_TX_PHY_CMPMODECTRL             0x0c
+#define HDMI_3D_TX_PHY_MEASCTRL                        0x0d
+#define HDMI_3D_TX_PHY_VLEVCTRL                        0x0e
+#define HDMI_3D_TX_PHY_D2ACTRL                 0x0f
+#define HDMI_3D_TX_PHY_CURRCTRL                        0x10
+#define HDMI_3D_TX_PHY_DRVANACTRL              0x11
+#define HDMI_3D_TX_PHY_PLLMEASCTRL             0x12
+#define HDMI_3D_TX_PHY_PLLPHBYCTRL             0x13
+#define HDMI_3D_TX_PHY_GRP_CTRL                        0x14
+#define HDMI_3D_TX_PHY_GMPCTRL                 0x15
+#define HDMI_3D_TX_PHY_MPLLMEASCTRL            0x16
+#define HDMI_3D_TX_PHY_MSM_CTRL                        0x17
+#define HDMI_3D_TX_PHY_SCRPB_STATUS            0x18
+#define HDMI_3D_TX_PHY_TXTERM                  0x19
+#define HDMI_3D_TX_PHY_PTRPT_ENBL              0x1a
+#define HDMI_3D_TX_PHY_PATTERNGEN              0x1b
+#define HDMI_3D_TX_PHY_SDCAP_MODE              0x1c
+#define HDMI_3D_TX_PHY_SCOPEMODE               0x1d
+#define HDMI_3D_TX_PHY_DIGTXMODE               0x1e
+#define HDMI_3D_TX_PHY_STR_STATUS              0x1f
+#define HDMI_3D_TX_PHY_SCOPECNT0               0x20
+#define HDMI_3D_TX_PHY_SCOPECNT1               0x21
+#define HDMI_3D_TX_PHY_SCOPECNT2               0x22
+#define HDMI_3D_TX_PHY_SCOPECNTCLK             0x23
+#define HDMI_3D_TX_PHY_SCOPESAMPLE             0x24
+#define HDMI_3D_TX_PHY_SCOPECNTMSB01           0x25
+#define HDMI_3D_TX_PHY_SCOPECNTMSB2CK          0x26
+
+/* HDMI_3D_TX_PHY_CKCALCTRL values */
+#define HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE              BIT(15)
+
+/* HDMI_3D_TX_PHY_MSM_CTRL values */
+#define HDMI_3D_TX_PHY_MSM_CTRL_MPLL_PH_SEL_CK         BIT(13)
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_CLK_REF_MPLL   (0 << 1)
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_OFF            (1 << 1)
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_PCLK           (2 << 1)
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK         (3 << 1)
+#define HDMI_3D_TX_PHY_MSM_CTRL_SCOPE_CK_SEL           BIT(0)
+
+/* HDMI_3D_TX_PHY_PTRPT_ENBL values */
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_OVERRIDE             BIT(15)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT2         BIT(8)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT1         BIT(7)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT0         BIT(6)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_CK_REF_ENB           BIT(5)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_RCAL_ENB             BIT(4)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_CLK_ALIGN_ENB     BIT(3)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_READY             BIT(2)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_CKO_WORD_ENB         BIT(1)
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_REFCLK_ENB           BIT(0)
+
+#endif /* __DW_HDMI_H__ */
index 236d947..9b892af 100644 (file)
@@ -1374,8 +1374,8 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                return 0;
 
        if (conn_state->crtc) {
-               crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state,
-                                                               conn_state->crtc);
+               crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
+                                                          conn_state->crtc);
 
                crtc_state->connector_mask &=
                        ~(1 << drm_connector_index(conn_state->connector));
@@ -1492,7 +1492,7 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 {
        struct drm_plane *plane;
 
-       WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc));
+       WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
 
        drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
                struct drm_plane_state *plane_state =
index 6b12396..4e26b73 100644 (file)
  */
 static void
 drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
+                               struct drm_plane_state *old_plane_state,
                                struct drm_plane_state *plane_state,
                                struct drm_plane *plane)
 {
        struct drm_crtc_state *crtc_state;
 
-       if (plane->state->crtc) {
-               crtc_state = drm_atomic_get_existing_crtc_state(state,
-                                                               plane->state->crtc);
+       if (old_plane_state->crtc) {
+               crtc_state = drm_atomic_get_new_crtc_state(state,
+                                                          old_plane_state->crtc);
 
                if (WARN_ON(!crtc_state))
                        return;
@@ -79,8 +80,7 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
        }
 
        if (plane_state->crtc) {
-               crtc_state = drm_atomic_get_existing_crtc_state(state,
-                                                               plane_state->crtc);
+               crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
 
                if (WARN_ON(!crtc_state))
                        return;
@@ -92,7 +92,7 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
 static int handle_conflicting_encoders(struct drm_atomic_state *state,
                                       bool disable_conflicting_encoders)
 {
-       struct drm_connector_state *conn_state;
+       struct drm_connector_state *new_conn_state;
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
        struct drm_encoder *encoder;
@@ -104,15 +104,15 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
         * part of the state. If the same encoder is assigned to multiple
         * connectors bail out.
         */
-       for_each_connector_in_state(state, connector, conn_state, i) {
+       for_each_new_connector_in_state(state, connector, new_conn_state, i) {
                const struct drm_connector_helper_funcs *funcs = connector->helper_private;
                struct drm_encoder *new_encoder;
 
-               if (!conn_state->crtc)
+               if (!new_conn_state->crtc)
                        continue;
 
                if (funcs->atomic_best_encoder)
-                       new_encoder = funcs->atomic_best_encoder(connector, conn_state);
+                       new_encoder = funcs->atomic_best_encoder(connector, new_conn_state);
                else if (funcs->best_encoder)
                        new_encoder = funcs->best_encoder(connector);
                else
@@ -149,7 +149,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
        drm_for_each_connector_iter(connector, &conn_iter) {
                struct drm_crtc_state *crtc_state;
 
-               if (drm_atomic_get_existing_connector_state(state, connector))
+               if (drm_atomic_get_new_connector_state(state, connector))
                        continue;
 
                encoder = connector->state->best_encoder;
@@ -166,20 +166,20 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
                        goto out;
                }
 
-               conn_state = drm_atomic_get_connector_state(state, connector);
-               if (IS_ERR(conn_state)) {
-                       ret = PTR_ERR(conn_state);
+               new_conn_state = drm_atomic_get_connector_state(state, connector);
+               if (IS_ERR(new_conn_state)) {
+                       ret = PTR_ERR(new_conn_state);
                        goto out;
                }
 
                DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n",
                                 encoder->base.id, encoder->name,
-                                conn_state->crtc->base.id, conn_state->crtc->name,
+                                new_conn_state->crtc->base.id, new_conn_state->crtc->name,
                                 connector->base.id, connector->name);
 
-               crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc);
+               crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
 
-               ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
+               ret = drm_atomic_set_crtc_for_connector(new_conn_state, NULL);
                if (ret)
                        goto out;
 
@@ -218,7 +218,7 @@ set_best_encoder(struct drm_atomic_state *state,
                 */
                WARN_ON(!crtc && encoder != conn_state->best_encoder);
                if (crtc) {
-                       crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
+                       crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 
                        crtc_state->encoder_mask &=
                                ~(1 << drm_encoder_index(conn_state->best_encoder));
@@ -229,7 +229,7 @@ set_best_encoder(struct drm_atomic_state *state,
                crtc = conn_state->crtc;
                WARN_ON(!crtc);
                if (crtc) {
-                       crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
+                       crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 
                        crtc_state->encoder_mask |=
                                1 << drm_encoder_index(encoder);
@@ -245,24 +245,24 @@ steal_encoder(struct drm_atomic_state *state,
 {
        struct drm_crtc_state *crtc_state;
        struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
+       struct drm_connector_state *old_connector_state, *new_connector_state;
        int i;
 
-       for_each_connector_in_state(state, connector, connector_state, i) {
+       for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
                struct drm_crtc *encoder_crtc;
 
-               if (connector_state->best_encoder != encoder)
+               if (new_connector_state->best_encoder != encoder)
                        continue;
 
-               encoder_crtc = connector->state->crtc;
+               encoder_crtc = old_connector_state->crtc;
 
                DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n",
                                 encoder->base.id, encoder->name,
                                 encoder_crtc->base.id, encoder_crtc->name);
 
-               set_best_encoder(state, connector_state, NULL);
+               set_best_encoder(state, new_connector_state, NULL);
 
-               crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc);
+               crtc_state = drm_atomic_get_new_crtc_state(state, encoder_crtc);
                crtc_state->connectors_changed = true;
 
                return;
@@ -272,7 +272,8 @@ steal_encoder(struct drm_atomic_state *state,
 static int
 update_connector_routing(struct drm_atomic_state *state,
                         struct drm_connector *connector,
-                        struct drm_connector_state *connector_state)
+                        struct drm_connector_state *old_connector_state,
+                        struct drm_connector_state *new_connector_state)
 {
        const struct drm_connector_helper_funcs *funcs;
        struct drm_encoder *new_encoder;
@@ -282,24 +283,24 @@ update_connector_routing(struct drm_atomic_state *state,
                         connector->base.id,
                         connector->name);
 
-       if (connector->state->crtc != connector_state->crtc) {
-               if (connector->state->crtc) {
-                       crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc);
+       if (old_connector_state->crtc != new_connector_state->crtc) {
+               if (old_connector_state->crtc) {
+                       crtc_state = drm_atomic_get_new_crtc_state(state, old_connector_state->crtc);
                        crtc_state->connectors_changed = true;
                }
 
-               if (connector_state->crtc) {
-                       crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc);
+               if (new_connector_state->crtc) {
+                       crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc);
                        crtc_state->connectors_changed = true;
                }
        }
 
-       if (!connector_state->crtc) {
+       if (!new_connector_state->crtc) {
                DRM_DEBUG_ATOMIC("Disabling [CONNECTOR:%d:%s]\n",
                                connector->base.id,
                                connector->name);
 
-               set_best_encoder(state, connector_state, NULL);
+               set_best_encoder(state, new_connector_state, NULL);
 
                return 0;
        }
@@ -308,7 +309,7 @@ update_connector_routing(struct drm_atomic_state *state,
 
        if (funcs->atomic_best_encoder)
                new_encoder = funcs->atomic_best_encoder(connector,
-                                                        connector_state);
+                                                        new_connector_state);
        else if (funcs->best_encoder)
                new_encoder = funcs->best_encoder(connector);
        else
@@ -321,34 +322,34 @@ update_connector_routing(struct drm_atomic_state *state,
                return -EINVAL;
        }
 
-       if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
+       if (!drm_encoder_crtc_ok(new_encoder, new_connector_state->crtc)) {
                DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d:%s]\n",
                                 new_encoder->base.id,
                                 new_encoder->name,
-                                connector_state->crtc->base.id,
-                                connector_state->crtc->name);
+                                new_connector_state->crtc->base.id,
+                                new_connector_state->crtc->name);
                return -EINVAL;
        }
 
-       if (new_encoder == connector_state->best_encoder) {
-               set_best_encoder(state, connector_state, new_encoder);
+       if (new_encoder == new_connector_state->best_encoder) {
+               set_best_encoder(state, new_connector_state, new_encoder);
 
                DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n",
                                 connector->base.id,
                                 connector->name,
                                 new_encoder->base.id,
                                 new_encoder->name,
-                                connector_state->crtc->base.id,
-                                connector_state->crtc->name);
+                                new_connector_state->crtc->base.id,
+                                new_connector_state->crtc->name);
 
                return 0;
        }
 
        steal_encoder(state, new_encoder);
 
-       set_best_encoder(state, connector_state, new_encoder);
+       set_best_encoder(state, new_connector_state, new_encoder);
 
-       crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc);
+       crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc);
        crtc_state->connectors_changed = true;
 
        DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n",
@@ -356,8 +357,8 @@ update_connector_routing(struct drm_atomic_state *state,
                         connector->name,
                         new_encoder->base.id,
                         new_encoder->name,
-                        connector_state->crtc->base.id,
-                        connector_state->crtc->name);
+                        new_connector_state->crtc->base.id,
+                        new_connector_state->crtc->name);
 
        return 0;
 }
@@ -366,57 +367,57 @@ static int
 mode_fixup(struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_connector *connector;
-       struct drm_connector_state *conn_state;
+       struct drm_connector_state *new_conn_state;
        int i;
        int ret;
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               if (!crtc_state->mode_changed &&
-                   !crtc_state->connectors_changed)
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+               if (!new_crtc_state->mode_changed &&
+                   !new_crtc_state->connectors_changed)
                        continue;
 
-               drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
+               drm_mode_copy(&new_crtc_state->adjusted_mode, &new_crtc_state->mode);
        }
 
-       for_each_connector_in_state(state, connector, conn_state, i) {
+       for_each_new_connector_in_state(state, connector, new_conn_state, i) {
                const struct drm_encoder_helper_funcs *funcs;
                struct drm_encoder *encoder;
 
-               WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc);
+               WARN_ON(!!new_conn_state->best_encoder != !!new_conn_state->crtc);
 
-               if (!conn_state->crtc || !conn_state->best_encoder)
+               if (!new_conn_state->crtc || !new_conn_state->best_encoder)
                        continue;
 
-               crtc_state = drm_atomic_get_existing_crtc_state(state,
-                                                               conn_state->crtc);
+               new_crtc_state =
+                       drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
 
                /*
                 * Each encoder has at most one connector (since we always steal
                 * it away), so we won't call ->mode_fixup twice.
                 */
-               encoder = conn_state->best_encoder;
+               encoder = new_conn_state->best_encoder;
                funcs = encoder->helper_private;
 
-               ret = drm_bridge_mode_fixup(encoder->bridge, &crtc_state->mode,
-                               &crtc_state->adjusted_mode);
+               ret = drm_bridge_mode_fixup(encoder->bridge, &new_crtc_state->mode,
+                               &new_crtc_state->adjusted_mode);
                if (!ret) {
                        DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
                        return -EINVAL;
                }
 
                if (funcs && funcs->atomic_check) {
-                       ret = funcs->atomic_check(encoder, crtc_state,
-                                                 conn_state);
+                       ret = funcs->atomic_check(encoder, new_crtc_state,
+                                                 new_conn_state);
                        if (ret) {
                                DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] check failed\n",
                                                 encoder->base.id, encoder->name);
                                return ret;
                        }
                } else if (funcs && funcs->mode_fixup) {
-                       ret = funcs->mode_fixup(encoder, &crtc_state->mode,
-                                               &crtc_state->adjusted_mode);
+                       ret = funcs->mode_fixup(encoder, &new_crtc_state->mode,
+                                               &new_crtc_state->adjusted_mode);
                        if (!ret) {
                                DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n",
                                                 encoder->base.id, encoder->name);
@@ -425,22 +426,22 @@ mode_fixup(struct drm_atomic_state *state)
                }
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
-               if (!crtc_state->enable)
+               if (!new_crtc_state->enable)
                        continue;
 
-               if (!crtc_state->mode_changed &&
-                   !crtc_state->connectors_changed)
+               if (!new_crtc_state->mode_changed &&
+                   !new_crtc_state->connectors_changed)
                        continue;
 
                funcs = crtc->helper_private;
                if (!funcs->mode_fixup)
                        continue;
 
-               ret = funcs->mode_fixup(crtc, &crtc_state->mode,
-                                       &crtc_state->adjusted_mode);
+               ret = funcs->mode_fixup(crtc, &new_crtc_state->mode,
+                                       &new_crtc_state->adjusted_mode);
                if (!ret) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] fixup failed\n",
                                         crtc->base.id, crtc->name);
@@ -487,19 +488,19 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                                struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
+       struct drm_connector_state *old_connector_state, *new_connector_state;
        int i, ret;
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n",
                                         crtc->base.id, crtc->name);
-                       crtc_state->mode_changed = true;
+                       new_crtc_state->mode_changed = true;
                }
 
-               if (crtc->state->enable != crtc_state->enable) {
+               if (old_crtc_state->enable != new_crtc_state->enable) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enable changed\n",
                                         crtc->base.id, crtc->name);
 
@@ -511,8 +512,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                         * The other way around is true as well. enable != 0
                         * iff connectors are attached and a mode is set.
                         */
-                       crtc_state->mode_changed = true;
-                       crtc_state->connectors_changed = true;
+                       new_crtc_state->mode_changed = true;
+                       new_crtc_state->connectors_changed = true;
                }
        }
 
@@ -520,22 +521,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
        if (ret)
                return ret;
 
-       for_each_connector_in_state(state, connector, connector_state, i) {
+       for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
                /*
                 * This only sets crtc->connectors_changed for routing changes,
                 * drivers must set crtc->connectors_changed themselves when
                 * connector properties need to be updated.
                 */
                ret = update_connector_routing(state, connector,
-                                              connector_state);
+                                              old_connector_state,
+                                              new_connector_state);
                if (ret)
                        return ret;
-               if (connector->state->crtc) {
-                       crtc_state = drm_atomic_get_existing_crtc_state(state,
-                                                                       connector->state->crtc);
-                       if (connector->state->link_status !=
-                           connector_state->link_status)
-                               crtc_state->connectors_changed = true;
+               if (old_connector_state->crtc) {
+                       new_crtc_state = drm_atomic_get_new_crtc_state(state,
+                                                                      old_connector_state->crtc);
+                       if (old_connector_state->link_status !=
+                           new_connector_state->link_status)
+                               new_crtc_state->connectors_changed = true;
                }
        }
 
@@ -545,28 +547,28 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
         * configuration. This must be done before calling mode_fixup in case a
         * crtc only changed its mode but has the same set of connectors.
         */
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                bool has_connectors =
-                       !!crtc_state->connector_mask;
+                       !!new_crtc_state->connector_mask;
 
                /*
                 * We must set ->active_changed after walking connectors for
                 * otherwise an update that only changes active would result in
                 * a full modeset because update_connector_routing force that.
                 */
-               if (crtc->state->active != crtc_state->active) {
+               if (old_crtc_state->active != new_crtc_state->active) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n",
                                         crtc->base.id, crtc->name);
-                       crtc_state->active_changed = true;
+                       new_crtc_state->active_changed = true;
                }
 
-               if (!drm_atomic_crtc_needs_modeset(crtc_state))
+               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
                        continue;
 
                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] needs all connectors, enable: %c, active: %c\n",
                                 crtc->base.id, crtc->name,
-                                crtc_state->enable ? 'y' : 'n',
-                                crtc_state->active ? 'y' : 'n');
+                                new_crtc_state->enable ? 'y' : 'n',
+                                new_crtc_state->active ? 'y' : 'n');
 
                ret = drm_atomic_add_affected_connectors(state, crtc);
                if (ret != 0)
@@ -576,7 +578,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                if (ret != 0)
                        return ret;
 
-               if (crtc_state->enable != has_connectors) {
+               if (new_crtc_state->enable != has_connectors) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n",
                                         crtc->base.id, crtc->name);
 
@@ -609,22 +611,22 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
                               struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *new_plane_state, *old_plane_state;
        int i, ret = 0;
 
-       for_each_plane_in_state(state, plane, plane_state, i) {
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 
                funcs = plane->helper_private;
 
-               drm_atomic_helper_plane_changed(state, plane_state, plane);
+               drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
 
                if (!funcs || !funcs->atomic_check)
                        continue;
 
-               ret = funcs->atomic_check(plane, plane_state);
+               ret = funcs->atomic_check(plane, new_plane_state);
                if (ret) {
                        DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic driver check failed\n",
                                         plane->base.id, plane->name);
@@ -632,7 +634,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
                }
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
                funcs = crtc->helper_private;
@@ -640,7 +642,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
                if (!funcs || !funcs->atomic_check)
                        continue;
 
-               ret = funcs->atomic_check(crtc, crtc_state);
+               ret = funcs->atomic_check(crtc, new_crtc_state);
                if (ret) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n",
                                         crtc->base.id, crtc->name);
@@ -694,12 +696,12 @@ static void
 disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 {
        struct drm_connector *connector;
-       struct drm_connector_state *old_conn_state;
+       struct drm_connector_state *old_conn_state, *new_conn_state;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        int i;
 
-       for_each_connector_in_state(old_state, connector, old_conn_state, i) {
+       for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) {
                const struct drm_encoder_helper_funcs *funcs;
                struct drm_encoder *encoder;
 
@@ -708,8 +710,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
                if (!old_conn_state->crtc)
                        continue;
 
-               old_crtc_state = drm_atomic_get_existing_crtc_state(old_state,
-                                                                   old_conn_state->crtc);
+               old_crtc_state = drm_atomic_get_old_crtc_state(old_state, old_conn_state->crtc);
 
                if (!old_crtc_state->active ||
                    !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
@@ -736,7 +737,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 
                /* Right function depends upon target state. */
                if (funcs) {
-                       if (connector->state->crtc && funcs->prepare)
+                       if (new_conn_state->crtc && funcs->prepare)
                                funcs->prepare(encoder);
                        else if (funcs->disable)
                                funcs->disable(encoder);
@@ -747,11 +748,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
                drm_bridge_post_disable(encoder->bridge);
        }
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
                /* Shut down everything that needs a full modeset. */
-               if (!drm_atomic_crtc_needs_modeset(crtc->state))
+               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
                        continue;
 
                if (!old_crtc_state->active)
@@ -764,7 +765,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 
 
                /* Right function depends upon target state. */
-               if (crtc->state->enable && funcs->prepare)
+               if (new_crtc_state->enable && funcs->prepare)
                        funcs->prepare(crtc);
                else if (funcs->atomic_disable)
                        funcs->atomic_disable(crtc, old_crtc_state);
@@ -793,13 +794,13 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
                                              struct drm_atomic_state *old_state)
 {
        struct drm_connector *connector;
-       struct drm_connector_state *old_conn_state;
+       struct drm_connector_state *old_conn_state, *new_conn_state;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        int i;
 
        /* clear out existing links and update dpms */
-       for_each_connector_in_state(old_state, connector, old_conn_state, i) {
+       for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) {
                if (connector->encoder) {
                        WARN_ON(!connector->encoder->crtc);
 
@@ -807,7 +808,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
                        connector->encoder = NULL;
                }
 
-               crtc = connector->state->crtc;
+               crtc = new_conn_state->crtc;
                if ((!crtc && old_conn_state->crtc) ||
                    (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) {
                        struct drm_property *dpms_prop =
@@ -824,33 +825,36 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
        }
 
        /* set new links */
-       for_each_connector_in_state(old_state, connector, old_conn_state, i) {
-               if (!connector->state->crtc)
+       for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
+               if (!new_conn_state->crtc)
                        continue;
 
-               if (WARN_ON(!connector->state->best_encoder))
+               if (WARN_ON(!new_conn_state->best_encoder))
                        continue;
 
-               connector->encoder = connector->state->best_encoder;
-               connector->encoder->crtc = connector->state->crtc;
+               connector->encoder = new_conn_state->best_encoder;
+               connector->encoder->crtc = new_conn_state->crtc;
        }
 
        /* set legacy state in the crtc structure */
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
                struct drm_plane *primary = crtc->primary;
+               struct drm_plane_state *new_plane_state;
 
-               crtc->mode = crtc->state->mode;
-               crtc->enabled = crtc->state->enable;
+               crtc->mode = new_crtc_state->mode;
+               crtc->enabled = new_crtc_state->enable;
 
-               if (drm_atomic_get_existing_plane_state(old_state, primary) &&
-                   primary->state->crtc == crtc) {
-                       crtc->x = primary->state->src_x >> 16;
-                       crtc->y = primary->state->src_y >> 16;
+               new_plane_state =
+                       drm_atomic_get_new_plane_state(old_state, primary);
+
+               if (new_plane_state && new_plane_state->crtc == crtc) {
+                       crtc->x = new_plane_state->src_x >> 16;
+                       crtc->y = new_plane_state->src_y >> 16;
                }
 
-               if (crtc->state->enable)
+               if (new_crtc_state->enable)
                        drm_calc_timestamping_constants(crtc,
-                                                       &crtc->state->adjusted_mode);
+                                                       &new_crtc_state->adjusted_mode);
        }
 }
 EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state);
@@ -859,20 +863,20 @@ static void
 crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_connector *connector;
-       struct drm_connector_state *old_conn_state;
+       struct drm_connector_state *new_conn_state;
        int i;
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
-               if (!crtc->state->mode_changed)
+               if (!new_crtc_state->mode_changed)
                        continue;
 
                funcs = crtc->helper_private;
 
-               if (crtc->state->enable && funcs->mode_set_nofb) {
+               if (new_crtc_state->enable && funcs->mode_set_nofb) {
                        DRM_DEBUG_ATOMIC("modeset on [CRTC:%d:%s]\n",
                                         crtc->base.id, crtc->name);
 
@@ -880,18 +884,17 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
                }
        }
 
-       for_each_connector_in_state(old_state, connector, old_conn_state, i) {
+       for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
                const struct drm_encoder_helper_funcs *funcs;
-               struct drm_crtc_state *new_crtc_state;
                struct drm_encoder *encoder;
                struct drm_display_mode *mode, *adjusted_mode;
 
-               if (!connector->state->best_encoder)
+               if (!new_conn_state->best_encoder)
                        continue;
 
-               encoder = connector->state->best_encoder;
+               encoder = new_conn_state->best_encoder;
                funcs = encoder->helper_private;
-               new_crtc_state = connector->state->crtc->state;
+               new_crtc_state = new_conn_state->crtc->state;
                mode = &new_crtc_state->mode;
                adjusted_mode = &new_crtc_state->adjusted_mode;
 
@@ -907,7 +910,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
                 */
                if (funcs && funcs->atomic_mode_set) {
                        funcs->atomic_mode_set(encoder, new_crtc_state,
-                                              connector->state);
+                                              new_conn_state);
                } else if (funcs && funcs->mode_set) {
                        funcs->mode_set(encoder, mode, adjusted_mode);
                }
@@ -959,24 +962,24 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
                                              struct drm_atomic_state *old_state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_connector *connector;
-       struct drm_connector_state *old_conn_state;
+       struct drm_connector_state *new_conn_state;
        int i;
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
                /* Need to filter out CRTCs where only planes change. */
-               if (!drm_atomic_crtc_needs_modeset(crtc->state))
+               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
                        continue;
 
-               if (!crtc->state->active)
+               if (!new_crtc_state->active)
                        continue;
 
                funcs = crtc->helper_private;
 
-               if (crtc->state->enable) {
+               if (new_crtc_state->enable) {
                        DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n",
                                         crtc->base.id, crtc->name);
 
@@ -987,18 +990,18 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
                }
        }
 
-       for_each_connector_in_state(old_state, connector, old_conn_state, i) {
+       for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
                const struct drm_encoder_helper_funcs *funcs;
                struct drm_encoder *encoder;
 
-               if (!connector->state->best_encoder)
+               if (!new_conn_state->best_encoder)
                        continue;
 
-               if (!connector->state->crtc->state->active ||
-                   !drm_atomic_crtc_needs_modeset(connector->state->crtc->state))
+               if (!new_conn_state->crtc->state->active ||
+                   !drm_atomic_crtc_needs_modeset(new_conn_state->crtc->state))
                        continue;
 
-               encoder = connector->state->best_encoder;
+               encoder = new_conn_state->best_encoder;
                funcs = encoder->helper_private;
 
                DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
@@ -1048,29 +1051,26 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
                                      bool pre_swap)
 {
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *new_plane_state;
        int i, ret;
 
-       for_each_plane_in_state(state, plane, plane_state, i) {
-               if (!pre_swap)
-                       plane_state = plane->state;
-
-               if (!plane_state->fence)
+       for_each_new_plane_in_state(state, plane, new_plane_state, i) {
+               if (!new_plane_state->fence)
                        continue;
 
-               WARN_ON(!plane_state->fb);
+               WARN_ON(!new_plane_state->fb);
 
                /*
                 * If waiting for fences pre-swap (ie: nonblock), userspace can
                 * still interrupt the operation. Instead of blocking until the
                 * timer expires, make the wait interruptible.
                 */
-               ret = dma_fence_wait(plane_state->fence, pre_swap);
+               ret = dma_fence_wait(new_plane_state->fence, pre_swap);
                if (ret)
                        return ret;
 
-               dma_fence_put(plane_state->fence);
-               plane_state->fence = NULL;
+               dma_fence_put(new_plane_state->fence);
+               new_plane_state->fence = NULL;
        }
 
        return 0;
@@ -1093,7 +1093,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
                struct drm_atomic_state *old_state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        int i, ret;
        unsigned crtc_mask = 0;
 
@@ -1104,9 +1104,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
        if (old_state->legacy_cursor_update)
                return;
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-               struct drm_crtc_state *new_crtc_state = crtc->state;
-
+       for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
                if (!new_crtc_state->active || !new_crtc_state->planes_changed)
                        continue;
 
@@ -1118,7 +1116,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
                old_state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc);
        }
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
                if (!(crtc_mask & drm_crtc_mask(crtc)))
                        continue;
 
@@ -1427,11 +1425,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
                                   bool nonblock)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_crtc_commit *commit;
        int i, ret;
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                commit = kzalloc(sizeof(*commit), GFP_KERNEL);
                if (!commit)
                        return -ENOMEM;
@@ -1452,7 +1450,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
                /* Drivers only send out events when at least either current or
                 * new CRTC state is active. Complete right away if everything
                 * stays off. */
-               if (!crtc->state->active && !crtc_state->active) {
+               if (!old_crtc_state->active && !new_crtc_state->active) {
                        complete_all(&commit->flip_done);
                        continue;
                }
@@ -1463,17 +1461,17 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
                        continue;
                }
 
-               if (!crtc_state->event) {
+               if (!new_crtc_state->event) {
                        commit->event = kzalloc(sizeof(*commit->event),
                                                GFP_KERNEL);
                        if (!commit->event)
                                return -ENOMEM;
 
-                       crtc_state->event = commit->event;
+                       new_crtc_state->event = commit->event;
                }
 
-               crtc_state->event->base.completion = &commit->flip_done;
-               crtc_state->event->base.completion_release = release_crtc_commit;
+               new_crtc_state->event->base.completion = &commit->flip_done;
+               new_crtc_state->event->base.completion_release = release_crtc_commit;
                drm_crtc_commit_get(commit);
        }
 
@@ -1512,12 +1510,12 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc)
 void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_crtc_commit *commit;
        int i;
        long ret;
 
-       for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
                spin_lock(&crtc->commit_lock);
                commit = preceeding_commit(crtc);
                if (commit)
@@ -1564,17 +1562,17 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
 void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_crtc_commit *commit;
        int i;
 
-       for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
                commit = old_state->crtcs[i].commit;
                if (!commit)
                        continue;
 
                /* backend must have consumed any event by now */
-               WARN_ON(crtc->state->event);
+               WARN_ON(new_crtc_state->event);
                spin_lock(&crtc->commit_lock);
                complete_all(&commit->hw_done);
                spin_unlock(&crtc->commit_lock);
@@ -1596,12 +1594,12 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done);
 void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_crtc_commit *commit;
        int i;
        long ret;
 
-       for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
                commit = old_state->crtcs[i].commit;
                if (WARN_ON(!commit))
                        continue;
@@ -1652,16 +1650,16 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
                                     struct drm_atomic_state *state)
 {
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *new_plane_state;
        int ret, i, j;
 
-       for_each_plane_in_state(state, plane, plane_state, i) {
+       for_each_new_plane_in_state(state, plane, new_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 
                funcs = plane->helper_private;
 
                if (funcs->prepare_fb) {
-                       ret = funcs->prepare_fb(plane, plane_state);
+                       ret = funcs->prepare_fb(plane, new_plane_state);
                        if (ret)
                                goto fail;
                }
@@ -1670,7 +1668,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
        return 0;
 
 fail:
-       for_each_plane_in_state(state, plane, plane_state, j) {
+       for_each_new_plane_in_state(state, plane, new_plane_state, j) {
                const struct drm_plane_helper_funcs *funcs;
 
                if (j >= i)
@@ -1679,7 +1677,7 @@ fail:
                funcs = plane->helper_private;
 
                if (funcs->cleanup_fb)
-                       funcs->cleanup_fb(plane, plane_state);
+                       funcs->cleanup_fb(plane, new_plane_state);
        }
 
        return ret;
@@ -1737,14 +1735,14 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                                     uint32_t flags)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_plane *plane;
-       struct drm_plane_state *old_plane_state;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
        int i;
        bool active_only = flags & DRM_PLANE_COMMIT_ACTIVE_ONLY;
        bool no_disable = flags & DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET;
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
                funcs = crtc->helper_private;
@@ -1752,13 +1750,13 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                if (!funcs || !funcs->atomic_begin)
                        continue;
 
-               if (active_only && !crtc->state->active)
+               if (active_only && !new_crtc_state->active)
                        continue;
 
                funcs->atomic_begin(crtc, old_crtc_state);
        }
 
-       for_each_plane_in_state(old_state, plane, old_plane_state, i) {
+       for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
                bool disabling;
 
@@ -1767,7 +1765,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                if (!funcs)
                        continue;
 
-               disabling = drm_atomic_plane_disabling(plane, old_plane_state);
+               disabling = drm_atomic_plane_disabling(old_plane_state,
+                                                      new_plane_state);
 
                if (active_only) {
                        /*
@@ -1777,7 +1776,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                         * CRTC to avoid skipping planes being disabled on an
                         * active CRTC.
                         */
-                       if (!disabling && !plane_crtc_active(plane->state))
+                       if (!disabling && !plane_crtc_active(new_plane_state))
                                continue;
                        if (disabling && !plane_crtc_active(old_plane_state))
                                continue;
@@ -1796,12 +1795,12 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                                continue;
 
                        funcs->atomic_disable(plane, old_plane_state);
-               } else if (plane->state->crtc || disabling) {
+               } else if (new_plane_state->crtc || disabling) {
                        funcs->atomic_update(plane, old_plane_state);
                }
        }
 
-       for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+       for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
                funcs = crtc->helper_private;
@@ -1809,7 +1808,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                if (!funcs || !funcs->atomic_flush)
                        continue;
 
-               if (active_only && !crtc->state->active)
+               if (active_only && !new_crtc_state->active)
                        continue;
 
                funcs->atomic_flush(crtc, old_crtc_state);
@@ -1852,7 +1851,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
 
        drm_for_each_plane_mask(plane, crtc->dev, plane_mask) {
                struct drm_plane_state *old_plane_state =
-                       drm_atomic_get_existing_plane_state(old_state, plane);
+                       drm_atomic_get_old_plane_state(old_state, plane);
                const struct drm_plane_helper_funcs *plane_funcs;
 
                plane_funcs = plane->helper_private;
@@ -1862,11 +1861,11 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
 
                WARN_ON(plane->state->crtc && plane->state->crtc != crtc);
 
-               if (drm_atomic_plane_disabling(plane, old_plane_state) &&
+               if (drm_atomic_plane_disabling(old_plane_state, plane->state) &&
                    plane_funcs->atomic_disable)
                        plane_funcs->atomic_disable(plane, old_plane_state);
                else if (plane->state->crtc ||
-                        drm_atomic_plane_disabling(plane, old_plane_state))
+                        drm_atomic_plane_disabling(old_plane_state, plane->state))
                        plane_funcs->atomic_update(plane, old_plane_state);
        }
 
@@ -1936,11 +1935,21 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
                                      struct drm_atomic_state *old_state)
 {
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
        int i;
 
-       for_each_plane_in_state(old_state, plane, plane_state, i) {
+       for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
+               struct drm_plane_state *plane_state;
+
+               /*
+                * This might be called before swapping when commit is aborted,
+                * in which case we have to cleanup the new state.
+                */
+               if (old_plane_state == plane->state)
+                       plane_state = new_plane_state;
+               else
+                       plane_state = old_plane_state;
 
                funcs = plane->helper_private;
 
@@ -1986,15 +1995,15 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
        int i;
        long ret;
        struct drm_connector *connector;
-       struct drm_connector_state *conn_state, *old_conn_state;
+       struct drm_connector_state *old_conn_state, *new_conn_state;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state, *old_crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state, *old_plane_state;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
        struct drm_crtc_commit *commit;
 
        if (stall) {
-               for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                        spin_lock(&crtc->commit_lock);
                        commit = list_first_entry_or_null(&crtc->commit_list,
                                        struct drm_crtc_commit, commit_entry);
@@ -2014,20 +2023,24 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
                }
        }
 
-       for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
+       for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) {
                WARN_ON(connector->state != old_conn_state);
 
-               connector->state->state = state;
-               swap(state->connectors[i].state, connector->state);
-               connector->state->state = NULL;
+               old_conn_state->state = state;
+               new_conn_state->state = NULL;
+
+               state->connectors[i].state = old_conn_state;
+               connector->state = new_conn_state;
        }
 
-       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                WARN_ON(crtc->state != old_crtc_state);
 
-               crtc->state->state = state;
-               swap(state->crtcs[i].state, crtc->state);
-               crtc->state->state = NULL;
+               old_crtc_state->state = state;
+               new_crtc_state->state = NULL;
+
+               state->crtcs[i].state = old_crtc_state;
+               crtc->state = new_crtc_state;
 
                if (state->crtcs[i].commit) {
                        spin_lock(&crtc->commit_lock);
@@ -2039,12 +2052,14 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
                }
        }
 
-       for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
                WARN_ON(plane->state != old_plane_state);
 
-               plane->state->state = state;
-               swap(state->planes[i].state, plane->state);
-               plane->state->state = NULL;
+               old_plane_state->state = state;
+               new_plane_state->state = NULL;
+
+               state->planes[i].state = old_plane_state;
+               plane->state = new_plane_state;
        }
 }
 EXPORT_SYMBOL(drm_atomic_helper_swap_state);
@@ -2227,9 +2242,9 @@ static int update_output_state(struct drm_atomic_state *state,
 {
        struct drm_device *dev = set->crtc->dev;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_connector *connector;
-       struct drm_connector_state *conn_state;
+       struct drm_connector_state *new_conn_state;
        int ret, i;
 
        ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
@@ -2242,31 +2257,32 @@ static int update_output_state(struct drm_atomic_state *state,
        if (ret)
                return ret;
 
-       for_each_connector_in_state(state, connector, conn_state, i) {
-               if (conn_state->crtc == set->crtc) {
-                       ret = drm_atomic_set_crtc_for_connector(conn_state,
+       for_each_new_connector_in_state(state, connector, new_conn_state, i) {
+               if (new_conn_state->crtc == set->crtc) {
+                       ret = drm_atomic_set_crtc_for_connector(new_conn_state,
                                                                NULL);
                        if (ret)
                                return ret;
+
                        /* Make sure legacy setCrtc always re-trains */
-                       conn_state->link_status = DRM_LINK_STATUS_GOOD;
+                       new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
                }
        }
 
        /* Then set all connectors from set->connectors on the target crtc */
        for (i = 0; i < set->num_connectors; i++) {
-               conn_state = drm_atomic_get_connector_state(state,
+               new_conn_state = drm_atomic_get_connector_state(state,
                                                            set->connectors[i]);
-               if (IS_ERR(conn_state))
-                       return PTR_ERR(conn_state);
+               if (IS_ERR(new_conn_state))
+                       return PTR_ERR(new_conn_state);
 
-               ret = drm_atomic_set_crtc_for_connector(conn_state,
+               ret = drm_atomic_set_crtc_for_connector(new_conn_state,
                                                        set->crtc);
                if (ret)
                        return ret;
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                /* Don't update ->enable for the CRTC in the set_config request,
                 * since a mismatch would indicate a bug in the upper layers.
                 * The actual modeset code later on will catch any
@@ -2274,13 +2290,13 @@ static int update_output_state(struct drm_atomic_state *state,
                if (crtc == set->crtc)
                        continue;
 
-               if (!crtc_state->connector_mask) {
-                       ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
+               if (!new_crtc_state->connector_mask) {
+                       ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
                                                                NULL);
                        if (ret < 0)
                                return ret;
 
-                       crtc_state->active = false;
+                       new_crtc_state->active = false;
                }
        }
 
@@ -2583,21 +2599,21 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
 {
        int i;
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *new_plane_state;
        struct drm_connector *connector;
-       struct drm_connector_state *conn_state;
+       struct drm_connector_state *new_conn_state;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *new_crtc_state;
 
        state->acquire_ctx = ctx;
 
-       for_each_new_plane_in_state(state, plane, plane_state, i)
+       for_each_new_plane_in_state(state, plane, new_plane_state, i)
                state->planes[i].old_state = plane->state;
 
-       for_each_new_crtc_in_state(state, crtc, crtc_state, i)
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
                state->crtcs[i].old_state = crtc->state;
 
-       for_each_new_connector_in_state(state, connector, conn_state, i)
+       for_each_new_connector_in_state(state, connector, new_conn_state, i)
                state->connectors[i].old_state = connector->state;
 
        return drm_atomic_commit(state);
@@ -2938,7 +2954,7 @@ retry:
        if (ret != 0)
                goto fail;
 
-       crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
+       crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
        if (WARN_ON(!crtc_state)) {
                ret = -EINVAL;
                goto fail;
index 665aafc..a0d0d68 100644 (file)
@@ -377,27 +377,26 @@ int drm_atomic_normalize_zpos(struct drm_device *dev,
                              struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
        int i, ret = 0;
 
-       for_each_plane_in_state(state, plane, plane_state, i) {
-               crtc = plane_state->crtc;
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+               crtc = new_plane_state->crtc;
                if (!crtc)
                        continue;
-               if (plane->state->zpos != plane_state->zpos) {
-                       crtc_state =
-                               drm_atomic_get_existing_crtc_state(state, crtc);
-                       crtc_state->zpos_changed = true;
+               if (old_plane_state->zpos != new_plane_state->zpos) {
+                       new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+                       new_crtc_state->zpos_changed = true;
                }
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               if (crtc_state->plane_mask != crtc->state->plane_mask ||
-                   crtc_state->zpos_changed) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               if (old_crtc_state->plane_mask != new_crtc_state->plane_mask ||
+                   new_crtc_state->zpos_changed) {
                        ret = drm_atomic_helper_crtc_normalize_zpos(crtc,
-                                                                   crtc_state);
+                                                                   new_crtc_state);
                        if (ret)
                                return ret;
                }
index 8b2c61a..1d2d18d 100644 (file)
@@ -242,14 +242,9 @@ static void drm_debugfs_remove_all_files(struct drm_minor *minor)
  */
 int drm_debugfs_cleanup(struct drm_minor *minor)
 {
-       struct drm_device *dev = minor->dev;
-
        if (!minor->debugfs_root)
                return 0;
 
-       if (dev->driver->debugfs_cleanup)
-               dev->driver->debugfs_cleanup(minor);
-
        drm_debugfs_remove_all_files(minor);
 
        debugfs_remove_recursive(minor->debugfs_root);
index 68908c1..3e5f521 100644 (file)
@@ -981,6 +981,78 @@ static const struct i2c_lock_operations drm_dp_i2c_lock_ops = {
        .unlock_bus = unlock_bus,
 };
 
+static int drm_dp_aux_get_crc(struct drm_dp_aux *aux, u8 *crc)
+{
+       u8 buf, count;
+       int ret;
+
+       ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK, &buf);
+       if (ret < 0)
+               return ret;
+
+       WARN_ON(!(buf & DP_TEST_SINK_START));
+
+       ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK_MISC, &buf);
+       if (ret < 0)
+               return ret;
+
+       count = buf & DP_TEST_COUNT_MASK;
+       if (count == aux->crc_count)
+               return -EAGAIN; /* No CRC yet */
+
+       aux->crc_count = count;
+
+       /*
+        * At DP_TEST_CRC_R_CR, there's 6 bytes containing CRC data, 2 bytes
+        * per component (RGB or CrYCb).
+        */
+       ret = drm_dp_dpcd_read(aux, DP_TEST_CRC_R_CR, crc, 6);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static void drm_dp_aux_crc_work(struct work_struct *work)
+{
+       struct drm_dp_aux *aux = container_of(work, struct drm_dp_aux,
+                                             crc_work);
+       struct drm_crtc *crtc;
+       u8 crc_bytes[6];
+       uint32_t crcs[3];
+       int ret;
+
+       if (WARN_ON(!aux->crtc))
+               return;
+
+       crtc = aux->crtc;
+       while (crtc->crc.opened) {
+               drm_crtc_wait_one_vblank(crtc);
+               if (!crtc->crc.opened)
+                       break;
+
+               ret = drm_dp_aux_get_crc(aux, crc_bytes);
+               if (ret == -EAGAIN) {
+                       usleep_range(1000, 2000);
+                       ret = drm_dp_aux_get_crc(aux, crc_bytes);
+               }
+
+               if (ret == -EAGAIN) {
+                       DRM_DEBUG_KMS("Get CRC failed after retrying: %d\n",
+                                     ret);
+                       continue;
+               } else if (ret) {
+                       DRM_DEBUG_KMS("Failed to get a CRC: %d\n", ret);
+                       continue;
+               }
+
+               crcs[0] = crc_bytes[0] | crc_bytes[1] << 8;
+               crcs[1] = crc_bytes[2] | crc_bytes[3] << 8;
+               crcs[2] = crc_bytes[4] | crc_bytes[5] << 8;
+               drm_crtc_add_crc_entry(crtc, false, 0, crcs);
+       }
+}
+
 /**
  * drm_dp_aux_init() - minimally initialise an aux channel
  * @aux: DisplayPort AUX channel
@@ -993,6 +1065,7 @@ static const struct i2c_lock_operations drm_dp_i2c_lock_ops = {
 void drm_dp_aux_init(struct drm_dp_aux *aux)
 {
        mutex_init(&aux->hw_mutex);
+       INIT_WORK(&aux->crc_work, drm_dp_aux_crc_work);
 
        aux->ddc.algo = &drm_dp_i2c_algo;
        aux->ddc.algo_data = aux;
@@ -1081,3 +1154,57 @@ int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE])
 EXPORT_SYMBOL(drm_dp_psr_setup_time);
 
 #undef PSR_SETUP_TIME
+
+/**
+ * drm_dp_start_crc() - start capture of frame CRCs
+ * @aux: DisplayPort AUX channel
+ * @crtc: CRTC displaying the frames whose CRCs are to be captured
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_start_crc(struct drm_dp_aux *aux, struct drm_crtc *crtc)
+{
+       u8 buf;
+       int ret;
+
+       ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK, &buf);
+       if (ret < 0)
+               return ret;
+
+       ret = drm_dp_dpcd_writeb(aux, DP_TEST_SINK, buf | DP_TEST_SINK_START);
+       if (ret < 0)
+               return ret;
+
+       aux->crc_count = 0;
+       aux->crtc = crtc;
+       schedule_work(&aux->crc_work);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_dp_start_crc);
+
+/**
+ * drm_dp_stop_crc() - stop capture of frame CRCs
+ * @aux: DisplayPort AUX channel
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_stop_crc(struct drm_dp_aux *aux)
+{
+       u8 buf;
+       int ret;
+
+       ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK, &buf);
+       if (ret < 0)
+               return ret;
+
+       ret = drm_dp_dpcd_writeb(aux, DP_TEST_SINK, buf & ~DP_TEST_SINK_START);
+       if (ret < 0)
+               return ret;
+
+       flush_work(&aux->crc_work);
+       aux->crtc = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_dp_stop_crc);
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
new file mode 100644 (file)
index 0000000..d9e63d7
--- /dev/null
@@ -0,0 +1,737 @@
+/*
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Daryll Strauss <daryll@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <drm/drm_file.h>
+#include <drm/drmP.h>
+
+#include "drm_legacy.h"
+#include "drm_internal.h"
+#include "drm_crtc_internal.h"
+
+/* from BKL pushdown */
+DEFINE_MUTEX(drm_global_mutex);
+
+/**
+ * DOC: file operations
+ *
+ * Drivers must define the file operations structure that forms the DRM
+ * userspace API entry point, even though most of those operations are
+ * implemented in the DRM core. The mandatory functions are drm_open(),
+ * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled
+ * (note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n). Drivers which
+ * implement private ioctls that require 32/64 bit compatibility support must
+ * provide their own .compat_ioctl() handler that processes private ioctls and
+ * calls drm_compat_ioctl() for core ioctls.
+ *
+ * In addition drm_read() and drm_poll() provide support for DRM events. DRM
+ * events are a generic and extensible means to send asynchronous events to
+ * userspace through the file descriptor. They are used to send vblank event and
+ * page flip completions by the KMS API. But drivers can also use it for their
+ * own needs, e.g. to signal completion of rendering.
+ *
+ * The memory mapping implementation will vary depending on how the driver
+ * manages memory. Legacy drivers will use the deprecated drm_legacy_mmap()
+ * function, modern drivers should use one of the provided memory-manager
+ * specific implementations. For GEM-based drivers this is drm_gem_mmap().
+ *
+ * No other file operations are supported by the DRM userspace API. Overall the
+ * following is an example #file_operations structure::
+ *
+ *     static const example_drm_fops = {
+ *             .owner = THIS_MODULE,
+ *             .open = drm_open,
+ *             .release = drm_release,
+ *             .unlocked_ioctl = drm_ioctl,
+ *             .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n
+ *             .poll = drm_poll,
+ *             .read = drm_read,
+ *             .llseek = no_llseek,
+ *             .mmap = drm_gem_mmap,
+ *     };
+ */
+
+static int drm_open_helper(struct file *filp, struct drm_minor *minor);
+
+static int drm_setup(struct drm_device * dev)
+{
+       int ret;
+
+       if (dev->driver->firstopen &&
+           drm_core_check_feature(dev, DRIVER_LEGACY)) {
+               ret = dev->driver->firstopen(dev);
+               if (ret != 0)
+                       return ret;
+       }
+
+       ret = drm_legacy_dma_setup(dev);
+       if (ret < 0)
+               return ret;
+
+
+       DRM_DEBUG("\n");
+       return 0;
+}
+
+/**
+ * drm_open - open method for DRM file
+ * @inode: device inode
+ * @filp: file pointer.
+ *
+ * This function must be used by drivers as their .open() #file_operations
+ * method. It looks up the correct DRM device and instantiates all the per-file
+ * resources for it.
+ *
+ * RETURNS:
+ *
+ * 0 on success or negative errno value on falure.
+ */
+int drm_open(struct inode *inode, struct file *filp)
+{
+       struct drm_device *dev;
+       struct drm_minor *minor;
+       int retcode;
+       int need_setup = 0;
+
+       minor = drm_minor_acquire(iminor(inode));
+       if (IS_ERR(minor))
+               return PTR_ERR(minor);
+
+       dev = minor->dev;
+       if (!dev->open_count++)
+               need_setup = 1;
+
+       /* share address_space across all char-devs of a single device */
+       filp->f_mapping = dev->anon_inode->i_mapping;
+
+       retcode = drm_open_helper(filp, minor);
+       if (retcode)
+               goto err_undo;
+       if (need_setup) {
+               retcode = drm_setup(dev);
+               if (retcode)
+                       goto err_undo;
+       }
+       return 0;
+
+err_undo:
+       dev->open_count--;
+       drm_minor_release(minor);
+       return retcode;
+}
+EXPORT_SYMBOL(drm_open);
+
+/*
+ * Check whether DRI will run on this CPU.
+ *
+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.
+ */
+static int drm_cpu_valid(void)
+{
+#if defined(__sparc__) && !defined(__sparc_v9__)
+       return 0;               /* No cmpxchg before v9 sparc. */
+#endif
+       return 1;
+}
+
+/*
+ * Called whenever a process opens /dev/drm.
+ *
+ * \param filp file pointer.
+ * \param minor acquired minor-object.
+ * \return zero on success or a negative number on failure.
+ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
+static int drm_open_helper(struct file *filp, struct drm_minor *minor)
+{
+       struct drm_device *dev = minor->dev;
+       struct drm_file *priv;
+       int ret;
+
+       if (filp->f_flags & O_EXCL)
+               return -EBUSY;  /* No exclusive opens */
+       if (!drm_cpu_valid())
+               return -EINVAL;
+       if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
+               return -EINVAL;
+
+       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       filp->private_data = priv;
+       priv->filp = filp;
+       priv->pid = get_pid(task_pid(current));
+       priv->minor = minor;
+
+       /* for compatibility root is always authenticated */
+       priv->authenticated = capable(CAP_SYS_ADMIN);
+       priv->lock_count = 0;
+
+       INIT_LIST_HEAD(&priv->lhead);
+       INIT_LIST_HEAD(&priv->fbs);
+       mutex_init(&priv->fbs_lock);
+       INIT_LIST_HEAD(&priv->blobs);
+       INIT_LIST_HEAD(&priv->pending_event_list);
+       INIT_LIST_HEAD(&priv->event_list);
+       init_waitqueue_head(&priv->event_wait);
+       priv->event_space = 4096; /* set aside 4k for event buffer */
+
+       mutex_init(&priv->event_read_lock);
+
+       if (drm_core_check_feature(dev, DRIVER_GEM))
+               drm_gem_open(dev, priv);
+
+       if (drm_core_check_feature(dev, DRIVER_PRIME))
+               drm_prime_init_file_private(&priv->prime);
+
+       if (dev->driver->open) {
+               ret = dev->driver->open(dev, priv);
+               if (ret < 0)
+                       goto out_prime_destroy;
+       }
+
+       if (drm_is_primary_client(priv)) {
+               ret = drm_master_open(priv);
+               if (ret)
+                       goto out_close;
+       }
+
+       mutex_lock(&dev->filelist_mutex);
+       list_add(&priv->lhead, &dev->filelist);
+       mutex_unlock(&dev->filelist_mutex);
+
+#ifdef __alpha__
+       /*
+        * Default the hose
+        */
+       if (!dev->hose) {
+               struct pci_dev *pci_dev;
+               pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+               if (pci_dev) {
+                       dev->hose = pci_dev->sysdata;
+                       pci_dev_put(pci_dev);
+               }
+               if (!dev->hose) {
+                       struct pci_bus *b = list_entry(pci_root_buses.next,
+                               struct pci_bus, node);
+                       if (b)
+                               dev->hose = b->sysdata;
+               }
+       }
+#endif
+
+       return 0;
+
+out_close:
+       if (dev->driver->postclose)
+               dev->driver->postclose(dev, priv);
+out_prime_destroy:
+       if (drm_core_check_feature(dev, DRIVER_PRIME))
+               drm_prime_destroy_file_private(&priv->prime);
+       if (drm_core_check_feature(dev, DRIVER_GEM))
+               drm_gem_release(dev, priv);
+       put_pid(priv->pid);
+       kfree(priv);
+       filp->private_data = NULL;
+       return ret;
+}
+
+static void drm_events_release(struct drm_file *file_priv)
+{
+       struct drm_device *dev = file_priv->minor->dev;
+       struct drm_pending_event *e, *et;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+
+       /* Unlink pending events */
+       list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
+                                pending_link) {
+               list_del(&e->pending_link);
+               e->file_priv = NULL;
+       }
+
+       /* Remove unconsumed events */
+       list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
+               list_del(&e->link);
+               kfree(e);
+       }
+
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+/*
+ * drm_legacy_dev_reinit
+ *
+ * Reinitializes a legacy/ums drm device in it's lastclose function.
+ */
+static void drm_legacy_dev_reinit(struct drm_device *dev)
+{
+       if (dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+       mutex_lock(&dev->struct_mutex);
+
+       drm_legacy_agp_clear(dev);
+
+       drm_legacy_sg_cleanup(dev);
+       drm_legacy_vma_flush(dev);
+       drm_legacy_dma_takedown(dev);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       dev->sigdata.lock = NULL;
+
+       dev->context_flag = 0;
+       dev->last_context = 0;
+       dev->if_version = 0;
+
+       DRM_DEBUG("lastclose completed\n");
+}
+
+/*
+ * Take down the DRM device.
+ *
+ * \param dev DRM device structure.
+ *
+ * Frees every resource in \p dev.
+ *
+ * \sa drm_device
+ */
+void drm_lastclose(struct drm_device * dev)
+{
+       DRM_DEBUG("\n");
+
+       if (dev->driver->lastclose)
+               dev->driver->lastclose(dev);
+       DRM_DEBUG("driver lastclose completed\n");
+
+       if (drm_core_check_feature(dev, DRIVER_LEGACY))
+               drm_legacy_dev_reinit(dev);
+}
+
+/**
+ * drm_release - release method for DRM file
+ * @inode: device inode
+ * @filp: file pointer.
+ *
+ * This function must be used by drivers as their .release() #file_operations
+ * method. It frees any resources associated with the open file, and if this is
+ * the last open file for the DRM device also proceeds to call drm_lastclose().
+ *
+ * RETURNS:
+ *
+ * Always succeeds and returns 0.
+ */
+int drm_release(struct inode *inode, struct file *filp)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_minor *minor = file_priv->minor;
+       struct drm_device *dev = minor->dev;
+
+       mutex_lock(&drm_global_mutex);
+
+       DRM_DEBUG("open_count = %d\n", dev->open_count);
+
+       mutex_lock(&dev->filelist_mutex);
+       list_del(&file_priv->lhead);
+       mutex_unlock(&dev->filelist_mutex);
+
+       if (dev->driver->preclose)
+               dev->driver->preclose(dev, file_priv);
+
+       /* ========================================================
+        * Begin inline drm_release
+        */
+
+       DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+                 task_pid_nr(current),
+                 (long)old_encode_dev(file_priv->minor->kdev->devt),
+                 dev->open_count);
+
+       if (drm_core_check_feature(dev, DRIVER_LEGACY))
+               drm_legacy_lock_release(dev, filp);
+
+       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               drm_legacy_reclaim_buffers(dev, file_priv);
+
+       drm_events_release(file_priv);
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               drm_fb_release(file_priv);
+               drm_property_destroy_user_blobs(dev, file_priv);
+       }
+
+       if (drm_core_check_feature(dev, DRIVER_GEM))
+               drm_gem_release(dev, file_priv);
+
+       drm_legacy_ctxbitmap_flush(dev, file_priv);
+
+       if (drm_is_primary_client(file_priv))
+               drm_master_release(file_priv);
+
+       if (dev->driver->postclose)
+               dev->driver->postclose(dev, file_priv);
+
+       if (drm_core_check_feature(dev, DRIVER_PRIME))
+               drm_prime_destroy_file_private(&file_priv->prime);
+
+       WARN_ON(!list_empty(&file_priv->event_list));
+
+       put_pid(file_priv->pid);
+       kfree(file_priv);
+
+       /* ========================================================
+        * End inline drm_release
+        */
+
+       if (!--dev->open_count) {
+               drm_lastclose(dev);
+               if (drm_device_is_unplugged(dev))
+                       drm_put_dev(dev);
+       }
+       mutex_unlock(&drm_global_mutex);
+
+       drm_minor_release(minor);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_release);
+
+/**
+ * drm_read - read method for DRM file
+ * @filp: file pointer
+ * @buffer: userspace destination pointer for the read
+ * @count: count in bytes to read
+ * @offset: offset to read
+ *
+ * This function must be used by drivers as their .read() #file_operations
+ * method iff they use DRM events for asynchronous signalling to userspace.
+ * Since events are used by the KMS API for vblank and page flip completion this
+ * means all modern display drivers must use it.
+ *
+ * @offset is ignore, DRM events are read like a pipe. Therefore drivers also
+ * must set the .llseek() #file_operation to no_llseek(). Polling support is
+ * provided by drm_poll().
+ *
+ * This function will only ever read a full event. Therefore userspace must
+ * supply a big enough buffer to fit any event to ensure forward progress. Since
+ * the maximum event space is currently 4K it's recommended to just use that for
+ * safety.
+ *
+ * RETURNS:
+ *
+ * Number of bytes read (always aligned to full events, and can be 0) or a
+ * negative error code on failure.
+ */
+ssize_t drm_read(struct file *filp, char __user *buffer,
+                size_t count, loff_t *offset)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
+       ssize_t ret;
+
+       if (!access_ok(VERIFY_WRITE, buffer, count))
+               return -EFAULT;
+
+       ret = mutex_lock_interruptible(&file_priv->event_read_lock);
+       if (ret)
+               return ret;
+
+       for (;;) {
+               struct drm_pending_event *e = NULL;
+
+               spin_lock_irq(&dev->event_lock);
+               if (!list_empty(&file_priv->event_list)) {
+                       e = list_first_entry(&file_priv->event_list,
+                                       struct drm_pending_event, link);
+                       file_priv->event_space += e->event->length;
+                       list_del(&e->link);
+               }
+               spin_unlock_irq(&dev->event_lock);
+
+               if (e == NULL) {
+                       if (ret)
+                               break;
+
+                       if (filp->f_flags & O_NONBLOCK) {
+                               ret = -EAGAIN;
+                               break;
+                       }
+
+                       mutex_unlock(&file_priv->event_read_lock);
+                       ret = wait_event_interruptible(file_priv->event_wait,
+                                                      !list_empty(&file_priv->event_list));
+                       if (ret >= 0)
+                               ret = mutex_lock_interruptible(&file_priv->event_read_lock);
+                       if (ret)
+                               return ret;
+               } else {
+                       unsigned length = e->event->length;
+
+                       if (length > count - ret) {
+put_back_event:
+                               spin_lock_irq(&dev->event_lock);
+                               file_priv->event_space -= length;
+                               list_add(&e->link, &file_priv->event_list);
+                               spin_unlock_irq(&dev->event_lock);
+                               break;
+                       }
+
+                       if (copy_to_user(buffer + ret, e->event, length)) {
+                               if (ret == 0)
+                                       ret = -EFAULT;
+                               goto put_back_event;
+                       }
+
+                       ret += length;
+                       kfree(e);
+               }
+       }
+       mutex_unlock(&file_priv->event_read_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_read);
+
+/**
+ * drm_poll - poll method for DRM file
+ * @filp: file pointer
+ * @wait: poll waiter table
+ *
+ * This function must be used by drivers as their .read() #file_operations
+ * method iff they use DRM events for asynchronous signalling to userspace.
+ * Since events are used by the KMS API for vblank and page flip completion this
+ * means all modern display drivers must use it.
+ *
+ * See also drm_read().
+ *
+ * RETURNS:
+ *
+ * Mask of POLL flags indicating the current status of the file.
+ */
+unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
+{
+       struct drm_file *file_priv = filp->private_data;
+       unsigned int mask = 0;
+
+       poll_wait(filp, &file_priv->event_wait, wait);
+
+       if (!list_empty(&file_priv->event_list))
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+EXPORT_SYMBOL(drm_poll);
+
+/**
+ * drm_event_reserve_init_locked - init a DRM event and reserve space for it
+ * @dev: DRM device
+ * @file_priv: DRM file private data
+ * @p: tracking structure for the pending event
+ * @e: actual event data to deliver to userspace
+ *
+ * This function prepares the passed in event for eventual delivery. If the event
+ * doesn't get delivered (because the IOCTL fails later on, before queuing up
+ * anything) then the even must be cancelled and freed using
+ * drm_event_cancel_free(). Successfully initialized events should be sent out
+ * using drm_send_event() or drm_send_event_locked() to signal completion of the
+ * asynchronous event to userspace.
+ *
+ * If callers embedded @p into a larger structure it must be allocated with
+ * kmalloc and @p must be the first member element.
+ *
+ * This is the locked version of drm_event_reserve_init() for callers which
+ * already hold &drm_device.event_lock.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+int drm_event_reserve_init_locked(struct drm_device *dev,
+                                 struct drm_file *file_priv,
+                                 struct drm_pending_event *p,
+                                 struct drm_event *e)
+{
+       if (file_priv->event_space < e->length)
+               return -ENOMEM;
+
+       file_priv->event_space -= e->length;
+
+       p->event = e;
+       list_add(&p->pending_link, &file_priv->pending_event_list);
+       p->file_priv = file_priv;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_event_reserve_init_locked);
+
+/**
+ * drm_event_reserve_init - init a DRM event and reserve space for it
+ * @dev: DRM device
+ * @file_priv: DRM file private data
+ * @p: tracking structure for the pending event
+ * @e: actual event data to deliver to userspace
+ *
+ * This function prepares the passed in event for eventual delivery. If the event
+ * doesn't get delivered (because the IOCTL fails later on, before queuing up
+ * anything) then the even must be cancelled and freed using
+ * drm_event_cancel_free(). Successfully initialized events should be sent out
+ * using drm_send_event() or drm_send_event_locked() to signal completion of the
+ * asynchronous event to userspace.
+ *
+ * If callers embedded @p into a larger structure it must be allocated with
+ * kmalloc and @p must be the first member element.
+ *
+ * Callers which already hold &drm_device.event_lock should use
+ * drm_event_reserve_init_locked() instead.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+int drm_event_reserve_init(struct drm_device *dev,
+                          struct drm_file *file_priv,
+                          struct drm_pending_event *p,
+                          struct drm_event *e)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       ret = drm_event_reserve_init_locked(dev, file_priv, p, e);
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_event_reserve_init);
+
+/**
+ * drm_event_cancel_free - free a DRM event and release it's space
+ * @dev: DRM device
+ * @p: tracking structure for the pending event
+ *
+ * This function frees the event @p initialized with drm_event_reserve_init()
+ * and releases any allocated space.
+ */
+void drm_event_cancel_free(struct drm_device *dev,
+                          struct drm_pending_event *p)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&dev->event_lock, flags);
+       if (p->file_priv) {
+               p->file_priv->event_space += p->event->length;
+               list_del(&p->pending_link);
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       if (p->fence)
+               dma_fence_put(p->fence);
+
+       kfree(p);
+}
+EXPORT_SYMBOL(drm_event_cancel_free);
+
+/**
+ * drm_send_event_locked - send DRM event to file descriptor
+ * @dev: DRM device
+ * @e: DRM event to deliver
+ *
+ * This function sends the event @e, initialized with drm_event_reserve_init(),
+ * to its associated userspace DRM file. Callers must already hold
+ * &drm_device.event_lock, see drm_send_event() for the unlocked version.
+ *
+ * Note that the core will take care of unlinking and disarming events when the
+ * corresponding DRM file is closed. Drivers need not worry about whether the
+ * DRM file for this event still exists and can call this function upon
+ * completion of the asynchronous work unconditionally.
+ */
+void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
+{
+       assert_spin_locked(&dev->event_lock);
+
+       if (e->completion) {
+               complete_all(e->completion);
+               e->completion_release(e->completion);
+               e->completion = NULL;
+       }
+
+       if (e->fence) {
+               dma_fence_signal(e->fence);
+               dma_fence_put(e->fence);
+       }
+
+       if (!e->file_priv) {
+               kfree(e);
+               return;
+       }
+
+       list_del(&e->pending_link);
+       list_add_tail(&e->link,
+                     &e->file_priv->event_list);
+       wake_up_interruptible(&e->file_priv->event_wait);
+}
+EXPORT_SYMBOL(drm_send_event_locked);
+
+/**
+ * drm_send_event - send DRM event to file descriptor
+ * @dev: DRM device
+ * @e: DRM event to deliver
+ *
+ * This function sends the event @e, initialized with drm_event_reserve_init(),
+ * to its associated userspace DRM file. This function acquires
+ * &drm_device.event_lock, see drm_send_event_locked() for callers which already
+ * hold this lock.
+ *
+ * Note that the core will take care of unlinking and disarming events when the
+ * corresponding DRM file is closed. Drivers need not worry about whether the
+ * DRM file for this event still exists and can call this function upon
+ * completion of the asynchronous work unconditionally.
+ */
+void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev->event_lock, irqflags);
+       drm_send_event_locked(dev, e);
+       spin_unlock_irqrestore(&dev->event_lock, irqflags);
+}
+EXPORT_SYMBOL(drm_send_event);
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
deleted file mode 100644 (file)
index afdf5b1..0000000
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- * \file drm_fops.c
- * File operations for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Daryll Strauss <daryll@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <drm/drmP.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include "drm_legacy.h"
-#include "drm_internal.h"
-#include "drm_crtc_internal.h"
-
-/* from BKL pushdown */
-DEFINE_MUTEX(drm_global_mutex);
-
-/**
- * DOC: file operations
- *
- * Drivers must define the file operations structure that forms the DRM
- * userspace API entry point, even though most of those operations are
- * implemented in the DRM core. The mandatory functions are drm_open(),
- * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled
- * (note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n). Drivers which
- * implement private ioctls that require 32/64 bit compatibility support must
- * provide their own .compat_ioctl() handler that processes private ioctls and
- * calls drm_compat_ioctl() for core ioctls.
- *
- * In addition drm_read() and drm_poll() provide support for DRM events. DRM
- * events are a generic and extensible means to send asynchronous events to
- * userspace through the file descriptor. They are used to send vblank event and
- * page flip completions by the KMS API. But drivers can also use it for their
- * own needs, e.g. to signal completion of rendering.
- *
- * The memory mapping implementation will vary depending on how the driver
- * manages memory. Legacy drivers will use the deprecated drm_legacy_mmap()
- * function, modern drivers should use one of the provided memory-manager
- * specific implementations. For GEM-based drivers this is drm_gem_mmap().
- *
- * No other file operations are supported by the DRM userspace API. Overall the
- * following is an example #file_operations structure::
- *
- *     static const example_drm_fops = {
- *             .owner = THIS_MODULE,
- *             .open = drm_open,
- *             .release = drm_release,
- *             .unlocked_ioctl = drm_ioctl,
- *             .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n
- *             .poll = drm_poll,
- *             .read = drm_read,
- *             .llseek = no_llseek,
- *             .mmap = drm_gem_mmap,
- *     };
- */
-
-static int drm_open_helper(struct file *filp, struct drm_minor *minor);
-
-static int drm_setup(struct drm_device * dev)
-{
-       int ret;
-
-       if (dev->driver->firstopen &&
-           drm_core_check_feature(dev, DRIVER_LEGACY)) {
-               ret = dev->driver->firstopen(dev);
-               if (ret != 0)
-                       return ret;
-       }
-
-       ret = drm_legacy_dma_setup(dev);
-       if (ret < 0)
-               return ret;
-
-
-       DRM_DEBUG("\n");
-       return 0;
-}
-
-/**
- * drm_open - open method for DRM file
- * @inode: device inode
- * @filp: file pointer.
- *
- * This function must be used by drivers as their .open() #file_operations
- * method. It looks up the correct DRM device and instantiates all the per-file
- * resources for it.
- *
- * RETURNS:
- *
- * 0 on success or negative errno value on falure.
- */
-int drm_open(struct inode *inode, struct file *filp)
-{
-       struct drm_device *dev;
-       struct drm_minor *minor;
-       int retcode;
-       int need_setup = 0;
-
-       minor = drm_minor_acquire(iminor(inode));
-       if (IS_ERR(minor))
-               return PTR_ERR(minor);
-
-       dev = minor->dev;
-       if (!dev->open_count++)
-               need_setup = 1;
-
-       /* share address_space across all char-devs of a single device */
-       filp->f_mapping = dev->anon_inode->i_mapping;
-
-       retcode = drm_open_helper(filp, minor);
-       if (retcode)
-               goto err_undo;
-       if (need_setup) {
-               retcode = drm_setup(dev);
-               if (retcode)
-                       goto err_undo;
-       }
-       return 0;
-
-err_undo:
-       dev->open_count--;
-       drm_minor_release(minor);
-       return retcode;
-}
-EXPORT_SYMBOL(drm_open);
-
-/*
- * Check whether DRI will run on this CPU.
- *
- * \return non-zero if the DRI will run on this CPU, or zero otherwise.
- */
-static int drm_cpu_valid(void)
-{
-#if defined(__sparc__) && !defined(__sparc_v9__)
-       return 0;               /* No cmpxchg before v9 sparc. */
-#endif
-       return 1;
-}
-
-/*
- * Called whenever a process opens /dev/drm.
- *
- * \param filp file pointer.
- * \param minor acquired minor-object.
- * \return zero on success or a negative number on failure.
- *
- * Creates and initializes a drm_file structure for the file private data in \p
- * filp and add it into the double linked list in \p dev.
- */
-static int drm_open_helper(struct file *filp, struct drm_minor *minor)
-{
-       struct drm_device *dev = minor->dev;
-       struct drm_file *priv;
-       int ret;
-
-       if (filp->f_flags & O_EXCL)
-               return -EBUSY;  /* No exclusive opens */
-       if (!drm_cpu_valid())
-               return -EINVAL;
-       if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
-               return -EINVAL;
-
-       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
-
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       filp->private_data = priv;
-       priv->filp = filp;
-       priv->pid = get_pid(task_pid(current));
-       priv->minor = minor;
-
-       /* for compatibility root is always authenticated */
-       priv->authenticated = capable(CAP_SYS_ADMIN);
-       priv->lock_count = 0;
-
-       INIT_LIST_HEAD(&priv->lhead);
-       INIT_LIST_HEAD(&priv->fbs);
-       mutex_init(&priv->fbs_lock);
-       INIT_LIST_HEAD(&priv->blobs);
-       INIT_LIST_HEAD(&priv->pending_event_list);
-       INIT_LIST_HEAD(&priv->event_list);
-       init_waitqueue_head(&priv->event_wait);
-       priv->event_space = 4096; /* set aside 4k for event buffer */
-
-       mutex_init(&priv->event_read_lock);
-
-       if (drm_core_check_feature(dev, DRIVER_GEM))
-               drm_gem_open(dev, priv);
-
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_prime_init_file_private(&priv->prime);
-
-       if (dev->driver->open) {
-               ret = dev->driver->open(dev, priv);
-               if (ret < 0)
-                       goto out_prime_destroy;
-       }
-
-       if (drm_is_primary_client(priv)) {
-               ret = drm_master_open(priv);
-               if (ret)
-                       goto out_close;
-       }
-
-       mutex_lock(&dev->filelist_mutex);
-       list_add(&priv->lhead, &dev->filelist);
-       mutex_unlock(&dev->filelist_mutex);
-
-#ifdef __alpha__
-       /*
-        * Default the hose
-        */
-       if (!dev->hose) {
-               struct pci_dev *pci_dev;
-               pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
-               if (pci_dev) {
-                       dev->hose = pci_dev->sysdata;
-                       pci_dev_put(pci_dev);
-               }
-               if (!dev->hose) {
-                       struct pci_bus *b = list_entry(pci_root_buses.next,
-                               struct pci_bus, node);
-                       if (b)
-                               dev->hose = b->sysdata;
-               }
-       }
-#endif
-
-       return 0;
-
-out_close:
-       if (dev->driver->postclose)
-               dev->driver->postclose(dev, priv);
-out_prime_destroy:
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_prime_destroy_file_private(&priv->prime);
-       if (drm_core_check_feature(dev, DRIVER_GEM))
-               drm_gem_release(dev, priv);
-       put_pid(priv->pid);
-       kfree(priv);
-       filp->private_data = NULL;
-       return ret;
-}
-
-static void drm_events_release(struct drm_file *file_priv)
-{
-       struct drm_device *dev = file_priv->minor->dev;
-       struct drm_pending_event *e, *et;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->event_lock, flags);
-
-       /* Unlink pending events */
-       list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
-                                pending_link) {
-               list_del(&e->pending_link);
-               e->file_priv = NULL;
-       }
-
-       /* Remove unconsumed events */
-       list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
-               list_del(&e->link);
-               kfree(e);
-       }
-
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-/*
- * drm_legacy_dev_reinit
- *
- * Reinitializes a legacy/ums drm device in it's lastclose function.
- */
-static void drm_legacy_dev_reinit(struct drm_device *dev)
-{
-       if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-       mutex_lock(&dev->struct_mutex);
-
-       drm_legacy_agp_clear(dev);
-
-       drm_legacy_sg_cleanup(dev);
-       drm_legacy_vma_flush(dev);
-       drm_legacy_dma_takedown(dev);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       dev->sigdata.lock = NULL;
-
-       dev->context_flag = 0;
-       dev->last_context = 0;
-       dev->if_version = 0;
-
-       DRM_DEBUG("lastclose completed\n");
-}
-
-/*
- * Take down the DRM device.
- *
- * \param dev DRM device structure.
- *
- * Frees every resource in \p dev.
- *
- * \sa drm_device
- */
-void drm_lastclose(struct drm_device * dev)
-{
-       DRM_DEBUG("\n");
-
-       if (dev->driver->lastclose)
-               dev->driver->lastclose(dev);
-       DRM_DEBUG("driver lastclose completed\n");
-
-       if (drm_core_check_feature(dev, DRIVER_LEGACY))
-               drm_legacy_dev_reinit(dev);
-}
-
-/**
- * drm_release - release method for DRM file
- * @inode: device inode
- * @filp: file pointer.
- *
- * This function must be used by drivers as their .release() #file_operations
- * method. It frees any resources associated with the open file, and if this is
- * the last open file for the DRM device also proceeds to call drm_lastclose().
- *
- * RETURNS:
- *
- * Always succeeds and returns 0.
- */
-int drm_release(struct inode *inode, struct file *filp)
-{
-       struct drm_file *file_priv = filp->private_data;
-       struct drm_minor *minor = file_priv->minor;
-       struct drm_device *dev = minor->dev;
-
-       mutex_lock(&drm_global_mutex);
-
-       DRM_DEBUG("open_count = %d\n", dev->open_count);
-
-       mutex_lock(&dev->filelist_mutex);
-       list_del(&file_priv->lhead);
-       mutex_unlock(&dev->filelist_mutex);
-
-       if (dev->driver->preclose)
-               dev->driver->preclose(dev, file_priv);
-
-       /* ========================================================
-        * Begin inline drm_release
-        */
-
-       DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
-                 task_pid_nr(current),
-                 (long)old_encode_dev(file_priv->minor->kdev->devt),
-                 dev->open_count);
-
-       if (drm_core_check_feature(dev, DRIVER_LEGACY))
-               drm_legacy_lock_release(dev, filp);
-
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               drm_legacy_reclaim_buffers(dev, file_priv);
-
-       drm_events_release(file_priv);
-
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               drm_fb_release(file_priv);
-               drm_property_destroy_user_blobs(dev, file_priv);
-       }
-
-       if (drm_core_check_feature(dev, DRIVER_GEM))
-               drm_gem_release(dev, file_priv);
-
-       drm_legacy_ctxbitmap_flush(dev, file_priv);
-
-       if (drm_is_primary_client(file_priv))
-               drm_master_release(file_priv);
-
-       if (dev->driver->postclose)
-               dev->driver->postclose(dev, file_priv);
-
-       if (drm_core_check_feature(dev, DRIVER_PRIME))
-               drm_prime_destroy_file_private(&file_priv->prime);
-
-       WARN_ON(!list_empty(&file_priv->event_list));
-
-       put_pid(file_priv->pid);
-       kfree(file_priv);
-
-       /* ========================================================
-        * End inline drm_release
-        */
-
-       if (!--dev->open_count) {
-               drm_lastclose(dev);
-               if (drm_device_is_unplugged(dev))
-                       drm_put_dev(dev);
-       }
-       mutex_unlock(&drm_global_mutex);
-
-       drm_minor_release(minor);
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_release);
-
-/**
- * drm_read - read method for DRM file
- * @filp: file pointer
- * @buffer: userspace destination pointer for the read
- * @count: count in bytes to read
- * @offset: offset to read
- *
- * This function must be used by drivers as their .read() #file_operations
- * method iff they use DRM events for asynchronous signalling to userspace.
- * Since events are used by the KMS API for vblank and page flip completion this
- * means all modern display drivers must use it.
- *
- * @offset is ignore, DRM events are read like a pipe. Therefore drivers also
- * must set the .llseek() #file_operation to no_llseek(). Polling support is
- * provided by drm_poll().
- *
- * This function will only ever read a full event. Therefore userspace must
- * supply a big enough buffer to fit any event to ensure forward progress. Since
- * the maximum event space is currently 4K it's recommended to just use that for
- * safety.
- *
- * RETURNS:
- *
- * Number of bytes read (always aligned to full events, and can be 0) or a
- * negative error code on failure.
- */
-ssize_t drm_read(struct file *filp, char __user *buffer,
-                size_t count, loff_t *offset)
-{
-       struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-       ssize_t ret;
-
-       if (!access_ok(VERIFY_WRITE, buffer, count))
-               return -EFAULT;
-
-       ret = mutex_lock_interruptible(&file_priv->event_read_lock);
-       if (ret)
-               return ret;
-
-       for (;;) {
-               struct drm_pending_event *e = NULL;
-
-               spin_lock_irq(&dev->event_lock);
-               if (!list_empty(&file_priv->event_list)) {
-                       e = list_first_entry(&file_priv->event_list,
-                                       struct drm_pending_event, link);
-                       file_priv->event_space += e->event->length;
-                       list_del(&e->link);
-               }
-               spin_unlock_irq(&dev->event_lock);
-
-               if (e == NULL) {
-                       if (ret)
-                               break;
-
-                       if (filp->f_flags & O_NONBLOCK) {
-                               ret = -EAGAIN;
-                               break;
-                       }
-
-                       mutex_unlock(&file_priv->event_read_lock);
-                       ret = wait_event_interruptible(file_priv->event_wait,
-                                                      !list_empty(&file_priv->event_list));
-                       if (ret >= 0)
-                               ret = mutex_lock_interruptible(&file_priv->event_read_lock);
-                       if (ret)
-                               return ret;
-               } else {
-                       unsigned length = e->event->length;
-
-                       if (length > count - ret) {
-put_back_event:
-                               spin_lock_irq(&dev->event_lock);
-                               file_priv->event_space -= length;
-                               list_add(&e->link, &file_priv->event_list);
-                               spin_unlock_irq(&dev->event_lock);
-                               break;
-                       }
-
-                       if (copy_to_user(buffer + ret, e->event, length)) {
-                               if (ret == 0)
-                                       ret = -EFAULT;
-                               goto put_back_event;
-                       }
-
-                       ret += length;
-                       kfree(e);
-               }
-       }
-       mutex_unlock(&file_priv->event_read_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL(drm_read);
-
-/**
- * drm_poll - poll method for DRM file
- * @filp: file pointer
- * @wait: poll waiter table
- *
- * This function must be used by drivers as their .read() #file_operations
- * method iff they use DRM events for asynchronous signalling to userspace.
- * Since events are used by the KMS API for vblank and page flip completion this
- * means all modern display drivers must use it.
- *
- * See also drm_read().
- *
- * RETURNS:
- *
- * Mask of POLL flags indicating the current status of the file.
- */
-unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
-{
-       struct drm_file *file_priv = filp->private_data;
-       unsigned int mask = 0;
-
-       poll_wait(filp, &file_priv->event_wait, wait);
-
-       if (!list_empty(&file_priv->event_list))
-               mask |= POLLIN | POLLRDNORM;
-
-       return mask;
-}
-EXPORT_SYMBOL(drm_poll);
-
-/**
- * drm_event_reserve_init_locked - init a DRM event and reserve space for it
- * @dev: DRM device
- * @file_priv: DRM file private data
- * @p: tracking structure for the pending event
- * @e: actual event data to deliver to userspace
- *
- * This function prepares the passed in event for eventual delivery. If the event
- * doesn't get delivered (because the IOCTL fails later on, before queuing up
- * anything) then the even must be cancelled and freed using
- * drm_event_cancel_free(). Successfully initialized events should be sent out
- * using drm_send_event() or drm_send_event_locked() to signal completion of the
- * asynchronous event to userspace.
- *
- * If callers embedded @p into a larger structure it must be allocated with
- * kmalloc and @p must be the first member element.
- *
- * This is the locked version of drm_event_reserve_init() for callers which
- * already hold &drm_device.event_lock.
- *
- * RETURNS:
- *
- * 0 on success or a negative error code on failure.
- */
-int drm_event_reserve_init_locked(struct drm_device *dev,
-                                 struct drm_file *file_priv,
-                                 struct drm_pending_event *p,
-                                 struct drm_event *e)
-{
-       if (file_priv->event_space < e->length)
-               return -ENOMEM;
-
-       file_priv->event_space -= e->length;
-
-       p->event = e;
-       list_add(&p->pending_link, &file_priv->pending_event_list);
-       p->file_priv = file_priv;
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_event_reserve_init_locked);
-
-/**
- * drm_event_reserve_init - init a DRM event and reserve space for it
- * @dev: DRM device
- * @file_priv: DRM file private data
- * @p: tracking structure for the pending event
- * @e: actual event data to deliver to userspace
- *
- * This function prepares the passed in event for eventual delivery. If the event
- * doesn't get delivered (because the IOCTL fails later on, before queuing up
- * anything) then the even must be cancelled and freed using
- * drm_event_cancel_free(). Successfully initialized events should be sent out
- * using drm_send_event() or drm_send_event_locked() to signal completion of the
- * asynchronous event to userspace.
- *
- * If callers embedded @p into a larger structure it must be allocated with
- * kmalloc and @p must be the first member element.
- *
- * Callers which already hold &drm_device.event_lock should use
- * drm_event_reserve_init_locked() instead.
- *
- * RETURNS:
- *
- * 0 on success or a negative error code on failure.
- */
-int drm_event_reserve_init(struct drm_device *dev,
-                          struct drm_file *file_priv,
-                          struct drm_pending_event *p,
-                          struct drm_event *e)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&dev->event_lock, flags);
-       ret = drm_event_reserve_init_locked(dev, file_priv, p, e);
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(drm_event_reserve_init);
-
-/**
- * drm_event_cancel_free - free a DRM event and release it's space
- * @dev: DRM device
- * @p: tracking structure for the pending event
- *
- * This function frees the event @p initialized with drm_event_reserve_init()
- * and releases any allocated space.
- */
-void drm_event_cancel_free(struct drm_device *dev,
-                          struct drm_pending_event *p)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&dev->event_lock, flags);
-       if (p->file_priv) {
-               p->file_priv->event_space += p->event->length;
-               list_del(&p->pending_link);
-       }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-
-       if (p->fence)
-               dma_fence_put(p->fence);
-
-       kfree(p);
-}
-EXPORT_SYMBOL(drm_event_cancel_free);
-
-/**
- * drm_send_event_locked - send DRM event to file descriptor
- * @dev: DRM device
- * @e: DRM event to deliver
- *
- * This function sends the event @e, initialized with drm_event_reserve_init(),
- * to its associated userspace DRM file. Callers must already hold
- * &drm_device.event_lock, see drm_send_event() for the unlocked version.
- *
- * Note that the core will take care of unlinking and disarming events when the
- * corresponding DRM file is closed. Drivers need not worry about whether the
- * DRM file for this event still exists and can call this function upon
- * completion of the asynchronous work unconditionally.
- */
-void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
-{
-       assert_spin_locked(&dev->event_lock);
-
-       if (e->completion) {
-               complete_all(e->completion);
-               e->completion_release(e->completion);
-               e->completion = NULL;
-       }
-
-       if (e->fence) {
-               dma_fence_signal(e->fence);
-               dma_fence_put(e->fence);
-       }
-
-       if (!e->file_priv) {
-               kfree(e);
-               return;
-       }
-
-       list_del(&e->pending_link);
-       list_add_tail(&e->link,
-                     &e->file_priv->event_list);
-       wake_up_interruptible(&e->file_priv->event_wait);
-}
-EXPORT_SYMBOL(drm_send_event_locked);
-
-/**
- * drm_send_event - send DRM event to file descriptor
- * @dev: DRM device
- * @e: DRM event to deliver
- *
- * This function sends the event @e, initialized with drm_event_reserve_init(),
- * to its associated userspace DRM file. This function acquires
- * &drm_device.event_lock, see drm_send_event_locked() for callers which already
- * hold this lock.
- *
- * Note that the core will take care of unlinking and disarming events when the
- * corresponding DRM file is closed. Drivers need not worry about whether the
- * DRM file for this event still exists and can call this function upon
- * completion of the asynchronous work unconditionally.
- */
-void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
-{
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev->event_lock, irqflags);
-       drm_send_event_locked(dev, e);
-       spin_unlock_irqrestore(&dev->event_lock, irqflags);
-}
-EXPORT_SYMBOL(drm_send_event);
index f37388c..92ff4b9 100644 (file)
@@ -24,7 +24,7 @@
 #define DRM_IF_MAJOR 1
 #define DRM_IF_MINOR 4
 
-/* drm_fops.c */
+/* drm_file.c */
 extern struct mutex drm_global_mutex;
 void drm_lastclose(struct drm_device *dev);
 
index 45db36c..6e35a56 100644 (file)
@@ -25,8 +25,7 @@
  *
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
+#include <linux/module.h>
 
 #include "drm_crtc_helper_internal.h"
 
index a3b356e..1eb4fc3 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
+#include <drm/drm_pci.h>
 #include <drm/drmP.h>
 #include "drm_internal.h"
 #include "drm_legacy.h"
@@ -36,6 +37,9 @@
  * @size: size of block to allocate
  * @align: alignment of block
  *
+ * FIXME: This is a needless abstraction of the Linux dma-api and should be
+ * removed.
+ *
  * Return: A handle to the allocated memory block on success or NULL on
  * failure.
  */
@@ -104,6 +108,9 @@ void __drm_legacy_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
  * drm_pci_free - Free a PCI consistent memory block
  * @dev: DRM device
  * @dmah: handle to memory block
+ *
+ * FIXME: This is a needless abstraction of the Linux dma-api and should be
+ * removed.
  */
 void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
index 244cf26..de1ac5e 100644 (file)
@@ -469,7 +469,7 @@ int drm_plane_helper_commit(struct drm_plane *plane,
         * Drivers may optionally implement the ->atomic_disable callback, so
         * special-case that here.
         */
-       if (drm_atomic_plane_disabling(plane, plane_state) &&
+       if (drm_atomic_plane_disabling(plane_state, plane->state) &&
            plane_funcs->atomic_disable)
                plane_funcs->atomic_disable(plane, plane_state);
        else
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
deleted file mode 100644 (file)
index 56d2f93..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Derived from drm_pci.c
- *
- * Copyright 2003 José Fonseca.
- * Copyright 2003 Leif Delgass.
- * Copyright (c) 2009, Code Aurora Forum.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/export.h>
-#include <drm/drmP.h>
-
-/*
- * Register.
- *
- * \param platdev - Platform device struture
- * \return zero on success or a negative number on failure.
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- */
-
-static int drm_get_platform_dev(struct platform_device *platdev,
-                               struct drm_driver *driver)
-{
-       struct drm_device *dev;
-       int ret;
-
-       DRM_DEBUG("\n");
-
-       dev = drm_dev_alloc(driver, &platdev->dev);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
-
-       dev->platformdev = platdev;
-
-       ret = drm_dev_register(dev, 0);
-       if (ret)
-               goto err_free;
-
-       return 0;
-
-err_free:
-       drm_dev_unref(dev);
-       return ret;
-}
-
-/**
- * drm_platform_init - Register a platform device with the DRM subsystem
- * @driver: DRM device driver
- * @platform_device: platform device to register
- *
- * Registers the specified DRM device driver and platform device with the DRM
- * subsystem, initializing a drm_device structure and calling the driver's
- * .load() function.
- *
- * NOTE: This function is deprecated, please use drm_dev_alloc() and
- * drm_dev_register() instead and remove your &drm_driver.load callback.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device)
-{
-       DRM_DEBUG("\n");
-
-       return drm_get_platform_dev(platform_device, driver);
-}
-EXPORT_SYMBOL(drm_platform_init);
index 866b294..9fb65b7 100644 (file)
@@ -29,8 +29,9 @@
 #include <linux/export.h>
 #include <linux/dma-buf.h>
 #include <linux/rbtree.h>
-#include <drm/drmP.h>
+#include <drm/drm_prime.h>
 #include <drm/drm_gem.h>
+#include <drm/drmP.h>
 
 #include "drm_internal.h"
 
index 35c5d99..16789fa 100644 (file)
@@ -86,8 +86,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
        int ret;
 
        pipe = container_of(plane, struct drm_simple_display_pipe, plane);
-       crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
-                                                       &pipe->crtc);
+       crtc_state = drm_atomic_get_new_crtc_state(plane_state->state,
+                                                  &pipe->crtc);
        if (crtc_state->enable != !!plane_state->crtc)
                return -EINVAL; /* plane must match crtc enable state */
 
index 1ef0be3..b445b50 100644 (file)
@@ -101,7 +101,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
        struct exynos_dp_device *dp = to_dp(plat_data);
        int ret;
 
-       drm_connector_register(connector);
        dp->connector = connector;
 
        /* Pre-empt DP connector creation if there's a bridge */
index ad6b73c..3aab71a 100644 (file)
@@ -114,7 +114,6 @@ static int exynos_dpi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
-       drm_connector_register(connector);
        drm_mode_connector_attach_encoder(connector, encoder);
 
        return 0;
index b4522f6..09d3c4c 100644 (file)
 
 static struct device *exynos_drm_get_dma_device(void);
 
-static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
-{
-       struct exynos_drm_private *private;
-       struct drm_encoder *encoder;
-       unsigned int clone_mask;
-       int cnt, ret;
-
-       private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
-       if (!private)
-               return -ENOMEM;
-
-       init_waitqueue_head(&private->wait);
-       spin_lock_init(&private->lock);
-
-       dev_set_drvdata(dev->dev, dev);
-       dev->dev_private = (void *)private;
-
-       /* the first real CRTC device is used for all dma mapping operations */
-       private->dma_dev = exynos_drm_get_dma_device();
-       if (!private->dma_dev) {
-               DRM_ERROR("no device found for DMA mapping operations.\n");
-               ret = -ENODEV;
-               goto err_free_private;
-       }
-       DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
-                dev_name(private->dma_dev));
-
-       /* create common IOMMU mapping for all devices attached to Exynos DRM */
-       ret = drm_create_iommu_mapping(dev);
-       if (ret < 0) {
-               DRM_ERROR("failed to create iommu mapping.\n");
-               goto err_free_private;
-       }
-
-       drm_mode_config_init(dev);
-
-       exynos_drm_mode_config_init(dev);
-
-       /* setup possible_clones. */
-       cnt = 0;
-       clone_mask = 0;
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-               clone_mask |= (1 << (cnt++));
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-               encoder->possible_clones = clone_mask;
-
-       platform_set_drvdata(dev->platformdev, dev);
-
-       /* Try to bind all sub drivers. */
-       ret = component_bind_all(dev->dev, dev);
-       if (ret)
-               goto err_mode_config_cleanup;
-
-       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
-       if (ret)
-               goto err_unbind_all;
-
-       /* Probe non kms sub drivers and virtual display driver. */
-       ret = exynos_drm_device_subdrv_probe(dev);
-       if (ret)
-               goto err_cleanup_vblank;
-
-       drm_mode_config_reset(dev);
-
-       /*
-        * enable drm irq mode.
-        * - with irq_enabled = true, we can use the vblank feature.
-        *
-        * P.S. note that we wouldn't use drm irq handler but
-        *      just specific driver own one instead because
-        *      drm framework supports only one irq handler.
-        */
-       dev->irq_enabled = true;
-
-       /* init kms poll for handling hpd */
-       drm_kms_helper_poll_init(dev);
-
-       /* force connectors detection */
-       drm_helper_hpd_irq_event(dev);
-
-       return 0;
-
-err_cleanup_vblank:
-       drm_vblank_cleanup(dev);
-err_unbind_all:
-       component_unbind_all(dev->dev, dev);
-err_mode_config_cleanup:
-       drm_mode_config_cleanup(dev);
-       drm_release_iommu_mapping(dev);
-err_free_private:
-       kfree(private);
-
-       return ret;
-}
-
-static void exynos_drm_unload(struct drm_device *dev)
-{
-       exynos_drm_device_subdrv_remove(dev);
-
-       exynos_drm_fbdev_fini(dev);
-       drm_kms_helper_poll_fini(dev);
-
-       drm_vblank_cleanup(dev);
-       component_unbind_all(dev->dev, dev);
-       drm_mode_config_cleanup(dev);
-       drm_release_iommu_mapping(dev);
-
-       kfree(dev->dev_private);
-       dev->dev_private = NULL;
-}
-
 int exynos_atomic_check(struct drm_device *dev,
                        struct drm_atomic_state *state)
 {
@@ -256,8 +144,6 @@ static const struct file_operations exynos_drm_driver_fops = {
 static struct drm_driver exynos_drm_driver = {
        .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
                                  | DRIVER_ATOMIC | DRIVER_RENDER,
-       .load                   = exynos_drm_load,
-       .unload                 = exynos_drm_unload,
        .open                   = exynos_drm_open,
        .preclose               = exynos_drm_preclose,
        .lastclose              = exynos_drm_lastclose,
@@ -432,12 +318,135 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
 
 static int exynos_drm_bind(struct device *dev)
 {
-       return drm_platform_init(&exynos_drm_driver, to_platform_device(dev));
+       struct exynos_drm_private *private;
+       struct drm_encoder *encoder;
+       struct drm_device *drm;
+       unsigned int clone_mask;
+       int cnt, ret;
+
+       drm = drm_dev_alloc(&exynos_drm_driver, dev);
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
+
+       private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
+       if (!private) {
+               ret = -ENOMEM;
+               goto err_free_drm;
+       }
+
+       init_waitqueue_head(&private->wait);
+       spin_lock_init(&private->lock);
+
+       dev_set_drvdata(dev, drm);
+       drm->dev_private = (void *)private;
+
+       /* the first real CRTC device is used for all dma mapping operations */
+       private->dma_dev = exynos_drm_get_dma_device();
+       if (!private->dma_dev) {
+               DRM_ERROR("no device found for DMA mapping operations.\n");
+               ret = -ENODEV;
+               goto err_free_private;
+       }
+       DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
+                dev_name(private->dma_dev));
+
+       /* create common IOMMU mapping for all devices attached to Exynos DRM */
+       ret = drm_create_iommu_mapping(drm);
+       if (ret < 0) {
+               DRM_ERROR("failed to create iommu mapping.\n");
+               goto err_free_private;
+       }
+
+       drm_mode_config_init(drm);
+
+       exynos_drm_mode_config_init(drm);
+
+       /* setup possible_clones. */
+       cnt = 0;
+       clone_mask = 0;
+       list_for_each_entry(encoder, &drm->mode_config.encoder_list, head)
+               clone_mask |= (1 << (cnt++));
+
+       list_for_each_entry(encoder, &drm->mode_config.encoder_list, head)
+               encoder->possible_clones = clone_mask;
+
+       /* Try to bind all sub drivers. */
+       ret = component_bind_all(drm->dev, drm);
+       if (ret)
+               goto err_mode_config_cleanup;
+
+       ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+       if (ret)
+               goto err_unbind_all;
+
+       /* Probe non kms sub drivers and virtual display driver. */
+       ret = exynos_drm_device_subdrv_probe(drm);
+       if (ret)
+               goto err_cleanup_vblank;
+
+       drm_mode_config_reset(drm);
+
+       /*
+        * enable drm irq mode.
+        * - with irq_enabled = true, we can use the vblank feature.
+        *
+        * P.S. note that we wouldn't use drm irq handler but
+        *      just specific driver own one instead because
+        *      drm framework supports only one irq handler.
+        */
+       drm->irq_enabled = true;
+
+       /* init kms poll for handling hpd */
+       drm_kms_helper_poll_init(drm);
+
+       /* force connectors detection */
+       drm_helper_hpd_irq_event(drm);
+
+       /* register the DRM device */
+       ret = drm_dev_register(drm, 0);
+       if (ret < 0)
+               goto err_cleanup_fbdev;
+
+       return 0;
+
+err_cleanup_fbdev:
+       exynos_drm_fbdev_fini(drm);
+       drm_kms_helper_poll_fini(drm);
+       exynos_drm_device_subdrv_remove(drm);
+err_cleanup_vblank:
+       drm_vblank_cleanup(drm);
+err_unbind_all:
+       component_unbind_all(drm->dev, drm);
+err_mode_config_cleanup:
+       drm_mode_config_cleanup(drm);
+       drm_release_iommu_mapping(drm);
+err_free_private:
+       kfree(private);
+err_free_drm:
+       drm_dev_unref(drm);
+
+       return ret;
 }
 
 static void exynos_drm_unbind(struct device *dev)
 {
-       drm_put_dev(dev_get_drvdata(dev));
+       struct drm_device *drm = dev_get_drvdata(dev);
+
+       drm_dev_unregister(drm);
+
+       exynos_drm_device_subdrv_remove(drm);
+
+       exynos_drm_fbdev_fini(drm);
+       drm_kms_helper_poll_fini(drm);
+
+       component_unbind_all(drm->dev, drm);
+       drm_mode_config_cleanup(drm);
+       drm_release_iommu_mapping(drm);
+
+       kfree(drm->dev_private);
+       drm->dev_private = NULL;
+
+       drm_dev_unref(drm);
 }
 
 static const struct component_master_ops exynos_drm_ops = {
index 812e2ec..43a45ab 100644 (file)
@@ -1587,7 +1587,6 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
-       drm_connector_register(connector);
        drm_mode_connector_attach_encoder(connector, encoder);
 
        return 0;
index 40aa505..6415312 100644 (file)
@@ -119,7 +119,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
        struct exynos_drm_gem *exynos_gem;
        struct drm_device *dev = helper->dev;
        struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-       struct platform_device *pdev = dev->platformdev;
        unsigned long size;
        int ret;
 
@@ -142,7 +141,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
         * memory area.
         */
        if (IS_ERR(exynos_gem) && is_drm_iommu_supported(dev)) {
-               dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
+               dev_warn(dev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
                exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG,
                                                   size);
        }
index 57fe514..6bbb0ea 100644 (file)
@@ -359,7 +359,6 @@ static int vidi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
-       drm_connector_register(connector);
        drm_mode_connector_attach_encoder(connector, encoder);
 
        return 0;
index 0814ed7..5243840 100644 (file)
@@ -920,7 +920,6 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
        }
 
        drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
-       drm_connector_register(connector);
        drm_mode_connector_attach_encoder(connector, encoder);
 
        if (hdata->bridge) {
index f645275..f039641 100644 (file)
@@ -175,7 +175,6 @@ static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
        .mpll_cfg   = imx_mpll_cfg,
        .cur_ctr    = imx_cur_ctr,
        .phy_config = imx_phy_config,
-       .dev_type   = IMX6Q_HDMI,
        .mode_valid = imx6q_hdmi_mode_valid,
 };
 
@@ -183,7 +182,6 @@ static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
        .mpll_cfg = imx_mpll_cfg,
        .cur_ctr  = imx_cur_ctr,
        .phy_config = imx_phy_config,
-       .dev_type = IMX6DL_HDMI,
        .mode_valid = imx6dl_hdmi_mode_valid,
 };
 
index 94ea963..a4e1206 100644 (file)
@@ -434,7 +434,7 @@ fail:
 
 struct msm_kms *mdp4_kms_init(struct drm_device *dev)
 {
-       struct platform_device *pdev = dev->platformdev;
+       struct platform_device *pdev = to_platform_device(dev->dev);
        struct mdp4_platform_config *config = mdp4_get_config(pdev);
        struct mdp4_kms *mdp4_kms;
        struct msm_kms *kms = NULL;
index 34ab553..ba2d017 100644 (file)
@@ -505,7 +505,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
                uint32_t major, uint32_t minor)
 {
        struct drm_device *dev = mdp5_kms->dev;
-       struct platform_device *pdev = dev->platformdev;
+       struct platform_device *pdev = to_platform_device(dev->dev);
        struct mdp5_cfg_handler *cfg_handler;
        struct mdp5_cfg_platform *pconfig;
        int i, ret = 0;
index d444a69..f8f48d0 100644 (file)
@@ -160,7 +160,7 @@ void msm_mdss_destroy(struct drm_device *dev)
 
 int msm_mdss_init(struct drm_device *dev)
 {
-       struct platform_device *pdev = dev->platformdev;
+       struct platform_device *pdev = to_platform_device(dev->dev);
        struct msm_drm_private *priv = dev->dev_private;
        struct msm_mdss *mdss;
        int ret;
index 75609a1..4f35d4e 100644 (file)
@@ -164,20 +164,5 @@ int msm_debugfs_init(struct drm_minor *minor)
 
        return ret;
 }
-
-void msm_debugfs_cleanup(struct drm_minor *minor)
-{
-       struct drm_device *dev = minor->dev;
-       struct msm_drm_private *priv = dev->dev_private;
-
-       if (!priv)
-               return;
-
-       if (priv->kms->funcs->debugfs_cleanup)
-               priv->kms->funcs->debugfs_cleanup(priv->kms, minor);
-
-       msm_rd_debugfs_cleanup(minor);
-       msm_perf_debugfs_cleanup(minor);
-}
 #endif
 
index 6110c97..f4077e3 100644 (file)
@@ -20,7 +20,6 @@
 
 #ifdef CONFIG_DEBUG_FS
 int msm_debugfs_init(struct drm_minor *minor);
-void msm_debugfs_cleanup(struct drm_minor *minor);
 #endif
 
 #endif /* __MSM_DEBUGFS_H__ */
index 6842d42..9208e67 100644 (file)
@@ -241,6 +241,9 @@ static int msm_drm_uninit(struct device *dev)
 
        drm_dev_unregister(ddev);
 
+       msm_perf_debugfs_cleanup(priv);
+       msm_rd_debugfs_cleanup(priv);
+
 #ifdef CONFIG_DRM_FBDEV_EMULATION
        if (fbdev && priv->fbdev)
                msm_fbdev_free(ddev);
@@ -383,7 +386,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
        }
 
        platform_set_drvdata(pdev, ddev);
-       ddev->platformdev = pdev;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
@@ -836,7 +838,6 @@ static struct drm_driver msm_driver = {
        .gem_prime_mmap     = msm_gem_prime_mmap,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init       = msm_debugfs_init,
-       .debugfs_cleanup    = msm_debugfs_cleanup,
 #endif
        .ioctls             = msm_ioctls,
        .num_ioctls         = DRM_MSM_NUM_IOCTLS,
index c3b1487..b51fb0d 100644 (file)
@@ -304,10 +304,10 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m);
 void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
 int msm_debugfs_late_init(struct drm_device *dev);
 int msm_rd_debugfs_init(struct drm_minor *minor);
-void msm_rd_debugfs_cleanup(struct drm_minor *minor);
+void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);
 void msm_rd_dump_submit(struct msm_gem_submit *submit);
 int msm_perf_debugfs_init(struct drm_minor *minor);
-void msm_perf_debugfs_cleanup(struct drm_minor *minor);
+void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
 #else
 static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
 static inline void msm_rd_dump_submit(struct msm_gem_submit *submit) {}
index 117635d..faa22c7 100644 (file)
@@ -64,7 +64,6 @@ struct msm_kms_funcs {
 #ifdef CONFIG_DEBUG_FS
        /* debugfs: */
        int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor);
-       void (*debugfs_cleanup)(struct msm_kms *kms, struct drm_minor *minor);
 #endif
 };
 
index fc5a948..5ab21bd 100644 (file)
@@ -231,13 +231,12 @@ int msm_perf_debugfs_init(struct drm_minor *minor)
        return 0;
 
 fail:
-       msm_perf_debugfs_cleanup(minor);
+       msm_perf_debugfs_cleanup(priv);
        return -1;
 }
 
-void msm_perf_debugfs_cleanup(struct drm_minor *minor)
+void msm_perf_debugfs_cleanup(struct msm_drm_private *priv)
 {
-       struct msm_drm_private *priv = minor->dev->dev_private;
        struct msm_perf_state *perf = priv->perf;
 
        if (!perf)
index ab0b39f..3df7322 100644 (file)
@@ -245,13 +245,12 @@ int msm_rd_debugfs_init(struct drm_minor *minor)
        return 0;
 
 fail:
-       msm_rd_debugfs_cleanup(minor);
+       msm_rd_debugfs_cleanup(priv);
        return -1;
 }
 
-void msm_rd_debugfs_cleanup(struct drm_minor *minor)
+void msm_rd_debugfs_cleanup(struct msm_drm_private *priv)
 {
-       struct msm_drm_private *priv = minor->dev->dev_private;
        struct msm_rd_state *rd = priv->rd;
 
        if (!rd)
index f0bb760..2b6ac24 100644 (file)
@@ -108,7 +108,7 @@ nouveau_name(struct drm_device *dev)
        if (dev->pdev)
                return nouveau_pci_name(dev->pdev);
        else
-               return nouveau_platform_name(dev->platformdev);
+               return nouveau_platform_name(to_platform_device(dev->dev));
 }
 
 static void
@@ -1095,7 +1095,6 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
                goto err_free;
        }
 
-       drm->platformdev = pdev;
        platform_set_drvdata(pdev, drm);
 
        return drm;
index 8e6c780..ffe821b 100644 (file)
@@ -129,16 +129,3 @@ int qxl_debugfs_add_files(struct qxl_device *qdev,
 #endif
        return 0;
 }
-
-void qxl_debugfs_remove_files(struct qxl_device *qdev)
-{
-#if defined(CONFIG_DEBUG_FS)
-       unsigned i;
-
-       for (i = 0; i < qdev->debugfs_count; i++) {
-               drm_debugfs_remove_files(qdev->debugfs[i].files,
-                                        qdev->debugfs[i].num_files,
-                                        qdev->ddev.primary);
-       }
-#endif
-}
index 2cd14be..9548bb5 100644 (file)
@@ -81,6 +81,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
                           qdev->rom->client_monitors_config_crc);
                return MONITORS_CONFIG_BAD_CRC;
        }
+       if (!num_monitors) {
+               DRM_DEBUG_KMS("no client monitors configured\n");
+               return status;
+       }
        if (num_monitors > qdev->monitors_config->max_allowed) {
                DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
                              qdev->monitors_config->max_allowed, num_monitors);
@@ -157,19 +161,23 @@ static void qxl_update_offset_props(struct qxl_device *qdev)
 
 void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
 {
-
        struct drm_device *dev = &qdev->ddev;
-       int status;
+       int status, retries;
 
-       status = qxl_display_copy_rom_client_monitors_config(qdev);
-       while (status == MONITORS_CONFIG_BAD_CRC) {
-               qxl_io_log(qdev, "failed crc check for client_monitors_config,"
-                                " retrying\n");
+       for (retries = 0; retries < 10; retries++) {
                status = qxl_display_copy_rom_client_monitors_config(qdev);
+               if (status != MONITORS_CONFIG_BAD_CRC)
+                       break;
+               udelay(5);
+       }
+       if (status == MONITORS_CONFIG_BAD_CRC) {
+               qxl_io_log(qdev, "config: bad crc\n");
+               DRM_DEBUG_KMS("ignoring client monitors config: bad crc");
+               return;
        }
        if (status == MONITORS_CONFIG_UNCHANGED) {
-               qxl_io_log(qdev, "config unchanged\n");
-               DRM_DEBUG("ignoring unchanged client monitors config");
+               qxl_io_log(qdev, "config: unchanged\n");
+               DRM_DEBUG_KMS("ignoring client monitors config: unchanged");
                return;
        }
 
@@ -194,9 +202,17 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
        struct drm_display_mode *mode = NULL;
        struct qxl_head *head;
 
+       if (!qdev->monitors_config)
+               return 0;
+       if (h >= qdev->monitors_config->max_allowed)
+               return 0;
        if (!qdev->client_monitors_config)
                return 0;
+       if (h >= qdev->client_monitors_config->count)
+               return 0;
+
        head = &qdev->client_monitors_config->heads[h];
+       DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height);
 
        mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
                            false);
@@ -903,19 +919,13 @@ static void qxl_enc_mode_set(struct drm_encoder *encoder,
 
 static int qxl_conn_get_modes(struct drm_connector *connector)
 {
-       int ret = 0;
-       struct qxl_device *qdev = connector->dev->dev_private;
        unsigned pwidth = 1024;
        unsigned pheight = 768;
+       int ret = 0;
 
-       DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config);
-       /* TODO: what should we do here? only show the configured modes for the
-        * device, or allow the full list, or both? */
-       if (qdev->monitors_config && qdev->monitors_config->count) {
-               ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
+       if (ret < 0)
+               return ret;
        ret += qxl_add_common_modes(connector, pwidth, pheight);
        return ret;
 }
@@ -1188,6 +1198,7 @@ int qxl_modeset_init(struct qxl_device *qdev)
                qdev_output_init(&qdev->ddev, i);
        }
 
+       qxl_display_read_client_monitors_config(qdev);
        qdev->mode_info.mode_config_initialized = true;
 
        drm_mode_config_reset(&qdev->ddev);
index c048170..5ea290a 100644 (file)
@@ -160,8 +160,6 @@ struct qxl_mman {
 };
 
 struct qxl_mode_info {
-       int num_modes;
-       struct qxl_mode *modes;
        bool mode_config_initialized;
 
        /* pointer to fbdev info structure */
@@ -232,7 +230,6 @@ int qxl_debugfs_add_files(struct qxl_device *rdev,
                             struct drm_info_list *files,
                             unsigned nfiles);
 int qxl_debugfs_fence_init(struct qxl_device *rdev);
-void qxl_debugfs_remove_files(struct qxl_device *qdev);
 
 struct qxl_device;
 
index 3512473..14e2a49 100644 (file)
@@ -368,9 +368,11 @@ static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
 
 int qxl_fbdev_init(struct qxl_device *qdev)
 {
+       int ret = 0;
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
        struct qxl_fbdev *qfbdev;
        int bpp_sel = 32; /* TODO: parameter from somewhere? */
-       int ret;
 
        qfbdev = kzalloc(sizeof(struct qxl_fbdev), GFP_KERNEL);
        if (!qfbdev)
@@ -403,6 +405,8 @@ fini:
        drm_fb_helper_fini(&qfbdev->helper);
 free:
        kfree(qfbdev);
+#endif
+
        return ret;
 }
 
@@ -418,6 +422,9 @@ void qxl_fbdev_fini(struct qxl_device *qdev)
 
 void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state)
 {
+       if (!qdev->mode_info.qfbdev)
+               return;
+
        drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state);
 }
 
index 2b1e1f3..c5716a0 100644 (file)
 
 int qxl_log_level;
 
-static void qxl_dump_mode(struct qxl_device *qdev, void *p)
-{
-       struct qxl_mode *m = p;
-       DRM_DEBUG_KMS("%d: %dx%d %d bits, stride %d, %dmm x %dmm, orientation %d\n",
-                     m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili,
-                     m->y_mili, m->orientation);
-}
-
 static bool qxl_check_device(struct qxl_device *qdev)
 {
        struct qxl_rom *rom = qdev->rom;
-       int mode_offset;
-       int i;
 
        if (rom->magic != 0x4f525851) {
                DRM_ERROR("bad rom signature %x\n", rom->magic);
@@ -53,8 +43,6 @@ static bool qxl_check_device(struct qxl_device *qdev)
        DRM_INFO("Device Version %d.%d\n", rom->id, rom->update_id);
        DRM_INFO("Compression level %d log level %d\n", rom->compression_level,
                 rom->log_level);
-       DRM_INFO("Currently using mode #%d, list at 0x%x\n",
-                rom->mode, rom->modes_offset);
        DRM_INFO("%d io pages at offset 0x%x\n",
                 rom->num_io_pages, rom->pages_offset);
        DRM_INFO("%d byte draw area at offset 0x%x\n",
@@ -62,14 +50,6 @@ static bool qxl_check_device(struct qxl_device *qdev)
 
        qdev->vram_size = rom->surface0_area_size;
        DRM_INFO("RAM header offset: 0x%x\n", rom->ram_header_offset);
-
-       mode_offset = rom->modes_offset / 4;
-       qdev->mode_info.num_modes = ((u32 *)rom)[mode_offset];
-       DRM_INFO("rom modes offset 0x%x for %d modes\n", rom->modes_offset,
-                qdev->mode_info.num_modes);
-       qdev->mode_info.modes = (void *)((uint32_t *)rom + mode_offset + 1);
-       for (i = 0; i < qdev->mode_info.num_modes; i++)
-               qxl_dump_mode(qdev, qdev->mode_info.modes + i);
        return true;
 }
 
@@ -282,7 +262,4 @@ void qxl_device_fini(struct qxl_device *qdev)
        iounmap(qdev->ram_header);
        iounmap(qdev->rom);
        qdev->rom = NULL;
-       qdev->mode_info.modes = NULL;
-       qdev->mode_info.num_modes = 0;
-       qxl_debugfs_remove_files(qdev);
 }
index a6d4a02..d538274 100644 (file)
@@ -237,7 +237,6 @@ static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
        .mpll_cfg   = rockchip_mpll_cfg,
        .cur_ctr    = rockchip_cur_ctr,
        .phy_config = rockchip_phy_config,
-       .dev_type   = RK3288_HDMI,
 };
 
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
index 94d7b73..2151e1c 100644 (file)
@@ -19,6 +19,9 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_flip_work.h>
 #include <drm/drm_plane_helper.h>
+#ifdef CONFIG_DRM_ANALOGIX_DP
+#include <drm/bridge/analogix_dp.h>
+#endif
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -1111,6 +1114,53 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc,
        kfree(s);
 }
 
+#ifdef CONFIG_DRM_ANALOGIX_DP
+static struct drm_connector *vop_get_edp_connector(struct vop *vop)
+{
+       struct drm_crtc *crtc = &vop->crtc;
+       struct drm_connector *connector;
+
+       mutex_lock(&crtc->dev->mode_config.mutex);
+       drm_for_each_connector(connector, crtc->dev)
+               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+                       mutex_unlock(&crtc->dev->mode_config.mutex);
+                       return connector;
+               }
+       mutex_unlock(&crtc->dev->mode_config.mutex);
+
+       return NULL;
+}
+
+static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
+                                  const char *source_name, size_t *values_cnt)
+{
+       struct vop *vop = to_vop(crtc);
+       struct drm_connector *connector;
+       int ret;
+
+       connector = vop_get_edp_connector(vop);
+       if (!connector)
+               return -EINVAL;
+
+       *values_cnt = 3;
+
+       if (source_name && strcmp(source_name, "auto") == 0)
+               ret = analogix_dp_start_crc(connector);
+       else if (!source_name)
+               ret = analogix_dp_stop_crc(connector);
+       else
+               ret = -EINVAL;
+
+       return ret;
+}
+#else
+static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
+                                  const char *source_name, size_t *values_cnt)
+{
+       return -ENODEV;
+}
+#endif
+
 static const struct drm_crtc_funcs vop_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
@@ -1120,6 +1170,7 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
        .atomic_destroy_state = vop_crtc_destroy_state,
        .enable_vblank = vop_crtc_enable_vblank,
        .disable_vblank = vop_crtc_disable_vblank,
+       .set_crc_source = vop_crtc_set_crc_source,
 };
 
 static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
index 8244890..5fcabc0 100644 (file)
@@ -711,13 +711,10 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev,
                return ret;
 
        drm_connector_helper_add(connector, &connector_helper_funcs);
-       ret = drm_connector_register(connector);
-       if (ret < 0)
-               goto err_cleanup;
 
        ret = shmob_drm_backlight_init(&sdev->connector);
        if (ret < 0)
-               goto err_sysfs;
+               goto err_cleanup;
 
        ret = drm_mode_connector_attach_encoder(connector, encoder);
        if (ret < 0)
@@ -731,8 +728,6 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev,
 
 err_backlight:
        shmob_drm_backlight_exit(&sdev->connector);
-err_sysfs:
-       drm_connector_unregister(connector);
 err_cleanup:
        drm_connector_cleanup(connector);
        return ret;
index 34fefa0..1c7b318 100644 (file)
@@ -103,100 +103,6 @@ static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
  * DRM operations
  */
 
-static void shmob_drm_unload(struct drm_device *dev)
-{
-       drm_kms_helper_poll_fini(dev);
-       drm_mode_config_cleanup(dev);
-       drm_vblank_cleanup(dev);
-       drm_irq_uninstall(dev);
-
-       dev->dev_private = NULL;
-}
-
-static int shmob_drm_load(struct drm_device *dev, unsigned long flags)
-{
-       struct shmob_drm_platform_data *pdata = dev->dev->platform_data;
-       struct platform_device *pdev = dev->platformdev;
-       struct shmob_drm_device *sdev;
-       struct resource *res;
-       unsigned int i;
-       int ret;
-
-       if (pdata == NULL) {
-               dev_err(dev->dev, "no platform data\n");
-               return -EINVAL;
-       }
-
-       sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL);
-       if (sdev == NULL) {
-               dev_err(dev->dev, "failed to allocate private data\n");
-               return -ENOMEM;
-       }
-
-       sdev->dev = &pdev->dev;
-       sdev->pdata = pdata;
-       spin_lock_init(&sdev->irq_lock);
-
-       sdev->ddev = dev;
-       dev->dev_private = sdev;
-
-       /* I/O resources and clocks */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get memory resource\n");
-               return -EINVAL;
-       }
-
-       sdev->mmio = devm_ioremap_nocache(&pdev->dev, res->start,
-                                         resource_size(res));
-       if (sdev->mmio == NULL) {
-               dev_err(&pdev->dev, "failed to remap memory resource\n");
-               return -ENOMEM;
-       }
-
-       ret = shmob_drm_setup_clocks(sdev, pdata->clk_source);
-       if (ret < 0)
-               return ret;
-
-       ret = shmob_drm_init_interface(sdev);
-       if (ret < 0)
-               return ret;
-
-       ret = shmob_drm_modeset_init(sdev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to initialize mode setting\n");
-               return ret;
-       }
-
-       for (i = 0; i < 4; ++i) {
-               ret = shmob_drm_plane_create(sdev, i);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to create plane %u\n", i);
-                       goto done;
-               }
-       }
-
-       ret = drm_vblank_init(dev, 1);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to initialize vblank\n");
-               goto done;
-       }
-
-       ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to install IRQ handler\n");
-               goto done;
-       }
-
-       platform_set_drvdata(pdev, sdev);
-
-done:
-       if (ret)
-               shmob_drm_unload(dev);
-
-       return ret;
-}
-
 static irqreturn_t shmob_drm_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
@@ -236,8 +142,6 @@ static const struct file_operations shmob_drm_fops = {
 static struct drm_driver shmob_drm_driver = {
        .driver_features        = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
                                | DRIVER_PRIME,
-       .load                   = shmob_drm_load,
-       .unload                 = shmob_drm_unload,
        .irq_handler            = shmob_drm_irq,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
@@ -297,18 +201,116 @@ static const struct dev_pm_ops shmob_drm_pm_ops = {
  * Platform driver
  */
 
-static int shmob_drm_probe(struct platform_device *pdev)
+static int shmob_drm_remove(struct platform_device *pdev)
 {
-       return drm_platform_init(&shmob_drm_driver, pdev);
+       struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
+       struct drm_device *ddev = sdev->ddev;
+
+       drm_dev_unregister(ddev);
+       drm_kms_helper_poll_fini(ddev);
+       drm_mode_config_cleanup(ddev);
+       drm_irq_uninstall(ddev);
+       drm_dev_unref(ddev);
+
+       return 0;
 }
 
-static int shmob_drm_remove(struct platform_device *pdev)
+static int shmob_drm_probe(struct platform_device *pdev)
 {
-       struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
+       struct shmob_drm_platform_data *pdata = pdev->dev.platform_data;
+       struct shmob_drm_device *sdev;
+       struct drm_device *ddev;
+       struct resource *res;
+       unsigned int i;
+       int ret;
+
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "no platform data\n");
+               return -EINVAL;
+       }
 
-       drm_put_dev(sdev->ddev);
+       /*
+        * Allocate and initialize the driver private data, I/O resources and
+        * clocks.
+        */
+       sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL);
+       if (sdev == NULL)
+               return -ENOMEM;
+
+       sdev->dev = &pdev->dev;
+       sdev->pdata = pdata;
+       spin_lock_init(&sdev->irq_lock);
+
+       platform_set_drvdata(pdev, sdev);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       sdev->mmio = devm_ioremap_resource(&pdev->dev, res);
+       if (sdev->mmio == NULL)
+               return -ENOMEM;
+
+       ret = shmob_drm_setup_clocks(sdev, pdata->clk_source);
+       if (ret < 0)
+               return ret;
+
+       ret = shmob_drm_init_interface(sdev);
+       if (ret < 0)
+               return ret;
+
+       /* Allocate and initialize the DRM device. */
+       ddev = drm_dev_alloc(&shmob_drm_driver, &pdev->dev);
+       if (IS_ERR(ddev))
+               return PTR_ERR(ddev);
+
+       sdev->ddev = ddev;
+       ddev->dev_private = sdev;
+
+       ret = shmob_drm_modeset_init(sdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to initialize mode setting\n");
+               goto err_free_drm_dev;
+       }
+
+       for (i = 0; i < 4; ++i) {
+               ret = shmob_drm_plane_create(sdev, i);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to create plane %u\n", i);
+                       goto err_modeset_cleanup;
+               }
+       }
+
+       ret = drm_vblank_init(ddev, 1);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to initialize vblank\n");
+               goto err_modeset_cleanup;
+       }
+
+       ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to install IRQ handler\n");
+               goto err_vblank_cleanup;
+       }
+
+       /*
+        * Register the DRM device with the core and the connectors with
+        * sysfs.
+        */
+       ret = drm_dev_register(ddev, 0);
+       if (ret < 0)
+               goto err_irq_uninstall;
 
        return 0;
+
+err_irq_uninstall:
+       drm_irq_uninstall(ddev);
+err_vblank_cleanup:
+       drm_vblank_cleanup(ddev);
+err_modeset_cleanup:
+       drm_kms_helper_poll_fini(ddev);
+       drm_mode_config_cleanup(ddev);
+err_free_drm_dev:
+       drm_dev_unref(ddev);
+
+       return ret;
 }
 
 static struct platform_driver shmob_drm_platform_driver = {
index 3b15c2c..6003c66 100644 (file)
@@ -263,8 +263,6 @@ static int sti_bind(struct device *dev)
        if (IS_ERR(ddev))
                return PTR_ERR(ddev);
 
-       ddev->platformdev = to_platform_device(dev);
-
        ret = sti_init(ddev);
        if (ret)
                goto err_drm_dev_unref;
index 81d80a2..5b4ed0e 100644 (file)
@@ -245,7 +245,6 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
        if (IS_ERR(ddev))
                return PTR_ERR(ddev);
 
-       ddev->platformdev = pdev;
        ddev->dev_private = priv;
        platform_set_drvdata(pdev, ddev);
        drm_mode_config_init(ddev);
index d59f689..93900a8 100644 (file)
@@ -178,9 +178,7 @@ struct virtio_gpu_device {
 
        struct virtio_gpu_queue ctrlq;
        struct virtio_gpu_queue cursorq;
-       struct list_head free_vbufs;
-       spinlock_t free_vbufs_lock;
-       void *vbufs;
+       struct kmem_cache *vbufs;
        bool vqs_ready;
 
        struct idr      resource_idr;
index 43ea0dc..472e349 100644 (file)
@@ -74,51 +74,19 @@ void virtio_gpu_cursor_ack(struct virtqueue *vq)
 
 int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev)
 {
-       struct virtio_gpu_vbuffer *vbuf;
-       int i, size, count = 16;
-       void *ptr;
-
-       INIT_LIST_HEAD(&vgdev->free_vbufs);
-       spin_lock_init(&vgdev->free_vbufs_lock);
-       count += virtqueue_get_vring_size(vgdev->ctrlq.vq);
-       count += virtqueue_get_vring_size(vgdev->cursorq.vq);
-       size = count * VBUFFER_SIZE;
-       DRM_INFO("virtio vbuffers: %d bufs, %zdB each, %dkB total.\n",
-                count, VBUFFER_SIZE, size / 1024);
-
-       vgdev->vbufs = kzalloc(size, GFP_KERNEL);
+       vgdev->vbufs = kmem_cache_create("virtio-gpu-vbufs",
+                                        VBUFFER_SIZE,
+                                        __alignof__(struct virtio_gpu_vbuffer),
+                                        0, NULL);
        if (!vgdev->vbufs)
                return -ENOMEM;
-
-       for (i = 0, ptr = vgdev->vbufs;
-            i < count;
-            i++, ptr += VBUFFER_SIZE) {
-               vbuf = ptr;
-               list_add(&vbuf->list, &vgdev->free_vbufs);
-       }
        return 0;
 }
 
 void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev)
 {
-       struct virtio_gpu_vbuffer *vbuf;
-       int i, count = 0;
-
-       count += virtqueue_get_vring_size(vgdev->ctrlq.vq);
-       count += virtqueue_get_vring_size(vgdev->cursorq.vq);
-
-       spin_lock(&vgdev->free_vbufs_lock);
-       for (i = 0; i < count; i++) {
-               if (WARN_ON(list_empty(&vgdev->free_vbufs))) {
-                       spin_unlock(&vgdev->free_vbufs_lock);
-                       return;
-               }
-               vbuf = list_first_entry(&vgdev->free_vbufs,
-                                       struct virtio_gpu_vbuffer, list);
-               list_del(&vbuf->list);
-       }
-       spin_unlock(&vgdev->free_vbufs_lock);
-       kfree(vgdev->vbufs);
+       kmem_cache_destroy(vgdev->vbufs);
+       vgdev->vbufs = NULL;
 }
 
 static struct virtio_gpu_vbuffer*
@@ -128,12 +96,9 @@ virtio_gpu_get_vbuf(struct virtio_gpu_device *vgdev,
 {
        struct virtio_gpu_vbuffer *vbuf;
 
-       spin_lock(&vgdev->free_vbufs_lock);
-       BUG_ON(list_empty(&vgdev->free_vbufs));
-       vbuf = list_first_entry(&vgdev->free_vbufs,
-                               struct virtio_gpu_vbuffer, list);
-       list_del(&vbuf->list);
-       spin_unlock(&vgdev->free_vbufs_lock);
+       vbuf = kmem_cache_alloc(vgdev->vbufs, GFP_KERNEL);
+       if (IS_ERR(vbuf))
+               return ERR_CAST(vbuf);
        memset(vbuf, 0, VBUFFER_SIZE);
 
        BUG_ON(size > MAX_INLINE_CMD_SIZE);
@@ -208,9 +173,7 @@ static void free_vbuf(struct virtio_gpu_device *vgdev,
        if (vbuf->resp_size > MAX_INLINE_RESP_SIZE)
                kfree(vbuf->resp_buf);
        kfree(vbuf->data_buf);
-       spin_lock(&vgdev->free_vbufs_lock);
-       list_add(&vbuf->list, &vgdev->free_vbufs);
-       spin_unlock(&vgdev->free_vbufs_lock);
+       kmem_cache_free(vgdev->vbufs, vbuf);
 }
 
 static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list)
index f6f0c06..c99d6ea 100644 (file)
@@ -49,4 +49,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
                     struct analogix_dp_plat_data *plat_data);
 void analogix_dp_unbind(struct device *dev, struct device *master, void *data);
 
+int analogix_dp_start_crc(struct drm_connector *connector);
+int analogix_dp_stop_crc(struct drm_connector *connector);
+
 #endif /* _ANALOGIX_DP_H_ */
index b080a17..bcceee8 100644 (file)
@@ -21,12 +21,6 @@ enum {
        DW_HDMI_RES_MAX,
 };
 
-enum dw_hdmi_devtype {
-       IMX6Q_HDMI,
-       IMX6DL_HDMI,
-       RK3288_HDMI,
-};
-
 enum dw_hdmi_phy_type {
        DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
        DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
@@ -57,13 +51,30 @@ struct dw_hdmi_phy_config {
        u16 vlev_ctr;   /* voltage level control */
 };
 
+struct dw_hdmi_phy_ops {
+       int (*init)(struct dw_hdmi *hdmi, void *data,
+                   struct drm_display_mode *mode);
+       void (*disable)(struct dw_hdmi *hdmi, void *data);
+       enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
+};
+
 struct dw_hdmi_plat_data {
-       enum dw_hdmi_devtype dev_type;
+       struct regmap *regm;
+       enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+                                          struct drm_display_mode *mode);
+
+       /* Vendor PHY support */
+       const struct dw_hdmi_phy_ops *phy_ops;
+       const char *phy_name;
+       void *phy_data;
+
+       /* Synopsys PHY support */
        const struct dw_hdmi_mpll_config *mpll_cfg;
        const struct dw_hdmi_curr_ctrl *cur_ctr;
        const struct dw_hdmi_phy_config *phy_config;
-       enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
-                                          struct drm_display_mode *mode);
+       int (*configure_phy)(struct dw_hdmi *hdmi,
+                            const struct dw_hdmi_plat_data *pdata,
+                            unsigned long mpixelclock);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
@@ -77,4 +88,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
 void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
 void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
 
+/* PHY configuration */
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
+                          unsigned char addr);
+
 #endif /* __IMX_HDMI_H__ */
index 6105c05..0e38343 100644 (file)
 #include <linux/miscdevice.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
-#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/poll.h>
 #include <linux/ratelimit.h>
-#include <linux/rbtree.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/workqueue.h>
 #include <linux/dma-fence.h>
+#include <linux/module.h>
 
 #include <asm/mman.h>
 #include <asm/pgalloc.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_os_linux.h>
 #include <drm/drm_sarea.h>
-#include <drm/drm_vma_manager.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_prime.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_file.h>
 
 struct module;
 
-struct drm_file;
 struct drm_device;
 struct drm_agp_head;
 struct drm_local_map;
 struct drm_device_dma;
-struct drm_dma_handle;
 struct drm_gem_object;
 struct drm_master;
 struct drm_vblank_crtc;
+struct drm_vma_offset_manager;
 
 struct device_node;
 struct videomode;
 struct reservation_object;
 struct dma_buf_attachment;
 
+struct pci_dev;
+struct pci_controller;
+
 /*
  * The following categories are defined:
  *
@@ -357,97 +360,6 @@ struct drm_ioctl_desc {
                .name = #ioctl                                          \
         }
 
-/* Event queued up for userspace to read */
-struct drm_pending_event {
-       struct completion *completion;
-       void (*completion_release)(struct completion *completion);
-       struct drm_event *event;
-       struct dma_fence *fence;
-       struct list_head link;
-       struct list_head pending_link;
-       struct drm_file *file_priv;
-       pid_t pid; /* pid of requester, no guarantee it's valid by the time
-                     we deliver the event, for tracing only */
-};
-
-struct drm_prime_file_private {
-       struct mutex lock;
-       struct rb_root dmabufs;
-       struct rb_root handles;
-};
-
-/** File private data */
-struct drm_file {
-       unsigned authenticated :1;
-       /* true when the client has asked us to expose stereo 3D mode flags */
-       unsigned stereo_allowed :1;
-       /*
-        * true if client understands CRTC primary planes and cursor planes
-        * in the plane list
-        */
-       unsigned universal_planes:1;
-       /* true if client understands atomic properties */
-       unsigned atomic:1;
-       /*
-        * This client is the creator of @master.
-        * Protected by struct drm_device::master_mutex.
-        */
-       unsigned is_master:1;
-
-       struct pid *pid;
-       drm_magic_t magic;
-       struct list_head lhead;
-       struct drm_minor *minor;
-       unsigned long lock_count;
-
-       /** Mapping of mm object handles to object pointers. */
-       struct idr object_idr;
-       /** Lock for synchronization of access to object_idr. */
-       spinlock_t table_lock;
-
-       struct file *filp;
-       void *driver_priv;
-
-       struct drm_master *master; /* master this node is currently associated with
-                                     N.B. not always dev->master */
-       /**
-        * fbs - List of framebuffers associated with this file.
-        *
-        * Protected by fbs_lock. Note that the fbs list holds a reference on
-        * the fb object to prevent it from untimely disappearing.
-        */
-       struct list_head fbs;
-       struct mutex fbs_lock;
-
-       /** User-created blob properties; this retains a reference on the
-        *  property. */
-       struct list_head blobs;
-
-       wait_queue_head_t event_wait;
-       struct list_head pending_event_list;
-       struct list_head event_list;
-       int event_space;
-
-       struct mutex event_read_lock;
-
-       struct drm_prime_file_private prime;
-};
-
-/**
- * Lock data.
- */
-struct drm_lock_data {
-       struct drm_hw_lock *hw_lock;    /**< Hardware lock */
-       /** Private of lock holder's file (NULL=kernel) */
-       struct drm_file *file_priv;
-       wait_queue_head_t lock_queue;   /**< Queue of blocked processes */
-       unsigned long lock_time;        /**< Time of last lock in jiffies */
-       spinlock_t spinlock;
-       uint32_t kernel_waiters;
-       uint32_t user_waiters;
-       int idle_has_lock;
-};
-
 /* Flags and return codes for get_vblank_timestamp() driver function. */
 #define DRM_CALLED_FROM_VBLIRQ 1
 #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
@@ -458,13 +370,6 @@ struct drm_lock_data {
 #define DRM_SCANOUTPOS_IN_VBLANK    (1 << 1)
 #define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
 
-enum drm_minor_type {
-       DRM_MINOR_PRIMARY,
-       DRM_MINOR_CONTROL,
-       DRM_MINOR_RENDER,
-       DRM_MINOR_CNT,
-};
-
 /**
  * Info file list entry. This structure represents a debugfs or proc file to
  * be created by the drm core
@@ -486,21 +391,6 @@ struct drm_info_node {
        struct dentry *dent;
 };
 
-/**
- * DRM minor structure. This structure represents a drm minor number.
- */
-struct drm_minor {
-       int index;                      /**< Minor device number */
-       int type;                       /**< Control or render */
-       struct device *kdev;            /**< Linux device */
-       struct drm_device *dev;
-
-       struct dentry *debugfs_root;
-
-       struct list_head debugfs_list;
-       struct mutex debugfs_lock; /* Protects debugfs_list. */
-};
-
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
@@ -611,7 +501,6 @@ struct drm_device {
        struct pci_controller *hose;
 #endif
 
-       struct platform_device *platformdev; /**< Platform device struture */
        struct virtio_device *virtdev;
 
        struct drm_sg_mem *sg;  /**< Scatter gather memory */
@@ -675,21 +564,6 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)
        return ret;
 }
 
-static inline bool drm_is_render_client(const struct drm_file *file_priv)
-{
-       return file_priv->minor->type == DRM_MINOR_RENDER;
-}
-
-static inline bool drm_is_control_client(const struct drm_file *file_priv)
-{
-       return file_priv->minor->type == DRM_MINOR_CONTROL;
-}
-
-static inline bool drm_is_primary_client(const struct drm_file *file_priv)
-{
-       return file_priv->minor->type == DRM_MINOR_PRIMARY;
-}
-
 /******************************************************************/
 /** \name Internal function definitions */
 /*@{*/
@@ -707,25 +581,6 @@ extern long drm_compat_ioctl(struct file *filp,
 #endif
 extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
 
-/* File Operations (drm_fops.c) */
-int drm_open(struct inode *inode, struct file *filp);
-ssize_t drm_read(struct file *filp, char __user *buffer,
-                size_t count, loff_t *offset);
-int drm_release(struct inode *inode, struct file *filp);
-unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
-int drm_event_reserve_init_locked(struct drm_device *dev,
-                                 struct drm_file *file_priv,
-                                 struct drm_pending_event *p,
-                                 struct drm_event *e);
-int drm_event_reserve_init(struct drm_device *dev,
-                          struct drm_file *file_priv,
-                          struct drm_pending_event *p,
-                          struct drm_event *e);
-void drm_event_cancel_free(struct drm_device *dev,
-                          struct drm_pending_event *p);
-void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e);
-void drm_send_event(struct drm_device *dev, struct drm_pending_event *e);
-
 /* Misc. IOCTL support (drm_ioctl.c) */
 int drm_noop(struct drm_device *dev, void *data,
             struct drm_file *file_priv);
@@ -759,70 +614,12 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
 }
 #endif
 
-struct dma_buf_export_info;
-
-extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-                                           struct drm_gem_object *obj,
-                                           int flags);
-extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
-               struct drm_file *file_priv, uint32_t handle, uint32_t flags,
-               int *prime_fd);
-extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
-               struct dma_buf *dma_buf);
-extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
-               struct drm_file *file_priv, int prime_fd, uint32_t *handle);
-struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
-                                     struct dma_buf_export_info *exp_info);
-extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
-
-extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
-                                           dma_addr_t *addrs, int max_pages);
-extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
-extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
-
-
-extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
-                                           size_t align);
-extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
-
                               /* sysfs support (drm_sysfs.c) */
 extern void drm_sysfs_hotplug_event(struct drm_device *dev);
 
 
 /*@}*/
 
-extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
-extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
-#ifdef CONFIG_PCI
-extern int drm_get_pci_dev(struct pci_dev *pdev,
-                          const struct pci_device_id *ent,
-                          struct drm_driver *driver);
-extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
-#else
-static inline int drm_get_pci_dev(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent,
-                                 struct drm_driver *driver)
-{
-       return -ENOSYS;
-}
-
-static inline int drm_pci_set_busid(struct drm_device *dev,
-                                   struct drm_master *master)
-{
-       return -ENOSYS;
-}
-#endif
-
-#define DRM_PCIE_SPEED_25 1
-#define DRM_PCIE_SPEED_50 2
-#define DRM_PCIE_SPEED_80 4
-
-extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
-extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
-
-/* platform section */
-extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
-
 /* returns true if currently okay to sleep */
 static __inline__ bool drm_can_sleep(void)
 {
index c6f355a..0147a04 100644 (file)
@@ -277,6 +277,9 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
  *
  * This function returns the crtc state for the given crtc, or NULL
  * if the crtc is not part of the global atomic state.
+ *
+ * This function is deprecated, @drm_atomic_get_old_crtc_state or
+ * @drm_atomic_get_new_crtc_state should be used instead.
  */
 static inline struct drm_crtc_state *
 drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
@@ -285,6 +288,35 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
        return state->crtcs[drm_crtc_index(crtc)].state;
 }
 
+/**
+ * drm_atomic_get_old_crtc_state - get old crtc state, if it exists
+ * @state: global atomic state object
+ * @crtc: crtc to grab
+ *
+ * This function returns the old crtc state for the given crtc, or
+ * NULL if the crtc is not part of the global atomic state.
+ */
+static inline struct drm_crtc_state *
+drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
+                             struct drm_crtc *crtc)
+{
+       return state->crtcs[drm_crtc_index(crtc)].old_state;
+}
+/**
+ * drm_atomic_get_new_crtc_state - get new crtc state, if it exists
+ * @state: global atomic state object
+ * @crtc: crtc to grab
+ *
+ * This function returns the new crtc state for the given crtc, or
+ * NULL if the crtc is not part of the global atomic state.
+ */
+static inline struct drm_crtc_state *
+drm_atomic_get_new_crtc_state(struct drm_atomic_state *state,
+                             struct drm_crtc *crtc)
+{
+       return state->crtcs[drm_crtc_index(crtc)].new_state;
+}
+
 /**
  * drm_atomic_get_existing_plane_state - get plane state, if it exists
  * @state: global atomic state object
@@ -292,6 +324,9 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
  *
  * This function returns the plane state for the given plane, or NULL
  * if the plane is not part of the global atomic state.
+ *
+ * This function is deprecated, @drm_atomic_get_old_plane_state or
+ * @drm_atomic_get_new_plane_state should be used instead.
  */
 static inline struct drm_plane_state *
 drm_atomic_get_existing_plane_state(struct drm_atomic_state *state,
@@ -300,6 +335,36 @@ drm_atomic_get_existing_plane_state(struct drm_atomic_state *state,
        return state->planes[drm_plane_index(plane)].state;
 }
 
+/**
+ * drm_atomic_get_old_plane_state - get plane state, if it exists
+ * @state: global atomic state object
+ * @plane: plane to grab
+ *
+ * This function returns the old plane state for the given plane, or
+ * NULL if the plane is not part of the global atomic state.
+ */
+static inline struct drm_plane_state *
+drm_atomic_get_old_plane_state(struct drm_atomic_state *state,
+                              struct drm_plane *plane)
+{
+       return state->planes[drm_plane_index(plane)].old_state;
+}
+
+/**
+ * drm_atomic_get_new_plane_state - get plane state, if it exists
+ * @state: global atomic state object
+ * @plane: plane to grab
+ *
+ * This function returns the new plane state for the given plane, or
+ * NULL if the plane is not part of the global atomic state.
+ */
+static inline struct drm_plane_state *
+drm_atomic_get_new_plane_state(struct drm_atomic_state *state,
+                              struct drm_plane *plane)
+{
+       return state->planes[drm_plane_index(plane)].new_state;
+}
+
 /**
  * drm_atomic_get_existing_connector_state - get connector state, if it exists
  * @state: global atomic state object
@@ -307,6 +372,9 @@ drm_atomic_get_existing_plane_state(struct drm_atomic_state *state,
  *
  * This function returns the connector state for the given connector,
  * or NULL if the connector is not part of the global atomic state.
+ *
+ * This function is deprecated, @drm_atomic_get_old_connector_state or
+ * @drm_atomic_get_new_connector_state should be used instead.
  */
 static inline struct drm_connector_state *
 drm_atomic_get_existing_connector_state(struct drm_atomic_state *state,
@@ -320,6 +388,46 @@ drm_atomic_get_existing_connector_state(struct drm_atomic_state *state,
        return state->connectors[index].state;
 }
 
+/**
+ * drm_atomic_get_old_connector_state - get connector state, if it exists
+ * @state: global atomic state object
+ * @connector: connector to grab
+ *
+ * This function returns the old connector state for the given connector,
+ * or NULL if the connector is not part of the global atomic state.
+ */
+static inline struct drm_connector_state *
+drm_atomic_get_old_connector_state(struct drm_atomic_state *state,
+                                  struct drm_connector *connector)
+{
+       int index = drm_connector_index(connector);
+
+       if (index >= state->num_connector)
+               return NULL;
+
+       return state->connectors[index].old_state;
+}
+
+/**
+ * drm_atomic_get_new_connector_state - get connector state, if it exists
+ * @state: global atomic state object
+ * @connector: connector to grab
+ *
+ * This function returns the new connector state for the given connector,
+ * or NULL if the connector is not part of the global atomic state.
+ */
+static inline struct drm_connector_state *
+drm_atomic_get_new_connector_state(struct drm_atomic_state *state,
+                                  struct drm_connector *connector)
+{
+       int index = drm_connector_index(connector);
+
+       if (index >= state->num_connector)
+               return NULL;
+
+       return state->connectors[index].new_state;
+}
+
 /**
  * __drm_atomic_get_current_plane_state - get current plane state
  * @state: global atomic state object
index 9ceda37..dc16274 100644 (file)
@@ -220,10 +220,10 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
                              __drm_atomic_get_current_plane_state((crtc_state)->state, \
                                                                   plane)))
 
-/*
+/**
  * drm_atomic_plane_disabling - check whether a plane is being disabled
- * @plane: plane object
- * @old_state: previous atomic state
+ * @old_plane_state: old atomic plane state
+ * @new_plane_state: new atomic plane state
  *
  * Checks the atomic state of a plane to determine whether it's being disabled
  * or not. This also WARNs if it detects an invalid state (both CRTC and FB
@@ -233,28 +233,18 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
  * True if the plane is being disabled, false otherwise.
  */
 static inline bool
-drm_atomic_plane_disabling(struct drm_plane *plane,
-                          struct drm_plane_state *old_state)
+drm_atomic_plane_disabling(struct drm_plane_state *old_plane_state,
+                          struct drm_plane_state *new_plane_state)
 {
        /*
         * When disabling a plane, CRTC and FB should always be NULL together.
         * Anything else should be considered a bug in the atomic core, so we
         * gently warn about it.
         */
-       WARN_ON((plane->state->crtc == NULL && plane->state->fb != NULL) ||
-               (plane->state->crtc != NULL && plane->state->fb == NULL));
+       WARN_ON((new_plane_state->crtc == NULL && new_plane_state->fb != NULL) ||
+               (new_plane_state->crtc != NULL && new_plane_state->fb == NULL));
 
-       /*
-        * When using the transitional helpers, old_state may be NULL. If so,
-        * we know nothing about the current state and have to assume that it
-        * might be enabled.
-        *
-        * When using the atomic helpers, old_state won't be NULL. Therefore
-        * this check assumes that either the driver will have reconstructed
-        * the correct state in ->reset() or that the driver will have taken
-        * appropriate measures to disable all planes.
-        */
-       return (!old_state || old_state->crtc) && !plane->state->crtc;
+       return old_plane_state->crtc && !new_plane_state->crtc;
 }
 
 #endif /* DRM_ATOMIC_HELPER_H_ */
index 1eb4a52..81a40c2 100644 (file)
 #ifndef _DRM_AUTH_H_
 #define _DRM_AUTH_H_
 
+/*
+ * Legacy DRI1 locking data structure. Only here instead of in drm_legacy.h for
+ * include ordering reasons.
+ *
+ * DO NOT USE.
+ */
+struct drm_lock_data {
+       struct drm_hw_lock *hw_lock;
+       struct drm_file *file_priv;
+       wait_queue_head_t lock_queue;
+       unsigned long lock_time;
+       spinlock_t spinlock;
+       uint32_t kernel_waiters;
+       uint32_t user_waiters;
+       int idle_has_lock;
+};
+
 /**
  * struct drm_master - drm master structure
  *
index bda9347..6ef59da 100644 (file)
@@ -204,6 +204,12 @@ struct drm_crtc_state {
         * drm_crtc_arm_vblank_event(). See the documentation of that function
         * for a detailed discussion of the constraints it needs to be used
         * safely.
+        *
+        * If the device can't notify of flip completion in a race-free way
+        * at all, then the event should be armed just after the page flip is
+        * committed. In the worst case the driver will send the event to
+        * userspace one frame too late. This doesn't allow for a real atomic
+        * update, but it should avoid tearing.
         */
        struct drm_pending_vblank_event *event;
 
@@ -776,6 +782,7 @@ struct drm_crtc {
         * Debugfs directory for this CRTC.
         */
        struct dentry *debugfs_entry;
+#endif
 
        /**
         * @crc:
@@ -783,7 +790,6 @@ struct drm_crtc {
         * Configuration settings of CRC capture.
         */
        struct drm_crtc_crc crc;
-#endif
 
        /**
         * @fence_context:
index ba89295..c0bd0d7 100644 (file)
@@ -789,7 +789,10 @@ struct drm_dp_aux_msg {
  * @name: user-visible name of this AUX channel and the I2C-over-AUX adapter
  * @ddc: I2C adapter that can be used for I2C-over-AUX communication
  * @dev: pointer to struct device that is the parent for this AUX channel
+ * @crtc: backpointer to the crtc that is currently using this AUX channel
  * @hw_mutex: internal mutex used for locking transfers
+ * @crc_work: worker that captures CRCs for each frame
+ * @crc_count: counter of captured frame CRCs
  * @transfer: transfers a message representing a single AUX transaction
  *
  * The .dev field should be set to a pointer to the device that implements
@@ -825,7 +828,10 @@ struct drm_dp_aux {
        const char *name;
        struct i2c_adapter ddc;
        struct device *dev;
+       struct drm_crtc *crtc;
        struct mutex hw_mutex;
+       struct work_struct crc_work;
+       u8 crc_count;
        ssize_t (*transfer)(struct drm_dp_aux *aux,
                            struct drm_dp_aux_msg *msg);
        /**
@@ -904,4 +910,7 @@ void drm_dp_aux_init(struct drm_dp_aux *aux);
 int drm_dp_aux_register(struct drm_dp_aux *aux);
 void drm_dp_aux_unregister(struct drm_dp_aux *aux);
 
+int drm_dp_start_crc(struct drm_dp_aux *aux, struct drm_crtc *crtc);
+int drm_dp_stop_crc(struct drm_dp_aux *aux);
+
 #endif /* _DRM_DP_HELPER_H_ */
index 4e66fbb..4321d01 100644 (file)
@@ -302,7 +302,6 @@ struct drm_driver {
        void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv);
 
        int (*debugfs_init)(struct drm_minor *minor);
-       void (*debugfs_cleanup)(struct drm_minor *minor);
 
        /**
         * @gem_free_object: deconstructor for drm_gem_objects
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
new file mode 100644 (file)
index 0000000..d1a25cc
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_FILE_H_
+#define _DRM_FILE_H_
+
+#include <linux/types.h>
+#include <linux/completion.h>
+
+#include <uapi/drm/drm.h>
+
+#include <drm/drm_prime.h>
+
+struct dma_fence;
+struct drm_file;
+struct drm_device;
+
+/*
+ * FIXME: Not sure we want to have drm_minor here in the end, but to avoid
+ * header include loops we need it here for now.
+ */
+enum drm_minor_type {
+       DRM_MINOR_PRIMARY,
+       DRM_MINOR_CONTROL,
+       DRM_MINOR_RENDER,
+};
+
+/**
+ * DRM minor structure. This structure represents a drm minor number.
+ */
+struct drm_minor {
+       int index;                      /**< Minor device number */
+       int type;                       /**< Control or render */
+       struct device *kdev;            /**< Linux device */
+       struct drm_device *dev;
+
+       struct dentry *debugfs_root;
+
+       struct list_head debugfs_list;
+       struct mutex debugfs_lock; /* Protects debugfs_list. */
+};
+
+/* Event queued up for userspace to read */
+struct drm_pending_event {
+       struct completion *completion;
+       void (*completion_release)(struct completion *completion);
+       struct drm_event *event;
+       struct dma_fence *fence;
+       struct list_head link;
+       struct list_head pending_link;
+       struct drm_file *file_priv;
+       pid_t pid; /* pid of requester, no guarantee it's valid by the time
+                     we deliver the event, for tracing only */
+};
+
+/** File private data */
+struct drm_file {
+       unsigned authenticated :1;
+       /* true when the client has asked us to expose stereo 3D mode flags */
+       unsigned stereo_allowed :1;
+       /*
+        * true if client understands CRTC primary planes and cursor planes
+        * in the plane list
+        */
+       unsigned universal_planes:1;
+       /* true if client understands atomic properties */
+       unsigned atomic:1;
+       /*
+        * This client is the creator of @master.
+        * Protected by struct drm_device::master_mutex.
+        */
+       unsigned is_master:1;
+
+       struct pid *pid;
+       drm_magic_t magic;
+       struct list_head lhead;
+       struct drm_minor *minor;
+       unsigned long lock_count;
+
+       /** Mapping of mm object handles to object pointers. */
+       struct idr object_idr;
+       /** Lock for synchronization of access to object_idr. */
+       spinlock_t table_lock;
+
+       struct file *filp;
+       void *driver_priv;
+
+       struct drm_master *master; /* master this node is currently associated with
+                                     N.B. not always dev->master */
+       /**
+        * fbs - List of framebuffers associated with this file.
+        *
+        * Protected by fbs_lock. Note that the fbs list holds a reference on
+        * the fb object to prevent it from untimely disappearing.
+        */
+       struct list_head fbs;
+       struct mutex fbs_lock;
+
+       /** User-created blob properties; this retains a reference on the
+        *  property. */
+       struct list_head blobs;
+
+       wait_queue_head_t event_wait;
+       struct list_head pending_event_list;
+       struct list_head event_list;
+       int event_space;
+
+       struct mutex event_read_lock;
+
+       struct drm_prime_file_private prime;
+};
+
+static inline bool drm_is_render_client(const struct drm_file *file_priv)
+{
+       return file_priv->minor->type == DRM_MINOR_RENDER;
+}
+
+static inline bool drm_is_control_client(const struct drm_file *file_priv)
+{
+       return file_priv->minor->type == DRM_MINOR_CONTROL;
+}
+
+static inline bool drm_is_primary_client(const struct drm_file *file_priv)
+{
+       return file_priv->minor->type == DRM_MINOR_PRIMARY;
+}
+
+int drm_open(struct inode *inode, struct file *filp);
+ssize_t drm_read(struct file *filp, char __user *buffer,
+                size_t count, loff_t *offset);
+int drm_release(struct inode *inode, struct file *filp);
+unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
+int drm_event_reserve_init_locked(struct drm_device *dev,
+                                 struct drm_file *file_priv,
+                                 struct drm_pending_event *p,
+                                 struct drm_event *e);
+int drm_event_reserve_init(struct drm_device *dev,
+                          struct drm_file *file_priv,
+                          struct drm_pending_event *p,
+                          struct drm_event *e);
+void drm_event_cancel_free(struct drm_device *dev,
+                          struct drm_pending_event *p);
+void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e);
+void drm_send_event(struct drm_device *dev, struct drm_pending_event *e);
+
+#endif /* _DRM_FILE_H_ */
index 3b2a28f..b9ade75 100644 (file)
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/kref.h>
+
+#include <drm/drm_vma_manager.h>
+
 /**
  * struct drm_gem_object - GEM buffer object
  *
diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h
new file mode 100644 (file)
index 0000000..f5ebfca
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_PCI_H_
+#define _DRM_PCI_H_
+
+#include <linux/pci.h>
+
+struct drm_dma_handle;
+struct drm_device;
+struct drm_driver;
+struct drm_master;
+
+extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
+                                           size_t align);
+extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
+
+extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
+extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
+#ifdef CONFIG_PCI
+extern int drm_get_pci_dev(struct pci_dev *pdev,
+                          const struct pci_device_id *ent,
+                          struct drm_driver *driver);
+extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
+#else
+static inline int drm_get_pci_dev(struct pci_dev *pdev,
+                                 const struct pci_device_id *ent,
+                                 struct drm_driver *driver)
+{
+       return -ENOSYS;
+}
+
+static inline int drm_pci_set_busid(struct drm_device *dev,
+                                   struct drm_master *master)
+{
+       return -ENOSYS;
+}
+#endif
+
+#define DRM_PCIE_SPEED_25 1
+#define DRM_PCIE_SPEED_50 2
+#define DRM_PCIE_SPEED_80 4
+
+extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
+extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
+
+#endif /* _DRM_PCI_H_ */
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
new file mode 100644 (file)
index 0000000..d09563e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2012 Red Hat
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *      Dave Airlie <airlied@redhat.com>
+ *      Rob Clark <rob.clark@linaro.org>
+ *
+ */
+
+#ifndef __DRM_PRIME_H__
+#define __DRM_PRIME_H__
+
+#include <linux/mutex.h>
+#include <linux/rbtree.h>
+#include <linux/scatterlist.h>
+
+/**
+ * struct drm_prime_file_private - per-file tracking for PRIME
+ *
+ * This just contains the internal &struct dma_buf and handle caches for each
+ * &struct drm_file used by the PRIME core code.
+ */
+
+struct drm_prime_file_private {
+/* private: */
+       struct mutex lock;
+       struct rb_root dmabufs;
+       struct rb_root handles;
+};
+
+struct dma_buf_export_info;
+struct dma_buf;
+
+struct drm_device;
+struct drm_gem_object;
+struct drm_file;
+
+extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
+                                           struct drm_gem_object *obj,
+                                           int flags);
+extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
+               struct drm_file *file_priv, uint32_t handle, uint32_t flags,
+               int *prime_fd);
+extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
+               struct dma_buf *dma_buf);
+extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+               struct drm_file *file_priv, int prime_fd, uint32_t *handle);
+struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
+                                     struct dma_buf_export_info *exp_info);
+extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+
+extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
+                                           dma_addr_t *addrs, int max_pages);
+extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
+extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
+
+
+#endif /* __DRM_PRIME_H__ */
index 9c03895..d84d52f 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <drm/drm_mm.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>