Browse Source

Merge tag 'drm-misc-next-2017-04-07' of git://anongit.freedesktop.org/git/drm-misc into drm-next

Last drm-misc-next pull req for 4.12

Core changes:
 - fb_helper checkpatch cleanup and simplified _add_one_connector() (Thierry)
 - drm_ioctl and drm_sysfs improved/gained documentation (Daniel)
 - [ABI] Repurpose reserved field in drm_event_vblank for crtc_id (Ander)
 - Plumb acquire ctx through legacy paths to avoid lock_all and legacy_backoff
   (Daniel)
 - Add connector_atomic_check to check conn constraints on modeset (Maarten)
 - Add drm_of_find_panel_or_bridge to remove boilerplate in drivers (Rob)

Driver changes:
 - meson moved to drm-misc (Neil)
 - Added support for Amlogic GX SoCs in dw-hdmi (Neil)
 - Rockchip unbind actually cleans up the things bind initializes (Jeffy)
 - A couple misc fixes in virtio, dw-hdmi

NOTE: this also includes a backmerge of drm-next as well rc5 (we needed vmwgfx
      as well as the new synopsys media formats)

* tag 'drm-misc-next-2017-04-07' of git://anongit.freedesktop.org/git/drm-misc: (77 commits)
  Revert "drm: Don't allow interruptions when opening debugfs/crc"
  drm: Only take cursor locks when the cursor plane exists
  drm/vmwgfx: Fix fbdev emulation using legacy functions
  drm/rockchip: Shutdown all crtcs when unbinding drm
  drm/rockchip: Reorder drm bind/unbind sequence
  drm/rockchip: analogix_dp: Disable clock when unbinding
  drm/rockchip: vop: Unprepare clocks when unbinding
  drm/rockchip: vop: Enable pm domain before vop_initial
  drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
  drm/rockchip: cdn-dp: Don't try to release firmware when not loaded
  drm: bridge: analogix: Destroy connector & encoder when unbinding
  drm: bridge: analogix: Disable clock when unbinding
  drm: bridge: analogix: Unregister dp aux when unbinding
  drm: bridge: analogix: Detach panel when unbinding analogix dp
  drm: Don't allow interruptions when opening debugfs/crc
  drm/virtio: don't leak bo on drm_gem_object_init failure
  drm: bridge: dw-hdmi: fix input format/encoding from plat_data
  drm: omap: use common OF graph helpers
  drm: convert drivers to use drm_of_find_panel_or_bridge
  drm: convert drivers to use of_graph_get_remote_node
  ...
Dave Airlie 8 years ago
parent
commit
df45eaca51
100 changed files with 6561 additions and 2671 deletions
  1. 111 0
      Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
  2. 5 0
      Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
  3. 15 0
      Documentation/gpu/bridge/dw-hdmi.rst
  4. 0 50
      Documentation/gpu/drm-internals.rst
  5. 24 0
      Documentation/gpu/drm-uapi.rst
  6. 2 0
      Documentation/gpu/index.rst
  7. 61 0
      Documentation/gpu/meson.rst
  8. 4 27
      Documentation/gpu/todo.rst
  9. 1979 1021
      Documentation/media/uapi/v4l/subdev-formats.rst
  10. 2 1
      MAINTAINERS
  11. 35 2
      drivers/dma-buf/dma-buf.c
  12. 2 1
      drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
  13. 2 1
      drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
  14. 2 1
      drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
  15. 2 1
      drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
  16. 2 1
      drivers/gpu/drm/amd/amdgpu/dce_virtual.c
  17. 3 19
      drivers/gpu/drm/arm/hdlcd_drv.c
  18. 4 24
      drivers/gpu/drm/arm/malidp_drv.c
  19. 2 1
      drivers/gpu/drm/ast/ast_mode.c
  20. 21 52
      drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
  21. 2 10
      drivers/gpu/drm/bridge/adv7511/adv7533.c
  22. 6 0
      drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
  23. 3 12
      drivers/gpu/drm/bridge/dumb-vga-dac.c
  24. 5 4
      drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
  25. 4 12
      drivers/gpu/drm/bridge/nxp-ptn3460.c
  26. 4 12
      drivers/gpu/drm/bridge/parade-ps8622.c
  27. 301 156
      drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
  28. 3 24
      drivers/gpu/drm/bridge/tc358767.c
  29. 5 10
      drivers/gpu/drm/bridge/ti-tfp410.c
  30. 2 1
      drivers/gpu/drm/cirrus/cirrus_mode.c
  31. 39 123
      drivers/gpu/drm/drm_atomic.c
  32. 77 42
      drivers/gpu/drm/drm_atomic_helper.c
  33. 27 24
      drivers/gpu/drm/drm_color_mgmt.c
  34. 2 0
      drivers/gpu/drm/drm_crtc.c
  35. 0 1
      drivers/gpu/drm/drm_crtc_internal.h
  36. 120 81
      drivers/gpu/drm/drm_fb_helper.c
  37. 115 22
      drivers/gpu/drm/drm_framebuffer.c
  38. 40 36
      drivers/gpu/drm/drm_ioc32.c
  39. 51 2
      drivers/gpu/drm/drm_ioctl.c
  40. 2 0
      drivers/gpu/drm/drm_irq.c
  41. 0 102
      drivers/gpu/drm/drm_modeset_lock.c
  42. 52 0
      drivers/gpu/drm/drm_of.c
  43. 24 25
      drivers/gpu/drm/drm_plane.c
  44. 93 9
      drivers/gpu/drm/drm_probe_helper.c
  45. 29 43
      drivers/gpu/drm/drm_property.c
  46. 27 43
      drivers/gpu/drm/drm_sysfs.c
  47. 12 23
      drivers/gpu/drm/exynos/exynos_dp.c
  48. 1 15
      drivers/gpu/drm/exynos/exynos_drm_dpi.c
  49. 3 10
      drivers/gpu/drm/exynos/exynos_drm_dsi.c
  50. 1 24
      drivers/gpu/drm/exynos/exynos_drm_mic.c
  51. 12 32
      drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
  52. 2 1
      drivers/gpu/drm/gma500/gma_display.c
  53. 2 1
      drivers/gpu/drm/gma500/gma_display.h
  54. 4 23
      drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
  55. 1 29
      drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
  56. 12 13
      drivers/gpu/drm/i915/intel_crt.c
  57. 15 70
      drivers/gpu/drm/i915/intel_display.c
  58. 9 12
      drivers/gpu/drm/i915/intel_dp.c
  59. 4 4
      drivers/gpu/drm/i915/intel_drv.h
  60. 2 1
      drivers/gpu/drm/i915/intel_hotplug.c
  61. 1 1
      drivers/gpu/drm/i915/intel_pipe_crc.c
  62. 11 10
      drivers/gpu/drm/i915/intel_tv.c
  63. 5 22
      drivers/gpu/drm/imx/imx-ldb.c
  64. 4 32
      drivers/gpu/drm/imx/parallel-display.c
  65. 3 9
      drivers/gpu/drm/mediatek/mtk_dpi.c
  66. 5 18
      drivers/gpu/drm/mediatek/mtk_dsi.c
  67. 3 23
      drivers/gpu/drm/mediatek/mtk_hdmi.c
  68. 6 0
      drivers/gpu/drm/meson/Kconfig
  69. 1 0
      drivers/gpu/drm/meson/Makefile
  70. 3 1
      drivers/gpu/drm/meson/meson_canvas.c
  71. 11 4
      drivers/gpu/drm/meson/meson_crtc.c
  72. 102 16
      drivers/gpu/drm/meson/meson_drv.c
  73. 3 0
      drivers/gpu/drm/meson/meson_drv.h
  74. 919 0
      drivers/gpu/drm/meson/meson_dw_hdmi.c
  75. 146 0
      drivers/gpu/drm/meson/meson_dw_hdmi.h
  76. 1 0
      drivers/gpu/drm/meson/meson_registers.h
  77. 619 13
      drivers/gpu/drm/meson/meson_vclk.c
  78. 4 2
      drivers/gpu/drm/meson/meson_vclk.h
  79. 1248 6
      drivers/gpu/drm/meson/meson_venc.c
  80. 7 0
      drivers/gpu/drm/meson/meson_venc.h
  81. 13 17
      drivers/gpu/drm/meson/meson_venc_cvbs.c
  82. 5 1
      drivers/gpu/drm/meson/meson_viu.c
  83. 6 2
      drivers/gpu/drm/meson/meson_vpp.c
  84. 2 0
      drivers/gpu/drm/meson/meson_vpp.h
  85. 2 1
      drivers/gpu/drm/mgag200/mgag200_mode.c
  86. 1 1
      drivers/gpu/drm/msm/dsi/dsi_host.c
  87. 1 27
      drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
  88. 6 34
      drivers/gpu/drm/mxsfb/mxsfb_out.c
  89. 2 1
      drivers/gpu/drm/nouveau/dispnv04/crtc.c
  90. 2 11
      drivers/gpu/drm/nouveau/nv50_display.c
  91. 1 1
      drivers/gpu/drm/omapdrm/dss/dpi.c
  92. 2 1
      drivers/gpu/drm/omapdrm/dss/dsi.c
  93. 3 99
      drivers/gpu/drm/omapdrm/dss/dss-of.c
  94. 13 48
      drivers/gpu/drm/omapdrm/dss/dss.c
  95. 2 1
      drivers/gpu/drm/omapdrm/dss/hdmi4.c
  96. 2 1
      drivers/gpu/drm/omapdrm/dss/hdmi5.c
  97. 0 11
      drivers/gpu/drm/omapdrm/dss/omapdss.h
  98. 1 1
      drivers/gpu/drm/omapdrm/dss/sdi.c
  99. 2 1
      drivers/gpu/drm/omapdrm/dss/venc.c
  100. 2 1
      drivers/gpu/drm/radeon/radeon_display.c

+ 111 - 0
Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt

@@ -0,0 +1,111 @@
+Amlogic specific extensions to the Synopsys Designware HDMI Controller
+======================================================================
+
+The Amlogic Meson Synopsys Designware Integration is composed of :
+- A Synopsys DesignWare HDMI Controller IP
+- A TOP control block controlling the Clocks and PHY
+- A custom HDMI PHY in order to convert video to TMDS signal
+ ___________________________________
+|            HDMI TOP               |<= HPD
+|___________________________________|
+|                  |                |
+|  Synopsys HDMI   |   HDMI PHY     |=> TMDS
+|    Controller    |________________|
+|___________________________________|<=> DDC
+
+The HDMI TOP block only supports HPD sensing.
+The Synopsys HDMI Controller interrupt is routed through the
+TOP Block interrupt.
+Communication to the TOP Block and the Synopsys HDMI Controller is done
+via a pair of dedicated addr+read/write registers.
+The HDMI PHY is configured by registers in the HHI register block.
+
+Pixel data arrives in 4:4:4 format from the VENC block and the VPU HDMI mux
+selects either the ENCI encoder for the 576i or 480i formats or the ENCP
+encoder for all the other formats including interlaced HD formats.
+
+The VENC uses a DVI encoder on top of the ENCI or ENCP encoders to generate
+DVI timings for the HDMI controller.
+
+Amlogic Meson GXBB, GXL and GXM SoCs families embeds the Synopsys DesignWare
+HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF
+audio source interfaces.
+
+Required properties:
+- compatible: value should be different for each SoC family as :
+	- GXBB (S905) : "amlogic,meson-gxbb-dw-hdmi"
+	- GXL (S905X, S905D) : "amlogic,meson-gxl-dw-hdmi"
+	- GXM (S912) : "amlogic,meson-gxm-dw-hdmi"
+	followed by the common "amlogic,meson-gx-dw-hdmi"
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The HDMI interrupt number
+- clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks,
+  and the Amlogic Meson venci clocks as described in
+  Documentation/devicetree/bindings/clock/clock-bindings.txt,
+  the clocks are soc specific, the clock-names should be "iahb", "isfr", "venci"
+- resets, resets-names: must have the phandles to the HDMI apb, glue and phy
+  resets as described in :
+  Documentation/devicetree/bindings/reset/reset.txt,
+  the reset-names should be "hdmitx_apb", "hdmitx", "hdmitx_phy"
+
+Required nodes:
+
+The connections to the HDMI ports are modeled using the OF graph
+bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+The following table lists for each supported model the port number
+corresponding to each HDMI output and input.
+
+		Port 0		Port 1
+-----------------------------------------
+ S905 (GXBB)	VENC Input	TMDS Output
+ S905X (GXL)	VENC Input	TMDS Output
+ S905D (GXL)	VENC Input	TMDS Output
+ S912 (GXM)	VENC Input	TMDS Output
+
+Example:
+
+hdmi-connector {
+	compatible = "hdmi-connector";
+	type = "a";
+
+	port {
+		hdmi_connector_in: endpoint {
+			remote-endpoint = <&hdmi_tx_tmds_out>;
+		};
+	};
+};
+
+hdmi_tx: hdmi-tx@c883a000 {
+	compatible = "amlogic,meson-gxbb-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
+	reg = <0x0 0xc883a000 0x0 0x1c>;
+	interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
+	resets = <&reset RESET_HDMITX_CAPB3>,
+		 <&reset RESET_HDMI_SYSTEM_RESET>,
+		 <&reset RESET_HDMI_TX>;
+	reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
+	clocks = <&clkc CLKID_HDMI_PCLK>,
+		 <&clkc CLKID_CLK81>,
+		 <&clkc CLKID_GCLK_VENCI_INT0>;
+	clock-names = "isfr", "iahb", "venci";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VPU VENC Input */
+	hdmi_tx_venc_port: port@0 {
+		reg = <0>;
+
+		hdmi_tx_in: endpoint {
+			remote-endpoint = <&hdmi_tx_out>;
+		};
+	};
+
+	/* TMDS Output */
+	hdmi_tx_tmds_port: port@1 {
+		reg = <1>;
+
+		hdmi_tx_tmds_out: endpoint {
+			remote-endpoint = <&hdmi_connector_in>;
+		};
+	};
+};

+ 5 - 0
Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt

@@ -17,9 +17,12 @@ Required properties:
 
 Optional properties:
 - power-domains: a phandle to mipi dsi power domain node.
+- resets: list of phandle + reset specifier pairs, as described in [3].
+- reset-names: string reset name, must be "apb".
 
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/media/video-interfaces.txt
+[3] Documentation/devicetree/bindings/reset/reset.txt
 
 Example:
 	mipi_dsi: mipi@ff960000 {
@@ -30,6 +33,8 @@ Example:
 		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPI_DSI0>;
 		clock-names = "ref", "pclk";
+		resets = <&cru SRST_MIPIDSI0>;
+		reset-names = "apb";
 		rockchip,grf = <&grf>;
 		status = "okay";
 

+ 15 - 0
Documentation/gpu/bridge/dw-hdmi.rst

@@ -0,0 +1,15 @@
+=======================================================
+ drm/bridge/dw-hdmi Synopsys DesignWare HDMI Controller
+=======================================================
+
+Synopsys DesignWare HDMI Controller
+===================================
+
+This section covers everything related to the Synopsys DesignWare HDMI
+Controller implemented as a DRM bridge.
+
+Supported Input Formats and Encodings
+-------------------------------------
+
+.. kernel-doc:: include/drm/bridge/dw_hdmi.h
+   :doc: Supported input formats and encodings

+ 0 - 50
Documentation/gpu/drm-internals.rst

@@ -255,56 +255,6 @@ File Operations
 .. kernel-doc:: drivers/gpu/drm/drm_file.c
    :export:
 
-IOCTLs
-------
-
-struct drm_ioctl_desc \*ioctls; int num_ioctls;
-    Driver-specific ioctls descriptors table.
-
-Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls
-descriptors table is indexed by the ioctl number offset from the base
-value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize
-the table entries.
-
-::
-
-    DRM_IOCTL_DEF_DRV(ioctl, func, flags)
-
-``ioctl`` is the ioctl name. Drivers must define the DRM_##ioctl and
-DRM_IOCTL_##ioctl macros to the ioctl number offset from
-DRM_COMMAND_BASE and the ioctl number respectively. The first macro is
-private to the device while the second must be exposed to userspace in a
-public header.
-
-``func`` is a pointer to the ioctl handler function compatible with the
-``drm_ioctl_t`` type.
-
-::
-
-    typedef int drm_ioctl_t(struct drm_device *dev, void *data,
-            struct drm_file *file_priv);
-
-``flags`` is a bitmask combination of the following values. It restricts
-how the ioctl is allowed to be called.
-
--  DRM_AUTH - Only authenticated callers allowed
-
--  DRM_MASTER - The ioctl can only be called on the master file handle
-
--  DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
-
--  DRM_CONTROL_ALLOW - The ioctl can only be called on a control
-   device
-
--  DRM_UNLOCKED - The ioctl handler will be called without locking the
-   DRM global mutex. This is the enforced default for kms drivers (i.e.
-   using the DRIVER_MODESET flag) and hence shouldn't be used any more
-   for new drivers.
-
-.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
-   :export:
-
-
 Misc Utilities
 ==============
 

+ 24 - 0
Documentation/gpu/drm-uapi.rst

@@ -160,6 +160,20 @@ other hand, a driver requires shared state between clients which is
 visible to user-space and accessible beyond open-file boundaries, they
 cannot support render nodes.
 
+IOCTL Support on Device Nodes
+=============================
+
+.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
+   :doc: driver specific ioctls
+
+.. kernel-doc:: include/drm/drm_ioctl.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
+   :export:
+
+.. kernel-doc:: drivers/gpu/drm/drm_ioc32.c
+   :export:
 
 Testing and validation
 ======================
@@ -219,6 +233,16 @@ Debugfs Support
 .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
    :export:
 
+Sysfs Support
+=============
+
+.. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
+   :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
+   :export:
+
+
 VBlank event handling
 =====================
 

+ 2 - 0
Documentation/gpu/index.rst

@@ -11,10 +11,12 @@ Linux GPU Driver Developer's Guide
    drm-kms-helpers
    drm-uapi
    i915
+   meson
    tinydrm
    vc4
    vga-switcheroo
    vgaarbiter
+   bridge/dw-hdmi
    todo
 
 .. only::  subproject and html

+ 61 - 0
Documentation/gpu/meson.rst

@@ -0,0 +1,61 @@
+=============================================
+drm/meson AmLogic Meson Video Processing Unit
+=============================================
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_drv.c
+   :doc: Video Processing Unit
+
+Video Processing Unit
+=====================
+
+The Amlogic Meson Display controller is composed of several components
+that are going to be documented below:
+
+.. code::
+
+  DMC|---------------VPU (Video Processing Unit)----------------|------HHI------|
+     | vd1   _______     _____________    _________________     |               |
+  D  |-------|      |----|            |   |                |    |   HDMI PLL    |
+  D  | vd2   | VIU  |    | Video Post |   | Video Encoders |<---|-----VCLK      |
+  R  |-------|      |----| Processing |   |                |    |               |
+     | osd2  |      |    |            |---| Enci ----------|----|-----VDAC------|
+  R  |-------| CSC  |----| Scalers    |   | Encp ----------|----|----HDMI-TX----|
+  A  | osd1  |      |    | Blenders   |   | Encl ----------|----|---------------|
+  M  |-------|______|----|____________|   |________________|    |               |
+  ___|__________________________________________________________|_______________|
+
+Video Input Unit
+================
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_viu.c
+   :doc: Video Input Unit
+
+Video Post Processing
+=====================
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_vpp.c
+   :doc: Video Post Processing
+
+Video Encoder
+=============
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_venc.c
+   :doc: Video Encoder
+
+Video Canvas Management
+=======================
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_canvas.c
+   :doc: Canvas
+
+Video Clocks
+============
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_vclk.c
+   :doc: Video Clocks
+
+HDMI Video Output
+=================
+
+.. kernel-doc:: drivers/gpu/drm/meson/meson_dw_hdmi.c
+   :doc: HDMI Output

+ 4 - 27
Documentation/gpu/todo.rst

@@ -16,7 +16,7 @@ De-midlayer drivers
 With the recent ``drm_bus`` cleanup patches for 3.17 it is no longer required
 to have a ``drm_bus`` structure set up. Drivers can directly set up the
 ``drm_device`` structure instead of relying on bus methods in ``drm_usb.c``
-and ``drm_platform.c``. The goal is to get rid of the driver's ``->load`` /
+and ``drm_pci.c``. The goal is to get rid of the driver's ``->load`` /
 ``->unload`` callbacks and open-code the load/unload sequence properly, using
 the new two-stage ``drm_device`` setup/teardown.
 
@@ -175,7 +175,7 @@ fine-grained per-buffer object and per-context lockings scheme. Currently the
 following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
 ``udl``.
 
-Contact: Daniel Vetter
+Contact: Daniel Vetter, respective driver maintainers
 
 Switch to drm_connector_list_iter for any connector_list walking
 ----------------------------------------------------------------
@@ -217,6 +217,8 @@ plan is to switch to per-file driver API headers, which will also structure
 the kerneldoc better. This should also allow more fine-grained ``#include``
 directives.
 
+In the end no .c file should need to include ``drmP.h`` anymore.
+
 Contact: Daniel Vetter
 
 Add missing kerneldoc for exported functions
@@ -244,13 +246,8 @@ be hidden so that driver writers don't accidentally end up using it. And to
 prevent security issues in those legacy IOCTLs from being exploited on modern
 drivers. This has multiple possible subtasks:
 
-* Make sure legacy IOCTLs can't be used on modern drivers.
 * Extract support code for legacy features into a ``drm-legacy.ko`` kernel
   module and compile it only when one of the legacy drivers is enabled.
-* Extract legacy functions into their own headers and remove it that from the
-  monolithic ``drmP.h`` header.
-* Remove any lingering cruft from the OS abstraction layer from modern
-  drivers.
 
 This is mostly done, the only thing left is to split up ``drm_irq.c`` into
 legacy cruft and the parts needed by modern KMS drivers.
@@ -408,23 +405,3 @@ Contact: Noralf Trønnes, Daniel Vetter
 
 Outside DRM
 ===========
-
-Better kerneldoc
-----------------
-
-This is pretty much done, but there's some advanced topics:
-
-Come up with a way to hyperlink to struct members. Currently you can hyperlink
-to the struct using ``#struct_name``, but not to a member within. Would need
-buy-in from kerneldoc maintainers, and the big question is how to make it work
-without totally unsightly
-``drm_foo_bar_really_long_structure->even_longer_memeber`` all over the text
-which breaks text flow.
-
-Figure out how to integrate the asciidoc support for ascii-diagrams. We have a
-few of those (e.g. to describe mode timings), and asciidoc supports converting
-some ascii-art dialect into pngs. Would be really pretty to make that work.
-
-Contact: Daniel Vetter, Jani Nikula
-
-Jani is working on this already, hopefully lands in 4.8.

+ 1979 - 1021
Documentation/media/uapi/v4l/subdev-formats.rst

@@ -1258,157 +1258,470 @@ The following tables list existing packed RGB formats.
       - b\ :sub:`2`
       - b\ :sub:`1`
       - b\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-RGB101010-1X30:
+
+      - MEDIA_BUS_FMT_RGB101010_1X30
+      - 0x1018
+      -
+      - 0
+      - 0
+      - r\ :sub:`9`
+      - r\ :sub:`8`
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+      - g\ :sub:`9`
+      - g\ :sub:`8`
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
+      - g\ :sub:`0`
+      - b\ :sub:`9`
+      - b\ :sub:`8`
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
 
 .. raw:: latex
 
     \endgroup
 
-On LVDS buses, usually each sample is transferred serialized in seven
-time slots per pixel clock, on three (18-bit) or four (24-bit)
-differential data pairs at the same time. The remaining bits are used
-for control signals as defined by SPWG/PSWG/VESA or JEIDA standards. The
-24-bit RGB format serialized in seven time slots on four lanes using
-JEIDA defined bit mapping will be named
-``MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA``, for example.
 
-.. raw:: latex
+The following table list existing packed 36bit wide RGB formats.
 
-    \begin{adjustbox}{width=\columnwidth}
+.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
 
-.. _v4l2-mbus-pixelcode-rgb-lvds:
+.. _v4l2-mbus-pixelcode-rgb-36:
 
-.. flat-table:: LVDS RGB formats
+.. raw:: latex
+
+    \begingroup
+    \tiny
+    \setlength{\tabcolsep}{2pt}
+
+.. flat-table:: 36bit RGB formats
     :header-rows:  2
     :stub-columns: 0
+    :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 
     * - Identifier
       - Code
       -
-      -
-      - :cspan:`3` Data organization
+      - :cspan:`35` Data organization
     * -
       -
-      - Timeslot
-      - Lane
+      - Bit
+      - 35
+      - 34
+      - 33
+      - 32
+      - 31
+      - 30
+      - 29
+      - 28
+      - 27
+      - 26
+      - 25
+      - 24
+      - 23
+      - 22
+      - 21
+      - 20
+      - 19
+      - 18
+      - 17
+      - 16
+      - 15
+      - 14
+      - 13
+      - 12
+      - 11
+      - 10
+      - 9
+      - 8
+      - 7
+      - 6
+      - 5
+      - 4
       - 3
       - 2
       - 1
       - 0
-    * .. _MEDIA-BUS-FMT-RGB666-1X7X3-SPWG:
+    * .. _MEDIA-BUS-FMT-RGB121212-1X36:
 
-      - MEDIA_BUS_FMT_RGB666_1X7X3_SPWG
-      - 0x1010
-      - 0
+      - MEDIA_BUS_FMT_RGB121212_1X36
+      - 0x1019
       -
-      -
-      - d
-      - b\ :sub:`1`
+      - r\ :sub:`11`
+      - r\ :sub:`10`
+      - r\ :sub:`9`
+      - r\ :sub:`8`
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+      - g\ :sub:`11`
+      - g\ :sub:`10`
+      - g\ :sub:`9`
+      - g\ :sub:`8`
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
       - g\ :sub:`0`
+      - b\ :sub:`11`
+      - b\ :sub:`10`
+      - b\ :sub:`9`
+      - b\ :sub:`8`
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
+
+.. raw:: latex
+
+    \endgroup
+
+
+The following table list existing packed 48bit wide RGB formats.
+
+.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
+
+.. _v4l2-mbus-pixelcode-rgb-48:
+
+.. raw:: latex
+
+    \begingroup
+    \tiny
+    \setlength{\tabcolsep}{2pt}
+
+.. flat-table:: 48bit RGB formats
+    :header-rows:  3
+    :stub-columns: 0
+    :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+
+    * - Identifier
+      - Code
+      -
+      - :cspan:`31` Data organization
     * -
       -
-      - 1
+      - Bit
       -
       -
-      - d
-      - b\ :sub:`0`
-      - r\ :sub:`5`
-    * -
       -
-      - 2
       -
       -
-      - d
-      - g\ :sub:`5`
-      - r\ :sub:`4`
-    * -
       -
-      - 3
       -
       -
-      - b\ :sub:`5`
-      - g\ :sub:`4`
-      - r\ :sub:`3`
-    * -
       -
-      - 4
       -
       -
-      - b\ :sub:`4`
-      - g\ :sub:`3`
-      - r\ :sub:`2`
-    * -
       -
-      - 5
       -
       -
-      - b\ :sub:`3`
-      - g\ :sub:`2`
-      - r\ :sub:`1`
+      -
+      -
+      - 47
+      - 46
+      - 45
+      - 44
+      - 43
+      - 42
+      - 41
+      - 40
+      - 39
+      - 38
+      - 37
+      - 36
+      - 35
+      - 34
+      - 33
+      - 32
     * -
       -
+      -
+      - 31
+      - 30
+      - 29
+      - 28
+      - 27
+      - 26
+      - 25
+      - 24
+      - 23
+      - 22
+      - 21
+      - 20
+      - 19
+      - 18
+      - 17
+      - 16
+      - 15
+      - 14
+      - 13
+      - 12
+      - 11
+      - 10
+      - 9
+      - 8
+      - 7
       - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+    * .. _MEDIA-BUS-FMT-RGB161616-1X48:
+
+      - MEDIA_BUS_FMT_RGB161616_1X48
+      - 0x101a
       -
       -
-      - b\ :sub:`2`
-      - g\ :sub:`1`
-      - r\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-RGB888-1X7X4-SPWG:
-
-      - MEDIA_BUS_FMT_RGB888_1X7X4_SPWG
-      - 0x1011
-      - 0
       -
-      - d
-      - d
-      - b\ :sub:`1`
-      - g\ :sub:`0`
-    * -
       -
-      - 1
       -
-      - b\ :sub:`7`
-      - d
-      - b\ :sub:`0`
-      - r\ :sub:`5`
-    * -
       -
-      - 2
       -
-      - b\ :sub:`6`
-      - d
-      - g\ :sub:`5`
-      - r\ :sub:`4`
-    * -
       -
-      - 3
       -
-      - g\ :sub:`7`
-      - b\ :sub:`5`
-      - g\ :sub:`4`
-      - r\ :sub:`3`
-    * -
       -
-      - 4
       -
-      - g\ :sub:`6`
-      - b\ :sub:`4`
-      - g\ :sub:`3`
-      - r\ :sub:`2`
-    * -
       -
-      - 5
       -
-      - r\ :sub:`7`
-      - b\ :sub:`3`
-      - g\ :sub:`2`
-      - r\ :sub:`1`
-    * -
       -
-      - 6
       -
-      - r\ :sub:`6`
-      - b\ :sub:`2`
-      - g\ :sub:`1`
+      -
+      -
+      - r\ :sub:`15`
+      - r\ :sub:`14`
+      - r\ :sub:`13`
+      - r\ :sub:`12`
+      - r\ :sub:`11`
+      - r\ :sub:`10`
+      - r\ :sub:`9`
+      - r\ :sub:`8`
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+    * -
+      -
+      -
+      - g\ :sub:`15`
+      - g\ :sub:`14`
+      - g\ :sub:`13`
+      - g\ :sub:`12`
+      - g\ :sub:`11`
+      - g\ :sub:`10`
+      - g\ :sub:`9`
+      - g\ :sub:`8`
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
+      - g\ :sub:`0`
+      - b\ :sub:`15`
+      - b\ :sub:`14`
+      - b\ :sub:`13`
+      - b\ :sub:`12`
+      - b\ :sub:`11`
+      - b\ :sub:`10`
+      - b\ :sub:`9`
+      - b\ :sub:`8`
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
+
+.. raw:: latex
+
+    \endgroup
+
+On LVDS buses, usually each sample is transferred serialized in seven
+time slots per pixel clock, on three (18-bit) or four (24-bit)
+differential data pairs at the same time. The remaining bits are used
+for control signals as defined by SPWG/PSWG/VESA or JEIDA standards. The
+24-bit RGB format serialized in seven time slots on four lanes using
+JEIDA defined bit mapping will be named
+``MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA``, for example.
+
+.. raw:: latex
+
+    \begin{adjustbox}{width=\columnwidth}
+
+.. _v4l2-mbus-pixelcode-rgb-lvds:
+
+.. flat-table:: LVDS RGB formats
+    :header-rows:  2
+    :stub-columns: 0
+
+    * - Identifier
+      - Code
+      -
+      -
+      - :cspan:`3` Data organization
+    * -
+      -
+      - Timeslot
+      - Lane
+      - 3
+      - 2
+      - 1
+      - 0
+    * .. _MEDIA-BUS-FMT-RGB666-1X7X3-SPWG:
+
+      - MEDIA_BUS_FMT_RGB666_1X7X3_SPWG
+      - 0x1010
+      - 0
+      -
+      -
+      - d
+      - b\ :sub:`1`
+      - g\ :sub:`0`
+    * -
+      -
+      - 1
+      -
+      -
+      - d
+      - b\ :sub:`0`
+      - r\ :sub:`5`
+    * -
+      -
+      - 2
+      -
+      -
+      - d
+      - g\ :sub:`5`
+      - r\ :sub:`4`
+    * -
+      -
+      - 3
+      -
+      -
+      - b\ :sub:`5`
+      - g\ :sub:`4`
+      - r\ :sub:`3`
+    * -
+      -
+      - 4
+      -
+      -
+      - b\ :sub:`4`
+      - g\ :sub:`3`
+      - r\ :sub:`2`
+    * -
+      -
+      - 5
+      -
+      -
+      - b\ :sub:`3`
+      - g\ :sub:`2`
+      - r\ :sub:`1`
+    * -
+      -
+      - 6
+      -
+      -
+      - b\ :sub:`2`
+      - g\ :sub:`1`
+      - r\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-RGB888-1X7X4-SPWG:
+
+      - MEDIA_BUS_FMT_RGB888_1X7X4_SPWG
+      - 0x1011
+      - 0
+      -
+      - d
+      - d
+      - b\ :sub:`1`
+      - g\ :sub:`0`
+    * -
+      -
+      - 1
+      -
+      - b\ :sub:`7`
+      - d
+      - b\ :sub:`0`
+      - r\ :sub:`5`
+    * -
+      -
+      - 2
+      -
+      - b\ :sub:`6`
+      - d
+      - g\ :sub:`5`
+      - r\ :sub:`4`
+    * -
+      -
+      - 3
+      -
+      - g\ :sub:`7`
+      - b\ :sub:`5`
+      - g\ :sub:`4`
+      - r\ :sub:`3`
+    * -
+      -
+      - 4
+      -
+      - g\ :sub:`6`
+      - b\ :sub:`4`
+      - g\ :sub:`3`
+      - r\ :sub:`2`
+    * -
+      -
+      - 5
+      -
+      - r\ :sub:`7`
+      - b\ :sub:`3`
+      - g\ :sub:`2`
+      - r\ :sub:`1`
+    * -
+      -
+      - 6
+      -
+      - r\ :sub:`6`
+      - b\ :sub:`2`
+      - g\ :sub:`1`
       - r\ :sub:`0`
     * .. _MEDIA-BUS-FMT-RGB888-1X7X4-JEIDA:
 
@@ -2344,7 +2657,8 @@ The format code is made of the following information.
 
 -  The number of bus samples per pixel. Pixels that are wider than the
    bus width must be transferred in multiple samples. Common values are
-   1, 1.5 (encoded as 1_5) and 2.
+   0.5 (encoded as 0_5; in this case two pixels are transferred per bus
+   sample), 1, 1.5 (encoded as 1_5) and 2.
 
 -  The bus width. When the bus width is larger than the number of bits
    per pixel component, several components are packed in a single bus
@@ -2472,10 +2786,399 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UV8-1X8:
-
-      - MEDIA_BUS_FMT_UV8_1X8
-      - 0x2015
+    * .. _MEDIA-BUS-FMT-UV8-1X8:
+
+      - MEDIA_BUS_FMT_UV8_1X8
+      - 0x2015
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYVY8-1_5X8:
+
+      - MEDIA_BUS_FMT_UYVY8_1_5X8
+      - 0x2002
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VYUY8-1_5X8:
+
+      - MEDIA_BUS_FMT_VYUY8_1_5X8
+      - 0x2003
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
       -
       -
       -
@@ -2536,18 +3239,123 @@ the following codes.
       -
       -
       -
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY8-1_5X8:
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YUYV8-1_5X8:
 
-      - MEDIA_BUS_FMT_UYVY8_1_5X8
-      - 0x2002
+      - MEDIA_BUS_FMT_YUYV8_1_5X8
+      - 0x2004
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
       -
       -
       -
@@ -2686,8 +3494,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * -
-      -
+    * .. _MEDIA-BUS-FMT-YVYU8-1_5X8:
+
+      - MEDIA_BUS_FMT_YVYU8_1_5X8
+      - 0x2005
       -
       -
       -
@@ -2756,10 +3566,8 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY8-1_5X8:
-
-      - MEDIA_BUS_FMT_VYUY8_1_5X8
-      - 0x2003
+    * -
+      -
       -
       -
       -
@@ -2898,6 +3706,43 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYVY8-2X8:
+
+      - MEDIA_BUS_FMT_UYVY8_2X8
+      - 0x2006
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
     * -
       -
       -
@@ -2933,6 +3778,41 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
     * -
       -
       -
@@ -2968,10 +3848,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV8-1_5X8:
+    * .. _MEDIA-BUS-FMT-VYUY8-2X8:
 
-      - MEDIA_BUS_FMT_YUYV8_1_5X8
-      - 0x2004
+      - MEDIA_BUS_FMT_VYUY8_2X8
+      - 0x2007
       -
       -
       -
@@ -2997,14 +3877,14 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
     * -
       -
       -
@@ -3110,8 +3990,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * -
-      -
+    * .. _MEDIA-BUS-FMT-YUYV8-2X8:
+
+      - MEDIA_BUS_FMT_YUYV8_2X8
+      - 0x2008
       -
       -
       -
@@ -3172,18 +4054,16 @@ the following codes.
       -
       -
       -
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU8-1_5X8:
-
-      - MEDIA_BUS_FMT_YVYU8_1_5X8
-      - 0x2005
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+    * -
+      -
       -
       -
       -
@@ -3244,6 +4124,43 @@ the following codes.
       -
       -
       -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YVYU8-2X8:
+
+      - MEDIA_BUS_FMT_YVYU8_2X8
+      - 0x2009
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3349,18 +4266,18 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * -
-      -
-      -
-      -
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-Y10-1X10:
+
+      - MEDIA_BUS_FMT_Y10_1X10
+      - 0x200a
       -
       -
       -
@@ -3384,20 +4301,20 @@ the following codes.
       -
       -
       -
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY8-2X8:
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYVY10-2X10:
 
-      - MEDIA_BUS_FMT_UYVY8_2X8
-      - 0x2006
-      -
-      -
+      - MEDIA_BUS_FMT_UYVY10_2X10
+      - 0x2018
       -
       -
       -
@@ -3421,6 +4338,8 @@ the following codes.
       -
       -
       -
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -3454,8 +4373,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3489,8 +4408,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -3524,8 +4443,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3534,12 +4453,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY8-2X8:
+    * .. _MEDIA-BUS-FMT-VYUY10-2X10:
 
-      - MEDIA_BUS_FMT_VYUY8_2X8
-      - 0x2007
-      -
-      -
+      - MEDIA_BUS_FMT_VYUY10_2X10
+      - 0x2019
       -
       -
       -
@@ -3563,6 +4480,8 @@ the following codes.
       -
       -
       -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -3596,8 +4515,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3631,8 +4550,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -3666,8 +4585,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3676,12 +4595,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV8-2X8:
+    * .. _MEDIA-BUS-FMT-YUYV10-2X10:
 
-      - MEDIA_BUS_FMT_YUYV8_2X8
-      - 0x2008
-      -
-      -
+      - MEDIA_BUS_FMT_YUYV10_2X10
+      - 0x200b
       -
       -
       -
@@ -3705,6 +4622,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3738,8 +4657,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -3773,8 +4692,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3808,8 +4727,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -3818,12 +4737,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU8-2X8:
+    * .. _MEDIA-BUS-FMT-YVYU10-2X10:
 
-      - MEDIA_BUS_FMT_YVYU8_2X8
-      - 0x2009
-      -
-      -
+      - MEDIA_BUS_FMT_YVYU10_2X10
+      - 0x200c
       -
       -
       -
@@ -3847,6 +4764,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3880,8 +4799,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -3915,8 +4834,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -3950,8 +4869,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -3960,12 +4879,10 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-Y10-1X10:
+    * .. _MEDIA-BUS-FMT-Y12-1X12:
 
-      - MEDIA_BUS_FMT_Y10_1X10
-      - 0x200a
-      -
-      -
+      - MEDIA_BUS_FMT_Y12_1X12
+      - 0x2013
       -
       -
       -
@@ -3987,6 +4904,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -3997,12 +4916,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY10-2X10:
+    * .. _MEDIA-BUS-FMT-UYVY12-2X12:
 
-      - MEDIA_BUS_FMT_UYVY10_2X10
-      - 0x2018
-      -
-      -
+      - MEDIA_BUS_FMT_UYVY12_2X12
+      - 0x201c
       -
       -
       -
@@ -4024,6 +4941,8 @@ the following codes.
       -
       -
       -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
       - u\ :sub:`9`
       - u\ :sub:`8`
       - u\ :sub:`7`
@@ -4057,8 +4976,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4092,8 +5011,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -4127,8 +5046,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4139,12 +5058,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY10-2X10:
+    * .. _MEDIA-BUS-FMT-VYUY12-2X12:
 
-      - MEDIA_BUS_FMT_VYUY10_2X10
-      - 0x2019
-      -
-      -
+      - MEDIA_BUS_FMT_VYUY12_2X12
+      - 0x201d
       -
       -
       -
@@ -4166,6 +5083,8 @@ the following codes.
       -
       -
       -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -4199,8 +5118,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4234,8 +5153,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
       - u\ :sub:`9`
       - u\ :sub:`8`
       - u\ :sub:`7`
@@ -4246,9 +5165,7 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * -
-      -
-      -
+    * -
       -
       -
       -
@@ -4271,6 +5188,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4281,12 +5200,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV10-2X10:
+    * .. _MEDIA-BUS-FMT-YUYV12-2X12:
 
-      - MEDIA_BUS_FMT_YUYV10_2X10
-      - 0x200b
-      -
-      -
+      - MEDIA_BUS_FMT_YUYV12_2X12
+      - 0x201e
       -
       -
       -
@@ -4308,6 +5225,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4341,8 +5260,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
       - u\ :sub:`9`
       - u\ :sub:`8`
       - u\ :sub:`7`
@@ -4376,8 +5295,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4411,8 +5330,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -4423,12 +5342,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU10-2X10:
+    * .. _MEDIA-BUS-FMT-YVYU12-2X12:
 
-      - MEDIA_BUS_FMT_YVYU10_2X10
-      - 0x200c
-      -
-      -
+      - MEDIA_BUS_FMT_YVYU12_2X12
+      - 0x201f
       -
       -
       -
@@ -4450,6 +5367,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4483,8 +5402,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -4518,8 +5437,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -4553,8 +5472,8 @@ the following codes.
       -
       -
       -
-      -
-      -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
       - u\ :sub:`9`
       - u\ :sub:`8`
       - u\ :sub:`7`
@@ -4565,51 +5484,10 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-Y12-1X12:
-
-      - MEDIA_BUS_FMT_Y12_1X12
-      - 0x2013
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY12-2X12:
+    * .. _MEDIA-BUS-FMT-UYVY8-1X16:
 
-      - MEDIA_BUS_FMT_UYVY12_2X12
-      - 0x201c
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_UYVY8_1X16
+      - 0x200f
       -
       -
       -
@@ -4627,10 +5505,6 @@ the following codes.
       -
       -
       -
-      - u\ :sub:`11`
-      - u\ :sub:`10`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -4639,6 +5513,14 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * -
       -
       -
@@ -4658,14 +5540,14 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -4674,12 +5556,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
+    * .. _MEDIA-BUS-FMT-VYUY8-1X16:
+
+      - MEDIA_BUS_FMT_VYUY8_1X16
+      - 0x2010
       -
       -
       -
@@ -4697,10 +5577,6 @@ the following codes.
       -
       -
       -
-      - v\ :sub:`11`
-      - v\ :sub:`10`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -4709,6 +5585,14 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * -
       -
       -
@@ -4728,14 +5612,14 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -4744,14 +5628,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY12-2X12:
+    * .. _MEDIA-BUS-FMT-YUYV8-1X16:
 
-      - MEDIA_BUS_FMT_VYUY12_2X12
-      - 0x201d
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_YUYV8_1X16
+      - 0x2011
       -
       -
       -
@@ -4769,18 +5649,22 @@ the following codes.
       -
       -
       -
-      - v\ :sub:`11`
-      - v\ :sub:`10`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
     * -
       -
       -
@@ -4800,14 +5684,6 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -4816,12 +5692,18 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YVYU8-1X16:
+
+      - MEDIA_BUS_FMT_YVYU8_1X16
+      - 0x2012
       -
       -
       -
@@ -4839,18 +5721,22 @@ the following codes.
       -
       -
       -
-      - u\ :sub:`11`
-      - u\ :sub:`10`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
     * -
       -
       -
@@ -4870,14 +5756,6 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -4886,14 +5764,18 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV12-2X12:
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YDYUYDYV8-1X16:
 
-      - MEDIA_BUS_FMT_YUYV12_2X12
-      - 0x201e
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_YDYUYDYV8_1X16
+      - 0x2014
       -
       -
       -
@@ -4911,10 +5793,6 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -4923,6 +5801,14 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - d
+      - d
+      - d
+      - d
+      - d
+      - d
+      - d
+      - d
     * -
       -
       -
@@ -4942,14 +5828,14 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - u\ :sub:`11`
-      - u\ :sub:`10`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -4977,14 +5863,6 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -4993,6 +5871,14 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - d
+      - d
+      - d
+      - d
+      - d
+      - d
+      - d
+      - d
     * -
       -
       -
@@ -5012,14 +5898,14 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - v\ :sub:`11`
-      - v\ :sub:`10`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -5028,18 +5914,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU12-2X12:
+    * .. _MEDIA-BUS-FMT-UYVY10-1X20:
 
-      - MEDIA_BUS_FMT_YVYU12_2X12
-      - 0x201f
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_UYVY10_1X20
+      - 0x201a
       -
       -
       -
@@ -5053,8 +5931,16 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -5080,16 +5966,6 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      - v\ :sub:`11`
-      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -5100,16 +5976,20 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VYUY10-1X20:
+
+      - MEDIA_BUS_FMT_VYUY10_1X20
+      - 0x201b
       -
       -
       -
@@ -5123,8 +6003,16 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -5150,16 +6038,6 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      - u\ :sub:`11`
-      - u\ :sub:`10`
       - u\ :sub:`9`
       - u\ :sub:`8`
       - u\ :sub:`7`
@@ -5170,14 +6048,20 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY8-1X16:
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YUYV10-1X20:
 
-      - MEDIA_BUS_FMT_UYVY8_1X16
-      - 0x200f
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_YUYV10_1X20
+      - 0x200d
       -
       -
       -
@@ -5191,14 +6075,8 @@ the following codes.
       -
       -
       -
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5207,6 +6085,16 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
     * -
       -
       -
@@ -5222,18 +6110,8 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5242,27 +6120,8 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY8-1X16:
-
-      - MEDIA_BUS_FMT_VYUY8_1X16
-      - 0x2010
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -5271,20 +6130,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
+    * .. _MEDIA-BUS-FMT-YVYU10-1X20:
+
+      - MEDIA_BUS_FMT_YVYU10_1X20
+      - 0x200e
       -
       -
       -
@@ -5298,14 +6147,8 @@ the following codes.
       -
       -
       -
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5314,13 +6157,17 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV8-1X16:
-
-      - MEDIA_BUS_FMT_YUYV8_1X16
-      - 0x2011
-      -
-      -
-      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * -
       -
       -
       -
@@ -5335,6 +6182,8 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5343,6 +6192,8 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -5351,7 +6202,10 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * -
+    * .. _MEDIA-BUS-FMT-VUY8-1X24:
+
+      - MEDIA_BUS_FMT_VUY8_1X24
+      - 0x201a
       -
       -
       -
@@ -5361,6 +6215,34 @@ the following codes.
       -
       -
       -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YUV8-1X24:
+
+      - MEDIA_BUS_FMT_YUV8_1X24
+      - 0x2025
       -
       -
       -
@@ -5378,6 +6260,14 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -5386,18 +6276,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU8-1X16:
+    * .. _MEDIA-BUS-FMT-UYYVYY8-0-5X24:
 
-      - MEDIA_BUS_FMT_YVYU8_1X16
-      - 0x2012
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_UYYVYY8_0_5X24
+      - 0x2026
       -
       -
       -
@@ -5407,6 +6289,22 @@ the following codes.
       -
       -
       -
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5415,14 +6313,6 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
     * -
       -
       -
@@ -5434,14 +6324,22 @@ the following codes.
       -
       -
       -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5450,6 +6348,23 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYVY12-1X24:
+
+      - MEDIA_BUS_FMT_UYVY12_1X24
+      - 0x2020
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -5458,10 +6373,20 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YDYUYDYV8-1X16:
-
-      - MEDIA_BUS_FMT_YDYUYDYV8_1X16
-      - 0x2014
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
       -
       -
       -
@@ -5471,6 +6396,35 @@ the following codes.
       -
       -
       -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VYUY12-1X24:
+
+      - MEDIA_BUS_FMT_VYUY12_1X24
+      - 0x2021
+      -
       -
       -
       -
@@ -5479,6 +6433,22 @@ the following codes.
       -
       -
       -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5487,14 +6457,6 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - d
-      - d
-      - d
-      - d
-      - d
-      - d
-      - d
-      - d
     * -
       -
       -
@@ -5506,6 +6468,35 @@ the following codes.
       -
       -
       -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YUYV12-1X24:
+
+      - MEDIA_BUS_FMT_YUYV12_1X24
+      - 0x2022
+      -
       -
       -
       -
@@ -5514,6 +6505,10 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5522,6 +6517,10 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
       - u\ :sub:`7`
       - u\ :sub:`6`
       - u\ :sub:`5`
@@ -5541,6 +6540,35 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YVYU12-1X24:
+
+      - MEDIA_BUS_FMT_YVYU12_1X24
+      - 0x2023
+      -
       -
       -
       -
@@ -5549,6 +6577,10 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5557,14 +6589,18 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - d
-      - d
-      - d
-      - d
-      - d
-      - d
-      - d
-      - d
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
     * -
       -
       -
@@ -5576,14 +6612,39 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-YUV10-1X30:
+
+      - MEDIA_BUS_FMT_YUV10_1X30
+      - 0x2016
       -
       -
       -
-      -
-      -
-      -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5592,6 +6653,18 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
       - v\ :sub:`7`
       - v\ :sub:`6`
       - v\ :sub:`5`
@@ -5600,20 +6673,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY10-1X20:
+    * .. _MEDIA-BUS-FMT-UYYVYY10-0-5X30:
 
-      - MEDIA_BUS_FMT_UYVY10_1X20
-      - 0x201a
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_UYYVYY10_0_5X30
+      - 0x2027
       -
       -
       -
@@ -5637,17 +6700,17 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
       -
       -
       -
@@ -5672,23 +6735,166 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY10-1X20:
-
-      - MEDIA_BUS_FMT_VYUY10_1X20
-      - 0x201b
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-AYUV8-1X32:
+
+      - MEDIA_BUS_FMT_AYUV8_1X32
+      - 0x2017
+      -
+      - a\ :sub:`7`
+      - a\ :sub:`6`
+      - a\ :sub:`5`
+      - a\ :sub:`4`
+      - a\ :sub:`3`
+      - a\ :sub:`2`
+      - a\ :sub:`1`
+      - a\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+
+
+.. raw:: latex
+
+	\endgroup
+
+
+The following table list existing packed 36bit wide YUV formats.
+
+.. raw:: latex
+
+    \begingroup
+    \tiny
+    \setlength{\tabcolsep}{2pt}
+
+.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
+
+.. _v4l2-mbus-pixelcode-yuv8-36bit:
+
+.. flat-table:: 36bit YUV Formats
+    :header-rows:  2
+    :stub-columns: 0
+    :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+
+    * - Identifier
+      - Code
+      -
+      - :cspan:`35` Data organization
+    * -
+      -
+      - Bit
+      - 35
+      - 34
+      - 33
+      - 32
+      - 31
+      - 30
+      - 29
+      - 28
+      - 27
+      - 26
+      - 25
+      - 24
+      - 23
+      - 22
+      - 21
+      - 10
+      - 19
+      - 18
+      - 17
+      - 16
+      - 15
+      - 14
+      - 13
+      - 12
+      - 11
+      - 10
+      - 9
+      - 8
+      - 7
+      - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+    * .. _MEDIA-BUS-FMT-UYYVYY12-0-5X36:
+
+      - MEDIA_BUS_FMT_UYYVYY12_0_5X36
+      - 0x2028
+      -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
       -
       -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -5699,6 +6905,8 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -5709,31 +6917,8 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      - u\ :sub:`9`
-      - u\ :sub:`8`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -5744,23 +6929,13 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV10-1X20:
+    * .. _MEDIA-BUS-FMT-YUV12-1X36:
 
-      - MEDIA_BUS_FMT_YUYV10_1X20
-      - 0x200d
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - MEDIA_BUS_FMT_YUV12_1X36
+      - 0x2029
       -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
       - y\ :sub:`9`
       - y\ :sub:`8`
       - y\ :sub:`7`
@@ -5771,6 +6946,8 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
       - u\ :sub:`9`
       - u\ :sub:`8`
       - u\ :sub:`7`
@@ -5781,31 +6958,8 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
+      - v\ :sub:`11`
+      - v\ :sub:`10`
       - v\ :sub:`9`
       - v\ :sub:`8`
       - v\ :sub:`7`
@@ -5816,44 +6970,41 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU10-1X20:
 
-      - MEDIA_BUS_FMT_YVYU10_1X20
-      - 0x200e
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+
+.. raw:: latex
+
+	\endgroup
+
+
+The following table list existing packed 48bit wide YUV formats.
+
+.. raw:: latex
+
+    \begingroup
+    \tiny
+    \setlength{\tabcolsep}{2pt}
+
+.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
+
+.. _v4l2-mbus-pixelcode-yuv8-48bit:
+
+.. flat-table:: 48bit YUV Formats
+    :header-rows:  3
+    :stub-columns: 0
+    :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+
+    * - Identifier
+      - Code
       -
+      - :cspan:`31` Data organization
+    * -
       -
+      - Bit
       -
       -
       -
       -
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-    * -
       -
       -
       -
@@ -5866,33 +7017,61 @@ the following codes.
       -
       -
       -
+      - 47
+      - 46
+      - 45
+      - 44
+      - 43
+      - 42
+      - 41
+      - 40
+      - 39
+      - 38
+      - 37
+      - 36
+      - 35
+      - 34
+      - 33
+      - 32
+    * -
       -
       -
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VUY8-1X24:
+      - 31
+      - 30
+      - 29
+      - 28
+      - 27
+      - 26
+      - 25
+      - 24
+      - 23
+      - 22
+      - 21
+      - 10
+      - 19
+      - 18
+      - 17
+      - 16
+      - 15
+      - 14
+      - 13
+      - 12
+      - 11
+      - 10
+      - 9
+      - 8
+      - 7
+      - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+    * .. _MEDIA-BUS-FMT-YUV16-1X48:
 
-      - MEDIA_BUS_FMT_VUY8_1X24
-      - 0x201a
-      -
+      - MEDIA_BUS_FMT_YUV16_1X48
+      - 0x202a
       -
       -
       -
@@ -5901,34 +7080,6 @@ the following codes.
       -
       -
       -
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUV8-1X24:
-
-      - MEDIA_BUS_FMT_YUV8_1X24
-      - 0x2025
       -
       -
       -
@@ -5938,6 +7089,14 @@ the following codes.
       -
       -
       -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`8`
+      - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
       - y\ :sub:`5`
@@ -5946,35 +7105,13 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-UYVY12-1X24:
-
-      - MEDIA_BUS_FMT_UYVY12_1X24
-      - 0x2020
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+    * -
       -
       -
+      - u\ :sub:`15`
+      - u\ :sub:`14`
+      - u\ :sub:`13`
+      - u\ :sub:`12`
       - u\ :sub:`11`
       - u\ :sub:`10`
       - u\ :sub:`9`
@@ -5987,29 +7124,10 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - v\ :sub:`15`
+      - v\ :sub:`14`
+      - v\ :sub:`13`
+      - v\ :sub:`12`
       - v\ :sub:`11`
       - v\ :sub:`10`
       - v\ :sub:`9`
@@ -6022,24 +7140,10 @@ the following codes.
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-VYUY12-1X24:
+    * .. _MEDIA-BUS-FMT-UYYVYY16-0-5X48:
 
-      - MEDIA_BUS_FMT_VYUY12_1X24
-      - 0x2021
-      -
-      -
+      - MEDIA_BUS_FMT_UYYVYY16_0_5X48
+      - 0x202b
       -
       -
       -
@@ -6047,31 +7151,6 @@ the following codes.
       -
       -
       -
-      - v\ :sub:`11`
-      - v\ :sub:`10`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-    * -
       -
       -
       -
@@ -6082,6 +7161,10 @@ the following codes.
       -
       -
       -
+      - u\ :sub:`15`
+      - u\ :sub:`14`
+      - u\ :sub:`13`
+      - u\ :sub:`12`
       - u\ :sub:`11`
       - u\ :sub:`10`
       - u\ :sub:`9`
@@ -6094,6 +7177,13 @@ the following codes.
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
+    * -
+      -
+      -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
       - y\ :sub:`11`
       - y\ :sub:`10`
       - y\ :sub:`9`
@@ -6106,22 +7196,13 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUYV12-1X24:
-
-      - MEDIA_BUS_FMT_YUYV12_1X24
-      - 0x2022
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
       - y\ :sub:`11`
       - y\ :sub:`10`
-      - y\ :sub:`9`
+      - y\ :sub:`8`
       - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
@@ -6131,18 +7212,6 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - u\ :sub:`11`
-      - u\ :sub:`10`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
     * -
       -
       -
@@ -6154,35 +7223,6 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-      - v\ :sub:`11`
-      - v\ :sub:`10`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YVYU12-1X24:
-
-      - MEDIA_BUS_FMT_YVYU12_1X24
-      - 0x2023
-      -
       -
       -
       -
@@ -6191,18 +7231,10 @@ the following codes.
       -
       -
       -
-      - y\ :sub:`11`
-      - y\ :sub:`10`
-      - y\ :sub:`9`
-      - y\ :sub:`8`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
+      - v\ :sub:`15`
+      - v\ :sub:`14`
+      - v\ :sub:`13`
+      - v\ :sub:`12`
       - v\ :sub:`11`
       - v\ :sub:`10`
       - v\ :sub:`9`
@@ -6218,14 +7250,10 @@ the following codes.
     * -
       -
       -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
-      -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
       - y\ :sub:`11`
       - y\ :sub:`10`
       - y\ :sub:`9`
@@ -6238,26 +7266,13 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - u\ :sub:`11`
-      - u\ :sub:`10`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-YUV10-1X30:
-
-      - MEDIA_BUS_FMT_YUV10_1X30
-      - 0x2016
-      -
-      -
-      -
-      - y\ :sub:`9`
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`8`
       - y\ :sub:`8`
       - y\ :sub:`7`
       - y\ :sub:`6`
@@ -6267,63 +7282,6 @@ the following codes.
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
-      - u\ :sub:`9`
-      - u\ :sub:`8`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-      - v\ :sub:`9`
-      - v\ :sub:`8`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
-    * .. _MEDIA-BUS-FMT-AYUV8-1X32:
-
-      - MEDIA_BUS_FMT_AYUV8_1X32
-      - 0x2017
-      -
-      - a\ :sub:`7`
-      - a\ :sub:`6`
-      - a\ :sub:`5`
-      - a\ :sub:`4`
-      - a\ :sub:`3`
-      - a\ :sub:`2`
-      - a\ :sub:`1`
-      - a\ :sub:`0`
-      - y\ :sub:`7`
-      - y\ :sub:`6`
-      - y\ :sub:`5`
-      - y\ :sub:`4`
-      - y\ :sub:`3`
-      - y\ :sub:`2`
-      - y\ :sub:`1`
-      - y\ :sub:`0`
-      - u\ :sub:`7`
-      - u\ :sub:`6`
-      - u\ :sub:`5`
-      - u\ :sub:`4`
-      - u\ :sub:`3`
-      - u\ :sub:`2`
-      - u\ :sub:`1`
-      - u\ :sub:`0`
-      - v\ :sub:`7`
-      - v\ :sub:`6`
-      - v\ :sub:`5`
-      - v\ :sub:`4`
-      - v\ :sub:`3`
-      - v\ :sub:`2`
-      - v\ :sub:`1`
-      - v\ :sub:`0`
 
 
 .. raw:: latex

+ 2 - 1
MAINTAINERS

@@ -4256,7 +4256,8 @@ W:	http://linux-meson.com/
 S:	Supported
 F:	drivers/gpu/drm/meson/
 F:	Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
-T:	git git://anongit.freedesktop.org/drm/drm-meson
+F:	Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
+F:	Documentation/gpu/meson.rst
 T:	git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR EXYNOS

+ 35 - 2
drivers/dma-buf/dma-buf.c

@@ -1059,7 +1059,11 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 	int ret;
 	struct dma_buf *buf_obj;
 	struct dma_buf_attachment *attach_obj;
-	int count = 0, attach_count;
+	struct reservation_object *robj;
+	struct reservation_object_list *fobj;
+	struct dma_fence *fence;
+	unsigned seq;
+	int count = 0, attach_count, shared_count, i;
 	size_t size = 0;
 
 	ret = mutex_lock_interruptible(&db_list.lock);
@@ -1068,7 +1072,8 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 		return ret;
 
 	seq_puts(s, "\nDma-buf Objects:\n");
-	seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
+	seq_printf(s, "%-8s\t%-8s\t%-8s\t%-8s\texp_name\n",
+		   "size", "flags", "mode", "count");
 
 	list_for_each_entry(buf_obj, &db_list.head, list_node) {
 		ret = mutex_lock_interruptible(&buf_obj->lock);
@@ -1085,6 +1090,34 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 				file_count(buf_obj->file),
 				buf_obj->exp_name);
 
+		robj = buf_obj->resv;
+		while (true) {
+			seq = read_seqcount_begin(&robj->seq);
+			rcu_read_lock();
+			fobj = rcu_dereference(robj->fence);
+			shared_count = fobj ? fobj->shared_count : 0;
+			fence = rcu_dereference(robj->fence_excl);
+			if (!read_seqcount_retry(&robj->seq, seq))
+				break;
+			rcu_read_unlock();
+		}
+
+		if (fence)
+			seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n",
+				   fence->ops->get_driver_name(fence),
+				   fence->ops->get_timeline_name(fence),
+				   dma_fence_is_signaled(fence) ? "" : "un");
+		for (i = 0; i < shared_count; i++) {
+			fence = rcu_dereference(fobj->shared[i]);
+			if (!dma_fence_get_rcu(fence))
+				continue;
+			seq_printf(s, "\tShared fence: %s %s %ssignalled\n",
+				   fence->ops->get_driver_name(fence),
+				   fence->ops->get_timeline_name(fence),
+				   dma_fence_is_signaled(fence) ? "" : "un");
+		}
+		rcu_read_unlock();
+
 		seq_puts(s, "\tAttached Devices:\n");
 		attach_count = 0;
 

+ 2 - 1
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c

@@ -2618,7 +2618,8 @@ static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
 }
 
 static int dce_v10_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				    u16 *blue, uint32_t size)
+				    u16 *blue, uint32_t size,
+				    struct drm_modeset_acquire_ctx *ctx)
 {
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	int i;

+ 2 - 1
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c

@@ -2638,7 +2638,8 @@ static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
 }
 
 static int dce_v11_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				    u16 *blue, uint32_t size)
+				    u16 *blue, uint32_t size,
+				    struct drm_modeset_acquire_ctx *ctx)
 {
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	int i;

+ 2 - 1
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c

@@ -1985,7 +1985,8 @@ static void dce_v6_0_cursor_reset(struct drm_crtc *crtc)
 }
 
 static int dce_v6_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				   u16 *blue, uint32_t size)
+				   u16 *blue, uint32_t size,
+				   struct drm_modeset_acquire_ctx *ctx)
 {
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	int i;

+ 2 - 1
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c

@@ -2469,7 +2469,8 @@ static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
 }
 
 static int dce_v8_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				   u16 *blue, uint32_t size)
+				   u16 *blue, uint32_t size,
+				   struct drm_modeset_acquire_ctx *ctx)
 {
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	int i;

+ 2 - 1
drivers/gpu/drm/amd/amdgpu/dce_virtual.c

@@ -165,7 +165,8 @@ static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
 }
 
 static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
-				      u16 *green, u16 *blue, uint32_t size)
+				      u16 *green, u16 *blue, uint32_t size,
+				      struct drm_modeset_acquire_ctx *ctx)
 {
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	int i;

+ 3 - 19
drivers/gpu/drm/arm/hdlcd_drv.c

@@ -392,29 +392,13 @@ static int compare_dev(struct device *dev, void *data)
 
 static int hdlcd_probe(struct platform_device *pdev)
 {
-	struct device_node *port, *ep;
+	struct device_node *port;
 	struct component_match *match = NULL;
 
-	if (!pdev->dev.of_node)
-		return -ENODEV;
-
 	/* there is only one output port inside each device, find it */
-	ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
-	if (!ep)
-		return -ENODEV;
-
-	if (!of_device_is_available(ep)) {
-		of_node_put(ep);
+	port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
+	if (!port)
 		return -ENODEV;
-	}
-
-	/* add the remote encoder port as component */
-	port = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-	if (!port || !of_device_is_available(port)) {
-		of_node_put(port);
-		return -EAGAIN;
-	}
 
 	drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
 	of_node_put(port);

+ 4 - 24
drivers/gpu/drm/arm/malidp_drv.c

@@ -283,7 +283,6 @@ static int malidp_bind(struct device *dev)
 {
 	struct resource *res;
 	struct drm_device *drm;
-	struct device_node *ep;
 	struct malidp_drm *malidp;
 	struct malidp_hw_device *hwdev;
 	struct platform_device *pdev = to_platform_device(dev);
@@ -398,12 +397,7 @@ static int malidp_bind(struct device *dev)
 		goto init_fail;
 
 	/* Set the CRTC's port so that the encoder component can find it */
-	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (!ep) {
-		ret = -EINVAL;
-		goto port_fail;
-	}
-	malidp->crtc.port = of_get_next_parent(ep);
+	malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
 
 	ret = component_bind_all(dev, drm);
 	if (ret) {
@@ -458,7 +452,6 @@ irq_init_fail:
 bind_fail:
 	of_node_put(malidp->crtc.port);
 	malidp->crtc.port = NULL;
-port_fail:
 	malidp_fini(drm);
 init_fail:
 	drm->dev_private = NULL;
@@ -516,29 +509,16 @@ static int malidp_compare_dev(struct device *dev, void *data)
 
 static int malidp_platform_probe(struct platform_device *pdev)
 {
-	struct device_node *port, *ep;
+	struct device_node *port;
 	struct component_match *match = NULL;
 
 	if (!pdev->dev.of_node)
 		return -ENODEV;
 
 	/* there is only one output port inside each device, find it */
-	ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
-	if (!ep)
-		return -ENODEV;
-
-	if (!of_device_is_available(ep)) {
-		of_node_put(ep);
+	port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
+	if (!port)
 		return -ENODEV;
-	}
-
-	/* add the remote encoder port as component */
-	port = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-	if (!port || !of_device_is_available(port)) {
-		of_node_put(port);
-		return -EAGAIN;
-	}
 
 	drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
 				   port);

+ 2 - 1
drivers/gpu/drm/ast/ast_mode.c

@@ -645,7 +645,8 @@ static void ast_crtc_reset(struct drm_crtc *crtc)
 }
 
 static int ast_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-			      u16 *blue, uint32_t size)
+			      u16 *blue, uint32_t size,
+			      struct drm_modeset_acquire_ctx *ctx)
 {
 	struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
 	int i;

+ 21 - 52
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c

@@ -22,7 +22,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drmP.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>
 
 #include "atmel_hlcdc_dc.h"
 
@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
-				      const struct of_endpoint *ep)
-{
-	struct device_node *np;
-	void *obj;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	obj = of_drm_find_panel(np);
-	if (!obj)
-		obj = of_drm_find_bridge(np);
-
-	of_node_put(np);
-
-	return obj ? 0 : -EPROBE_DEFER;
-}
-
 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
-				       const struct of_endpoint *ep)
+				       const struct device_node *np)
 {
 	struct atmel_hlcdc_dc *dc = dev->dev_private;
 	struct atmel_hlcdc_rgb_output *output;
-	struct device_node *np;
 	struct drm_panel *panel;
 	struct drm_bridge *bridge;
 	int ret;
@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 
 	output->encoder.possible_crtcs = 0x1;
 
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	ret = -EPROBE_DEFER;
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
+	if (ret)
+		return ret;
 
-	panel = of_drm_find_panel(np);
 	if (panel) {
-		of_node_put(np);
 		output->connector.dpms = DRM_MODE_DPMS_OFF;
 		output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
 		drm_connector_helper_add(&output->connector,
@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 		return 0;
 	}
 
-	bridge = of_drm_find_bridge(np);
-	of_node_put(np);
-
 	if (bridge) {
 		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
 		if (!ret)
@@ -243,31 +220,23 @@ err_encoder_cleanup:
 
 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
-	struct device_node *ep_np = NULL;
-	struct of_endpoint ep;
-	int ret;
-
-	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = atmel_hlcdc_check_endpoint(dev, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
-			return ret;
-		}
-	}
-
-	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = atmel_hlcdc_attach_endpoint(dev, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
+	struct device_node *remote;
+	int ret, endpoint = 0;
+
+	while (true) {
+		/* Loop thru possible multiple connections to the output */
+		remote = of_graph_get_remote_node(dev->dev->of_node, 0,
+						  endpoint++);
+		if (!remote)
+			break;
+
+		ret = atmel_hlcdc_attach_endpoint(dev, remote);
+		of_node_put(remote);
+		if (ret)
 			return ret;
-		}
 	}
 
-	return 0;
+	if (!endpoint)
+		return -ENODEV;
+	return ret;
 }

+ 2 - 10
drivers/gpu/drm/bridge/adv7511/adv7533.c

@@ -232,7 +232,6 @@ void adv7533_detach_dsi(struct adv7511 *adv)
 int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
 {
 	u32 num_lanes;
-	struct device_node *endpoint;
 
 	of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
 
@@ -241,17 +240,10 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
 
 	adv->num_dsi_lanes = num_lanes;
 
-	endpoint = of_graph_get_next_endpoint(np, NULL);
-	if (!endpoint)
+	adv->host_node = of_graph_get_remote_node(np, 0, 0);
+	if (!adv->host_node)
 		return -ENODEV;
 
-	adv->host_node = of_graph_get_remote_port_parent(endpoint);
-	if (!adv->host_node) {
-		of_node_put(endpoint);
-		return -ENODEV;
-	}
-
-	of_node_put(endpoint);
 	of_node_put(adv->host_node);
 
 	adv->use_timing_gen = !of_property_read_bool(np,

+ 6 - 0
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c

@@ -1439,13 +1439,19 @@ void analogix_dp_unbind(struct device *dev, struct device *master,
 	struct analogix_dp_device *dp = dev_get_drvdata(dev);
 
 	analogix_dp_bridge_disable(dp->bridge);
+	dp->connector.funcs->destroy(&dp->connector);
+	dp->encoder->funcs->destroy(dp->encoder);
 
 	if (dp->plat_data->panel) {
 		if (drm_panel_unprepare(dp->plat_data->panel))
 			DRM_ERROR("failed to turnoff the panel\n");
+		if (drm_panel_detach(dp->plat_data->panel))
+			DRM_ERROR("failed to detach the panel\n");
 	}
 
+	drm_dp_aux_unregister(&dp->aux);
 	pm_runtime_disable(dev);
+	clk_disable_unprepare(dp->clock);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_unbind);
 

+ 3 - 12
drivers/gpu/drm/bridge/dumb-vga-dac.c

@@ -154,21 +154,12 @@ static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
 
 static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
 {
-	struct device_node *end_node, *phandle, *remote;
+	struct device_node *phandle, *remote;
 	struct i2c_adapter *ddc;
 
-	end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
-	if (!end_node) {
-		dev_err(dev, "Missing connector endpoint\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(end_node);
-	of_node_put(end_node);
-	if (!remote) {
-		dev_err(dev, "Enable to parse remote node\n");
+	remote = of_graph_get_remote_node(dev->of_node, 1, -1);
+	if (!remote)
 		return ERR_PTR(-EINVAL);
-	}
 
 	phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
 	of_node_put(remote);

+ 5 - 4
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c

@@ -279,10 +279,6 @@ static int ge_b850v3_lvds_init(struct device *dev)
 		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;
@@ -317,6 +313,11 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c,
 	ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;
 	i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr);
 
+	/* drm bridge initialization */
+	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);
+
 	/* Clear pending interrupts since power up. */
 	i2c_smbus_write_word_data(stdp4028_i2c,
 				  STDP4028_DPTX_IRQ_STS_REG,

+ 4 - 12
drivers/gpu/drm/bridge/nxp-ptn3460.c

@@ -20,8 +20,8 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
-#include <linux/of_graph.h>
 
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "drm_crtc.h"
@@ -292,7 +292,6 @@ static int ptn3460_probe(struct i2c_client *client,
 {
 	struct device *dev = &client->dev;
 	struct ptn3460_bridge *ptn_bridge;
-	struct device_node *endpoint, *panel_node;
 	int ret;
 
 	ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
@@ -300,16 +299,9 @@ static int ptn3460_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		if (panel_node) {
-			ptn_bridge->panel = of_drm_find_panel(panel_node);
-			of_node_put(panel_node);
-			if (!ptn_bridge->panel)
-				return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL);
+	if (ret)
+		return ret;
 
 	ptn_bridge->client = client;
 

+ 4 - 12
drivers/gpu/drm/bridge/parade-ps8622.c

@@ -22,10 +22,10 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
 
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "drmP.h"
@@ -536,7 +536,6 @@ static int ps8622_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *endpoint, *panel_node;
 	struct ps8622_bridge *ps8622;
 	int ret;
 
@@ -544,16 +543,9 @@ static int ps8622_probe(struct i2c_client *client,
 	if (!ps8622)
 		return -ENOMEM;
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		if (panel_node) {
-			ps8622->panel = of_drm_find_panel(panel_node);
-			of_node_put(panel_node);
-			if (!ps8622->panel)
-				return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL);
+	if (ret)
+		return ret;
 
 	ps8622->client = client;
 

+ 301 - 156
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c

@@ -30,18 +30,15 @@
 #include <drm/drm_encoder_slave.h>
 #include <drm/bridge/dw_hdmi.h>
 
+#include <uapi/linux/media-bus-format.h>
+#include <uapi/linux/videodev2.h>
+
 #include "dw-hdmi.h"
 #include "dw-hdmi-audio.h"
 
 #define DDC_SEGMENT_ADDR	0x30
 #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,
@@ -95,10 +92,10 @@ struct hdmi_vmode {
 };
 
 struct hdmi_data_info {
-	unsigned int enc_in_format;
-	unsigned int enc_out_format;
-	unsigned int enc_color_depth;
-	unsigned int colorimetry;
+	unsigned int enc_in_bus_format;
+	unsigned int enc_out_bus_format;
+	unsigned int enc_in_encoding;
+	unsigned int enc_out_encoding;
 	unsigned int pix_repet_factor;
 	unsigned int hdcp_enable;
 	struct hdmi_vmode video_mode;
@@ -567,6 +564,78 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
 
+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_YUV16_1X48:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		return 8;
+
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+		return 10;
+
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
+		return 12;
+
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+	case MEDIA_BUS_FMT_YUV16_1X48:
+	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
+		return 16;
+
+	default:
+		return 0;
+	}
+}
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
@@ -579,37 +648,49 @@ 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;
+	switch (hdmi->hdmi_data.enc_in_bus_format) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		color_format = 0x01;
+		break;
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+		color_format = 0x03;
+		break;
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+		color_format = 0x05;
+		break;
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+		color_format = 0x07;
+		break;
+
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		color_format = 0x09;
+		break;
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+		color_format = 0x0B;
+		break;
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
+		color_format = 0x0D;
+		break;
+	case MEDIA_BUS_FMT_YUV16_1X48:
+	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
+		color_format = 0x0F;
+		break;
+
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		color_format = 0x16;
+		break;
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		color_format = 0x14;
+		break;
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+		color_format = 0x12;
+		break;
+
+	default:
+		return;
 	}
 
 	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
@@ -632,26 +713,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
 
 static int is_color_space_conversion(struct dw_hdmi *hdmi)
 {
-	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
+	return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
 }
 
 static int is_color_space_decimation(struct dw_hdmi *hdmi)
 {
-	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
+	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
 		return 0;
-	if (hdmi->hdmi_data.enc_in_format == RGB ||
-	    hdmi->hdmi_data.enc_in_format == YCBCR444)
+
+	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
+	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
 		return 1;
+
 	return 0;
 }
 
 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
 {
-	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
+	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
 		return 0;
-	if (hdmi->hdmi_data.enc_out_format == RGB ||
-	    hdmi->hdmi_data.enc_out_format == YCBCR444)
+
+	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
+	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
 		return 1;
+
 	return 0;
 }
 
@@ -662,15 +747,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
 	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)
+		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+			if (hdmi->hdmi_data.enc_out_encoding ==
+						V4L2_YCBCR_ENC_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)
+		} else if (hdmi_bus_fmt_is_rgb(
+					hdmi->hdmi_data.enc_in_bus_format)) {
+			if (hdmi->hdmi_data.enc_out_encoding ==
+						V4L2_YCBCR_ENC_601)
 				csc_coeff = &csc_coeff_rgb_in_eitu601;
 			else
 				csc_coeff = &csc_coeff_rgb_in_eitu709;
@@ -708,16 +794,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
 	else if (is_color_space_decimation(hdmi))
 		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
 
-	if (hdmi->hdmi_data.enc_color_depth == 8)
+	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
+	case 8:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
-	else if (hdmi->hdmi_data.enc_color_depth == 10)
+		break;
+	case 10:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
-	else if (hdmi->hdmi_data.enc_color_depth == 12)
+		break;
+	case 12:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
-	else if (hdmi->hdmi_data.enc_color_depth == 16)
+		break;
+	case 16:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
-	else
+		break;
+
+	default:
 		return;
+	}
 
 	/* Configure the CSC registers */
 	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
@@ -740,32 +833,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 	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) {
+	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
+	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) {
+		switch (hdmi_bus_fmt_color_depth(
+					hdmi->hdmi_data.enc_out_bus_format)) {
+		case 8:
 			color_depth = 4;
 			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-		} else if (hdmi_data->enc_color_depth == 10) {
+			break;
+		case 10:
 			color_depth = 5;
-		} else if (hdmi_data->enc_color_depth == 12) {
+			break;
+		case 12:
 			color_depth = 6;
-		} else if (hdmi_data->enc_color_depth == 16) {
+			break;
+		case 16:
 			color_depth = 7;
-		} else {
-			return;
+			break;
+		default:
+			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
 		}
-	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
-		if (!hdmi_data->enc_color_depth ||
-		    hdmi_data->enc_color_depth == 8)
+	} else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
+		switch (hdmi_bus_fmt_color_depth(
+					hdmi->hdmi_data.enc_out_bus_format)) {
+		case 0:
+		case 8:
 			remap_size = HDMI_VP_REMAP_YCC422_16bit;
-		else if (hdmi_data->enc_color_depth == 10)
+			break;
+		case 10:
 			remap_size = HDMI_VP_REMAP_YCC422_20bit;
-		else if (hdmi_data->enc_color_depth == 12)
+			break;
+		case 12:
 			remap_size = HDMI_VP_REMAP_YCC422_24bit;
-		else
+			break;
+
+		default:
 			return;
+		}
 		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
 	} else {
 		return;
@@ -1111,10 +1215,46 @@ static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
 		connector_status_connected : connector_status_disconnected;
 }
 
+static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
+				   bool force, bool disabled, bool rxsense)
+{
+	u8 old_mask = hdmi->phy_mask;
+
+	if (force || disabled || !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 void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data)
+{
+	/*
+	 * Configure the PHY RX SENSE and HPD interrupts polarities and clear
+	 * any pending interrupt.
+	 */
+	hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
+	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+		    HDMI_IH_PHY_STAT0);
+
+	/* Enable cable hot plug irq. */
+	hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
+
+	/* Clear and unmute interrupts. */
+	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+		    HDMI_IH_PHY_STAT0);
+	hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
+		    HDMI_IH_MUTE_PHY_STAT0);
+}
+
 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,
+	.update_hpd = dw_hdmi_phy_update_hpd,
+	.setup_hpd = dw_hdmi_phy_setup_hpd,
 };
 
 /* -----------------------------------------------------------------------------
@@ -1148,28 +1288,36 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	/* Initialise info frame from DRM mode */
 	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 
-	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
+	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
 		frame.colorspace = HDMI_COLORSPACE_YUV444;
-	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
+	else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
 		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 =
+	switch (hdmi->hdmi_data.enc_out_encoding) {
+	case V4L2_YCBCR_ENC_601:
+		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
+			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+		else
+			frame.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 =
+		break;
+	case V4L2_YCBCR_ENC_709:
+		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
+			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+		else
+			frame.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;
+		break;
+	default: /* Carries no data */
+		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+		frame.extended_colorimetry =
+				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+		break;
 	}
 
 	frame.scan_mode = HDMI_SCAN_MODE_NONE;
@@ -1498,19 +1646,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	    (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;
+		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
 	else
-		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_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;
+	/* TOFIX: Get input format from plat data or fallback to RGB888 */
+	if (hdmi->plat_data->input_bus_format)
+		hdmi->hdmi_data.enc_in_bus_format =
+			hdmi->plat_data->input_bus_format;
+	else
+		hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+	/* TOFIX: Get input encoding from plat data or fallback to none */
+	if (hdmi->plat_data->input_bus_encoding)
+		hdmi->hdmi_data.enc_in_encoding =
+			hdmi->plat_data->input_bus_encoding;
+	else
+		hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
 
-	hdmi->hdmi_data.enc_out_format = RGB;
+	/* TOFIX: Default to RGB888 output format */
+	hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 
-	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;
@@ -1558,8 +1717,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	return 0;
 }
 
-/* Wait until we are registered to enable interrupts */
-static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
+static void dw_hdmi_setup_i2c(struct dw_hdmi *hdmi)
 {
 	hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
 		    HDMI_PHY_I2CM_INT_ADDR);
@@ -1567,15 +1725,6 @@ static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
 	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)
@@ -1682,15 +1831,10 @@ static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
  */
 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);
+	if (hdmi->phy.ops->update_hpd)
+		hdmi->phy.ops->update_hpd(hdmi, hdmi->phy.data,
+					  hdmi->force, hdmi->disabled,
+					  hdmi->rxsense);
 }
 
 static enum drm_connector_status
@@ -1882,6 +2026,41 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
 	return ret;
 }
 
+void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
+{
+	mutex_lock(&hdmi->mutex);
+
+	if (!hdmi->force) {
+		/*
+		 * If the RX sense status indicates we're disconnected,
+		 * clear the software rxsense status.
+		 */
+		if (!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 (hpd)
+			hdmi->rxsense = true;
+
+		dw_hdmi_update_power(hdmi);
+		dw_hdmi_update_phy_mask(hdmi);
+	}
+	mutex_unlock(&hdmi->mutex);
+}
+
+void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
+{
+	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
+
+	__dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
+
 static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
 {
 	struct dw_hdmi *hdmi = dev_id;
@@ -1914,30 +2093,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
 	 * 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->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);
-	}
+	    (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD))
+		__dw_hdmi_setup_rx_sense(hdmi,
+					 phy_stat & HDMI_PHY_HPD,
+					 phy_stat & HDMI_PHY_RX_SENSE);
 
 	if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
 		dev_dbg(hdmi->dev, "EVENT=%s\n",
@@ -2204,29 +2363,15 @@ __dw_hdmi_probe(struct platform_device *pdev,
 			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);
+	dw_hdmi_setup_i2c(hdmi);
+	if (hdmi->phy.ops->setup_hpd)
+		hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
 
 	memset(&pdevinfo, 0, sizeof(pdevinfo));
 	pdevinfo.parent = dev;

+ 3 - 24
drivers/gpu/drm/bridge/tc358767.c

@@ -1244,7 +1244,6 @@ static const struct regmap_config tc_regmap_config = {
 static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *ep;
 	struct tc_data *tc;
 	int ret;
 
@@ -1255,29 +1254,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	tc->dev = dev;
 
 	/* port@2 is the output port */
-	ep = of_graph_get_endpoint_by_regs(dev->of_node, 2, -1);
-	if (ep) {
-		struct device_node *remote;
-
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote) {
-			dev_warn(dev, "endpoint %s not connected\n",
-				 ep->full_name);
-			of_node_put(ep);
-			return -ENODEV;
-		}
-		of_node_put(ep);
-		tc->panel = of_drm_find_panel(remote);
-		if (tc->panel) {
-			dev_dbg(dev, "found panel %s\n", remote->full_name);
-		} else {
-			dev_dbg(dev, "waiting for panel %s\n",
-				remote->full_name);
-			of_node_put(remote);
-			return -EPROBE_DEFER;
-		}
-		of_node_put(remote);
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL);
+	if (ret)
+		return ret;
 
 	/* Shut down GPIO is optional */
 	tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);

+ 5 - 10
drivers/gpu/drm/bridge/ti-tfp410.c

@@ -165,18 +165,13 @@ static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg)
 
 static int tfp410_get_connector_properties(struct tfp410 *dvi)
 {
-	struct device_node *ep = NULL, *connector_node = NULL;
-	struct device_node *ddc_phandle = NULL;
+	struct device_node *connector_node, *ddc_phandle;
 	int ret = 0;
 
 	/* port@1 is the connector node */
-	ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 1, -1);
-	if (!ep)
-		goto fail;
-
-	connector_node = of_graph_get_remote_port_parent(ep);
+	connector_node = of_graph_get_remote_node(dvi->dev->of_node, 1, -1);
 	if (!connector_node)
-		goto fail;
+		return -ENODEV;
 
 	dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode,
 					"hpd-gpios", 0, GPIOD_IN, "hpd");
@@ -199,10 +194,10 @@ static int tfp410_get_connector_properties(struct tfp410 *dvi)
 	else
 		ret = -EPROBE_DEFER;
 
+	of_node_put(ddc_phandle);
+
 fail:
-	of_node_put(ep);
 	of_node_put(connector_node);
-	of_node_put(ddc_phandle);
 	return ret;
 }
 

+ 2 - 1
drivers/gpu/drm/cirrus/cirrus_mode.c

@@ -327,7 +327,8 @@ static void cirrus_crtc_commit(struct drm_crtc *crtc)
  * but it's a requirement that we provide the function
  */
 static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				 u16 *blue, uint32_t size)
+				 u16 *blue, uint32_t size,
+				 struct drm_modeset_acquire_ctx *ctx)
 {
 	struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
 	int i;

+ 39 - 123
drivers/gpu/drm/drm_atomic.c

@@ -1516,19 +1516,9 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes);
 void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
-	unsigned crtc_mask = 0;
-	struct drm_crtc *crtc;
 	int ret;
 	bool global = false;
 
-	drm_for_each_crtc(crtc, dev) {
-		if (crtc->acquire_ctx != state->acquire_ctx)
-			continue;
-
-		crtc_mask |= drm_crtc_mask(crtc);
-		crtc->acquire_ctx = NULL;
-	}
-
 	if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
 		global = true;
 
@@ -1542,10 +1532,6 @@ retry:
 	if (ret)
 		goto retry;
 
-	drm_for_each_crtc(crtc, dev)
-		if (drm_crtc_mask(crtc) & crtc_mask)
-			crtc->acquire_ctx = state->acquire_ctx;
-
 	if (global)
 		dev->mode_config.acquire_ctx = state->acquire_ctx;
 }
@@ -1690,22 +1676,8 @@ static void drm_atomic_print_state(const struct drm_atomic_state *state)
 		drm_atomic_connector_print_state(&p, connector_state);
 }
 
-/**
- * drm_state_dump - dump entire device atomic state
- * @dev: the drm device
- * @p: where to print the state to
- *
- * Just for debugging.  Drivers might want an option to dump state
- * to dmesg in case of error irq's.  (Hint, you probably want to
- * ratelimit this!)
- *
- * The caller must drm_modeset_lock_all(), or if this is called
- * from error irq handler, it should not be enabled by default.
- * (Ie. if you are debugging errors you might not care that this
- * is racey.  But calling this without all modeset locks held is
- * not inherently safe.)
- */
-void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
+static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
+			     bool take_locks)
 {
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_plane *plane;
@@ -1716,17 +1688,51 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
 	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
 		return;
 
-	list_for_each_entry(plane, &config->plane_list, head)
+	list_for_each_entry(plane, &config->plane_list, head) {
+		if (take_locks)
+			drm_modeset_lock(&plane->mutex, NULL);
 		drm_atomic_plane_print_state(p, plane->state);
+		if (take_locks)
+			drm_modeset_unlock(&plane->mutex);
+	}
 
-	list_for_each_entry(crtc, &config->crtc_list, head)
+	list_for_each_entry(crtc, &config->crtc_list, head) {
+		if (take_locks)
+			drm_modeset_lock(&crtc->mutex, NULL);
 		drm_atomic_crtc_print_state(p, crtc->state);
+		if (take_locks)
+			drm_modeset_unlock(&crtc->mutex);
+	}
 
 	drm_connector_list_iter_begin(dev, &conn_iter);
+	if (take_locks)
+		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 	drm_for_each_connector_iter(connector, &conn_iter)
 		drm_atomic_connector_print_state(p, connector->state);
+	if (take_locks)
+		drm_modeset_unlock(&dev->mode_config.connection_mutex);
 	drm_connector_list_iter_end(&conn_iter);
 }
+
+/**
+ * drm_state_dump - dump entire device atomic state
+ * @dev: the drm device
+ * @p: where to print the state to
+ *
+ * Just for debugging.  Drivers might want an option to dump state
+ * to dmesg in case of error irq's.  (Hint, you probably want to
+ * ratelimit this!)
+ *
+ * The caller must drm_modeset_lock_all(), or if this is called
+ * from error irq handler, it should not be enabled by default.
+ * (Ie. if you are debugging errors you might not care that this
+ * is racey.  But calling this without all modeset locks held is
+ * not inherently safe.)
+ */
+void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
+{
+	__drm_state_dump(dev, p, false);
+}
 EXPORT_SYMBOL(drm_state_dump);
 
 #ifdef CONFIG_DEBUG_FS
@@ -1736,9 +1742,7 @@ static int drm_state_info(struct seq_file *m, void *data)
 	struct drm_device *dev = node->minor->dev;
 	struct drm_printer p = drm_seq_file_printer(m);
 
-	drm_modeset_lock_all(dev);
-	drm_state_dump(dev, &p);
-	drm_modeset_unlock_all(dev);
+	__drm_state_dump(dev, &p, true);
 
 	return 0;
 }
@@ -2077,94 +2081,6 @@ static void complete_crtc_signaling(struct drm_device *dev,
 	kfree(fence_state);
 }
 
-int drm_atomic_remove_fb(struct drm_framebuffer *fb)
-{
-	struct drm_modeset_acquire_ctx ctx;
-	struct drm_device *dev = fb->dev;
-	struct drm_atomic_state *state;
-	struct drm_plane *plane;
-	struct drm_connector *conn;
-	struct drm_connector_state *conn_state;
-	int i, ret = 0;
-	unsigned plane_mask;
-
-	state = drm_atomic_state_alloc(dev);
-	if (!state)
-		return -ENOMEM;
-
-	drm_modeset_acquire_init(&ctx, 0);
-	state->acquire_ctx = &ctx;
-
-retry:
-	plane_mask = 0;
-	ret = drm_modeset_lock_all_ctx(dev, &ctx);
-	if (ret)
-		goto unlock;
-
-	drm_for_each_plane(plane, dev) {
-		struct drm_plane_state *plane_state;
-
-		if (plane->state->fb != fb)
-			continue;
-
-		plane_state = drm_atomic_get_plane_state(state, plane);
-		if (IS_ERR(plane_state)) {
-			ret = PTR_ERR(plane_state);
-			goto unlock;
-		}
-
-		if (plane_state->crtc->primary == plane) {
-			struct drm_crtc_state *crtc_state;
-
-			crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
-
-			ret = drm_atomic_add_affected_connectors(state, plane_state->crtc);
-			if (ret)
-				goto unlock;
-
-			crtc_state->active = false;
-			ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
-			if (ret)
-				goto unlock;
-		}
-
-		drm_atomic_set_fb_for_plane(plane_state, NULL);
-		ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
-		if (ret)
-			goto unlock;
-
-		plane_mask |= BIT(drm_plane_index(plane));
-
-		plane->old_fb = plane->fb;
-	}
-
-	for_each_connector_in_state(state, conn, conn_state, i) {
-		ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
-
-		if (ret)
-			goto unlock;
-	}
-
-	if (plane_mask)
-		ret = drm_atomic_commit(state);
-
-unlock:
-	if (plane_mask)
-		drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
-	if (ret == -EDEADLK) {
-		drm_modeset_backoff(&ctx);
-		goto retry;
-	}
-
-	drm_atomic_state_put(state);
-
-	drm_modeset_drop_locks(&ctx);
-	drm_modeset_acquire_fini(&ctx);
-
-	return ret;
-}
-
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv)
 {

+ 77 - 42
drivers/gpu/drm/drm_atomic_helper.c

@@ -459,10 +459,20 @@ mode_fixup(struct drm_atomic_state *state)
  *
  * Check the state object to see if the requested state is physically possible.
  * This does all the crtc and connector related computations for an atomic
- * update and adds any additional connectors needed for full modesets and calls
- * down into &drm_crtc_helper_funcs.mode_fixup and
- * &drm_encoder_helper_funcs.mode_fixup or
- * &drm_encoder_helper_funcs.atomic_check functions of the driver backend.
+ * update and adds any additional connectors needed for full modesets. It calls
+ * the various per-object callbacks in the follow order:
+ *
+ * 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder.
+ * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state.
+ * 3. If it's determined a modeset is needed then all connectors on the affected crtc
+ *    crtc are added and &drm_connector_helper_funcs.atomic_check is run on them.
+ * 4. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
+ * 5. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
+ *    This function is only called when the encoder will be part of a configured crtc,
+ *    it must not be used for implementing connector property validation.
+ *    If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called
+ *    instead.
+ * 6. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
  *
  * &drm_crtc_state.mode_changed is set when the input mode is changed.
  * &drm_crtc_state.connectors_changed is set when a connector is added or
@@ -492,8 +502,12 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 	struct drm_connector *connector;
 	struct drm_connector_state *old_connector_state, *new_connector_state;
 	int i, ret;
+	unsigned connectors_mask = 0;
 
 	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+		bool has_connectors =
+			!!new_crtc_state->connector_mask;
+
 		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);
@@ -515,13 +529,28 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 			new_crtc_state->mode_changed = true;
 			new_crtc_state->connectors_changed = true;
 		}
+
+		if (old_crtc_state->active != new_crtc_state->active) {
+			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n",
+					 crtc->base.id, crtc->name);
+			new_crtc_state->active_changed = true;
+		}
+
+		if (new_crtc_state->enable != has_connectors) {
+			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n",
+					 crtc->base.id, crtc->name);
+
+			return -EINVAL;
+		}
 	}
 
-	ret = handle_conflicting_encoders(state, state->legacy_set_config);
+	ret = handle_conflicting_encoders(state, false);
 	if (ret)
 		return ret;
 
 	for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
+		const struct drm_connector_helper_funcs *funcs = connector->helper_private;
+
 		/*
 		 * This only sets crtc->connectors_changed for routing changes,
 		 * drivers must set crtc->connectors_changed themselves when
@@ -539,6 +568,13 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 			    new_connector_state->link_status)
 				new_crtc_state->connectors_changed = true;
 		}
+
+		if (funcs->atomic_check)
+			ret = funcs->atomic_check(connector, new_connector_state);
+		if (ret)
+			return ret;
+
+		connectors_mask += BIT(i);
 	}
 
 	/*
@@ -548,20 +584,6 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 	 * crtc only changed its mode but has the same set of connectors.
 	 */
 	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
-		bool has_connectors =
-			!!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 (old_crtc_state->active != new_crtc_state->active) {
-			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n",
-					 crtc->base.id, crtc->name);
-			new_crtc_state->active_changed = true;
-		}
-
 		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
 			continue;
 
@@ -577,13 +599,22 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 		ret = drm_atomic_add_affected_planes(state, crtc);
 		if (ret != 0)
 			return ret;
+	}
 
-		if (new_crtc_state->enable != has_connectors) {
-			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n",
-					 crtc->base.id, crtc->name);
+	/*
+	 * Iterate over all connectors again, to make sure atomic_check()
+	 * has been called on them when a modeset is forced.
+	 */
+	for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
+		const struct drm_connector_helper_funcs *funcs = connector->helper_private;
 
-			return -EINVAL;
-		}
+		if (connectors_mask & BIT(i))
+			continue;
+
+		if (funcs->atomic_check)
+			ret = funcs->atomic_check(connector, new_connector_state);
+		if (ret)
+			return ret;
 	}
 
 	return mode_fixup(state);
@@ -2289,12 +2320,15 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set,
 	if (!state)
 		return -ENOMEM;
 
-	state->legacy_set_config = true;
 	state->acquire_ctx = ctx;
 	ret = __drm_atomic_helper_set_config(set, state);
 	if (ret != 0)
 		goto fail;
 
+	ret = handle_conflicting_encoders(state, true);
+	if (ret)
+		return ret;
+
 	ret = drm_atomic_commit(state);
 
 fail:
@@ -2622,14 +2656,22 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
 int drm_atomic_helper_resume(struct drm_device *dev,
 			     struct drm_atomic_state *state)
 {
-	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_modeset_acquire_ctx ctx;
 	int err;
 
 	drm_mode_config_reset(dev);
 
-	drm_modeset_lock_all(dev);
-	err = drm_atomic_helper_commit_duplicated_state(state, config->acquire_ctx);
-	drm_modeset_unlock_all(dev);
+	drm_modeset_acquire_init(&ctx, 0);
+	while (1) {
+		err = drm_atomic_helper_commit_duplicated_state(state, &ctx);
+		if (err != -EDEADLK)
+			break;
+
+		drm_modeset_backoff(&ctx);
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
 
 	return err;
 }
@@ -2975,7 +3017,7 @@ int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
 	if (!state)
 		return -ENOMEM;
 
-	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
 retry:
 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
 	if (IS_ERR(crtc_state)) {
@@ -3471,6 +3513,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
  * @green: green correction table
  * @blue: green correction table
  * @size: size of the tables
+ * @ctx: lock acquire context
  *
  * Implements support for legacy gamma correction table for drivers
  * that support color management through the DEGAMMA_LUT/GAMMA_LUT
@@ -3478,7 +3521,8 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
  */
 int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
 				       u16 *red, u16 *green, u16 *blue,
-				       uint32_t size)
+				       uint32_t size,
+				       struct drm_modeset_acquire_ctx *ctx)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_mode_config *config = &dev->mode_config;
@@ -3509,8 +3553,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
 		blob_data[i].blue = blue[i];
 	}
 
-	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
-retry:
+	state->acquire_ctx = ctx;
 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
 	if (IS_ERR(crtc_state)) {
 		ret = PTR_ERR(crtc_state);
@@ -3534,18 +3577,10 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-fail:
-	if (ret == -EDEADLK)
-		goto backoff;
 
+fail:
 	drm_atomic_state_put(state);
 	drm_property_blob_put(blob);
 	return ret;
-
-backoff:
-	drm_atomic_state_clear(state);
-	drm_atomic_legacy_backoff(state);
-
-	goto retry;
 }
 EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);

+ 27 - 24
drivers/gpu/drm/drm_color_mgmt.c

@@ -218,28 +218,28 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 	struct drm_crtc *crtc;
 	void *r_base, *g_base, *b_base;
 	int size;
+	struct drm_modeset_acquire_ctx ctx;
 	int ret = 0;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
-	drm_modeset_lock_all(dev);
 	crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
-	if (!crtc) {
-		ret = -ENOENT;
-		goto out;
-	}
+	if (!crtc)
+		return -ENOENT;
 
-	if (crtc->funcs->gamma_set == NULL) {
-		ret = -ENOSYS;
-		goto out;
-	}
+	if (crtc->funcs->gamma_set == NULL)
+		return -ENOSYS;
 
 	/* memcpy into gamma store */
-	if (crtc_lut->gamma_size != crtc->gamma_size) {
-		ret = -EINVAL;
+	if (crtc_lut->gamma_size != crtc->gamma_size)
+		return -EINVAL;
+
+	drm_modeset_acquire_init(&ctx, 0);
+retry:
+	ret = drm_modeset_lock_all_ctx(dev, &ctx);
+	if (ret)
 		goto out;
-	}
 
 	size = crtc_lut->gamma_size * (sizeof(uint16_t));
 	r_base = crtc->gamma_store;
@@ -260,10 +260,17 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 		goto out;
 	}
 
-	ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
+	ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
+				     crtc->gamma_size, &ctx);
 
 out:
-	drm_modeset_unlock_all(dev);
+	if (ret == -EDEADLK) {
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	}
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
 	return ret;
 
 }
@@ -295,19 +302,15 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
-	drm_modeset_lock_all(dev);
 	crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
-	if (!crtc) {
-		ret = -ENOENT;
-		goto out;
-	}
+	if (!crtc)
+		return -ENOENT;
 
 	/* memcpy into gamma store */
-	if (crtc_lut->gamma_size != crtc->gamma_size) {
-		ret = -EINVAL;
-		goto out;
-	}
+	if (crtc_lut->gamma_size != crtc->gamma_size)
+		return -EINVAL;
 
+	drm_modeset_lock(&crtc->mutex, NULL);
 	size = crtc_lut->gamma_size * (sizeof(uint16_t));
 	r_base = crtc->gamma_store;
 	if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
@@ -327,6 +330,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
 		goto out;
 	}
 out:
-	drm_modeset_unlock_all(dev);
+	drm_modeset_unlock(&crtc->mutex);
 	return ret;
 }

+ 2 - 0
drivers/gpu/drm/drm_crtc.c

@@ -576,6 +576,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 	}
 	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
+	mutex_lock(&crtc->dev->mode_config.mutex);
 	drm_modeset_acquire_init(&ctx, 0);
 retry:
 	ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
@@ -721,6 +722,7 @@ out:
 	}
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
+	mutex_unlock(&crtc->dev->mode_config.mutex);
 
 	return ret;
 }

+ 0 - 1
drivers/gpu/drm/drm_crtc_internal.h

@@ -182,7 +182,6 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
 			    struct drm_property *property, uint64_t *val);
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
-int drm_atomic_remove_fb(struct drm_framebuffer *fb);
 
 
 /* drm_plane.c */

+ 120 - 81
drivers/gpu/drm/drm_fb_helper.c

@@ -109,6 +109,42 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
 	for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \
 	     i__ = 0; i__ < (fbh)->connector_count; i__++)
 
+int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
+				    struct drm_connector *connector)
+{
+	struct drm_fb_helper_connector *fb_conn;
+	struct drm_fb_helper_connector **temp;
+	unsigned int count;
+
+	if (!drm_fbdev_emulation)
+		return 0;
+
+	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
+
+	count = fb_helper->connector_count + 1;
+
+	if (count > fb_helper->connector_info_alloc_count) {
+		size_t size = count * sizeof(fb_conn);
+
+		temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL);
+		if (!temp)
+			return -ENOMEM;
+
+		fb_helper->connector_info_alloc_count = count;
+		fb_helper->connector_info = temp;
+	}
+
+	fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL);
+	if (!fb_conn)
+		return -ENOMEM;
+
+	drm_connector_get(connector);
+	fb_conn->connector = connector;
+	fb_helper->connector_info[fb_helper->connector_count++] = fb_conn;
+	return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
+
 /**
  * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
  * 					       emulation helper
@@ -162,36 +198,6 @@ out:
 }
 EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
 
-int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector)
-{
-	struct drm_fb_helper_connector **temp;
-	struct drm_fb_helper_connector *fb_helper_connector;
-
-	if (!drm_fbdev_emulation)
-		return 0;
-
-	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
-	if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
-		temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
-		if (!temp)
-			return -ENOMEM;
-
-		fb_helper->connector_info_alloc_count = fb_helper->connector_count + 1;
-		fb_helper->connector_info = temp;
-	}
-
-
-	fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
-	if (!fb_helper_connector)
-		return -ENOMEM;
-
-	drm_connector_get(connector);
-	fb_helper_connector->connector = connector;
-	fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
-	return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
-
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 				       struct drm_connector *connector)
 {
@@ -213,9 +219,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 	fb_helper_connector = fb_helper->connector_info[i];
 	drm_connector_put(fb_helper_connector->connector);
 
-	for (j = i + 1; j < fb_helper->connector_count; j++) {
+	for (j = i + 1; j < fb_helper->connector_count; j++)
 		fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
-	}
+
 	fb_helper->connector_count--;
 	kfree(fb_helper_connector);
 
@@ -250,7 +256,8 @@ static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
 	g_base = r_base + crtc->gamma_size;
 	b_base = g_base + crtc->gamma_size;
 
-	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
+	crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
+			       crtc->gamma_size, NULL);
 }
 
 /**
@@ -275,6 +282,9 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
 			if (funcs->mode_set_base_atomic == NULL)
 				continue;
 
+			if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev))
+				continue;
+
 			drm_fb_helper_save_lut_atomic(mode_set->crtc, helper);
 			funcs->mode_set_base_atomic(mode_set->crtc,
 						    mode_set->fb,
@@ -316,6 +326,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 
 	for (i = 0; i < helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
+
 		crtc = mode_set->crtc;
 		funcs = crtc->helper_private;
 		fb = drm_mode_config_fb(crtc);
@@ -331,6 +342,9 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 		if (funcs->mode_set_base_atomic == NULL)
 			continue;
 
+		if (drm_drv_uses_atomic_modeset(crtc->dev))
+			continue;
+
 		drm_fb_helper_restore_lut_atomic(mode_set->crtc);
 		funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
 					    crtc->y, LEAVE_ATOMIC_MODE_SET);
@@ -346,7 +360,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
 	struct drm_plane *plane;
 	struct drm_atomic_state *state;
 	int i, ret;
-	unsigned plane_mask;
+	unsigned int plane_mask;
 
 	state = drm_atomic_state_alloc(dev);
 	if (!state)
@@ -378,7 +392,7 @@ retry:
 			goto fail;
 	}
 
-	for(i = 0; i < fb_helper->crtc_count; i++) {
+	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
 
 		ret = __drm_atomic_helper_set_config(mode_set, state);
@@ -404,17 +418,12 @@ backoff:
 	goto retry;
 }
 
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
 {
 	struct drm_device *dev = fb_helper->dev;
 	struct drm_plane *plane;
 	int i;
 
-	drm_warn_on_modeset_not_all_locked(dev);
-
-	if (drm_drv_uses_atomic_modeset(dev))
-		return restore_fbdev_mode_atomic(fb_helper);
-
 	drm_for_each_plane(plane, dev) {
 		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
 			drm_plane_force_disable(plane);
@@ -448,6 +457,18 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 	return 0;
 }
 
+static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+{
+	struct drm_device *dev = fb_helper->dev;
+
+	drm_warn_on_modeset_not_all_locked(dev);
+
+	if (drm_drv_uses_atomic_modeset(dev))
+		return restore_fbdev_mode_atomic(fb_helper);
+	else
+		return restore_fbdev_mode_legacy(fb_helper);
+}
+
 /**
  * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
  * @fb_helper: fbcon to restore
@@ -488,8 +509,10 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 	struct drm_crtc *crtc;
 	int bound = 0, crtcs_bound = 0;
 
-	/* Sometimes user space wants everything disabled, so don't steal the
-	 * display if there's a master. */
+	/*
+	 * Sometimes user space wants everything disabled, so don't steal the
+	 * display if there's a master.
+	 */
 	if (READ_ONCE(dev->master))
 		return false;
 
@@ -537,6 +560,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
 static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
 {
 	bool ret;
+
 	ret = drm_fb_helper_force_kernel_mode();
 	if (ret == true)
 		DRM_ERROR("Failed to restore crtc configuration\n");
@@ -870,9 +894,8 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 	mutex_lock(&kernel_fb_helper_lock);
 	if (!list_empty(&fb_helper->kernel_fb_list)) {
 		list_del(&fb_helper->kernel_fb_list);
-		if (list_empty(&kernel_fb_helper_list)) {
+		if (list_empty(&kernel_fb_helper_list))
 			unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
-		}
 	}
 	mutex_unlock(&kernel_fb_helper_lock);
 
@@ -1165,6 +1188,7 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
 			(blue << info->var.blue.offset);
 		if (info->var.transp.length > 0) {
 			u32 mask = (1 << info->var.transp.length) - 1;
+
 			mask <<= info->var.transp.offset;
 			value |= mask;
 		}
@@ -1447,7 +1471,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
 	struct drm_atomic_state *state;
 	struct drm_plane *plane;
 	int i, ret;
-	unsigned plane_mask;
+	unsigned int plane_mask;
 
 	state = drm_atomic_state_alloc(dev);
 	if (!state)
@@ -1456,7 +1480,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
 	state->acquire_ctx = dev->mode_config.acquire_ctx;
 retry:
 	plane_mask = 0;
-	for(i = 0; i < fb_helper->crtc_count; i++) {
+	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set;
 
 		mode_set = &fb_helper->crtc_info[i].mode_set;
@@ -1496,34 +1520,14 @@ backoff:
 	goto retry;
 }
 
-/**
- * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display
- * @var: updated screen information
- * @info: fbdev registered by the helper
- */
-int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
+static int pan_display_legacy(struct fb_var_screeninfo *var,
 			      struct fb_info *info)
 {
 	struct drm_fb_helper *fb_helper = info->par;
-	struct drm_device *dev = fb_helper->dev;
 	struct drm_mode_set *modeset;
 	int ret = 0;
 	int i;
 
-	if (oops_in_progress)
-		return -EBUSY;
-
-	drm_modeset_lock_all(dev);
-	if (!drm_fb_helper_is_bound(fb_helper)) {
-		drm_modeset_unlock_all(dev);
-		return -EBUSY;
-	}
-
-	if (drm_drv_uses_atomic_modeset(dev)) {
-		ret = pan_display_atomic(var, info);
-		goto unlock;
-	}
-
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		modeset = &fb_helper->crtc_info[i].mode_set;
 
@@ -1538,8 +1542,37 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
 			}
 		}
 	}
-unlock:
+
+	return ret;
+}
+
+/**
+ * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display
+ * @var: updated screen information
+ * @info: fbdev registered by the helper
+ */
+int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct drm_fb_helper *fb_helper = info->par;
+	struct drm_device *dev = fb_helper->dev;
+	int ret;
+
+	if (oops_in_progress)
+		return -EBUSY;
+
+	drm_modeset_lock_all(dev);
+	if (!drm_fb_helper_is_bound(fb_helper)) {
+		drm_modeset_unlock_all(dev);
+		return -EBUSY;
+	}
+
+	if (drm_drv_uses_atomic_modeset(dev))
+		ret = pan_display_atomic(var, info);
+	else
+		ret = pan_display_legacy(var, info);
 	drm_modeset_unlock_all(dev);
+
 	return ret;
 }
 EXPORT_SYMBOL(drm_fb_helper_pan_display);
@@ -1561,11 +1594,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
 	sizes.surface_depth = 24;
 	sizes.surface_bpp = 32;
-	sizes.fb_width = (unsigned)-1;
-	sizes.fb_height = (unsigned)-1;
+	sizes.fb_width = (u32)-1;
+	sizes.fb_height = (u32)-1;
 
-	/* if driver picks 8 or 16 by default use that
-	   for both depth/bpp */
+	/* if driver picks 8 or 16 by default use that for both depth/bpp */
 	if (preferred_bpp != sizes.surface_bpp)
 		sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
 
@@ -1630,6 +1662,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 
 		for (j = 0; j < mode_set->num_connectors; j++) {
 			struct drm_connector *connector = mode_set->connectors[j];
+
 			if (connector->has_tile) {
 				lasth = (connector->tile_h_loc == (connector->num_h_tile - 1));
 				lastv = (connector->tile_v_loc == (connector->num_v_tile - 1));
@@ -1645,8 +1678,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	}
 
 	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
-		/* hmm everyone went away - assume VGA cable just fell out
-		   and will come back later. */
+		/*
+		 * hmm everyone went away - assume VGA cable just fell out
+		 * and will come back later.
+		 */
 		DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
 		sizes.fb_width = sizes.surface_width = 1024;
 		sizes.fb_height = sizes.surface_height = 768;
@@ -1703,7 +1738,6 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 	info->fix.accel = FB_ACCEL_NONE;
 
 	info->fix.line_length = pitch;
-	return;
 }
 EXPORT_SYMBOL(drm_fb_helper_fill_fix);
 
@@ -1725,6 +1759,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
 			    uint32_t fb_width, uint32_t fb_height)
 {
 	struct drm_framebuffer *fb = fb_helper->fb;
+
 	info->pseudo_palette = fb_helper->pseudo_palette;
 	info->var.xres_virtual = fb->width;
 	info->var.yres_virtual = fb->height;
@@ -2057,13 +2092,15 @@ retry:
 				continue;
 
 		} else {
-			if (fb_helper_conn->connector->tile_h_loc != tile_pass -1 &&
+			if (fb_helper_conn->connector->tile_h_loc != tile_pass - 1 &&
 			    fb_helper_conn->connector->tile_v_loc != tile_pass - 1)
 			/* if this tile_pass doesn't cover any of the tiles - keep going */
 				continue;
 
-			/* find the tile offsets for this pass - need
-			   to find all tiles left and above */
+			/*
+			 * find the tile offsets for this pass - need to find
+			 * all tiles left and above
+			 */
 			drm_get_tile_offsets(fb_helper, modes, offsets,
 					     i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc);
 		}
@@ -2147,8 +2184,10 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 	if (!encoder)
 		goto out;
 
-	/* select a crtc for this connector and then attempt to configure
-	   remaining connectors */
+	/*
+	 * select a crtc for this connector and then attempt to configure
+	 * remaining connectors
+	 */
 	for (c = 0; c < fb_helper->crtc_count; c++) {
 		crtc = &fb_helper->crtc_info[c];
 

+ 115 - 22
drivers/gpu/drm/drm_framebuffer.c

@@ -24,6 +24,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_auth.h>
 #include <drm/drm_framebuffer.h>
+#include <drm/drm_atomic.h>
 
 #include "drm_crtc_internal.h"
 
@@ -755,6 +756,117 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 }
 EXPORT_SYMBOL(drm_framebuffer_cleanup);
 
+static int atomic_remove_fb(struct drm_framebuffer *fb)
+{
+	struct drm_modeset_acquire_ctx ctx;
+	struct drm_device *dev = fb->dev;
+	struct drm_atomic_state *state;
+	struct drm_plane *plane;
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i, ret = 0;
+	unsigned plane_mask;
+
+	state = drm_atomic_state_alloc(dev);
+	if (!state)
+		return -ENOMEM;
+
+	drm_modeset_acquire_init(&ctx, 0);
+	state->acquire_ctx = &ctx;
+
+retry:
+	plane_mask = 0;
+	ret = drm_modeset_lock_all_ctx(dev, &ctx);
+	if (ret)
+		goto unlock;
+
+	drm_for_each_plane(plane, dev) {
+		struct drm_plane_state *plane_state;
+
+		if (plane->state->fb != fb)
+			continue;
+
+		plane_state = drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state)) {
+			ret = PTR_ERR(plane_state);
+			goto unlock;
+		}
+
+		if (plane_state->crtc->primary == plane) {
+			struct drm_crtc_state *crtc_state;
+
+			crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
+
+			ret = drm_atomic_add_affected_connectors(state, plane_state->crtc);
+			if (ret)
+				goto unlock;
+
+			crtc_state->active = false;
+			ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
+			if (ret)
+				goto unlock;
+		}
+
+		drm_atomic_set_fb_for_plane(plane_state, NULL);
+		ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+		if (ret)
+			goto unlock;
+
+		plane_mask |= BIT(drm_plane_index(plane));
+
+		plane->old_fb = plane->fb;
+	}
+
+	for_each_connector_in_state(state, conn, conn_state, i) {
+		ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
+
+		if (ret)
+			goto unlock;
+	}
+
+	if (plane_mask)
+		ret = drm_atomic_commit(state);
+
+unlock:
+	if (plane_mask)
+		drm_atomic_clean_old_fb(dev, plane_mask, ret);
+
+	if (ret == -EDEADLK) {
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	}
+
+	drm_atomic_state_put(state);
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return ret;
+}
+
+static void legacy_remove_fb(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = fb->dev;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+
+	drm_modeset_lock_all(dev);
+	/* remove from any CRTC */
+	drm_for_each_crtc(crtc, dev) {
+		if (crtc->primary->fb == fb) {
+			/* should turn off the crtc */
+			if (drm_crtc_force_disable(crtc))
+				DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
+		}
+	}
+
+	drm_for_each_plane(plane, dev) {
+		if (plane->fb == fb)
+			drm_plane_force_disable(plane);
+	}
+	drm_modeset_unlock_all(dev);
+}
+
 /**
  * drm_framebuffer_remove - remove and unreference a framebuffer object
  * @fb: framebuffer to remove
@@ -770,8 +882,6 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
 void drm_framebuffer_remove(struct drm_framebuffer *fb)
 {
 	struct drm_device *dev;
-	struct drm_crtc *crtc;
-	struct drm_plane *plane;
 
 	if (!fb)
 		return;
@@ -797,29 +907,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 	 */
 	if (drm_framebuffer_read_refcount(fb) > 1) {
 		if (drm_drv_uses_atomic_modeset(dev)) {
-			int ret = drm_atomic_remove_fb(fb);
+			int ret = atomic_remove_fb(fb);
 			WARN(ret, "atomic remove_fb failed with %i\n", ret);
-			goto out;
-		}
-
-		drm_modeset_lock_all(dev);
-		/* remove from any CRTC */
-		drm_for_each_crtc(crtc, dev) {
-			if (crtc->primary->fb == fb) {
-				/* should turn off the crtc */
-				if (drm_crtc_force_disable(crtc))
-					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
-			}
-		}
-
-		drm_for_each_plane(plane, dev) {
-			if (plane->fb == fb)
-				drm_plane_force_disable(plane);
-		}
-		drm_modeset_unlock_all(dev);
+		} else
+			legacy_remove_fb(fb);
 	}
 
-out:
 	drm_framebuffer_put(fb);
 }
 EXPORT_SYMBOL(drm_framebuffer_remove);

+ 40 - 36
drivers/gpu/drm/drm_ioc32.c

@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_ioc32.c
  *
  * 32-bit ioctl compatibility routines for the DRM.
@@ -72,15 +72,15 @@
 #define DRM_IOCTL_MODE_ADDFB232		DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
 
 typedef struct drm_version_32 {
-	int version_major;	  /**< Major version */
-	int version_minor;	  /**< Minor version */
-	int version_patchlevel;	   /**< Patch level */
-	u32 name_len;		  /**< Length of name buffer */
-	u32 name;		  /**< Name of driver */
-	u32 date_len;		  /**< Length of date buffer */
-	u32 date;		  /**< User-space buffer to hold date */
-	u32 desc_len;		  /**< Length of desc buffer */
-	u32 desc;		  /**< User-space buffer to hold desc */
+	int version_major;	  /* Major version */
+	int version_minor;	  /* Minor version */
+	int version_patchlevel;	   /* Patch level */
+	u32 name_len;		  /* Length of name buffer */
+	u32 name;		  /* Name of driver */
+	u32 date_len;		  /* Length of date buffer */
+	u32 date;		  /* User-space buffer to hold date */
+	u32 desc_len;		  /* Length of desc buffer */
+	u32 desc;		  /* User-space buffer to hold desc */
 } drm_version32_t;
 
 static int compat_drm_version(struct file *file, unsigned int cmd,
@@ -126,8 +126,8 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_unique32 {
-	u32 unique_len;	/**< Length of unique */
-	u32 unique;	/**< Unique name for driver instantiation */
+	u32 unique_len;	/* Length of unique */
+	u32 unique;	/* Unique name for driver instantiation */
 } drm_unique32_t;
 
 static int compat_drm_getunique(struct file *file, unsigned int cmd,
@@ -180,12 +180,12 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_map32 {
-	u32 offset;		/**< Requested physical address (0 for SAREA)*/
-	u32 size;		/**< Requested physical size (bytes) */
-	enum drm_map_type type;	/**< Type of memory to map */
-	enum drm_map_flags flags;	/**< Flags */
-	u32 handle;		/**< User-space: "Handle" to pass to mmap() */
-	int mtrr;		/**< MTRR slot used */
+	u32 offset;		/* Requested physical address (0 for SAREA) */
+	u32 size;		/* Requested physical size (bytes) */
+	enum drm_map_type type;	/* Type of memory to map */
+	enum drm_map_flags flags;	/* Flags */
+	u32 handle;		/* User-space: "Handle" to pass to mmap() */
+	int mtrr;		/* MTRR slot used */
 } drm_map32_t;
 
 static int compat_drm_getmap(struct file *file, unsigned int cmd,
@@ -286,12 +286,12 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_client32 {
-	int idx;	/**< Which client desired? */
-	int auth;	/**< Is client authenticated? */
-	u32 pid;	/**< Process ID */
-	u32 uid;	/**< User ID */
-	u32 magic;	/**< Magic */
-	u32 iocs;	/**< Ioctl count */
+	int idx;	/* Which client desired? */
+	int auth;	/* Is client authenticated? */
+	u32 pid;	/* Process ID */
+	u32 uid;	/* User ID */
+	u32 magic;	/* Magic */
+	u32 iocs;	/* Ioctl count */
 } drm_client32_t;
 
 static int compat_drm_getclient(struct file *file, unsigned int cmd,
@@ -366,12 +366,12 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_buf_desc32 {
-	int count;		 /**< Number of buffers of this size */
-	int size;		 /**< Size in bytes */
-	int low_mark;		 /**< Low water mark */
-	int high_mark;		 /**< High water mark */
+	int count;		 /* Number of buffers of this size */
+	int size;		 /* Size in bytes */
+	int low_mark;		 /* Low water mark */
+	int high_mark;		 /* High water mark */
 	int flags;
-	u32 agp_start;		 /**< Start address in the AGP aperture */
+	u32 agp_start;		 /* Start address in the AGP aperture */
 } drm_buf_desc32_t;
 
 static int compat_drm_addbufs(struct file *file, unsigned int cmd,
@@ -1111,13 +1111,18 @@ static drm_ioctl_compat_t *drm_compat_ioctls[] = {
 };
 
 /**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/drm.
+ * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers
+ * @filp: file this ioctl is called on
+ * @cmd: ioctl cmd number
+ * @arg: user argument
+ *
+ * Compatibility handler for 32 bit userspace running on 64 kernels. All actual
+ * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as
+ * appropriate. Note that this only handles DRM core IOCTLs, if the driver has
+ * botched IOCTL itself, it must handle those by wrapping this function.
  *
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
+ * Returns:
+ * Zero on success, negative error code on failure.
  */
 long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
@@ -1141,5 +1146,4 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(drm_compat_ioctl);

+ 51 - 2
drivers/gpu/drm/drm_ioctl.c

@@ -286,6 +286,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
 	case DRM_CAP_ADDFB2_MODIFIERS:
 		req->value = dev->mode_config.allow_fb_modifiers;
 		break;
+	case DRM_CAP_CRTC_IN_VBLANK_EVENT:
+		req->value = 1;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -646,14 +649,60 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
 
+/**
+ * DOC: driver specific ioctls
+ *
+ * First things first, driver private IOCTLs should only be needed for drivers
+ * supporting rendering. Kernel modesetting is all standardized, and extended
+ * through properties. There are a few exceptions in some existing drivers,
+ * which define IOCTL for use by the display DRM master, but they all predate
+ * properties.
+ *
+ * Now if you do have a render driver you always have to support it through
+ * driver private properties. There's a few steps needed to wire all the things
+ * up.
+ *
+ * First you need to define the structure for your IOCTL in your driver private
+ * UAPI header in ``include/uapi/drm/my_driver_drm.h``::
+ *
+ *     struct my_driver_operation {
+ *             u32 some_thing;
+ *             u32 another_thing;
+ *     };
+ *
+ * Please make sure that you follow all the best practices from
+ * ``Documentation/ioctl/botching-up-ioctls.txt``. Note that drm_ioctl()
+ * automatically zero-extends structures, hence make sure you can add more stuff
+ * at the end, i.e. don't put a variable sized array there.
+ *
+ * Then you need to define your IOCTL number, using one of DRM_IO(), DRM_IOR(),
+ * DRM_IOW() or DRM_IOWR(). It must start with the DRM_IOCTL\_ prefix::
+ *
+ *     ##define DRM_IOCTL_MY_DRIVER_OPERATION \
+ *         DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation)
+ * 
+ * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to
+ * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire
+ * up the handlers and set the access rights:
+ *
+ *     static const struct drm_ioctl_desc my_driver_ioctls[] = {
+ *         DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation,
+ *                 DRM_AUTH|DRM_RENDER_ALLOW),
+ *     };
+ *
+ * And then assign this to the &drm_driver.ioctls field in your driver
+ * structure.
+ */
+
 /**
  * drm_ioctl - ioctl callback implementation for DRM drivers
  * @filp: file this ioctl is called on
  * @cmd: ioctl cmd number
  * @arg: user argument
  *
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
+ * Looks up the ioctl function in the DRM core and the driver dispatch table,
+ * stored in &drm_driver.ioctls. It checks for necessary permission by calling
+ * drm_ioctl_permit(), and dispatches to the respective function.
  *
  * Returns:
  * Zero on success, negative error code on failure.

+ 2 - 0
drivers/gpu/drm/drm_irq.c

@@ -1026,6 +1026,7 @@ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
 
 	e->pipe = pipe;
 	e->event.sequence = drm_vblank_count(dev, pipe);
+	e->event.crtc_id = crtc->base.id;
 	list_add_tail(&e->base.link, &dev->vblank_event_list);
 }
 EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
@@ -1056,6 +1057,7 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
 		now = get_drm_timestamp();
 	}
 	e->pipe = pipe;
+	e->event.crtc_id = crtc->base.id;
 	send_vblank_event(dev, e, seq, &now);
 }
 EXPORT_SYMBOL(drm_crtc_send_vblank_event);

+ 0 - 102
drivers/gpu/drm/drm_modeset_lock.c

@@ -148,108 +148,6 @@ void drm_modeset_unlock_all(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_modeset_unlock_all);
 
-/**
- * drm_modeset_lock_crtc - lock crtc with hidden acquire ctx for a plane update
- * @crtc: DRM CRTC
- * @plane: DRM plane to be updated on @crtc
- *
- * This function locks the given crtc and plane (which should be either the
- * primary or cursor plane) using a hidden acquire context. This is necessary so
- * that drivers internally using the atomic interfaces can grab further locks
- * with the lock acquire context.
- *
- * Note that @plane can be NULL, e.g. when the cursor support hasn't yet been
- * converted to universal planes yet.
- */
-void drm_modeset_lock_crtc(struct drm_crtc *crtc,
-			   struct drm_plane *plane)
-{
-	struct drm_modeset_acquire_ctx *ctx;
-	int ret;
-
-	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-	if (WARN_ON(!ctx))
-		return;
-
-	drm_modeset_acquire_init(ctx, 0);
-
-retry:
-	ret = drm_modeset_lock(&crtc->mutex, ctx);
-	if (ret)
-		goto fail;
-
-	if (plane) {
-		ret = drm_modeset_lock(&plane->mutex, ctx);
-		if (ret)
-			goto fail;
-
-		if (plane->crtc) {
-			ret = drm_modeset_lock(&plane->crtc->mutex, ctx);
-			if (ret)
-				goto fail;
-		}
-	}
-
-	WARN_ON(crtc->acquire_ctx);
-
-	/* now we hold the locks, so now that it is safe, stash the
-	 * ctx for drm_modeset_unlock_crtc():
-	 */
-	crtc->acquire_ctx = ctx;
-
-	return;
-
-fail:
-	if (ret == -EDEADLK) {
-		drm_modeset_backoff(ctx);
-		goto retry;
-	}
-}
-EXPORT_SYMBOL(drm_modeset_lock_crtc);
-
-/**
- * drm_modeset_legacy_acquire_ctx - find acquire ctx for legacy ioctls
- * @crtc: drm crtc
- *
- * Legacy ioctl operations like cursor updates or page flips only have per-crtc
- * locking, and store the acquire ctx in the corresponding crtc. All other
- * legacy operations take all locks and use a global acquire context. This
- * function grabs the right one.
- */
-struct drm_modeset_acquire_ctx *
-drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc)
-{
-	if (crtc->acquire_ctx)
-		return crtc->acquire_ctx;
-
-	WARN_ON(!crtc->dev->mode_config.acquire_ctx);
-
-	return crtc->dev->mode_config.acquire_ctx;
-}
-EXPORT_SYMBOL(drm_modeset_legacy_acquire_ctx);
-
-/**
- * drm_modeset_unlock_crtc - drop crtc lock
- * @crtc: drm crtc
- *
- * This drops the crtc lock acquire with drm_modeset_lock_crtc() and all other
- * locks acquired through the hidden context.
- */
-void drm_modeset_unlock_crtc(struct drm_crtc *crtc)
-{
-	struct drm_modeset_acquire_ctx *ctx = crtc->acquire_ctx;
-
-	if (WARN_ON(!ctx))
-		return;
-
-	crtc->acquire_ctx = NULL;
-	drm_modeset_drop_locks(ctx);
-	drm_modeset_acquire_fini(ctx);
-
-	kfree(ctx);
-}
-EXPORT_SYMBOL(drm_modeset_unlock_crtc);
-
 /**
  * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
  * @dev: device

+ 52 - 0
drivers/gpu/drm/drm_of.c

@@ -3,8 +3,10 @@
 #include <linux/list.h>
 #include <linux/of_graph.h>
 #include <drm/drmP.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
+#include <drm/drm_panel.h>
 #include <drm/drm_of.h>
 
 static void drm_release_of(struct device *dev, void *data)
@@ -208,3 +210,53 @@ int drm_of_encoder_active_endpoint(struct device_node *node,
 	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
+
+/*
+ * drm_of_find_panel_or_bridge - return connected panel or bridge device
+ * @np: device tree node containing encoder output ports
+ * @panel: pointer to hold returned drm_panel
+ * @bridge: pointer to hold returned drm_bridge
+ *
+ * Given a DT node's port and endpoint number, find the connected node and
+ * return either the associated struct drm_panel or drm_bridge device. Either
+ * @panel or @bridge must not be NULL.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+int drm_of_find_panel_or_bridge(const struct device_node *np,
+				int port, int endpoint,
+				struct drm_panel **panel,
+				struct drm_bridge **bridge)
+{
+	int ret = -EPROBE_DEFER;
+	struct device_node *remote;
+
+	if (!panel && !bridge)
+		return -EINVAL;
+
+	remote = of_graph_get_remote_node(np, port, endpoint);
+	if (!remote)
+		return -ENODEV;
+
+	if (panel) {
+		*panel = of_drm_find_panel(remote);
+		if (*panel)
+			ret = 0;
+	}
+
+	/* No panel found yet, check for a bridge next. */
+	if (bridge) {
+		if (ret) {
+			*bridge = of_drm_find_bridge(remote);
+			if (*bridge)
+				ret = 0;
+		} else {
+			*bridge = NULL;
+		}
+
+	}
+
+	of_node_put(remote);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);

+ 24 - 25
drivers/gpu/drm/drm_plane.c

@@ -620,7 +620,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 
 static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 				     struct drm_mode_cursor2 *req,
-				     struct drm_file *file_priv)
+				     struct drm_file *file_priv,
+				     struct drm_modeset_acquire_ctx *ctx)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_framebuffer *fb = NULL;
@@ -634,21 +635,11 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 	int32_t crtc_x, crtc_y;
 	uint32_t crtc_w = 0, crtc_h = 0;
 	uint32_t src_w = 0, src_h = 0;
-	struct drm_modeset_acquire_ctx ctx;
 	int ret = 0;
 
 	BUG_ON(!crtc->cursor);
 	WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
 
-	drm_modeset_acquire_init(&ctx, 0);
-retry:
-	ret = drm_modeset_lock(&crtc->mutex, &ctx);
-	if (ret)
-		goto fail;
-	ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
-	if (ret)
-		goto fail;
-
 	/*
 	 * Obtain fb we'll be using (either new or existing) and take an extra
 	 * reference to it if fb != null.  setplane will take care of dropping
@@ -693,7 +684,7 @@ retry:
 	 */
 	ret = __setplane_internal(crtc->cursor, crtc, fb,
 				crtc_x, crtc_y, crtc_w, crtc_h,
-				0, 0, src_w, src_h, &ctx);
+				0, 0, src_w, src_h, ctx);
 
 	/* Update successful; save new cursor position, if necessary */
 	if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -701,15 +692,6 @@ retry:
 		crtc->cursor_y = req->y;
 	}
 
-fail:
-	if (ret == -EDEADLK) {
-		drm_modeset_backoff(&ctx);
-		goto retry;
-	}
-
-	drm_modeset_drop_locks(&ctx);
-	drm_modeset_acquire_fini(&ctx);
-
 	return ret;
 }
 
@@ -718,6 +700,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
 				  struct drm_file *file_priv)
 {
 	struct drm_crtc *crtc;
+	struct drm_modeset_acquire_ctx ctx;
 	int ret = 0;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -732,14 +715,24 @@ static int drm_mode_cursor_common(struct drm_device *dev,
 		return -ENOENT;
 	}
 
+	drm_modeset_acquire_init(&ctx, 0);
+retry:
+	ret = drm_modeset_lock(&crtc->mutex, &ctx);
+	if (ret)
+		goto out;
 	/*
 	 * If this crtc has a universal cursor plane, call that plane's update
 	 * handler rather than using legacy cursor handlers.
 	 */
-	if (crtc->cursor)
-		return drm_mode_cursor_universal(crtc, req, file_priv);
+	if (crtc->cursor) {
+		ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
+		if (ret)
+			goto out;
+
+		ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
+		goto out;
+	}
 
-	drm_modeset_lock_crtc(crtc, crtc->cursor);
 	if (req->flags & DRM_MODE_CURSOR_BO) {
 		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
 			ret = -ENXIO;
@@ -763,7 +756,13 @@ static int drm_mode_cursor_common(struct drm_device *dev,
 		}
 	}
 out:
-	drm_modeset_unlock_crtc(crtc);
+	if (ret == -EDEADLK) {
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
 
 	return ret;
 

+ 93 - 9
drivers/gpu/drm/drm_probe_helper.c

@@ -44,7 +44,7 @@
  *
  * This library provides some helper code for output probing. It provides an
  * implementation of the core &drm_connector_funcs.fill_modes interface with
- * drm_helper_probe_single_connector_modes.
+ * drm_helper_probe_single_connector_modes().
  *
  * It also provides support for polling connectors with a work item and for
  * generic hotplug interrupt handling where the driver doesn't or cannot keep
@@ -169,12 +169,73 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
 EXPORT_SYMBOL(drm_kms_helper_poll_enable);
 
 static enum drm_connector_status
-drm_connector_detect(struct drm_connector *connector, bool force)
+drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)
 {
-	return connector->funcs->detect ?
-		connector->funcs->detect(connector, force) :
-		connector_status_connected;
+	const struct drm_connector_helper_funcs *funcs = connector->helper_private;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret;
+
+	drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+	ret = drm_modeset_lock(&connector->dev->mode_config.connection_mutex, &ctx);
+	if (!ret) {
+		if (funcs->detect_ctx)
+			ret = funcs->detect_ctx(connector, &ctx, force);
+		else if (connector->funcs->detect)
+			ret = connector->funcs->detect(connector, force);
+		else
+			ret = connector_status_connected;
+	}
+
+	if (ret == -EDEADLK) {
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	}
+
+	if (WARN_ON(ret < 0))
+		ret = connector_status_unknown;
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return ret;
+}
+
+/**
+ * drm_helper_probe_detect - probe connector status
+ * @connector: connector to probe
+ * @ctx: acquire_ctx, or NULL to let this function handle locking.
+ * @force: Whether destructive probe operations should be performed.
+ *
+ * This function calls the detect callbacks of the connector.
+ * This function returns &drm_connector_status, or
+ * if @ctx is set, it might also return -EDEADLK.
+ */
+int
+drm_helper_probe_detect(struct drm_connector *connector,
+			struct drm_modeset_acquire_ctx *ctx,
+			bool force)
+{
+	const struct drm_connector_helper_funcs *funcs = connector->helper_private;
+	struct drm_device *dev = connector->dev;
+	int ret;
+
+	if (!ctx)
+		return drm_helper_probe_detect_ctx(connector, force);
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+	if (ret)
+		return ret;
+
+	if (funcs->detect_ctx)
+		return funcs->detect_ctx(connector, ctx, force);
+	else if (connector->funcs->detect)
+		return connector->funcs->detect(connector, force);
+	else
+		return connector_status_connected;
 }
+EXPORT_SYMBOL(drm_helper_probe_detect);
 
 /**
  * drm_helper_probe_single_connector_modes - get complete set of display modes
@@ -239,15 +300,27 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 	struct drm_display_mode *mode;
 	const struct drm_connector_helper_funcs *connector_funcs =
 		connector->helper_private;
-	int count = 0;
+	int count = 0, ret;
 	int mode_flags = 0;
 	bool verbose_prune = true;
 	enum drm_connector_status old_status;
+	struct drm_modeset_acquire_ctx ctx;
 
 	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
+	drm_modeset_acquire_init(&ctx, 0);
+
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
 			connector->name);
+
+retry:
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
+	if (ret == -EDEADLK) {
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	} else
+		WARN_ON(ret < 0);
+
 	/* set all old modes to the stale state */
 	list_for_each_entry(mode, &connector->modes, head)
 		mode->status = MODE_STALE;
@@ -263,7 +336,15 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 		if (connector->funcs->force)
 			connector->funcs->force(connector);
 	} else {
-		connector->status = drm_connector_detect(connector, true);
+		ret = drm_helper_probe_detect(connector, &ctx, true);
+
+		if (ret == -EDEADLK) {
+			drm_modeset_backoff(&ctx);
+			goto retry;
+		} else if (WARN(ret < 0, "Invalid return value %i for connector detection\n", ret))
+			ret = connector_status_unknown;
+
+		connector->status = ret;
 	}
 
 	/*
@@ -355,6 +436,9 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 prune:
 	drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
 
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
 	if (list_empty(&connector->modes))
 		return 0;
 
@@ -440,7 +524,7 @@ static void output_poll_execute(struct work_struct *work)
 
 		repoll = true;
 
-		connector->status = drm_connector_detect(connector, false);
+		connector->status = drm_helper_probe_detect(connector, NULL, false);
 		if (old_status != connector->status) {
 			const char *old, *new;
 
@@ -588,7 +672,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
 
 		old_status = connector->status;
 
-		connector->status = drm_connector_detect(connector, false);
+		connector->status = drm_helper_probe_detect(connector, NULL, false);
 		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
 			      connector->base.id,
 			      connector->name,

+ 29 - 43
drivers/gpu/drm/drm_property.c

@@ -442,8 +442,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
 	struct drm_property *property;
 	int enum_count = 0;
 	int value_count = 0;
-	int ret = 0, i;
-	int copied;
+	int i, copied;
 	struct drm_property_enum *prop_enum;
 	struct drm_mode_property_enum __user *enum_ptr;
 	uint64_t __user *values_ptr;
@@ -451,55 +450,43 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
-	drm_modeset_lock_all(dev);
 	property = drm_property_find(dev, out_resp->prop_id);
-	if (!property) {
-		ret = -ENOENT;
-		goto done;
-	}
-
-	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-		list_for_each_entry(prop_enum, &property->enum_list, head)
-			enum_count++;
-	}
-
-	value_count = property->num_values;
+	if (!property)
+		return -ENOENT;
 
 	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
 	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
 	out_resp->flags = property->flags;
 
-	if ((out_resp->count_values >= value_count) && value_count) {
-		values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
-		for (i = 0; i < value_count; i++) {
-			if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
-				ret = -EFAULT;
-				goto done;
-			}
+	value_count = property->num_values;
+	values_ptr = u64_to_user_ptr(out_resp->values_ptr);
+
+	for (i = 0; i < value_count; i++) {
+		if (i < out_resp->count_values &&
+		    put_user(property->values[i], values_ptr + i)) {
+			return -EFAULT;
 		}
 	}
 	out_resp->count_values = value_count;
 
+	copied = 0;
+	enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
+
 	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-		if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
-			copied = 0;
-			enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
-			list_for_each_entry(prop_enum, &property->enum_list, head) {
-
-				if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
-					ret = -EFAULT;
-					goto done;
-				}
-
-				if (copy_to_user(&enum_ptr[copied].name,
-						 &prop_enum->name, DRM_PROP_NAME_LEN)) {
-					ret = -EFAULT;
-					goto done;
-				}
-				copied++;
-			}
+	    drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
+		list_for_each_entry(prop_enum, &property->enum_list, head) {
+			enum_count++;
+			if (out_resp->count_enum_blobs <= enum_count)
+				continue;
+
+			if (copy_to_user(&enum_ptr[copied].value,
+					 &prop_enum->value, sizeof(uint64_t)))
+				return -EFAULT;
+
+			if (copy_to_user(&enum_ptr[copied].name,
+					 &prop_enum->name, DRM_PROP_NAME_LEN))
+				return -EFAULT;
+			copied++;
 		}
 		out_resp->count_enum_blobs = enum_count;
 	}
@@ -514,9 +501,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
 	 */
 	if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
 		out_resp->count_enum_blobs = 0;
-done:
-	drm_modeset_unlock_all(dev);
-	return ret;
+
+	return 0;
 }
 
 static void drm_property_free_blob(struct kref *kref)

+ 27 - 43
drivers/gpu/drm/drm_sysfs.c

@@ -25,6 +25,20 @@
 #define to_drm_minor(d) dev_get_drvdata(d)
 #define to_drm_connector(d) dev_get_drvdata(d)
 
+/**
+ * DOC: overview
+ *
+ * DRM provides very little additional support to drivers for sysfs
+ * interactions, beyond just all the standard stuff. Drivers who want to expose
+ * additional sysfs properties and property groups can attach them at either
+ * &drm_device.dev or &drm_connector.kdev.
+ *
+ * Registration is automatically handled when calling drm_dev_register(), or
+ * drm_connector_register() in case of hot-plugged connectors. Unregistration is
+ * also automatically handled by drm_dev_unregister() and
+ * drm_connector_unregister().
+ */
+
 static struct device_type drm_sysfs_device_minor = {
 	.name = "drm_minor"
 };
@@ -250,15 +264,6 @@ static const struct attribute_group *connector_dev_groups[] = {
 	NULL
 };
 
-/**
- * drm_sysfs_connector_add - add a connector to sysfs
- * @connector: connector to add
- *
- * Create a connector device in sysfs, along with its associated connector
- * properties (so far, connection status, dpms, mode list and edid) and
- * generate a hotplug event so userspace knows there's a new connector
- * available.
- */
 int drm_sysfs_connector_add(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -285,19 +290,6 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
 	return 0;
 }
 
-/**
- * drm_sysfs_connector_remove - remove an connector device from sysfs
- * @connector: connector to remove
- *
- * Remove @connector and its associated attributes from sysfs.  Note that
- * the device model core will take care of sending the "remove" uevent
- * at this time, so we don't need to do it.
- *
- * Note:
- * This routine should only be called if the connector was previously
- * successfully registered.  If @connector hasn't been registered yet,
- * you'll likely see a panic somewhere deep in sysfs code when called.
- */
 void drm_sysfs_connector_remove(struct drm_connector *connector)
 {
 	if (!connector->kdev)
@@ -333,20 +325,6 @@ static void drm_sysfs_release(struct device *dev)
 	kfree(dev);
 }
 
-/**
- * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
- * @minor: minor to allocate sysfs device for
- *
- * This allocates a new sysfs device for @minor and returns it. The device is
- * not registered nor linked. The caller has to use device_add() and
- * device_del() to register and unregister it.
- *
- * Note that dev_get_drvdata() on the new device will return the minor.
- * However, the device does not hold a ref-count to the minor nor to the
- * underlying drm_device. This is unproblematic as long as you access the
- * private data only in sysfs callbacks. device_del() disables those
- * synchronously, so they cannot be called after you cleanup a minor.
- */
 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
 {
 	const char *minor_str;
@@ -384,15 +362,13 @@ err_free:
 }
 
 /**
- * drm_class_device_register - Register a struct device in the drm class.
+ * drm_class_device_register - register new device with the DRM sysfs class
+ * @dev: device to register
  *
- * @dev: pointer to struct device to register.
- *
- * @dev should have all relevant members pre-filled with the exception
- * of the class member. In particular, the device_type member must
- * be set.
+ * Registers a new &struct device within the DRM sysfs class. Essentially only
+ * used by ttm to have a place for its global settings. Drivers should never use
+ * this.
  */
-
 int drm_class_device_register(struct device *dev)
 {
 	if (!drm_class || IS_ERR(drm_class))
@@ -403,6 +379,14 @@ int drm_class_device_register(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(drm_class_device_register);
 
+/**
+ * drm_class_device_unregister - unregister device with the DRM sysfs class
+ * @dev: device to unregister
+ *
+ * Unregisters a &struct device from the DRM sysfs class. Essentially only used
+ * by ttm to have a place for its global settings. Drivers should never use
+ * this.
+ */
 void drm_class_device_unregister(struct device *dev)
 {
 	return device_unregister(dev);

+ 12 - 23
drivers/gpu/drm/exynos/exynos_dp.c

@@ -23,6 +23,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include <drm/bridge/analogix_dp.h>
@@ -211,8 +212,11 @@ static const struct component_ops exynos_dp_ops = {
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = NULL, *endpoint = NULL;
+	struct device_node *np;
 	struct exynos_dp_device *dp;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	int ret;
 
 	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
 			  GFP_KERNEL);
@@ -236,28 +240,13 @@ static int exynos_dp_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		np = of_graph_get_remote_port_parent(endpoint);
-		if (np) {
-			/* The remote port can be either a panel or a bridge */
-			dp->plat_data.panel = of_drm_find_panel(np);
-			if (!dp->plat_data.panel) {
-				dp->ptn_bridge = of_drm_find_bridge(np);
-				if (!dp->ptn_bridge) {
-					of_node_put(np);
-					return -EPROBE_DEFER;
-				}
-			}
-			of_node_put(np);
-		} else {
-			DRM_ERROR("no remote endpoint device node found.\n");
-			return -EINVAL;
-		}
-	} else {
-		DRM_ERROR("no port endpoint subnode found.\n");
-		return -EINVAL;
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge);
+	if (ret)
+		return ret;
+
+	/* The remote port can be either a panel or a bridge */
+	dp->plat_data.panel = panel;
+	dp->ptn_bridge = bridge;
 
 out:
 	return component_add(&pdev->dev, &exynos_dp_ops);

+ 1 - 15
drivers/gpu/drm/exynos/exynos_drm_dpi.c

@@ -163,27 +163,13 @@ enum {
 	FIMD_PORT_WRB,
 };
 
-static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev)
-{
-	struct device_node *np, *ep;
-
-	ep = of_graph_get_endpoint_by_regs(dev->of_node, FIMD_PORT_RGB, 0);
-	if (!ep)
-		return NULL;
-
-	np = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-
-	return np;
-}
-
 static int exynos_dpi_parse_dt(struct exynos_dpi *ctx)
 {
 	struct device *dev = ctx->dev;
 	struct device_node *dn = dev->of_node;
 	struct device_node *np;
 
-	ctx->panel_node = exynos_dpi_of_find_panel_node(dev);
+	ctx->panel_node = of_graph_get_remote_node(dn, FIMD_PORT_RGB, 0);
 
 	np = of_get_child_by_name(dn, "display-timings");
 	if (np) {

+ 3 - 10
drivers/gpu/drm/exynos/exynos_drm_dsi.c

@@ -1659,17 +1659,10 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
 
 	of_node_put(ep);
 
-	ep = of_graph_get_next_endpoint(node, NULL);
-	if (!ep) {
-		ret = -EINVAL;
-		goto end;
-	}
+	dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0);
+	if (!dsi->bridge_node)
+		return -EINVAL;
 
-	dsi->bridge_node = of_graph_get_remote_port_parent(ep);
-	if (!dsi->bridge_node) {
-		ret = -EINVAL;
-		goto end;
-	}
 end:
 	of_node_put(ep);
 

+ 1 - 24
drivers/gpu/drm/exynos/exynos_drm_mic.c

@@ -229,29 +229,6 @@ static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
 	writel(reg, mic->reg + MIC_OP);
 }
 
-static struct device_node *get_remote_node(struct device_node *from, int reg)
-{
-	struct device_node *endpoint = NULL, *remote_node = NULL;
-
-	endpoint = of_graph_get_endpoint_by_regs(from, reg, -1);
-	if (!endpoint) {
-		DRM_ERROR("mic: Failed to find remote port from %s",
-				from->full_name);
-		goto exit;
-	}
-
-	remote_node = of_graph_get_remote_port_parent(endpoint);
-	if (!remote_node) {
-		DRM_ERROR("mic: Failed to find remote port parent from %s",
-							from->full_name);
-		goto exit;
-	}
-
-exit:
-	of_node_put(endpoint);
-	return remote_node;
-}
-
 static int parse_dt(struct exynos_mic *mic)
 {
 	int ret = 0, i, j;
@@ -263,7 +240,7 @@ static int parse_dt(struct exynos_mic *mic)
 	 * The first node must be for decon and the second one must be for dsi.
 	 */
 	for (i = 0, j = 0; i < NUM_ENDPOINTS; i++) {
-		remote_node = get_remote_node(mic->dev->of_node, i);
+		remote_node = of_graph_get_remote_node(mic->dev->of_node, i, 0);
 		if (!remote_node) {
 			ret = -EPIPE;
 			goto exit;

+ 12 - 32
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c

@@ -15,6 +15,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "fsl_dcu_drm_drv.h"
@@ -141,32 +142,11 @@ err_cleanup:
 	return ret;
 }
 
-static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
-				   const struct of_endpoint *ep)
-{
-	struct drm_bridge *bridge;
-	struct device_node *np;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	fsl_dev->connector.panel = of_drm_find_panel(np);
-	if (fsl_dev->connector.panel) {
-		of_node_put(np);
-		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
-	}
-
-	bridge = of_drm_find_bridge(np);
-	of_node_put(np);
-	if (!bridge)
-		return -ENODEV;
-
-	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
-}
-
 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 {
-	struct of_endpoint ep;
-	struct device_node *ep_node, *panel_node;
+	struct device_node *panel_node;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
 	int ret;
 
 	/* This is for backward compatibility */
@@ -179,14 +159,14 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
 	}
 
-	ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
-	if (!ep_node)
-		return -ENODEV;
-
-	ret = of_graph_parse_endpoint(ep_node, &ep);
-	of_node_put(ep_node);
+	ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);
 	if (ret)
-		return -ENODEV;
+		return ret;
+
+	if (panel) {
+		fsl_dev->connector.panel = panel;
+		return fsl_dcu_attach_panel(fsl_dev, panel);
+	}
 
-	return fsl_dcu_attach_endpoint(fsl_dev, &ep);
+	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
 }

+ 2 - 1
drivers/gpu/drm/gma500/gma_display.c

@@ -177,7 +177,8 @@ void gma_crtc_load_lut(struct drm_crtc *crtc)
 }
 
 int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue,
-		       u32 size)
+		       u32 size,
+		       struct drm_modeset_acquire_ctx *ctx)
 {
 	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
 	int i;

+ 2 - 1
drivers/gpu/drm/gma500/gma_display.h

@@ -73,7 +73,8 @@ extern int gma_crtc_cursor_set(struct drm_crtc *crtc,
 extern int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 extern void gma_crtc_load_lut(struct drm_crtc *crtc);
 extern int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-			      u16 *blue, u32 size);
+			      u16 *blue, u32 size,
+			      struct drm_modeset_acquire_ctx *ctx);
 extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode);
 extern void gma_crtc_prepare(struct drm_crtc *crtc);
 extern void gma_crtc_commit(struct drm_crtc *crtc);

+ 4 - 23
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c

@@ -17,7 +17,6 @@
 
 #include <linux/clk.h>
 #include <linux/component.h>
-#include <linux/of_graph.h>
 
 #include <drm/drm_of.h>
 #include <drm/drm_crtc_helper.h>
@@ -754,34 +753,16 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
 {
 	struct dsi_hw_ctx *ctx = dsi->ctx;
 	struct device_node *np = pdev->dev.of_node;
-	struct device_node *endpoint, *bridge_node;
-	struct drm_bridge *bridge;
 	struct resource *res;
+	int ret;
 
 	/*
 	 * Get the endpoint node. In our case, dsi has one output port1
 	 * to which the external HDMI bridge is connected.
 	 */
-	endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
-	if (!endpoint) {
-		DRM_ERROR("no valid endpoint node\n");
-		return -ENODEV;
-	}
-	of_node_put(endpoint);
-
-	bridge_node = of_graph_get_remote_port_parent(endpoint);
-	if (!bridge_node) {
-		DRM_ERROR("no valid bridge node\n");
-		return -ENODEV;
-	}
-	of_node_put(bridge_node);
-
-	bridge = of_drm_find_bridge(bridge_node);
-	if (!bridge) {
-		DRM_INFO("wait for external HDMI bridge driver.\n");
-		return -EPROBE_DEFER;
-	}
-	dsi->bridge = bridge;
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
+	if (ret)
+		return ret;
 
 	ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(ctx->pclk)) {

+ 1 - 29
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c

@@ -230,34 +230,6 @@ static const struct component_master_ops kirin_drm_ops = {
 	.unbind = kirin_drm_unbind,
 };
 
-static struct device_node *kirin_get_remote_node(struct device_node *np)
-{
-	struct device_node *endpoint, *remote;
-
-	/* get the first endpoint, in our case only one remote node
-	 * is connected to display controller.
-	 */
-	endpoint = of_graph_get_next_endpoint(np, NULL);
-	if (!endpoint) {
-		DRM_ERROR("no valid endpoint node\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(endpoint);
-	of_node_put(endpoint);
-	if (!remote) {
-		DRM_ERROR("no valid remote node\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (!of_device_is_available(remote)) {
-		DRM_ERROR("not available for remote node\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	return remote;
-}
-
 static int kirin_drm_platform_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -271,7 +243,7 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	remote = kirin_get_remote_node(np);
+	remote = of_graph_get_remote_node(np, 0, 0);
 	if (IS_ERR(remote))
 		return PTR_ERR(remote);
 

+ 12 - 13
drivers/gpu/drm/i915/intel_crt.c

@@ -669,15 +669,16 @@ static const struct dmi_system_id intel_spurious_crt_detect[] = {
 	{ }
 };
 
-static enum drm_connector_status
-intel_crt_detect(struct drm_connector *connector, bool force)
+static int
+intel_crt_detect(struct drm_connector *connector,
+		 struct drm_modeset_acquire_ctx *ctx,
+		 bool force)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_crt *crt = intel_attached_crt(connector);
 	struct intel_encoder *intel_encoder = &crt->base;
-	enum drm_connector_status status;
+	int status, ret;
 	struct intel_load_detect_pipe tmp;
-	struct drm_modeset_acquire_ctx ctx;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
 		      connector->base.id, connector->name,
@@ -721,10 +722,9 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 		goto out;
 	}
 
-	drm_modeset_acquire_init(&ctx, 0);
-
 	/* for pre-945g platforms use load detect */
-	if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
+	ret = intel_get_load_detect_pipe(connector, NULL, &tmp, ctx);
+	if (ret > 0) {
 		if (intel_crt_detect_ddc(connector))
 			status = connector_status_connected;
 		else if (INTEL_GEN(dev_priv) < 4)
@@ -734,12 +734,11 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 			status = connector_status_disconnected;
 		else
 			status = connector_status_unknown;
-		intel_release_load_detect_pipe(connector, &tmp, &ctx);
-	} else
+		intel_release_load_detect_pipe(connector, &tmp, ctx);
+	} else if (ret == 0)
 		status = connector_status_unknown;
-
-	drm_modeset_drop_locks(&ctx);
-	drm_modeset_acquire_fini(&ctx);
+	else if (ret < 0)
+		status = ret;
 
 out:
 	intel_display_power_put(dev_priv, intel_encoder->power_domain);
@@ -811,7 +810,6 @@ void intel_crt_reset(struct drm_encoder *encoder)
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
-	.detect = intel_crt_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.late_register = intel_connector_register,
 	.early_unregister = intel_connector_unregister,
@@ -823,6 +821,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
 };
 
 static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
+	.detect_ctx = intel_crt_detect,
 	.mode_valid = intel_crt_mode_valid,
 	.get_modes = intel_crt_get_modes,
 };

+ 15 - 70
drivers/gpu/drm/i915/intel_display.c

@@ -3412,17 +3412,6 @@ static void skylake_disable_primary_plane(struct drm_plane *primary,
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-/* Assume fb object is pinned & idle & fenced and just update base pointers */
-static int
-intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-			   int x, int y, enum mode_set_atomic state)
-{
-	/* Support for kgdboc is disabled, this needs a major rework. */
-	DRM_ERROR("legacy panic handler not supported any more.\n");
-
-	return -ENODEV;
-}
-
 static void intel_complete_page_flips(struct drm_i915_private *dev_priv)
 {
 	struct intel_crtc *crtc;
@@ -9503,10 +9492,10 @@ static int intel_modeset_setup_plane_state(struct drm_atomic_state *state,
 	return 0;
 }
 
-bool intel_get_load_detect_pipe(struct drm_connector *connector,
-				struct drm_display_mode *mode,
-				struct intel_load_detect_pipe *old,
-				struct drm_modeset_acquire_ctx *ctx)
+int intel_get_load_detect_pipe(struct drm_connector *connector,
+			       struct drm_display_mode *mode,
+			       struct intel_load_detect_pipe *old,
+			       struct drm_modeset_acquire_ctx *ctx)
 {
 	struct intel_crtc *intel_crtc;
 	struct intel_encoder *intel_encoder =
@@ -9529,10 +9518,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 
 	old->restore_state = NULL;
 
-retry:
-	ret = drm_modeset_lock(&config->connection_mutex, ctx);
-	if (ret)
-		goto fail;
+	WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
 
 	/*
 	 * Algorithm gets a little messy:
@@ -9682,10 +9668,8 @@ fail:
 		restore_state = NULL;
 	}
 
-	if (ret == -EDEADLK) {
-		drm_modeset_backoff(ctx);
-		goto retry;
-	}
+	if (ret == -EDEADLK)
+		return ret;
 
 	return false;
 }
@@ -10727,7 +10711,7 @@ out_hang:
 		state = drm_atomic_state_alloc(dev);
 		if (!state)
 			return -ENOMEM;
-		state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+		state->acquire_ctx = dev->mode_config.acquire_ctx;
 
 retry:
 		plane_state = drm_atomic_get_plane_state(state, primary);
@@ -11017,7 +11001,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
 }
 
 static const struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.mode_set_base_atomic = intel_pipe_set_base_atomic,
 	.atomic_begin = intel_begin_crtc_commit,
 	.atomic_flush = intel_finish_crtc_commit,
 	.atomic_check = intel_crtc_atomic_check,
@@ -13090,7 +13073,7 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
 		return;
 	}
 
-	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
 
 retry:
 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
@@ -13113,50 +13096,8 @@ out:
 	drm_atomic_state_put(state);
 }
 
-/*
- * FIXME: Remove this once i915 is fully DRIVER_ATOMIC by calling
- *        drm_atomic_helper_legacy_gamma_set() directly.
- */
-static int intel_atomic_legacy_gamma_set(struct drm_crtc *crtc,
-					 u16 *red, u16 *green, u16 *blue,
-					 uint32_t size)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-	struct drm_crtc_state *state;
-	int ret;
-
-	ret = drm_atomic_helper_legacy_gamma_set(crtc, red, green, blue, size);
-	if (ret)
-		return ret;
-
-	/*
-	 * Make sure we update the legacy properties so this works when
-	 * atomic is not enabled.
-	 */
-
-	state = crtc->state;
-
-	drm_object_property_set_value(&crtc->base,
-				      config->degamma_lut_property,
-				      (state->degamma_lut) ?
-				      state->degamma_lut->base.id : 0);
-
-	drm_object_property_set_value(&crtc->base,
-				      config->ctm_property,
-				      (state->ctm) ?
-				      state->ctm->base.id : 0);
-
-	drm_object_property_set_value(&crtc->base,
-				      config->gamma_lut_property,
-				      (state->gamma_lut) ?
-				      state->gamma_lut->base.id : 0);
-
-	return 0;
-}
-
 static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.gamma_set = intel_atomic_legacy_gamma_set,
+	.gamma_set = drm_atomic_helper_legacy_gamma_set,
 	.set_config = drm_atomic_helper_set_config,
 	.set_property = drm_atomic_helper_crtc_set_property,
 	.destroy = intel_crtc_destroy,
@@ -15107,6 +15048,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
 	struct drm_connector *crt = NULL;
 	struct intel_load_detect_pipe load_detect_temp;
 	struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
+	int ret;
 
 	/* We can't just switch on the pipe A, we need to set things up with a
 	 * proper mode and output configuration. As a gross hack, enable pipe A
@@ -15123,7 +15065,10 @@ static void intel_enable_pipe_a(struct drm_device *dev)
 	if (!crt)
 		return;
 
-	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
+	ret = intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx);
+	WARN(ret < 0, "All modeset mutexes are locked, but intel_get_load_detect_pipe failed\n");
+
+	if (ret > 0)
 		intel_release_load_detect_pipe(crt, &load_detect_temp, ctx);
 }
 

+ 9 - 12
drivers/gpu/drm/i915/intel_dp.c

@@ -4566,7 +4566,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->has_audio = false;
 }
 
-static enum drm_connector_status
+static int
 intel_dp_long_pulse(struct intel_connector *intel_connector)
 {
 	struct drm_connector *connector = &intel_connector->base;
@@ -4577,6 +4577,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	enum drm_connector_status status;
 	u8 sink_irq_vector = 0;
 
+	WARN_ON(!drm_modeset_is_locked(&connector->dev->mode_config.connection_mutex));
+
 	intel_display_power_get(to_i915(dev), intel_dp->aux_power_domain);
 
 	/* Can't disconnect eDP, but you can close the lid... */
@@ -4635,14 +4637,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 		status = connector_status_disconnected;
 		goto out;
 	} else if (connector->status == connector_status_connected) {
-		/*
-		 * If display was connected already and is still connected
-		 * check links status, there has been known issues of
-		 * link loss triggerring long pulse!!!!
-		 */
-		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 		intel_dp_check_link_status(intel_dp);
-		drm_modeset_unlock(&dev->mode_config.connection_mutex);
 		goto out;
 	}
 
@@ -4682,11 +4677,13 @@ out:
 	return status;
 }
 
-static enum drm_connector_status
-intel_dp_detect(struct drm_connector *connector, bool force)
+static int
+intel_dp_detect(struct drm_connector *connector,
+		struct drm_modeset_acquire_ctx *ctx,
+		bool force)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	enum drm_connector_status status = connector->status;
+	int status = connector->status;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
@@ -5014,7 +5011,6 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
-	.detect = intel_dp_detect,
 	.force = intel_dp_force,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dp_set_property,
@@ -5027,6 +5023,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
 };
 
 static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
+	.detect_ctx = intel_dp_detect,
 	.get_modes = intel_dp_get_modes,
 	.mode_valid = intel_dp_mode_valid,
 };

+ 4 - 4
drivers/gpu/drm/i915/intel_drv.h

@@ -1358,10 +1358,10 @@ int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
 void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
 			 struct intel_digital_port *dport,
 			 unsigned int expected_mask);
-bool intel_get_load_detect_pipe(struct drm_connector *connector,
-				struct drm_display_mode *mode,
-				struct intel_load_detect_pipe *old,
-				struct drm_modeset_acquire_ctx *ctx);
+int intel_get_load_detect_pipe(struct drm_connector *connector,
+			       struct drm_display_mode *mode,
+			       struct intel_load_detect_pipe *old,
+			       struct drm_modeset_acquire_ctx *ctx);
 void intel_release_load_detect_pipe(struct drm_connector *connector,
 				    struct intel_load_detect_pipe *old,
 				    struct drm_modeset_acquire_ctx *ctx);

+ 2 - 1
drivers/gpu/drm/i915/intel_hotplug.c

@@ -243,7 +243,8 @@ static bool intel_hpd_irq_event(struct drm_device *dev,
 	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 	old_status = connector->status;
 
-	connector->status = connector->funcs->detect(connector, false);
+	connector->status = drm_helper_probe_detect(connector, NULL, false);
+
 	if (old_status == connector->status)
 		return false;
 

+ 1 - 1
drivers/gpu/drm/i915/intel_pipe_crc.c

@@ -522,7 +522,7 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv,
 		goto unlock;
 	}
 
-	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(&crtc->base);
+	state->acquire_ctx = crtc->base.dev->mode_config.acquire_ctx;
 	pipe_config = intel_atomic_get_crtc_state(state, crtc);
 	if (IS_ERR(pipe_config)) {
 		ret = PTR_ERR(pipe_config);

+ 11 - 10
drivers/gpu/drm/i915/intel_tv.c

@@ -1315,8 +1315,10 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
  * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
  * we have a pipe programmed in order to probe the TV.
  */
-static enum drm_connector_status
-intel_tv_detect(struct drm_connector *connector, bool force)
+static int
+intel_tv_detect(struct drm_connector *connector,
+		struct drm_modeset_acquire_ctx *ctx,
+		bool force)
 {
 	struct drm_display_mode mode;
 	struct intel_tv *intel_tv = intel_attached_tv(connector);
@@ -1331,21 +1333,20 @@ intel_tv_detect(struct drm_connector *connector, bool force)
 
 	if (force) {
 		struct intel_load_detect_pipe tmp;
-		struct drm_modeset_acquire_ctx ctx;
+		int ret;
 
-		drm_modeset_acquire_init(&ctx, 0);
+		ret = intel_get_load_detect_pipe(connector, &mode, &tmp, ctx);
+		if (ret < 0)
+			return ret;
 
-		if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
+		if (ret > 0) {
 			type = intel_tv_detect_type(intel_tv, connector);
-			intel_release_load_detect_pipe(connector, &tmp, &ctx);
+			intel_release_load_detect_pipe(connector, &tmp, ctx);
 			status = type < 0 ?
 				connector_status_disconnected :
 				connector_status_connected;
 		} else
 			status = connector_status_unknown;
-
-		drm_modeset_drop_locks(&ctx);
-		drm_modeset_acquire_fini(&ctx);
 	} else
 		return connector->status;
 
@@ -1516,7 +1517,6 @@ out:
 
 static const struct drm_connector_funcs intel_tv_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
-	.detect = intel_tv_detect,
 	.late_register = intel_connector_register,
 	.early_unregister = intel_connector_unregister,
 	.destroy = intel_tv_destroy,
@@ -1528,6 +1528,7 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = {
 };
 
 static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
+	.detect_ctx = intel_tv_detect,
 	.mode_valid = intel_tv_mode_valid,
 	.get_modes = intel_tv_get_modes,
 };

+ 5 - 22
drivers/gpu/drm/imx/imx-ldb.c

@@ -647,7 +647,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 
 	for_each_child_of_node(np, child) {
 		struct imx_ldb_channel *channel;
-		struct device_node *ep;
 		int bus_format;
 
 		ret = of_property_read_u32(child, "reg", &i);
@@ -671,27 +670,11 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 		 * The output port is port@4 with an external 4-port mux or
 		 * port@2 with the internal 2-port mux.
 		 */
-		ep = of_graph_get_endpoint_by_regs(child,
-						   imx_ldb->lvds_mux ? 4 : 2,
-						   -1);
-		if (ep) {
-			struct device_node *remote;
-
-			remote = of_graph_get_remote_port_parent(ep);
-			of_node_put(ep);
-			if (remote) {
-				channel->panel = of_drm_find_panel(remote);
-				channel->bridge = of_drm_find_bridge(remote);
-			} else
-				return -EPROBE_DEFER;
-			of_node_put(remote);
-
-			if (!channel->panel && !channel->bridge) {
-				dev_err(dev, "panel/bridge not found: %s\n",
-					remote->full_name);
-				return -EPROBE_DEFER;
-			}
-		}
+		ret = drm_of_find_panel_or_bridge(child,
+						  imx_ldb->lvds_mux ? 4 : 2, 0,
+						  &channel->panel, &channel->bridge);
+		if (ret)
+			return ret;
 
 		/* panel ddc only if there is no bridge */
 		if (!channel->bridge) {

+ 4 - 32
drivers/gpu/drm/imx/parallel-display.c

@@ -19,10 +19,10 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <linux/videodev2.h>
 #include <video/of_display_timing.h>
-#include <linux/of_graph.h>
 
 #include "imx-drm.h"
 
@@ -208,7 +208,6 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
-	struct device_node *ep;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
@@ -237,36 +236,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 	imxpd->bus_format = bus_format;
 
 	/* port@1 is the output port */
-	ep = of_graph_get_endpoint_by_regs(np, 1, -1);
-	if (ep) {
-		struct device_node *remote;
-
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote) {
-			dev_warn(dev, "endpoint %s not connected\n",
-				 ep->full_name);
-			of_node_put(ep);
-			return -ENODEV;
-		}
-		of_node_put(ep);
-
-		imxpd->panel = of_drm_find_panel(remote);
-		if (imxpd->panel) {
-			dev_dbg(dev, "found panel %s\n", remote->full_name);
-		} else {
-			imxpd->bridge = of_drm_find_bridge(remote);
-			if (imxpd->bridge)
-				dev_dbg(dev, "found bridge %s\n",
-					remote->full_name);
-		}
-		if (!imxpd->panel && !imxpd->bridge) {
-			dev_dbg(dev, "waiting for panel or bridge %s\n",
-				remote->full_name);
-			of_node_put(remote);
-			return -EPROBE_DEFER;
-		}
-		of_node_put(remote);
-	}
+	ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, &imxpd->bridge);
+	if (ret)
+		return ret;
 
 	imxpd->dev = dev;
 

+ 3 - 9
drivers/gpu/drm/mediatek/mtk_dpi.c

@@ -661,7 +661,7 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct mtk_dpi *dpi;
 	struct resource *mem;
-	struct device_node *ep, *bridge_node = NULL;
+	struct device_node *bridge_node;
 	int comp_id;
 	int ret;
 
@@ -706,15 +706,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (ep) {
-		bridge_node = of_graph_get_remote_port_parent(ep);
-		of_node_put(ep);
-	}
-	if (!bridge_node) {
-		dev_err(dev, "Failed to find bridge node\n");
+	bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0);
+	if (!bridge_node)
 		return -ENODEV;
-	}
 
 	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
 

+ 5 - 18
drivers/gpu/drm/mediatek/mtk_dsi.c

@@ -16,12 +16,12 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_of.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/of_graph.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <video/mipi_display.h>
@@ -1097,7 +1097,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct device_node *remote_node, *endpoint;
 	struct resource *regs;
 	int irq_num;
 	int comp_id;
@@ -1110,22 +1109,10 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->host.ops = &mtk_dsi_ops;
 	dsi->host.dev = dev;
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		remote_node = of_graph_get_remote_port_parent(endpoint);
-		if (!remote_node) {
-			dev_err(dev, "No panel connected\n");
-			return -ENODEV;
-		}
-
-		dsi->bridge = of_drm_find_bridge(remote_node);
-		dsi->panel = of_drm_find_panel(remote_node);
-		of_node_put(remote_node);
-		if (!dsi->bridge && !dsi->panel) {
-			dev_info(dev, "Waiting for bridge or panel driver\n");
-			return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+					  &dsi->panel, &dsi->bridge);
+	if (ret)
+		return ret;
 
 	dsi->engine_clk = devm_clk_get(dev, "engine");
 	if (IS_ERR(dsi->engine_clk)) {

+ 3 - 23
drivers/gpu/drm/mediatek/mtk_hdmi.c

@@ -1434,7 +1434,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *cec_np, *port, *ep, *remote, *i2c_np;
+	struct device_node *cec_np, *remote, *i2c_np;
 	struct platform_device *cec_pdev;
 	struct regmap *regmap;
 	struct resource *mem;
@@ -1486,29 +1486,9 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 	if (IS_ERR(hdmi->regs))
 		return PTR_ERR(hdmi->regs);
 
-	port = of_graph_get_port_by_id(np, 1);
-	if (!port) {
-		dev_err(dev, "Missing output port node\n");
+	remote = of_graph_get_remote_node(np, 1, 0);
+	if (!remote)
 		return -EINVAL;
-	}
-
-	ep = of_get_child_by_name(port, "endpoint");
-	if (!ep) {
-		dev_err(dev, "Missing endpoint node in port %s\n",
-			port->full_name);
-		of_node_put(port);
-		return -EINVAL;
-	}
-	of_node_put(port);
-
-	remote = of_graph_get_remote_port_parent(ep);
-	if (!remote) {
-		dev_err(dev, "Missing connector/bridge node for endpoint %s\n",
-			ep->full_name);
-		of_node_put(ep);
-		return -EINVAL;
-	}
-	of_node_put(ep);
 
 	if (!of_device_is_compatible(remote, "hdmi-connector")) {
 		hdmi->next_bridge = of_drm_find_bridge(remote);

+ 6 - 0
drivers/gpu/drm/meson/Kconfig

@@ -7,3 +7,9 @@ config DRM_MESON
 	select DRM_GEM_CMA_HELPER
 	select VIDEOMODE_HELPERS
 	select REGMAP_MMIO
+
+config DRM_MESON_DW_HDMI
+	tristate "HDMI Synopsys Controller support for Amlogic Meson Display"
+	depends on DRM_MESON
+	default y if DRM_MESON
+	select DRM_DW_HDMI

+ 1 - 0
drivers/gpu/drm/meson/Makefile

@@ -2,3 +2,4 @@ meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
 meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
 
 obj-$(CONFIG_DRM_MESON) += meson-drm.o
+obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o

+ 3 - 1
drivers/gpu/drm/meson/meson_canvas.c

@@ -24,7 +24,9 @@
 #include "meson_canvas.h"
 #include "meson_registers.h"
 
-/*
+/**
+ * DOC: Canvas
+ *
  * CANVAS is a memory zone where physical memory frames information
  * are stored for the VIU to scanout.
  */

+ 11 - 4
drivers/gpu/drm/meson/meson_crtc.c

@@ -82,11 +82,18 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
 static void meson_crtc_enable(struct drm_crtc *crtc)
 {
 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
-	struct drm_plane *plane = meson_crtc->priv->primary_plane;
+	struct drm_crtc_state *crtc_state = crtc->state;
 	struct meson_drm *priv = meson_crtc->priv;
 
+	DRM_DEBUG_DRIVER("\n");
+
+	if (!crtc_state) {
+		DRM_ERROR("Invalid crtc_state\n");
+		return;
+	}
+
 	/* Enable VPP Postblend */
-	writel(plane->state->crtc_w,
+	writel(crtc_state->mode.hdisplay,
 	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
 
 	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
@@ -101,6 +108,7 @@ static void meson_crtc_disable(struct drm_crtc *crtc)
 	struct meson_drm *priv = meson_crtc->priv;
 
 	priv->viu.osd1_enabled = false;
+	priv->viu.osd1_commit = false;
 
 	/* Disable VPP Postblend */
 	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
@@ -137,8 +145,7 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 	struct meson_drm *priv = meson_crtc->priv;
 
-	if (priv->viu.osd1_enabled)
-		priv->viu.osd1_commit = true;
+	priv->viu.osd1_commit = true;
 }
 
 static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {

+ 102 - 16
drivers/gpu/drm/meson/meson_drv.c

@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/component.h>
 #include <linux/of_graph.h>
 
 #include <drm/drmP.h>
@@ -51,13 +52,14 @@
 #define DRIVER_NAME "meson"
 #define DRIVER_DESC "Amlogic Meson DRM driver"
 
-/*
- * Video Processing Unit
+/**
+ * DOC: Video Processing Unit
  *
  * VPU Handles the Global Video Processing, it includes management of the
  * clocks gates, blocks reset lines and power domains.
  *
  * What is missing :
+ *
  * - Full reset of entire video processing HW blocks
  * - Scaling and setup of the VPU clock
  * - Bus clock gates
@@ -150,9 +152,9 @@ static struct regmap_config meson_regmap_config = {
 	.max_register   = 0x1000,
 };
 
-static int meson_drv_probe(struct platform_device *pdev)
+static int meson_drv_bind(struct device *dev)
 {
-	struct device *dev = &pdev->dev;
+	struct platform_device *pdev = to_platform_device(dev);
 	struct meson_drm *priv;
 	struct drm_device *drm;
 	struct resource *res;
@@ -215,6 +217,15 @@ static int meson_drv_probe(struct platform_device *pdev)
 
 	drm_vblank_init(drm, 1);
 	drm_mode_config_init(drm);
+	drm->mode_config.max_width = 3840;
+	drm->mode_config.max_height = 2160;
+	drm->mode_config.funcs = &meson_mode_config_funcs;
+
+	/* Hardware Initialization */
+
+	meson_venc_init(priv);
+	meson_vpp_init(priv);
+	meson_viu_init(priv);
 
 	/* Encoder Initialization */
 
@@ -222,11 +233,11 @@ static int meson_drv_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_drm;
 
-	/* Hardware Initialization */
-
-	meson_venc_init(priv);
-	meson_vpp_init(priv);
-	meson_viu_init(priv);
+	ret = component_bind_all(drm->dev, drm);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't bind all components\n");
+		goto free_drm;
+	}
 
 	ret = meson_plane_create(priv);
 	if (ret)
@@ -241,9 +252,6 @@ static int meson_drv_probe(struct platform_device *pdev)
 		goto free_drm;
 
 	drm_mode_config_reset(drm);
-	drm->mode_config.max_width = 8192;
-	drm->mode_config.max_height = 8192;
-	drm->mode_config.funcs = &meson_mode_config_funcs;
 
 	priv->fbdev = drm_fbdev_cma_init(drm, 32,
 					 drm->mode_config.num_connector);
@@ -268,9 +276,9 @@ free_drm:
 	return ret;
 }
 
-static int meson_drv_remove(struct platform_device *pdev)
+static void meson_drv_unbind(struct device *dev)
 {
-	struct drm_device *drm = dev_get_drvdata(&pdev->dev);
+	struct drm_device *drm = dev_get_drvdata(dev);
 	struct meson_drm *priv = drm->dev_private;
 
 	drm_dev_unregister(drm);
@@ -280,9 +288,88 @@ static int meson_drv_remove(struct platform_device *pdev)
 	drm_vblank_cleanup(drm);
 	drm_dev_unref(drm);
 
-	return 0;
 }
 
+static const struct component_master_ops meson_drv_master_ops = {
+	.bind	= meson_drv_bind,
+	.unbind	= meson_drv_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	DRM_DEBUG_DRIVER("Comparing of node %s with %s\n",
+			 of_node_full_name(dev->of_node),
+			 of_node_full_name(data));
+
+	return dev->of_node == data;
+}
+
+/* Possible connectors nodes to ignore */
+static const struct of_device_id connectors_match[] = {
+	{ .compatible = "composite-video-connector" },
+	{ .compatible = "svideo-connector" },
+	{ .compatible = "hdmi-connector" },
+	{ .compatible = "dvi-connector" },
+	{}
+};
+
+static int meson_probe_remote(struct platform_device *pdev,
+			      struct component_match **match,
+			      struct device_node *parent,
+			      struct device_node *remote)
+{
+	struct device_node *ep, *remote_node;
+	int count = 1;
+
+	/* If node is a connector, return and do not add to match table */
+	if (of_match_node(connectors_match, remote))
+		return 1;
+
+	component_match_add(&pdev->dev, match, compare_of, remote);
+
+	for_each_endpoint_of_node(remote, ep) {
+		remote_node = of_graph_get_remote_port_parent(ep);
+		if (!remote_node ||
+		    remote_node == parent || /* Ignore parent endpoint */
+		    !of_device_is_available(remote_node))
+			continue;
+
+		count += meson_probe_remote(pdev, match, remote, remote_node);
+
+		of_node_put(remote_node);
+	}
+
+	return count;
+}
+
+static int meson_drv_probe(struct platform_device *pdev)
+{
+	struct component_match *match = NULL;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *ep, *remote;
+	int count = 0;
+
+	for_each_endpoint_of_node(np, ep) {
+		remote = of_graph_get_remote_port_parent(ep);
+		if (!remote || !of_device_is_available(remote))
+			continue;
+
+		count += meson_probe_remote(pdev, &match, np, remote);
+	}
+
+	/* If some endpoints were found, initialize the nodes */
+	if (count) {
+		dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
+
+		return component_master_add_with_match(&pdev->dev,
+						       &meson_drv_master_ops,
+						       match);
+	}
+
+	/* If no output endpoints were available, simply bail out */
+	return 0;
+};
+
 static const struct of_device_id dt_match[] = {
 	{ .compatible = "amlogic,meson-gxbb-vpu" },
 	{ .compatible = "amlogic,meson-gxl-vpu" },
@@ -293,7 +380,6 @@ MODULE_DEVICE_TABLE(of, dt_match);
 
 static struct platform_driver meson_drm_platform_driver = {
 	.probe      = meson_drv_probe,
-	.remove     = meson_drv_remove,
 	.driver     = {
 		.name	= "meson-drm",
 		.of_match_table = dt_match,

+ 3 - 0
drivers/gpu/drm/meson/meson_drv.h

@@ -47,6 +47,9 @@ struct meson_drm {
 
 	struct {
 		unsigned int current_mode;
+		bool hdmi_repeat;
+		bool venc_repeat;
+		bool hdmi_use_enci;
 	} venc;
 };
 

+ 919 - 0
drivers/gpu/drm/meson/meson_dw_hdmi.c

@@ -0,0 +1,919 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include <uapi/linux/media-bus-format.h>
+#include <uapi/linux/videodev2.h>
+
+#include "meson_drv.h"
+#include "meson_venc.h"
+#include "meson_vclk.h"
+#include "meson_dw_hdmi.h"
+#include "meson_registers.h"
+
+#define DRIVER_NAME "meson-dw-hdmi"
+#define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
+
+/**
+ * DOC: HDMI Output
+ *
+ * HDMI Output is composed of :
+ *
+ * - A Synopsys DesignWare HDMI Controller IP
+ * - A TOP control block controlling the Clocks and PHY
+ * - A custom HDMI PHY in order convert video to TMDS signal
+ *
+ * .. code::
+ *
+ *    ___________________________________
+ *   |            HDMI TOP               |<= HPD
+ *   |___________________________________|
+ *   |                  |                |
+ *   |  Synopsys HDMI   |   HDMI PHY     |=> TMDS
+ *   |    Controller    |________________|
+ *   |___________________________________|<=> DDC
+ *
+ *
+ * The HDMI TOP block only supports HPD sensing.
+ * The Synopsys HDMI Controller interrupt is routed
+ * through the TOP Block interrupt.
+ * Communication to the TOP Block and the Synopsys
+ * HDMI Controller is done a pair of addr+read/write
+ * registers.
+ * The HDMI PHY is configured by registers in the
+ * HHI register block.
+ *
+ * Pixel data arrives in 4:4:4 format from the VENC
+ * block and the VPU HDMI mux selects either the ENCI
+ * encoder for the 576i or 480i formats or the ENCP
+ * encoder for all the other formats including
+ * interlaced HD formats.
+ * The VENC uses a DVI encoder on top of the ENCI
+ * or ENCP encoders to generate DVI timings for the
+ * HDMI controller.
+ *
+ * GXBB, GXL and GXM embeds the Synopsys DesignWare
+ * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF
+ * audio source interfaces.
+ *
+ * We handle the following features :
+ *
+ * - HPD Rise & Fall interrupt
+ * - HDMI Controller Interrupt
+ * - HDMI PHY Init for 480i to 1080p60
+ * - VENC & HDMI Clock setup for 480i to 1080p60
+ * - VENC Mode setup for 480i to 1080p60
+ *
+ * What is missing :
+ *
+ * - PHY, Clock and Mode setup for 2k && 4k modes
+ * - SDDC Scrambling mode for HDMI 2.0a
+ * - HDCP Setup
+ * - CEC Management
+ */
+
+/* TOP Block Communication Channel */
+#define HDMITX_TOP_ADDR_REG	0x0
+#define HDMITX_TOP_DATA_REG	0x4
+#define HDMITX_TOP_CTRL_REG	0x8
+
+/* Controller Communication Channel */
+#define HDMITX_DWC_ADDR_REG	0x10
+#define HDMITX_DWC_DATA_REG	0x14
+#define HDMITX_DWC_CTRL_REG	0x18
+
+/* HHI Registers */
+#define HHI_MEM_PD_REG0		0x100 /* 0x40 */
+#define HHI_HDMI_CLK_CNTL	0x1cc /* 0x73 */
+#define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 */
+#define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
+#define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
+#define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
+
+static DEFINE_SPINLOCK(reg_lock);
+
+enum meson_venc_source {
+	MESON_VENC_SOURCE_NONE = 0,
+	MESON_VENC_SOURCE_ENCI = 1,
+	MESON_VENC_SOURCE_ENCP = 2,
+};
+
+struct meson_dw_hdmi {
+	struct drm_encoder encoder;
+	struct dw_hdmi_plat_data dw_plat_data;
+	struct meson_drm *priv;
+	struct device *dev;
+	void __iomem *hdmitx;
+	struct reset_control *hdmitx_apb;
+	struct reset_control *hdmitx_ctrl;
+	struct reset_control *hdmitx_phy;
+	struct clk *hdmi_pclk;
+	struct clk *venci_clk;
+	u32 irq_stat;
+};
+#define encoder_to_meson_dw_hdmi(x) \
+	container_of(x, struct meson_dw_hdmi, encoder)
+
+static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
+					const char *compat)
+{
+	return of_device_is_compatible(dw_hdmi->dev->of_node, compat);
+}
+
+/* PHY (via TOP bridge) and Controller dedicated register interface */
+
+static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
+				     unsigned int addr)
+{
+	unsigned long flags;
+	unsigned int data;
+
+	spin_lock_irqsave(&reg_lock, flags);
+
+	/* ADDR must be written twice */
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
+
+	/* Read needs a second DATA read */
+	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
+	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
+
+	spin_unlock_irqrestore(&reg_lock, flags);
+
+	return data;
+}
+
+static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
+				     unsigned int addr, unsigned int data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&reg_lock, flags);
+
+	/* ADDR must be written twice */
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
+
+	/* Write needs single DATA write */
+	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
+
+	spin_unlock_irqrestore(&reg_lock, flags);
+}
+
+/* Helper to change specific bits in PHY registers */
+static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
+					  unsigned int addr,
+					  unsigned int mask,
+					  unsigned int val)
+{
+	unsigned int data = dw_hdmi_top_read(dw_hdmi, addr);
+
+	data &= ~mask;
+	data |= val;
+
+	dw_hdmi_top_write(dw_hdmi, addr, data);
+}
+
+static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
+				     unsigned int addr)
+{
+	unsigned long flags;
+	unsigned int data;
+
+	spin_lock_irqsave(&reg_lock, flags);
+
+	/* ADDR must be written twice */
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
+
+	/* Read needs a second DATA read */
+	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
+	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
+
+	spin_unlock_irqrestore(&reg_lock, flags);
+
+	return data;
+}
+
+static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
+				     unsigned int addr, unsigned int data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&reg_lock, flags);
+
+	/* ADDR must be written twice */
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
+	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
+
+	/* Write needs single DATA write */
+	writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
+
+	spin_unlock_irqrestore(&reg_lock, flags);
+}
+
+/* Helper to change specific bits in controller registers */
+static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
+					  unsigned int addr,
+					  unsigned int mask,
+					  unsigned int val)
+{
+	unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr);
+
+	data &= ~mask;
+	data |= val;
+
+	dw_hdmi_dwc_write(dw_hdmi, addr, data);
+}
+
+/* Bridge */
+
+/* Setup PHY bandwidth modes */
+static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
+				      struct drm_display_mode *mode)
+{
+	struct meson_drm *priv = dw_hdmi->priv;
+	unsigned int pixel_clock = mode->clock;
+
+	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
+	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
+		if (pixel_clock >= 371250) {
+			/* 5.94Gbps, 3.7125Gbps */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b);
+		} else if (pixel_clock >= 297000) {
+			/* 2.97Gbps */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b);
+		} else if (pixel_clock >= 148500) {
+			/* 1.485Gbps */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b);
+		} else {
+			/* 742.5Mbps, and below */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b);
+		}
+	} else if (dw_hdmi_is_compatible(dw_hdmi,
+					 "amlogic,meson-gxbb-dw-hdmi")) {
+		if (pixel_clock >= 371250) {
+			/* 5.94Gbps, 3.7125Gbps */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b);
+		} else if (pixel_clock >= 297000) {
+			/* 2.97Gbps */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b);
+		} else {
+			/* 1.485Gbps, and below */
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
+			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
+		}
+	}
+}
+
+static inline void dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
+{
+	struct meson_drm *priv = dw_hdmi->priv;
+
+	/* Enable and software reset */
+	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf);
+
+	mdelay(2);
+
+	/* Enable and unreset */
+	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe);
+
+	mdelay(2);
+}
+
+static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
+			     struct drm_display_mode *mode)
+{
+	struct meson_drm *priv = dw_hdmi->priv;
+	int vic = drm_match_cea_mode(mode);
+	unsigned int vclk_freq;
+	unsigned int venc_freq;
+	unsigned int hdmi_freq;
+
+	vclk_freq = mode->clock;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		vclk_freq *= 2;
+
+	venc_freq = vclk_freq;
+	hdmi_freq = vclk_freq;
+
+	if (meson_venc_hdmi_venc_repeat(vic))
+		venc_freq *= 2;
+
+	vclk_freq = max(venc_freq, hdmi_freq);
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		venc_freq /= 2;
+
+	DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
+		vclk_freq, venc_freq, hdmi_freq,
+		priv->venc.hdmi_use_enci);
+
+	meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
+			 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
+}
+
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+			    struct drm_display_mode *mode)
+{
+	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
+	struct meson_drm *priv = dw_hdmi->priv;
+	unsigned int wr_clk =
+		readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	DRM_DEBUG_DRIVER("%d:\"%s\"\n", mode->base.id, mode->name);
+
+	/* Enable clocks */
+	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
+
+	/* Bring HDMITX MEM output of power down */
+	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
+
+	/* Bring out of reset */
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
+
+	/* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
+	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
+			       0x3, 0x3);
+	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
+			       0x3 << 4, 0x3 << 4);
+
+	/* Enable normal output to PHY */
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
+
+	/* TMDS pattern setup (TOFIX pattern for 4k2k scrambling) */
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f);
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f);
+
+	/* Load TMDS pattern */
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
+	msleep(20);
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
+
+	/* Setup PHY parameters */
+	meson_hdmi_phy_setup_mode(dw_hdmi, mode);
+
+	/* Setup PHY */
+	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+			   0xffff << 16, 0x0390 << 16);
+
+	/* BIT_INVERT */
+	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
+	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+				   BIT(17), 0);
+	else
+		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+				   BIT(17), BIT(17));
+
+	/* Disable clock, fifo, fifo_wr */
+	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
+
+	msleep(100);
+
+	/* Reset PHY 3 times in a row */
+	dw_hdmi_phy_reset(dw_hdmi);
+	dw_hdmi_phy_reset(dw_hdmi);
+	dw_hdmi_phy_reset(dw_hdmi);
+
+	/* Temporary Disable VENC video stream */
+	if (priv->venc.hdmi_use_enci)
+		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
+	else
+		writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
+
+	/* Temporary Disable HDMI video stream to HDMI-TX */
+	writel_bits_relaxed(0x3, 0,
+			    priv->io_base + _REG(VPU_HDMI_SETTING));
+	writel_bits_relaxed(0xf << 8, 0,
+			    priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	/* Re-Enable VENC video stream */
+	if (priv->venc.hdmi_use_enci)
+		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+	else
+		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
+
+	/* Push back HDMI clock settings */
+	writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
+			    priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	/* Enable and Select HDMI video source for HDMI-TX */
+	if (priv->venc.hdmi_use_enci)
+		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
+				    priv->io_base + _REG(VPU_HDMI_SETTING));
+	else
+		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
+				    priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	return 0;
+}
+
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
+				void *data)
+{
+	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
+	struct meson_drm *priv = dw_hdmi->priv;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
+}
+
+static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
+			     void *data)
+{
+	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
+
+	return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
+			      void *data)
+{
+	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
+
+	/* Setup HPD Filter */
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
+			  (0xa << 12) | 0xa0);
+
+	/* Clear interrupts */
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
+			  HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
+
+	/* Unmask interrupts */
+	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
+			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
+			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
+}
+
+static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
+	.init = dw_hdmi_phy_init,
+	.disable = dw_hdmi_phy_disable,
+	.read_hpd = dw_hdmi_read_hpd,
+	.setup_hpd = dw_hdmi_setup_hpd,
+};
+
+static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
+{
+	struct meson_dw_hdmi *dw_hdmi = dev_id;
+	u32 stat;
+
+	stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
+	dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
+
+	/* HPD Events, handle in the threaded interrupt handler */
+	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
+		dw_hdmi->irq_stat = stat;
+		return IRQ_WAKE_THREAD;
+	}
+
+	/* HDMI Controller Interrupt */
+	if (stat & 1)
+		return IRQ_NONE;
+
+	/* TOFIX Handle HDCP Interrupts */
+
+	return IRQ_HANDLED;
+}
+
+/* Threaded interrupt handler to manage HPD events */
+static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
+{
+	struct meson_dw_hdmi *dw_hdmi = dev_id;
+	u32 stat = dw_hdmi->irq_stat;
+
+	/* HPD Events */
+	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
+		bool hpd_connected = false;
+
+		if (stat & HDMITX_TOP_INTR_HPD_RISE)
+			hpd_connected = true;
+
+		dw_hdmi_setup_rx_sense(dw_hdmi->dev, hpd_connected,
+				       hpd_connected);
+
+		drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* TOFIX Enable support for non-vic modes */
+static enum drm_mode_status dw_hdmi_mode_valid(struct drm_connector *connector,
+					       struct drm_display_mode *mode)
+{
+	unsigned int vclk_freq;
+	unsigned int venc_freq;
+	unsigned int hdmi_freq;
+	int vic = drm_match_cea_mode(mode);
+
+	DRM_DEBUG_DRIVER("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
+		mode->base.id, mode->name, mode->vrefresh, mode->clock,
+		mode->hdisplay, mode->hsync_start,
+		mode->hsync_end, mode->htotal,
+		mode->vdisplay, mode->vsync_start,
+		mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+
+	/* For now, only accept VIC modes */
+	if (!vic)
+		return MODE_BAD;
+
+	/* For now, filter by supported VIC modes */
+	if (!meson_venc_hdmi_supported_vic(vic))
+		return MODE_BAD;
+
+	vclk_freq = mode->clock;
+
+	/* 480i/576i needs global pixel doubling */
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		vclk_freq *= 2;
+
+	venc_freq = vclk_freq;
+	hdmi_freq = vclk_freq;
+
+	/* VENC double pixels for 1080i and 720p modes */
+	if (meson_venc_hdmi_venc_repeat(vic))
+		venc_freq *= 2;
+
+	vclk_freq = max(venc_freq, hdmi_freq);
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		venc_freq /= 2;
+
+	dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
+		vclk_freq, venc_freq, hdmi_freq);
+
+	/* Finally filter by configurable vclk frequencies */
+	switch (vclk_freq) {
+	case 54000:
+	case 74250:
+	case 148500:
+	case 297000:
+	case 594000:
+		return MODE_OK;
+	}
+
+	return MODE_CLOCK_RANGE;
+}
+
+/* Encoder */
+
+static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
+	.destroy        = meson_venc_hdmi_encoder_destroy,
+};
+
+static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
+	struct meson_drm *priv = dw_hdmi->priv;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	writel_bits_relaxed(0x3, 0,
+			    priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
+	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
+}
+
+static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
+	struct meson_drm *priv = dw_hdmi->priv;
+
+	DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
+
+	if (priv->venc.hdmi_use_enci)
+		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+	else
+		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
+}
+
+static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
+	struct meson_drm *priv = dw_hdmi->priv;
+	int vic = drm_match_cea_mode(mode);
+
+	DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n",
+			 mode->base.id, mode->name, vic);
+
+	/* Should have been filtered */
+	if (!vic)
+		return;
+
+	/* VENC + VENC-DVI Mode setup */
+	meson_venc_hdmi_mode_set(priv, vic, mode);
+
+	/* VCLK Set clock */
+	dw_hdmi_set_vclk(dw_hdmi, mode);
+
+	/* Setup YUV444 to HDMI-TX, no 10bit diphering */
+	writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+}
+
+static const struct drm_encoder_helper_funcs
+				meson_venc_hdmi_encoder_helper_funcs = {
+	.atomic_check	= meson_venc_hdmi_encoder_atomic_check,
+	.disable	= meson_venc_hdmi_encoder_disable,
+	.enable		= meson_venc_hdmi_encoder_enable,
+	.mode_set	= meson_venc_hdmi_encoder_mode_set,
+};
+
+/* DW HDMI Regmap */
+
+static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
+				  unsigned int *result)
+{
+	*result = dw_hdmi_dwc_read(context, reg);
+
+	return 0;
+
+}
+
+static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
+				   unsigned int val)
+{
+	dw_hdmi_dwc_write(context, reg, val);
+
+	return 0;
+}
+
+static const struct regmap_config meson_dw_hdmi_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_read = meson_dw_hdmi_reg_read,
+	.reg_write = meson_dw_hdmi_reg_write,
+	.max_register = 0x10000,
+};
+
+static bool meson_hdmi_connector_is_available(struct device *dev)
+{
+	struct device_node *ep, *remote;
+
+	/* HDMI Connector is on the second port, first endpoint */
+	ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
+	if (!ep)
+		return false;
+
+	/* If the endpoint node exists, consider it enabled */
+	remote = of_graph_get_remote_port(ep);
+	if (remote) {
+		of_node_put(ep);
+		return true;
+	}
+
+	of_node_put(ep);
+	of_node_put(remote);
+
+	return false;
+}
+
+static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
+				void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct meson_dw_hdmi *meson_dw_hdmi;
+	struct drm_device *drm = data;
+	struct meson_drm *priv = drm->dev_private;
+	struct dw_hdmi_plat_data *dw_plat_data;
+	struct drm_encoder *encoder;
+	struct resource *res;
+	int irq;
+	int ret;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (!meson_hdmi_connector_is_available(dev)) {
+		dev_info(drm->dev, "HDMI Output connector not available\n");
+		return -ENODEV;
+	}
+
+	meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
+				     GFP_KERNEL);
+	if (!meson_dw_hdmi)
+		return -ENOMEM;
+
+	meson_dw_hdmi->priv = priv;
+	meson_dw_hdmi->dev = dev;
+	dw_plat_data = &meson_dw_hdmi->dw_plat_data;
+	encoder = &meson_dw_hdmi->encoder;
+
+	meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
+						"hdmitx_apb");
+	if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
+		dev_err(dev, "Failed to get hdmitx_apb reset\n");
+		return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
+	}
+
+	meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
+						"hdmitx");
+	if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
+		dev_err(dev, "Failed to get hdmitx reset\n");
+		return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
+	}
+
+	meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
+						"hdmitx_phy");
+	if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
+		dev_err(dev, "Failed to get hdmitx_phy reset\n");
+		return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
+	if (IS_ERR(meson_dw_hdmi->hdmitx))
+		return PTR_ERR(meson_dw_hdmi->hdmitx);
+
+	meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
+	if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
+		dev_err(dev, "Unable to get HDMI pclk\n");
+		return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
+	}
+	clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
+
+	meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
+	if (IS_ERR(meson_dw_hdmi->venci_clk)) {
+		dev_err(dev, "Unable to get venci clk\n");
+		return PTR_ERR(meson_dw_hdmi->venci_clk);
+	}
+	clk_prepare_enable(meson_dw_hdmi->venci_clk);
+
+	dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
+					      &meson_dw_hdmi_regmap_config);
+	if (IS_ERR(dw_plat_data->regm))
+		return PTR_ERR(dw_plat_data->regm);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "Failed to get hdmi top irq\n");
+		return irq;
+	}
+
+	ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
+					dw_hdmi_top_thread_irq, IRQF_SHARED,
+					"dw_hdmi_top_irq", meson_dw_hdmi);
+	if (ret) {
+		dev_err(dev, "Failed to request hdmi top irq\n");
+		return ret;
+	}
+
+	/* Encoder */
+
+	drm_encoder_helper_add(encoder, &meson_venc_hdmi_encoder_helper_funcs);
+
+	ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, "meson_hdmi");
+	if (ret) {
+		dev_err(priv->dev, "Failed to init HDMI encoder\n");
+		return ret;
+	}
+
+	encoder->possible_crtcs = BIT(0);
+
+	DRM_DEBUG_DRIVER("encoder initialized\n");
+
+	/* Enable clocks */
+	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
+
+	/* Bring HDMITX MEM output of power down */
+	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
+
+	/* Reset HDMITX APB & TX & PHY */
+	reset_control_reset(meson_dw_hdmi->hdmitx_apb);
+	reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
+	reset_control_reset(meson_dw_hdmi->hdmitx_phy);
+
+	/* Enable APB3 fail on error */
+	writel_bits_relaxed(BIT(15), BIT(15),
+			    meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
+	writel_bits_relaxed(BIT(15), BIT(15),
+			    meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
+
+	/* Bring out of reset */
+	dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET,  0);
+
+	msleep(20);
+
+	dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff);
+
+	/* Enable HDMI-TX Interrupt */
+	dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
+			  HDMITX_TOP_INTR_CORE);
+
+	dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
+			  HDMITX_TOP_INTR_CORE);
+
+	/* Bridge / Connector */
+
+	dw_plat_data->mode_valid = dw_hdmi_mode_valid;
+	dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
+	dw_plat_data->phy_name = "meson_dw_hdmi_phy";
+	dw_plat_data->phy_data = meson_dw_hdmi;
+	dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
+	dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
+
+	ret = dw_hdmi_bind(pdev, encoder, &meson_dw_hdmi->dw_plat_data);
+	if (ret)
+		return ret;
+
+	DRM_DEBUG_DRIVER("HDMI controller initialized\n");
+
+	return 0;
+}
+
+static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
+				   void *data)
+{
+	dw_hdmi_unbind(dev);
+}
+
+static const struct component_ops meson_dw_hdmi_ops = {
+	.bind	= meson_dw_hdmi_bind,
+	.unbind	= meson_dw_hdmi_unbind,
+};
+
+static int meson_dw_hdmi_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &meson_dw_hdmi_ops);
+}
+
+static int meson_dw_hdmi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &meson_dw_hdmi_ops);
+
+	return 0;
+}
+
+static const struct of_device_id meson_dw_hdmi_of_table[] = {
+	{ .compatible = "amlogic,meson-gxbb-dw-hdmi" },
+	{ .compatible = "amlogic,meson-gxl-dw-hdmi" },
+	{ .compatible = "amlogic,meson-gxm-dw-hdmi" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
+
+static struct platform_driver meson_dw_hdmi_platform_driver = {
+	.probe		= meson_dw_hdmi_probe,
+	.remove		= meson_dw_hdmi_remove,
+	.driver		= {
+		.name		= DRIVER_NAME,
+		.of_match_table	= meson_dw_hdmi_of_table,
+	},
+};
+module_platform_driver(meson_dw_hdmi_platform_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");

+ 146 - 0
drivers/gpu/drm/meson/meson_dw_hdmi.h

@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MESON_DW_HDMI_H
+#define __MESON_DW_HDMI_H
+
+/*
+ * Bit 7 RW Reserved. Default 1.
+ * Bit 6 RW Reserved. Default 1.
+ * Bit 5 RW Reserved. Default 1.
+ * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset.
+ *     Default 1.
+ * Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset;
+ *     0=Release from reset.
+ *     Default 1.
+ * Bit 2 RW sw_reset_mem: KSV/REVOC mem. 1=Apply reset; 0=Release from reset.
+ *     Default 1.
+ * Bit 1 RW sw_reset_rnd: random number interface to HDCP. 1=Apply reset;
+ *     0=Release from reset. Default 1.
+ * Bit 0 RW sw_reset_core: connects to IP's ~irstz. 1=Apply reset;
+ *     0=Release from reset. Default 1.
+ */
+#define HDMITX_TOP_SW_RESET                     (0x000)
+
+/*
+ * Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0.
+ * Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0.
+ * Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0.
+ * Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0.
+ * Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0.
+ * Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0.
+ * Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0.
+ * Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0.
+ * Bit 1 RW tmds_clk_en: 1=enable tmds_clk;  0=disable. Default 0.
+ * Bit 0 RW pixel_clk_en: 1=enable pixel_clk; 0=disable. Default 0.
+ */
+#define HDMITX_TOP_CLK_CNTL                     (0x001)
+
+/*
+ * Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024.    Default 0.
+ * Bit 15:12 RW hpd_glitch_width: filter out glitch <= N.       Default 0.
+ */
+#define HDMITX_TOP_HPD_FILTER                   (0x002)
+
+/*
+ * intr_maskn: MASK_N, one bit per interrupt source.
+ *     1=Enable interrupt source; 0=Disable interrupt source. Default 0.
+ * [  4] hdcp22_rndnum_err
+ * [  3] nonce_rfrsh_rise
+ * [  2] hpd_fall_intr
+ * [  1] hpd_rise_intr
+ * [  0] core_intr
+ */
+#define HDMITX_TOP_INTR_MASKN                   (0x003)
+
+/*
+ * Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt
+ *     bit, read back the interrupt status.
+ * Bit    31 R  IP interrupt status
+ * Bit     2 RW hpd_fall
+ * Bit     1 RW hpd_rise
+ * Bit     0 RW IP interrupt
+ */
+#define HDMITX_TOP_INTR_STAT                    (0x004)
+
+/*
+ * [4]	  hdcp22_rndnum_err
+ * [3]	  nonce_rfrsh_rise
+ * [2]	  hpd_fall
+ * [1]	  hpd_rise
+ * [0]	  core_intr_rise
+ */
+#define HDMITX_TOP_INTR_STAT_CLR                (0x005)
+
+#define HDMITX_TOP_INTR_CORE		BIT(0)
+#define HDMITX_TOP_INTR_HPD_RISE	BIT(1)
+#define HDMITX_TOP_INTR_HPD_FALL	BIT(2)
+
+/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data;
+ *     3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0.
+ * Bit 11: 9 RW shift_pttn_repeat: 0=New pattern every clk cycle; 1=New pattern
+ *     every 2 clk cycles; ...; 7=New pattern every 8 clk cycles. Default 0.
+ * Bit 8 RW shift_pttn_en: 1= Enable shift pattern generator; 0=Disable.
+ *     Default 0.
+ * Bit 4: 3 RW prbs_pttn_mode: 0=PRBS11; 1=PRBS15; 2=PRBS7; 3=PRBS31. Default 0.
+ * Bit 2: 1 RW prbs_pttn_width: 0=idle; 1=output 8-bit pattern;
+ *     2=Output 1-bit pattern; 3=output 10-bit pattern. Default 0.
+ * Bit 0 RW prbs_pttn_en: 1=Enable PRBS generator; 0=Disable. Default 0.
+ */
+#define HDMITX_TOP_BIST_CNTL                    (0x006)
+
+/* Bit 29:20 RW shift_pttn_data[59:50]. Default 0. */
+/* Bit 19:10 RW shift_pttn_data[69:60]. Default 0. */
+/* Bit  9: 0 RW shift_pttn_data[79:70]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_012               (0x007)
+
+/* Bit 29:20 RW shift_pttn_data[29:20]. Default 0. */
+/* Bit 19:10 RW shift_pttn_data[39:30]. Default 0. */
+/* Bit  9: 0 RW shift_pttn_data[49:40]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_345               (0x008)
+
+/* Bit 19:10 RW shift_pttn_data[ 9: 0]. Default 0. */
+/* Bit  9: 0 RW shift_pttn_data[19:10]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_67                (0x009)
+
+/* Bit 25:16 RW tmds_clk_pttn[19:10]. Default 0. */
+/* Bit  9: 0 RW tmds_clk_pttn[ 9: 0]. Default 0. */
+#define HDMITX_TOP_TMDS_CLK_PTTN_01             (0x00A)
+
+/* Bit 25:16 RW tmds_clk_pttn[39:30]. Default 0. */
+/* Bit  9: 0 RW tmds_clk_pttn[29:20]. Default 0. */
+#define HDMITX_TOP_TMDS_CLK_PTTN_23             (0x00B)
+
+/* Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern,
+ * used when TMDS CLK rate = TMDS character rate /4. Default 0.
+ * Bit 0 R  Reserved. Default 0.
+ * [	1] shift_tmds_clk_pttn
+ * [	0] load_tmds_clk_pttn
+ */
+#define HDMITX_TOP_TMDS_CLK_PTTN_CNTL           (0x00C)
+
+/* Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM
+ * failure, write 1 to clear the failure flag.  Default 0.
+ */
+#define HDMITX_TOP_REVOCMEM_STAT                (0x00D)
+
+/* Bit     0 R  filtered HPD status. */
+#define HDMITX_TOP_STAT0                        (0x00E)
+
+#endif /* __MESON_DW_HDMI_H */

+ 1 - 0
drivers/gpu/drm/meson/meson_registers.h

@@ -1319,6 +1319,7 @@
 #define VPU_MISC_CTRL 0x2740
 #define VPU_ISP_GCLK_CTRL0 0x2741
 #define VPU_ISP_GCLK_CTRL1 0x2742
+#define VPU_HDMI_FMT_CTRL 0x2743
 #define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
 #define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
 #define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745

+ 619 - 13
drivers/gpu/drm/meson/meson_vclk.c

@@ -23,13 +23,38 @@
 #include "meson_drv.h"
 #include "meson_vclk.h"
 
-/*
+/**
+ * DOC: Video Clocks
+ *
  * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
  * We handle the following encodings :
+ *
  * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
+ * - HDMI Pixel Clocks generation
  *
  * What is missing :
- * - HDMI Pixel Clocks generation
+ *
+ * - Genenate Pixel clocks for 2K/4K 10bit formats
+ *
+ * Clock generator scheme :
+ *
+ * .. code::
+ *
+ *    __________   _________            _____
+ *   |          | |         |          |     |--ENCI
+ *   | HDMI PLL |-| PLL_DIV |--- VCLK--|     |--ENCL
+ *   |__________| |_________| \        | MUX |--ENCP
+ *                             --VCLK2-|     |--VDAC
+ *                                     |_____|--HDMI-TX
+ *
+ * Final clocks can take input for either VCLK or VCLK2, but
+ * VCLK is the preferred path for HDMI clocking and VCLK2 is the
+ * preferred path for CVBS VDAC clocking.
+ *
+ * VCLK and VCLK2 have fixed divided clocks paths for /1, /2, /4, /6 or /12.
+ *
+ * The PLL_DIV can achieve an additional fractional dividing like
+ * 1.5, 3.5, 3.75... to generate special 2K and 4K 10bit clocks.
  */
 
 /* HHI Registers */
@@ -50,11 +75,34 @@
 #define VCLK2_SOFT_RESET	BIT(15)
 #define VCLK2_DIV1_EN		BIT(0)
 #define HHI_VID_CLK_DIV		0x164 /* 0x59 offset in data sheet */
+#define VCLK_DIV_MASK		0xff
+#define VCLK_DIV_EN		BIT(16)
+#define VCLK_DIV_RESET		BIT(17)
+#define CTS_ENCP_SEL_MASK	(0xf << 24)
+#define CTS_ENCP_SEL_SHIFT	24
 #define CTS_ENCI_SEL_MASK	(0xf << 28)
 #define CTS_ENCI_SEL_SHIFT	28
+#define HHI_VID_CLK_CNTL	0x17c /* 0x5f offset in data sheet */
+#define VCLK_EN			BIT(19)
+#define VCLK_SEL_MASK		(0x7 << 16)
+#define VCLK_SEL_SHIFT		16
+#define VCLK_SOFT_RESET		BIT(15)
+#define VCLK_DIV1_EN		BIT(0)
+#define VCLK_DIV2_EN		BIT(1)
+#define VCLK_DIV4_EN		BIT(2)
+#define VCLK_DIV6_EN		BIT(3)
+#define VCLK_DIV12_EN		BIT(4)
 #define HHI_VID_CLK_CNTL2	0x194 /* 0x65 offset in data sheet */
 #define CTS_ENCI_EN		BIT(0)
+#define CTS_ENCP_EN		BIT(2)
 #define CTS_VDAC_EN		BIT(4)
+#define HDMI_TX_PIXEL_EN	BIT(5)
+#define HHI_HDMI_CLK_CNTL	0x1cc /* 0x73 offset in data sheet */
+#define HDMI_TX_PIXEL_SEL_MASK	(0xf << 16)
+#define HDMI_TX_PIXEL_SEL_SHIFT	16
+#define CTS_HDMI_SYS_SEL_MASK	(0x7 << 9)
+#define CTS_HDMI_SYS_DIV_MASK	(0x7f)
+#define CTS_HDMI_SYS_EN		BIT(8)
 
 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
@@ -69,6 +117,126 @@
 #define HDMI_PLL_RESET		BIT(28)
 #define HDMI_PLL_LOCK		BIT(31)
 
+/* VID PLL Dividers */
+enum {
+	VID_PLL_DIV_1 = 0,
+	VID_PLL_DIV_2,
+	VID_PLL_DIV_2p5,
+	VID_PLL_DIV_3,
+	VID_PLL_DIV_3p5,
+	VID_PLL_DIV_3p75,
+	VID_PLL_DIV_4,
+	VID_PLL_DIV_5,
+	VID_PLL_DIV_6,
+	VID_PLL_DIV_6p25,
+	VID_PLL_DIV_7,
+	VID_PLL_DIV_7p5,
+	VID_PLL_DIV_12,
+	VID_PLL_DIV_14,
+	VID_PLL_DIV_15,
+};
+
+void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
+{
+	unsigned int shift_val = 0;
+	unsigned int shift_sel = 0;
+
+	/* Disable vid_pll output clock */
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
+
+	switch (div) {
+	case VID_PLL_DIV_2:
+		shift_val = 0x0aaa;
+		shift_sel = 0;
+		break;
+	case VID_PLL_DIV_2p5:
+		shift_val = 0x5294;
+		shift_sel = 2;
+		break;
+	case VID_PLL_DIV_3:
+		shift_val = 0x0db6;
+		shift_sel = 0;
+		break;
+	case VID_PLL_DIV_3p5:
+		shift_val = 0x36cc;
+		shift_sel = 1;
+		break;
+	case VID_PLL_DIV_3p75:
+		shift_val = 0x6666;
+		shift_sel = 2;
+		break;
+	case VID_PLL_DIV_4:
+		shift_val = 0x0ccc;
+		shift_sel = 0;
+		break;
+	case VID_PLL_DIV_5:
+		shift_val = 0x739c;
+		shift_sel = 2;
+		break;
+	case VID_PLL_DIV_6:
+		shift_val = 0x0e38;
+		shift_sel = 0;
+		break;
+	case VID_PLL_DIV_6p25:
+		shift_val = 0x0000;
+		shift_sel = 3;
+		break;
+	case VID_PLL_DIV_7:
+		shift_val = 0x3c78;
+		shift_sel = 1;
+		break;
+	case VID_PLL_DIV_7p5:
+		shift_val = 0x78f0;
+		shift_sel = 2;
+		break;
+	case VID_PLL_DIV_12:
+		shift_val = 0x0fc0;
+		shift_sel = 0;
+		break;
+	case VID_PLL_DIV_14:
+		shift_val = 0x3f80;
+		shift_sel = 1;
+		break;
+	case VID_PLL_DIV_15:
+		shift_val = 0x7f80;
+		shift_sel = 2;
+		break;
+	}
+
+	if (div == VID_PLL_DIV_1)
+		/* Enable vid_pll bypass to HDMI pll */
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   VID_PLL_BYPASS, VID_PLL_BYPASS);
+	else {
+		/* Disable Bypass */
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   VID_PLL_BYPASS, 0);
+		/* Clear sel */
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   3 << 16, 0);
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   VID_PLL_PRESET, 0);
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   0x7fff, 0);
+
+		/* Setup sel and val */
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   3 << 16, shift_sel << 16);
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   VID_PLL_PRESET, VID_PLL_PRESET);
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   0x7fff, shift_val);
+
+		regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				   VID_PLL_PRESET, 0);
+	}
+
+	/* Enable the vid_pll output clock */
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				VID_PLL_EN, VID_PLL_EN);
+}
+
 /*
  * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
  *
@@ -110,15 +278,8 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
 	/* Disable VCLK2 */
 	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
 
-	/* Disable vid_pll output clock */
-	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
-	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
-	/* Enable vid_pll bypass to HDMI pll */
-	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
-				VID_PLL_BYPASS, VID_PLL_BYPASS);
-	/* Enable the vid_pll output clock */
-	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
-				VID_PLL_EN, VID_PLL_EN);
+	/* Setup vid_pll to /1 */
+	meson_vid_pll_set(priv, VID_PLL_DIV_1);
 
 	/* Setup the VCLK2 divider value to achieve 27MHz */
 	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
@@ -159,9 +320,454 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
 				CTS_VDAC_EN, CTS_VDAC_EN);
 }
 
+
+/* PLL	O1 O2 O3 VP DV     EN TX */
+/* 4320 /4 /4 /1 /5 /1  => /2 /2 */
+#define MESON_VCLK_HDMI_ENCI_54000	1
+/* 4320 /4 /4 /1 /5 /1  => /1 /2 */
+#define MESON_VCLK_HDMI_DDR_54000	2
+/* 2970 /4 /1 /1 /5 /1  => /1 /2 */
+#define MESON_VCLK_HDMI_DDR_148500	3
+/* 2970 /2 /2 /2 /5 /1  => /1 /1 */
+#define MESON_VCLK_HDMI_74250		4
+/* 2970 /1 /2 /2 /5 /1  => /1 /1 */
+#define MESON_VCLK_HDMI_148500		5
+/* 2970 /1 /1 /1 /5 /2  => /1 /1 */
+#define MESON_VCLK_HDMI_297000		6
+/* 5940 /1 /1 /2 /5 /1  => /1 /1 */
+#define MESON_VCLK_HDMI_594000		7
+
+struct meson_vclk_params {
+	unsigned int pll_base_freq;
+	unsigned int pll_od1;
+	unsigned int pll_od2;
+	unsigned int pll_od3;
+	unsigned int vid_pll_div;
+	unsigned int vclk_div;
+} params[] = {
+	[MESON_VCLK_HDMI_ENCI_54000] = {
+		.pll_base_freq = 4320000,
+		.pll_od1 = 4,
+		.pll_od2 = 4,
+		.pll_od3 = 1,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 1,
+	},
+	[MESON_VCLK_HDMI_DDR_54000] = {
+		.pll_base_freq = 4320000,
+		.pll_od1 = 4,
+		.pll_od2 = 4,
+		.pll_od3 = 1,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 1,
+	},
+	[MESON_VCLK_HDMI_DDR_148500] = {
+		.pll_base_freq = 2970000,
+		.pll_od1 = 4,
+		.pll_od2 = 1,
+		.pll_od3 = 1,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 1,
+	},
+	[MESON_VCLK_HDMI_74250] = {
+		.pll_base_freq = 2970000,
+		.pll_od1 = 2,
+		.pll_od2 = 2,
+		.pll_od3 = 2,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 1,
+	},
+	[MESON_VCLK_HDMI_148500] = {
+		.pll_base_freq = 2970000,
+		.pll_od1 = 1,
+		.pll_od2 = 2,
+		.pll_od3 = 2,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 1,
+	},
+	[MESON_VCLK_HDMI_297000] = {
+		.pll_base_freq = 2970000,
+		.pll_od1 = 1,
+		.pll_od2 = 1,
+		.pll_od3 = 1,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 2,
+	},
+	[MESON_VCLK_HDMI_594000] = {
+		.pll_base_freq = 5940000,
+		.pll_od1 = 1,
+		.pll_od2 = 1,
+		.pll_od3 = 2,
+		.vid_pll_div = VID_PLL_DIV_5,
+		.vclk_div = 1,
+	},
+};
+
+static inline unsigned int pll_od_to_reg(unsigned int od)
+{
+	switch (od) {
+	case 1:
+		return 0;
+	case 2:
+		return 1;
+	case 4:
+		return 2;
+	case 8:
+		return 3;
+	}
+
+	/* Invalid */
+	return 0;
+}
+
+void meson_hdmi_pll_set(struct meson_drm *priv,
+			unsigned int base,
+			unsigned int od1,
+			unsigned int od2,
+			unsigned int od3)
+{
+	unsigned int val;
+
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+		switch (base) {
+		case 2970000:
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
+
+			/* Enable and unreset */
+			regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+						0x7 << 28, 0x4 << 28);
+
+			/* Poll for lock bit */
+			regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
+					val, (val & HDMI_PLL_LOCK), 10, 0);
+
+			/* div_frac */
+			regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+						0xFFFF,  0x4e00);
+			break;
+
+		case 4320000:
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
+
+			/* unreset */
+			regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+						BIT(28), 0);
+
+			/* Poll for lock bit */
+			regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
+					val, (val & HDMI_PLL_LOCK), 10, 0);
+			break;
+
+		case 5940000:
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800027b);
+			regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+						0xFFFF,  0x4c00);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
+
+			/* unreset */
+			regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+						BIT(28), 0);
+
+			/* Poll for lock bit */
+			regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
+					val, (val & HDMI_PLL_LOCK), 10, 0);
+			break;
+		};
+	} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+		   meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+		switch (base) {
+		case 2970000:
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
+			break;
+
+		case 4320000:
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
+			break;
+
+		case 5940000:
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002f7);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb200);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
+			regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
+			break;
+
+		};
+
+		/* Reset PLL */
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET, HDMI_PLL_RESET);
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET, 0);
+
+		/* Poll for lock bit */
+		regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+				(val & HDMI_PLL_LOCK), 10, 0);
+	};
+
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+				   3 << 16, pll_od_to_reg(od1) << 16);
+	else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+		 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
+				   3 << 21, pll_od_to_reg(od1) << 21);
+
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+				   3 << 22, pll_od_to_reg(od2) << 22);
+	else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+		 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
+				   3 << 23, pll_od_to_reg(od2) << 23);
+
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+				   3 << 18, pll_od_to_reg(od3) << 18);
+	else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+		 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
+				   3 << 19, pll_od_to_reg(od3) << 19);
+}
+
 void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
-		      unsigned int freq)
+		      unsigned int vclk_freq, unsigned int venc_freq,
+		      unsigned int dac_freq, bool hdmi_use_enci)
 {
-	if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS)
+	unsigned int freq;
+	unsigned int hdmi_tx_div;
+	unsigned int venc_div;
+
+	if (target == MESON_VCLK_TARGET_CVBS) {
 		meson_venci_cvbs_clock_config(priv);
+		return;
+	}
+
+	hdmi_tx_div = vclk_freq / dac_freq;
+
+	if (hdmi_tx_div == 0) {
+		pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
+				dac_freq);
+		return;
+	}
+
+	venc_div = vclk_freq / venc_freq;
+
+	if (venc_div == 0) {
+		pr_err("Fatal Error, invalid HDMI venc freq %d\n",
+				venc_freq);
+		return;
+	}
+
+	switch (vclk_freq) {
+	case 54000:
+		if (hdmi_use_enci)
+			freq = MESON_VCLK_HDMI_ENCI_54000;
+		else
+			freq = MESON_VCLK_HDMI_DDR_54000;
+		break;
+	case 74250:
+		freq = MESON_VCLK_HDMI_74250;
+		break;
+	case 148500:
+		if (dac_freq != 148500)
+			freq = MESON_VCLK_HDMI_DDR_148500;
+		else
+			freq = MESON_VCLK_HDMI_148500;
+		break;
+	case 297000:
+		freq = MESON_VCLK_HDMI_297000;
+		break;
+	case 594000:
+		freq = MESON_VCLK_HDMI_594000;
+		break;
+	default:
+		pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
+			vclk_freq);
+		return;
+	}
+
+	/* Set HDMI-TX sys clock */
+	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			   CTS_HDMI_SYS_SEL_MASK, 0);
+	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			   CTS_HDMI_SYS_DIV_MASK, 0);
+	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			   CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
+
+	/* Set HDMI PLL rate */
+	meson_hdmi_pll_set(priv, params[freq].pll_base_freq,
+			   params[freq].pll_od1,
+			   params[freq].pll_od2,
+			   params[freq].pll_od3);
+
+	/* Setup vid_pll divider */
+	meson_vid_pll_set(priv, params[freq].vid_pll_div);
+
+	/* Set VCLK div */
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+			   VCLK_SEL_MASK, 0);
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+			   VCLK_DIV_MASK, params[freq].vclk_div - 1);
+
+	/* Set HDMI-TX source */
+	switch (hdmi_tx_div) {
+	case 1:
+		/* enable vclk_div1 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV1_EN, VCLK_DIV1_EN);
+
+		/* select vclk_div1 for HDMI-TX */
+		regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+				   HDMI_TX_PIXEL_SEL_MASK, 0);
+		break;
+	case 2:
+		/* enable vclk_div2 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV2_EN, VCLK_DIV2_EN);
+
+		/* select vclk_div2 for HDMI-TX */
+		regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
+		break;
+	case 4:
+		/* enable vclk_div4 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV4_EN, VCLK_DIV4_EN);
+
+		/* select vclk_div4 for HDMI-TX */
+		regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
+		break;
+	case 6:
+		/* enable vclk_div6 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV6_EN, VCLK_DIV6_EN);
+
+		/* select vclk_div6 for HDMI-TX */
+		regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
+		break;
+	case 12:
+		/* enable vclk_div12 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV12_EN, VCLK_DIV12_EN);
+
+		/* select vclk_div12 for HDMI-TX */
+		regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+			HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
+		break;
+	}
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+				   HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
+
+	/* Set ENCI/ENCP Source */
+	switch (venc_div) {
+	case 1:
+		/* enable vclk_div1 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV1_EN, VCLK_DIV1_EN);
+
+		if (hdmi_use_enci)
+			/* select vclk_div1 for enci */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+					   CTS_ENCI_SEL_MASK, 0);
+		else
+			/* select vclk_div1 for encp */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+					   CTS_ENCP_SEL_MASK, 0);
+		break;
+	case 2:
+		/* enable vclk_div2 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV2_EN, VCLK_DIV2_EN);
+
+		if (hdmi_use_enci)
+			/* select vclk_div2 for enci */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
+		else
+			/* select vclk_div2 for encp */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
+		break;
+	case 4:
+		/* enable vclk_div4 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV4_EN, VCLK_DIV4_EN);
+
+		if (hdmi_use_enci)
+			/* select vclk_div4 for enci */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
+		else
+			/* select vclk_div4 for encp */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
+		break;
+	case 6:
+		/* enable vclk_div6 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV6_EN, VCLK_DIV6_EN);
+
+		if (hdmi_use_enci)
+			/* select vclk_div6 for enci */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
+		else
+			/* select vclk_div6 for encp */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
+		break;
+	case 12:
+		/* enable vclk_div12 gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+				   VCLK_DIV12_EN, VCLK_DIV12_EN);
+
+		if (hdmi_use_enci)
+			/* select vclk_div12 for enci */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
+		else
+			/* select vclk_div12 for encp */
+			regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
+		break;
+	}
+
+	if (hdmi_use_enci)
+		/* Enable ENCI clock gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+				   CTS_ENCI_EN, CTS_ENCI_EN);
+	else
+		/* Enable ENCP clock gate */
+		regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+				   CTS_ENCP_EN, CTS_ENCP_EN);
+
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
 }
+EXPORT_SYMBOL_GPL(meson_vclk_setup);

+ 4 - 2
drivers/gpu/drm/meson/meson_vclk.h

@@ -23,12 +23,14 @@
 
 enum {
 	MESON_VCLK_TARGET_CVBS = 0,
+	MESON_VCLK_TARGET_HDMI = 1,
 };
 
 /* 27MHz is the CVBS Pixel Clock */
-#define MESON_VCLK_CVBS	27000
+#define MESON_VCLK_CVBS			27000
 
 void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
-		      unsigned int freq);
+		      unsigned int vclk_freq, unsigned int venc_freq,
+		      unsigned int dac_freq, bool hdmi_use_enci);
 
 #endif /* __MESON_VCLK_H */

+ 1248 - 6
drivers/gpu/drm/meson/meson_venc.c

@@ -26,16 +26,48 @@
 #include "meson_vclk.h"
 #include "meson_registers.h"
 
-/*
+/**
+ * DOC: Video Encoder
+ *
  * VENC Handle the pixels encoding to the output formats.
  * We handle the following encodings :
- * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
  *
- * What is missing :
+ * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
  * - TMDS/HDMI Encoding via ENCI_DIV and ENCP
  * - Setup of more clock rates for HDMI modes
+ *
+ * What is missing :
+ *
  * - LCD Panel encoding via ENCL
  * - TV Panel encoding via ENCT
+ *
+ * VENC paths :
+ *
+ * .. code::
+ *
+ *          _____   _____   ____________________
+ *   vd1---|     |-|     | | VENC     /---------|----VDAC
+ *   vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-|
+ *   osd1--|     |-|     | | \                  | X--HDMI-TX
+ *   osd2--|_____|-|_____| |  |\-ENCP--ENCP_DVI-|-|
+ *                         |  |                 |
+ *                         |  \--ENCL-----------|----LVDS
+ *                         |____________________|
+ *
+ * The ENCI is designed for PAl or NTSC encoding and can go through the VDAC
+ * directly for CVBS encoding or through the ENCI_DVI encoder for HDMI.
+ * The ENCP is designed for Progressive encoding but can also generate
+ * 1080i interlaced pixels, and was initialy desined to encode pixels for
+ * VDAC to output RGB ou YUV analog outputs.
+ * It's output is only used through the ENCP_DVI encoder for HDMI.
+ * The ENCL LVDS encoder is not implemented.
+ *
+ * The ENCI and ENCP encoders needs specially defined parameters for each
+ * supported mode and thus cannot be determined from standard video timings.
+ *
+ * The ENCI end ENCP DVI encoders are more generic and can generate any timings
+ * from the pixel data generated by ENCI or ENCP, so can use the standard video
+ * timings are source for HW parameters.
  */
 
 /* HHI Registers */
@@ -91,6 +123,1219 @@ struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
 	.analog_sync_adj = 0x9c00,
 };
 
+union meson_hdmi_venc_mode {
+	struct {
+		unsigned int mode_tag;
+		unsigned int hso_begin;
+		unsigned int hso_end;
+		unsigned int vso_even;
+		unsigned int vso_odd;
+		unsigned int macv_max_amp;
+		unsigned int video_prog_mode;
+		unsigned int video_mode;
+		unsigned int sch_adjust;
+		unsigned int yc_delay;
+		unsigned int pixel_start;
+		unsigned int pixel_end;
+		unsigned int top_field_line_start;
+		unsigned int top_field_line_end;
+		unsigned int bottom_field_line_start;
+		unsigned int bottom_field_line_end;
+	} enci;
+	struct {
+		unsigned int dvi_settings;
+		unsigned int video_mode;
+		unsigned int video_mode_adv;
+		unsigned int video_prog_mode;
+		bool video_prog_mode_present;
+		unsigned int video_sync_mode;
+		bool video_sync_mode_present;
+		unsigned int video_yc_dly;
+		bool video_yc_dly_present;
+		unsigned int video_rgb_ctrl;
+		bool video_rgb_ctrl_present;
+		unsigned int video_filt_ctrl;
+		bool video_filt_ctrl_present;
+		unsigned int video_ofld_voav_ofst;
+		bool video_ofld_voav_ofst_present;
+		unsigned int yfp1_htime;
+		unsigned int yfp2_htime;
+		unsigned int max_pxcnt;
+		unsigned int hspuls_begin;
+		unsigned int hspuls_end;
+		unsigned int hspuls_switch;
+		unsigned int vspuls_begin;
+		unsigned int vspuls_end;
+		unsigned int vspuls_bline;
+		unsigned int vspuls_eline;
+		unsigned int eqpuls_begin;
+		bool eqpuls_begin_present;
+		unsigned int eqpuls_end;
+		bool eqpuls_end_present;
+		unsigned int eqpuls_bline;
+		bool eqpuls_bline_present;
+		unsigned int eqpuls_eline;
+		bool eqpuls_eline_present;
+		unsigned int havon_begin;
+		unsigned int havon_end;
+		unsigned int vavon_bline;
+		unsigned int vavon_eline;
+		unsigned int hso_begin;
+		unsigned int hso_end;
+		unsigned int vso_begin;
+		unsigned int vso_end;
+		unsigned int vso_bline;
+		unsigned int vso_eline;
+		bool vso_eline_present;
+		unsigned int sy_val;
+		bool sy_val_present;
+		unsigned int sy2_val;
+		bool sy2_val_present;
+		unsigned int max_lncnt;
+	} encp;
+};
+
+union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
+	.enci = {
+		.hso_begin = 5,
+		.hso_end = 129,
+		.vso_even = 3,
+		.vso_odd = 260,
+		.macv_max_amp = 0x810b,
+		.video_prog_mode = 0xf0,
+		.video_mode = 0x8,
+		.sch_adjust = 0x20,
+		.yc_delay = 0,
+		.pixel_start = 227,
+		.pixel_end = 1667,
+		.top_field_line_start = 18,
+		.top_field_line_end = 258,
+		.bottom_field_line_start = 19,
+		.bottom_field_line_end = 259,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
+	.enci = {
+		.hso_begin = 3,
+		.hso_end = 129,
+		.vso_even = 3,
+		.vso_odd = 260,
+		.macv_max_amp = 8107,
+		.video_prog_mode = 0xff,
+		.video_mode = 0x13,
+		.sch_adjust = 0x28,
+		.yc_delay = 0x333,
+		.pixel_start = 251,
+		.pixel_end = 1691,
+		.top_field_line_start = 22,
+		.top_field_line_end = 310,
+		.bottom_field_line_start = 23,
+		.bottom_field_line_end = 311,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
+	.encp = {
+		.dvi_settings = 0x21,
+		.video_mode = 0x4000,
+		.video_mode_adv = 0x9,
+		.video_prog_mode = 0,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 7,
+		.video_sync_mode_present = true,
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		.video_filt_ctrl = 0x2052,
+		.video_filt_ctrl_present = true,
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 244,
+		.yfp2_htime = 1630,
+		.max_pxcnt = 1715,
+		.hspuls_begin = 0x22,
+		.hspuls_end = 0xa0,
+		.hspuls_switch = 88,
+		.vspuls_begin = 0,
+		.vspuls_end = 1589,
+		.vspuls_bline = 0,
+		.vspuls_eline = 5,
+		.havon_begin = 249,
+		.havon_end = 1689,
+		.vavon_bline = 42,
+		.vavon_eline = 521,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		/* eqpuls_bline */
+		/* eqpuls_eline */
+		.hso_begin = 3,
+		.hso_end = 5,
+		.vso_begin = 3,
+		.vso_end = 5,
+		.vso_bline = 0,
+		/* vso_eline */
+		.sy_val	= 8,
+		.sy_val_present = true,
+		.sy2_val = 0x1d8,
+		.sy2_val_present = true,
+		.max_lncnt = 524,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
+	.encp = {
+		.dvi_settings = 0x21,
+		.video_mode = 0x4000,
+		.video_mode_adv = 0x9,
+		.video_prog_mode = 0,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 7,
+		.video_sync_mode_present = true,
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		.video_filt_ctrl = 0x52,
+		.video_filt_ctrl_present = true,
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 235,
+		.yfp2_htime = 1674,
+		.max_pxcnt = 1727,
+		.hspuls_begin = 0,
+		.hspuls_end = 0x80,
+		.hspuls_switch = 88,
+		.vspuls_begin = 0,
+		.vspuls_end = 1599,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 235,
+		.havon_end = 1674,
+		.vavon_bline = 44,
+		.vavon_eline = 619,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		/* eqpuls_bline */
+		/* eqpuls_eline */
+		.hso_begin = 0x80,
+		.hso_end = 0,
+		.vso_begin = 0,
+		.vso_end = 5,
+		.vso_bline = 0,
+		/* vso_eline */
+		.sy_val	= 8,
+		.sy_val_present = true,
+		.sy2_val = 0x1d8,
+		.sy2_val_present = true,
+		.max_lncnt = 624,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
+	.encp = {
+		.dvi_settings = 0x2029,
+		.video_mode = 0x4040,
+		.video_mode_adv = 0x19,
+		/* video_prog_mode */
+		/* video_sync_mode */
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		/* video_filt_ctrl */
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 648,
+		.yfp2_htime = 3207,
+		.max_pxcnt = 3299,
+		.hspuls_begin = 80,
+		.hspuls_end = 240,
+		.hspuls_switch = 80,
+		.vspuls_begin = 688,
+		.vspuls_end = 3248,
+		.vspuls_bline = 4,
+		.vspuls_eline = 8,
+		.havon_begin = 648,
+		.havon_end = 3207,
+		.vavon_bline = 29,
+		.vavon_eline = 748,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		/* eqpuls_bline */
+		/* eqpuls_eline */
+		.hso_begin = 256,
+		.hso_end = 168,
+		.vso_begin = 168,
+		.vso_end = 256,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 749,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
+	.encp = {
+		.dvi_settings = 0x202d,
+		.video_mode = 0x4040,
+		.video_mode_adv = 0x19,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 0x407,
+		.video_sync_mode_present = true,
+		.video_yc_dly = 0,
+		.video_yc_dly_present = true,
+		/* video_rgb_ctrl */
+		/* video_filt_ctrl */
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 648,
+		.yfp2_htime = 3207,
+		.max_pxcnt = 3959,
+		.hspuls_begin = 80,
+		.hspuls_end = 240,
+		.hspuls_switch = 80,
+		.vspuls_begin = 688,
+		.vspuls_end = 3248,
+		.vspuls_bline = 4,
+		.vspuls_eline = 8,
+		.havon_begin = 648,
+		.havon_end = 3207,
+		.vavon_bline = 29,
+		.vavon_eline = 748,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		/* eqpuls_bline */
+		/* eqpuls_eline */
+		.hso_begin = 128,
+		.hso_end = 208,
+		.vso_begin = 128,
+		.vso_end = 128,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 749,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
+	.encp = {
+		.dvi_settings = 0x2029,
+		.video_mode = 0x5ffc,
+		.video_mode_adv = 0x19,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 0x207,
+		.video_sync_mode_present = true,
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		/* video_filt_ctrl */
+		.video_ofld_voav_ofst = 0x11,
+		.video_ofld_voav_ofst_present = true,
+		.yfp1_htime = 516,
+		.yfp2_htime = 4355,
+		.max_pxcnt = 4399,
+		.hspuls_begin = 88,
+		.hspuls_end = 264,
+		.hspuls_switch = 88,
+		.vspuls_begin = 440,
+		.vspuls_end = 2200,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 516,
+		.havon_end = 4355,
+		.vavon_bline = 20,
+		.vavon_eline = 559,
+		.eqpuls_begin = 2288,
+		.eqpuls_begin_present = true,
+		.eqpuls_end = 2464,
+		.eqpuls_end_present = true,
+		.eqpuls_bline = 0,
+		.eqpuls_bline_present = true,
+		.eqpuls_eline = 4,
+		.eqpuls_eline_present = true,
+		.hso_begin = 264,
+		.hso_end = 176,
+		.vso_begin = 88,
+		.vso_end = 88,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 1124,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
+	.encp = {
+		.dvi_settings = 0x202d,
+		.video_mode = 0x5ffc,
+		.video_mode_adv = 0x19,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 0x7,
+		.video_sync_mode_present = true,
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		/* video_filt_ctrl */
+		.video_ofld_voav_ofst = 0x11,
+		.video_ofld_voav_ofst_present = true,
+		.yfp1_htime = 526,
+		.yfp2_htime = 4365,
+		.max_pxcnt = 5279,
+		.hspuls_begin = 88,
+		.hspuls_end = 264,
+		.hspuls_switch = 88,
+		.vspuls_begin = 440,
+		.vspuls_end = 2200,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 526,
+		.havon_end = 4365,
+		.vavon_bline = 20,
+		.vavon_eline = 559,
+		.eqpuls_begin = 2288,
+		.eqpuls_begin_present = true,
+		.eqpuls_end = 2464,
+		.eqpuls_end_present = true,
+		.eqpuls_bline = 0,
+		.eqpuls_bline_present = true,
+		.eqpuls_eline = 4,
+		.eqpuls_eline_present = true,
+		.hso_begin = 142,
+		.hso_end = 230,
+		.vso_begin = 142,
+		.vso_end = 142,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 1124,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
+	.encp = {
+		.dvi_settings = 0xd,
+		.video_mode = 0x4040,
+		.video_mode_adv = 0x18,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 0x7,
+		.video_sync_mode_present = true,
+		.video_yc_dly = 0,
+		.video_yc_dly_present = true,
+		.video_rgb_ctrl = 2,
+		.video_rgb_ctrl_present = true,
+		.video_filt_ctrl = 0x1052,
+		.video_filt_ctrl_present = true,
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 271,
+		.yfp2_htime = 2190,
+		.max_pxcnt = 2749,
+		.hspuls_begin = 44,
+		.hspuls_end = 132,
+		.hspuls_switch = 44,
+		.vspuls_begin = 220,
+		.vspuls_end = 2140,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 271,
+		.havon_end = 2190,
+		.vavon_bline = 41,
+		.vavon_eline = 1120,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		.eqpuls_bline = 0,
+		.eqpuls_bline_present = true,
+		.eqpuls_eline = 4,
+		.eqpuls_eline_present = true,
+		.hso_begin = 79,
+		.hso_end = 123,
+		.vso_begin = 79,
+		.vso_end = 79,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 1124,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
+	.encp = {
+		.dvi_settings = 0x1,
+		.video_mode = 0x4040,
+		.video_mode_adv = 0x18,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		/* video_sync_mode */
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		.video_filt_ctrl = 0x1052,
+		.video_filt_ctrl_present = true,
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 140,
+		.yfp2_htime = 2060,
+		.max_pxcnt = 2199,
+		.hspuls_begin = 2156,
+		.hspuls_end = 44,
+		.hspuls_switch = 44,
+		.vspuls_begin = 140,
+		.vspuls_end = 2059,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 148,
+		.havon_end = 2067,
+		.vavon_bline = 41,
+		.vavon_eline = 1120,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		/* eqpuls_bline */
+		/* eqpuls_eline */
+		.hso_begin = 44,
+		.hso_end = 2156,
+		.vso_begin = 2100,
+		.vso_end = 2164,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 1124,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
+	.encp = {
+		.dvi_settings = 0xd,
+		.video_mode = 0x4040,
+		.video_mode_adv = 0x18,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		.video_sync_mode = 0x7,
+		.video_sync_mode_present = true,
+		.video_yc_dly = 0,
+		.video_yc_dly_present = true,
+		.video_rgb_ctrl = 2,
+		.video_rgb_ctrl_present = true,
+		/* video_filt_ctrl */
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 271,
+		.yfp2_htime = 2190,
+		.max_pxcnt = 2639,
+		.hspuls_begin = 44,
+		.hspuls_end = 132,
+		.hspuls_switch = 44,
+		.vspuls_begin = 220,
+		.vspuls_end = 2140,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 271,
+		.havon_end = 2190,
+		.vavon_bline = 41,
+		.vavon_eline = 1120,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		.eqpuls_bline = 0,
+		.eqpuls_bline_present = true,
+		.eqpuls_eline = 4,
+		.eqpuls_eline_present = true,
+		.hso_begin = 79,
+		.hso_end = 123,
+		.vso_begin = 79,
+		.vso_end = 79,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 1124,
+	},
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
+	.encp = {
+		.dvi_settings = 0x1,
+		.video_mode = 0x4040,
+		.video_mode_adv = 0x18,
+		.video_prog_mode = 0x100,
+		.video_prog_mode_present = true,
+		/* video_sync_mode */
+		/* video_yc_dly */
+		/* video_rgb_ctrl */
+		.video_filt_ctrl = 0x1052,
+		.video_filt_ctrl_present = true,
+		/* video_ofld_voav_ofst */
+		.yfp1_htime = 140,
+		.yfp2_htime = 2060,
+		.max_pxcnt = 2199,
+		.hspuls_begin = 2156,
+		.hspuls_end = 44,
+		.hspuls_switch = 44,
+		.vspuls_begin = 140,
+		.vspuls_end = 2059,
+		.vspuls_bline = 0,
+		.vspuls_eline = 4,
+		.havon_begin = 148,
+		.havon_end = 2067,
+		.vavon_bline = 41,
+		.vavon_eline = 1120,
+		/* eqpuls_begin */
+		/* eqpuls_end */
+		/* eqpuls_bline */
+		/* eqpuls_eline */
+		.hso_begin = 44,
+		.hso_end = 2156,
+		.vso_begin = 2100,
+		.vso_end = 2164,
+		.vso_bline = 0,
+		.vso_eline = 5,
+		.vso_eline_present = true,
+		/* sy_val */
+		/* sy2_val */
+		.max_lncnt = 1124,
+	},
+};
+
+struct meson_hdmi_venc_vic_mode {
+	unsigned int vic;
+	union meson_hdmi_venc_mode *mode;
+} meson_hdmi_venc_vic_modes[] = {
+	{ 6, &meson_hdmi_enci_mode_480i },
+	{ 7, &meson_hdmi_enci_mode_480i },
+	{ 21, &meson_hdmi_enci_mode_576i },
+	{ 22, &meson_hdmi_enci_mode_576i },
+	{ 2, &meson_hdmi_encp_mode_480p },
+	{ 3, &meson_hdmi_encp_mode_480p },
+	{ 17, &meson_hdmi_encp_mode_576p },
+	{ 18, &meson_hdmi_encp_mode_576p },
+	{ 4, &meson_hdmi_encp_mode_720p60 },
+	{ 19, &meson_hdmi_encp_mode_720p50 },
+	{ 5, &meson_hdmi_encp_mode_1080i60 },
+	{ 20, &meson_hdmi_encp_mode_1080i50 },
+	{ 32, &meson_hdmi_encp_mode_1080p24 },
+	{ 34, &meson_hdmi_encp_mode_1080p30 },
+	{ 31, &meson_hdmi_encp_mode_1080p50 },
+	{ 16, &meson_hdmi_encp_mode_1080p60 },
+	{ 0, NULL}, /* sentinel */
+};
+
+static signed int to_signed(unsigned int a)
+{
+	if (a <= 7)
+		return a;
+	else
+		return a - 16;
+}
+
+static unsigned long modulo(unsigned long a, unsigned long b)
+{
+	if (a >= b)
+		return a - b;
+	else
+		return a;
+}
+
+bool meson_venc_hdmi_supported_vic(int vic)
+{
+	struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
+
+	while (vmode->vic && vmode->mode) {
+		if (vmode->vic == vic)
+			return true;
+		vmode++;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
+
+static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
+{
+	struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
+
+	while (vmode->vic && vmode->mode) {
+		if (vmode->vic == vic)
+			return vmode->mode;
+		vmode++;
+	}
+
+	return NULL;
+}
+
+bool meson_venc_hdmi_venc_repeat(int vic)
+{
+	/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
+	if (vic == 6 || vic == 7 || /* 480i */
+	    vic == 21 || vic == 22 || /* 576i */
+	    vic == 17 || vic == 18 || /* 576p */
+	    vic == 2 || vic == 3 || /* 480p */
+	    vic == 4 || /* 720p60 */
+	    vic == 19 || /* 720p50 */
+	    vic == 5 || /* 1080i60 */
+	    vic == 20)	/* 1080i50 */
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
+
+void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
+			      struct drm_display_mode *mode)
+{
+	union meson_hdmi_venc_mode *vmode = NULL;
+	bool use_enci = false;
+	bool venc_repeat = false;
+	bool hdmi_repeat = false;
+	unsigned int venc_hdmi_latency = 2;
+	unsigned long total_pixels_venc = 0;
+	unsigned long active_pixels_venc = 0;
+	unsigned long front_porch_venc = 0;
+	unsigned long hsync_pixels_venc = 0;
+	unsigned long de_h_begin = 0;
+	unsigned long de_h_end = 0;
+	unsigned long de_v_begin_even = 0;
+	unsigned long de_v_end_even = 0;
+	unsigned long de_v_begin_odd = 0;
+	unsigned long de_v_end_odd = 0;
+	unsigned long hs_begin = 0;
+	unsigned long hs_end = 0;
+	unsigned long vs_adjust = 0;
+	unsigned long vs_bline_evn = 0;
+	unsigned long vs_eline_evn = 0;
+	unsigned long vs_bline_odd = 0;
+	unsigned long vs_eline_odd = 0;
+	unsigned long vso_begin_evn = 0;
+	unsigned long vso_begin_odd = 0;
+	unsigned int eof_lines;
+	unsigned int sof_lines;
+	unsigned int vsync_lines;
+
+	vmode = meson_venc_hdmi_get_vic_vmode(vic);
+	if (!vmode) {
+		dev_err(priv->dev, "%s: Fatal Error, unsupported vic %d\n",
+			__func__, vic);
+		return;
+	}
+
+	/* Use VENCI for 480i and 576i and double HDMI pixels */
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
+		hdmi_repeat = true;
+		use_enci = true;
+		venc_hdmi_latency = 1;
+	}
+
+	/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
+	if (meson_venc_hdmi_venc_repeat(vic))
+		venc_repeat = true;
+
+	eof_lines = mode->vsync_start - mode->vdisplay;
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		eof_lines /= 2;
+	sof_lines = mode->vtotal - mode->vsync_end;
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		sof_lines /= 2;
+	vsync_lines = mode->vsync_end - mode->vsync_start;
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vsync_lines /= 2;
+
+	total_pixels_venc = mode->htotal;
+	if (hdmi_repeat)
+		total_pixels_venc /= 2;
+	if (venc_repeat)
+		total_pixels_venc *= 2;
+
+	active_pixels_venc = mode->hdisplay;
+	if (hdmi_repeat)
+		active_pixels_venc /= 2;
+	if (venc_repeat)
+		active_pixels_venc *= 2;
+
+	front_porch_venc = (mode->hsync_start - mode->hdisplay);
+	if (hdmi_repeat)
+		front_porch_venc /= 2;
+	if (venc_repeat)
+		front_porch_venc *= 2;
+
+	hsync_pixels_venc = (mode->hsync_end - mode->hsync_start);
+	if (hdmi_repeat)
+		hsync_pixels_venc /= 2;
+	if (venc_repeat)
+		hsync_pixels_venc *= 2;
+
+	/* Disable VDACs */
+	writel_bits_relaxed(0x1f, 0x1f,
+			priv->io_base + _REG(VENC_VDAC_SETTING));
+
+	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
+	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
+
+	if (use_enci) {
+		unsigned int lines_f0;
+		unsigned int lines_f1;
+
+		/* CVBS Filter settings */
+		writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
+		writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+
+		/* Digital Video Select : Interlace, clk27 clk, external */
+		writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
+
+		/* Reset Video Mode */
+		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
+		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+
+		/* Horizontal sync signal output */
+		writel_relaxed(vmode->enci.hso_begin,
+				priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
+		writel_relaxed(vmode->enci.hso_end,
+				priv->io_base + _REG(ENCI_SYNC_HSO_END));
+
+		/* Vertical Sync lines */
+		writel_relaxed(vmode->enci.vso_even,
+				priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
+		writel_relaxed(vmode->enci.vso_odd,
+				priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
+
+		/* Macrovision max amplitude change */
+		writel_relaxed(vmode->enci.macv_max_amp,
+				priv->io_base + _REG(ENCI_MACV_MAX_AMP));
+
+		/* Video mode */
+		writel_relaxed(vmode->enci.video_prog_mode,
+				priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
+		writel_relaxed(vmode->enci.video_mode,
+				priv->io_base + _REG(ENCI_VIDEO_MODE));
+
+		/* Advanced Video Mode :
+		 * Demux shifting 0x2
+		 * Blank line end at line17/22
+		 * High bandwidth Luma Filter
+		 * Low bandwidth Chroma Filter
+		 * Bypass luma low pass filter
+		 * No macrovision on CSYNC
+		 */
+		writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+
+		writel(vmode->enci.sch_adjust,
+				priv->io_base + _REG(ENCI_VIDEO_SCH));
+
+		/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
+		writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
+
+		if (vmode->enci.yc_delay)
+			writel_relaxed(vmode->enci.yc_delay,
+					priv->io_base + _REG(ENCI_YC_DELAY));
+
+
+		/* UNreset Interlaced TV Encoder */
+		writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
+
+		/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
+		writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+
+		/* Timings */
+		writel_relaxed(vmode->enci.pixel_start,
+			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
+		writel_relaxed(vmode->enci.pixel_end,
+			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
+
+		writel_relaxed(vmode->enci.top_field_line_start,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
+		writel_relaxed(vmode->enci.top_field_line_end,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
+
+		writel_relaxed(vmode->enci.bottom_field_line_start,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
+		writel_relaxed(vmode->enci.bottom_field_line_end,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
+
+		/* Select ENCI for VIU */
+		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
+
+		/* Interlace video enable */
+		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+
+		lines_f0 = mode->vtotal >> 1;
+		lines_f1 = lines_f0 + 1;
+
+		de_h_begin = modulo(readl_relaxed(priv->io_base +
+					_REG(ENCI_VFIFO2VD_PIXEL_START))
+					+ venc_hdmi_latency,
+				    total_pixels_venc);
+		de_h_end  = modulo(de_h_begin + active_pixels_venc,
+				   total_pixels_venc);
+
+		writel_relaxed(de_h_begin,
+				priv->io_base + _REG(ENCI_DE_H_BEGIN));
+		writel_relaxed(de_h_end,
+				priv->io_base + _REG(ENCI_DE_H_END));
+
+		de_v_begin_even = readl_relaxed(priv->io_base +
+					_REG(ENCI_VFIFO2VD_LINE_TOP_START));
+		de_v_end_even  = de_v_begin_even + mode->vdisplay;
+		de_v_begin_odd = readl_relaxed(priv->io_base +
+					_REG(ENCI_VFIFO2VD_LINE_BOT_START));
+		de_v_end_odd = de_v_begin_odd + mode->vdisplay;
+
+		writel_relaxed(de_v_begin_even,
+				priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN));
+		writel_relaxed(de_v_end_even,
+				priv->io_base + _REG(ENCI_DE_V_END_EVEN));
+		writel_relaxed(de_v_begin_odd,
+				priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD));
+		writel_relaxed(de_v_end_odd,
+				priv->io_base + _REG(ENCI_DE_V_END_ODD));
+
+		/* Program Hsync timing */
+		hs_begin = de_h_end + front_porch_venc;
+		if (de_h_end + front_porch_venc >= total_pixels_venc) {
+			hs_begin -= total_pixels_venc;
+			vs_adjust  = 1;
+		} else {
+			hs_begin = de_h_end + front_porch_venc;
+			vs_adjust  = 0;
+		}
+
+		hs_end = modulo(hs_begin + hsync_pixels_venc,
+				total_pixels_venc);
+		writel_relaxed(hs_begin,
+				priv->io_base + _REG(ENCI_DVI_HSO_BEGIN));
+		writel_relaxed(hs_end,
+				priv->io_base + _REG(ENCI_DVI_HSO_END));
+
+		/* Program Vsync timing for even field */
+		if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) {
+			vs_bline_evn = (de_v_end_odd - 1)
+					+ eof_lines
+					+ vs_adjust
+					- lines_f1;
+			vs_eline_evn = vs_bline_evn + vsync_lines;
+
+			writel_relaxed(vs_bline_evn,
+				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
+
+			writel_relaxed(vs_eline_evn,
+				priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));
+
+			writel_relaxed(hs_begin,
+				priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN));
+			writel_relaxed(hs_begin,
+				priv->io_base + _REG(ENCI_DVI_VSO_END_EVN));
+		} else {
+			vs_bline_odd = (de_v_end_odd - 1)
+					+ eof_lines
+					+ vs_adjust;
+
+			writel_relaxed(vs_bline_odd,
+				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
+
+			writel_relaxed(hs_begin,
+				priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
+
+			if ((vs_bline_odd + vsync_lines) >= lines_f1) {
+				vs_eline_evn = vs_bline_odd
+						+ vsync_lines
+						- lines_f1;
+
+				writel_relaxed(vs_eline_evn, priv->io_base
+						+ _REG(ENCI_DVI_VSO_ELINE_EVN));
+
+				writel_relaxed(hs_begin, priv->io_base
+						+ _REG(ENCI_DVI_VSO_END_EVN));
+			} else {
+				vs_eline_odd = vs_bline_odd
+						+ vsync_lines;
+
+				writel_relaxed(vs_eline_odd, priv->io_base
+						+ _REG(ENCI_DVI_VSO_ELINE_ODD));
+
+				writel_relaxed(hs_begin, priv->io_base
+						+ _REG(ENCI_DVI_VSO_END_ODD));
+			}
+		}
+
+		/* Program Vsync timing for odd field */
+		if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) {
+			vs_bline_odd = (de_v_end_even - 1)
+					+ (eof_lines + 1)
+					- lines_f0;
+			vs_eline_odd = vs_bline_odd + vsync_lines;
+
+			writel_relaxed(vs_bline_odd,
+				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
+
+			writel_relaxed(vs_eline_odd,
+				priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));
+
+			vso_begin_odd  = modulo(hs_begin
+						+ (total_pixels_venc >> 1),
+						total_pixels_venc);
+
+			writel_relaxed(vso_begin_odd,
+				priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
+			writel_relaxed(vso_begin_odd,
+				priv->io_base + _REG(ENCI_DVI_VSO_END_ODD));
+		} else {
+			vs_bline_evn = (de_v_end_even - 1)
+					+ (eof_lines + 1);
+
+			writel_relaxed(vs_bline_evn,
+				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
+
+			vso_begin_evn  = modulo(hs_begin
+						+ (total_pixels_venc >> 1),
+						total_pixels_venc);
+
+			writel_relaxed(vso_begin_evn, priv->io_base
+					+ _REG(ENCI_DVI_VSO_BEGIN_EVN));
+
+			if (vs_bline_evn + vsync_lines >= lines_f0) {
+				vs_eline_odd = vs_bline_evn
+						+ vsync_lines
+						- lines_f0;
+
+				writel_relaxed(vs_eline_odd, priv->io_base
+						+ _REG(ENCI_DVI_VSO_ELINE_ODD));
+
+				writel_relaxed(vso_begin_evn, priv->io_base
+						+ _REG(ENCI_DVI_VSO_END_ODD));
+			} else {
+				vs_eline_evn = vs_bline_evn + vsync_lines;
+
+				writel_relaxed(vs_eline_evn, priv->io_base
+						+ _REG(ENCI_DVI_VSO_ELINE_EVN));
+
+				writel_relaxed(vso_begin_evn, priv->io_base
+						+ _REG(ENCI_DVI_VSO_END_EVN));
+			}
+		}
+	} else {
+		writel_relaxed(vmode->encp.dvi_settings,
+				priv->io_base + _REG(VENC_DVI_SETTING));
+		writel_relaxed(vmode->encp.video_mode,
+				priv->io_base + _REG(ENCP_VIDEO_MODE));
+		writel_relaxed(vmode->encp.video_mode_adv,
+				priv->io_base + _REG(ENCP_VIDEO_MODE_ADV));
+		if (vmode->encp.video_prog_mode_present)
+			writel_relaxed(vmode->encp.video_prog_mode,
+				priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
+		if (vmode->encp.video_sync_mode_present)
+			writel_relaxed(vmode->encp.video_sync_mode,
+				priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE));
+		if (vmode->encp.video_yc_dly_present)
+			writel_relaxed(vmode->encp.video_yc_dly,
+				priv->io_base + _REG(ENCP_VIDEO_YC_DLY));
+		if (vmode->encp.video_rgb_ctrl_present)
+			writel_relaxed(vmode->encp.video_rgb_ctrl,
+				priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL));
+		if (vmode->encp.video_filt_ctrl_present)
+			writel_relaxed(vmode->encp.video_filt_ctrl,
+				priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL));
+		if (vmode->encp.video_ofld_voav_ofst_present)
+			writel_relaxed(vmode->encp.video_ofld_voav_ofst,
+				priv->io_base
+				+ _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
+		writel_relaxed(vmode->encp.yfp1_htime,
+				priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME));
+		writel_relaxed(vmode->encp.yfp2_htime,
+				priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME));
+		writel_relaxed(vmode->encp.max_pxcnt,
+				priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT));
+		writel_relaxed(vmode->encp.hspuls_begin,
+				priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN));
+		writel_relaxed(vmode->encp.hspuls_end,
+				priv->io_base + _REG(ENCP_VIDEO_HSPULS_END));
+		writel_relaxed(vmode->encp.hspuls_switch,
+				priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH));
+		writel_relaxed(vmode->encp.vspuls_begin,
+				priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN));
+		writel_relaxed(vmode->encp.vspuls_end,
+				priv->io_base + _REG(ENCP_VIDEO_VSPULS_END));
+		writel_relaxed(vmode->encp.vspuls_bline,
+				priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE));
+		writel_relaxed(vmode->encp.vspuls_eline,
+				priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE));
+		if (vmode->encp.eqpuls_begin_present)
+			writel_relaxed(vmode->encp.eqpuls_begin,
+				priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN));
+		if (vmode->encp.eqpuls_end_present)
+			writel_relaxed(vmode->encp.eqpuls_end,
+				priv->io_base + _REG(ENCP_VIDEO_EQPULS_END));
+		if (vmode->encp.eqpuls_bline_present)
+			writel_relaxed(vmode->encp.eqpuls_bline,
+				priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE));
+		if (vmode->encp.eqpuls_eline_present)
+			writel_relaxed(vmode->encp.eqpuls_eline,
+				priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE));
+		writel_relaxed(vmode->encp.havon_begin,
+				priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN));
+		writel_relaxed(vmode->encp.havon_end,
+				priv->io_base + _REG(ENCP_VIDEO_HAVON_END));
+		writel_relaxed(vmode->encp.vavon_bline,
+				priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE));
+		writel_relaxed(vmode->encp.vavon_eline,
+				priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE));
+		writel_relaxed(vmode->encp.hso_begin,
+				priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN));
+		writel_relaxed(vmode->encp.hso_end,
+				priv->io_base + _REG(ENCP_VIDEO_HSO_END));
+		writel_relaxed(vmode->encp.vso_begin,
+				priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN));
+		writel_relaxed(vmode->encp.vso_end,
+				priv->io_base + _REG(ENCP_VIDEO_VSO_END));
+		writel_relaxed(vmode->encp.vso_bline,
+				priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE));
+		if (vmode->encp.vso_eline_present)
+			writel_relaxed(vmode->encp.vso_eline,
+				priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE));
+		if (vmode->encp.sy_val_present)
+			writel_relaxed(vmode->encp.sy_val,
+				priv->io_base + _REG(ENCP_VIDEO_SY_VAL));
+		if (vmode->encp.sy2_val_present)
+			writel_relaxed(vmode->encp.sy2_val,
+				priv->io_base + _REG(ENCP_VIDEO_SY2_VAL));
+		writel_relaxed(vmode->encp.max_lncnt,
+				priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT));
+
+		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
+
+		/* Set DE signal’s polarity is active high */
+		writel_bits_relaxed(BIT(14), BIT(14),
+				    priv->io_base + _REG(ENCP_VIDEO_MODE));
+
+		/* Program DE timing */
+		de_h_begin = modulo(readl_relaxed(priv->io_base +
+					_REG(ENCP_VIDEO_HAVON_BEGIN))
+					+ venc_hdmi_latency,
+				    total_pixels_venc);
+		de_h_end = modulo(de_h_begin + active_pixels_venc,
+				  total_pixels_venc);
+
+		writel_relaxed(de_h_begin,
+				priv->io_base + _REG(ENCP_DE_H_BEGIN));
+		writel_relaxed(de_h_end,
+				priv->io_base + _REG(ENCP_DE_H_END));
+
+		/* Program DE timing for even field */
+		de_v_begin_even = readl_relaxed(priv->io_base
+						+ _REG(ENCP_VIDEO_VAVON_BLINE));
+		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+			de_v_end_even = de_v_begin_even +
+					(mode->vdisplay / 2);
+		else
+			de_v_end_even = de_v_begin_even + mode->vdisplay;
+
+		writel_relaxed(de_v_begin_even,
+				priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN));
+		writel_relaxed(de_v_end_even,
+				priv->io_base + _REG(ENCP_DE_V_END_EVEN));
+
+		/* Program DE timing for odd field if needed */
+		if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+			unsigned int ofld_voav_ofst =
+				readl_relaxed(priv->io_base +
+					_REG(ENCP_VIDEO_OFLD_VOAV_OFST));
+			de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4)
+						+ de_v_begin_even
+						+ ((mode->vtotal - 1) / 2);
+			de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2);
+
+			writel_relaxed(de_v_begin_odd,
+				priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD));
+			writel_relaxed(de_v_end_odd,
+				priv->io_base + _REG(ENCP_DE_V_END_ODD));
+		}
+
+		/* Program Hsync timing */
+		if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
+			hs_begin = de_h_end
+				   + front_porch_venc
+				   - total_pixels_venc;
+			vs_adjust  = 1;
+		} else {
+			hs_begin = de_h_end
+				   + front_porch_venc;
+			vs_adjust  = 0;
+		}
+
+		hs_end = modulo(hs_begin + hsync_pixels_venc,
+				total_pixels_venc);
+
+		writel_relaxed(hs_begin,
+				priv->io_base + _REG(ENCP_DVI_HSO_BEGIN));
+		writel_relaxed(hs_end,
+				priv->io_base + _REG(ENCP_DVI_HSO_END));
+
+		/* Program Vsync timing for even field */
+		if (de_v_begin_even >=
+				(sof_lines + vsync_lines + (1 - vs_adjust)))
+			vs_bline_evn = de_v_begin_even
+					- sof_lines
+					- vsync_lines
+					- (1 - vs_adjust);
+		else
+			vs_bline_evn = mode->vtotal
+					+ de_v_begin_even
+					- sof_lines
+					- vsync_lines
+					- (1 - vs_adjust);
+
+		vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
+					mode->vtotal);
+
+		writel_relaxed(vs_bline_evn,
+				priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN));
+		writel_relaxed(vs_eline_evn,
+				priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN));
+
+		vso_begin_evn = hs_begin;
+		writel_relaxed(vso_begin_evn,
+				priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN));
+		writel_relaxed(vso_begin_evn,
+				priv->io_base + _REG(ENCP_DVI_VSO_END_EVN));
+
+		/* Program Vsync timing for odd field if needed */
+		if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+			vs_bline_odd = (de_v_begin_odd - 1)
+					- sof_lines
+					- vsync_lines;
+			vs_eline_odd = (de_v_begin_odd - 1)
+					- vsync_lines;
+			vso_begin_odd  = modulo(hs_begin
+						+ (total_pixels_venc >> 1),
+						total_pixels_venc);
+
+			writel_relaxed(vs_bline_odd,
+				priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD));
+			writel_relaxed(vs_eline_odd,
+				priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD));
+			writel_relaxed(vso_begin_odd,
+				priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD));
+			writel_relaxed(vso_begin_odd,
+				priv->io_base + _REG(ENCP_DVI_VSO_END_ODD));
+		}
+
+		/* Select ENCP for VIU */
+		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
+	}
+
+	writel_relaxed((use_enci ? 1 : 2) |
+		       (mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
+		       (mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
+		       4 << 5 |
+		       (venc_repeat ? 1 << 8 : 0) |
+		       (hdmi_repeat ? 1 << 12 : 0),
+		       priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	priv->venc.hdmi_repeat = hdmi_repeat;
+	priv->venc.venc_repeat = venc_repeat;
+	priv->venc.hdmi_use_enci = use_enci;
+
+	priv->venc.current_mode = MESON_VENC_MODE_HDMI;
+}
+EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
+
 void meson_venci_cvbs_mode_set(struct meson_drm *priv,
 			       struct meson_cvbs_enci_mode *mode)
 {
@@ -223,9 +1468,6 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
 	writel_relaxed(mode->analog_sync_adj,
 			priv->io_base + _REG(ENCI_SYNC_ADJ));
 
-	/* Setup 27MHz vclk2 for ENCI and VDAC */
-	meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS);
-
 	priv->venc.current_mode = mode->mode_tag;
 }
 

+ 7 - 0
drivers/gpu/drm/meson/meson_venc.h

@@ -30,6 +30,7 @@ enum {
 	MESON_VENC_MODE_NONE = 0,
 	MESON_VENC_MODE_CVBS_PAL,
 	MESON_VENC_MODE_CVBS_NTSC,
+	MESON_VENC_MODE_HDMI,
 };
 
 struct meson_cvbs_enci_mode {
@@ -56,12 +57,18 @@ struct meson_cvbs_enci_mode {
 	unsigned int analog_sync_adj;
 };
 
+/* HDMI Clock parameters */
+bool meson_venc_hdmi_supported_vic(int vic);
+bool meson_venc_hdmi_venc_repeat(int vic);
+
 /* CVBS Timings and Parameters */
 extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal;
 extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;
 
 void meson_venci_cvbs_mode_set(struct meson_drm *priv,
 			       struct meson_cvbs_enci_mode *mode);
+void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
+			      struct drm_display_mode *mode);
 unsigned int meson_venci_get_field(struct meson_drm *priv);
 
 void meson_venc_enable_vsync(struct meson_drm *priv);

+ 13 - 17
drivers/gpu/drm/meson/meson_venc_cvbs.c

@@ -32,6 +32,7 @@
 
 #include "meson_venc_cvbs.h"
 #include "meson_venc.h"
+#include "meson_vclk.h"
 #include "meson_registers.h"
 
 /* HHI VDAC Registers */
@@ -194,14 +195,20 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
 {
 	struct meson_venc_cvbs *meson_venc_cvbs =
 					encoder_to_meson_venc_cvbs(encoder);
+	struct meson_drm *priv = meson_venc_cvbs->priv;
 	int i;
 
 	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
 		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
 
 		if (drm_mode_equal(mode, &meson_mode->mode)) {
-			meson_venci_cvbs_mode_set(meson_venc_cvbs->priv,
+			meson_venci_cvbs_mode_set(priv,
 						  meson_mode->enci);
+
+			/* Setup 27MHz vclk2 for ENCI and VDAC */
+			meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
+					 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
+					 MESON_VCLK_CVBS, true);
 			break;
 		}
 	}
@@ -217,25 +224,14 @@ static const struct drm_encoder_helper_funcs
 
 static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv)
 {
-	struct device_node *ep, *remote;
+	struct device_node *remote;
 
-	/* CVBS VDAC output is on the first port, first endpoint */
-	ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0);
-	if (!ep)
+	remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0);
+	if (!remote)
 		return false;
 
-
-	/* If the endpoint node exists, consider it enabled */
-	remote = of_graph_get_remote_port(ep);
-	if (remote) {
-		of_node_put(ep);
-		return true;
-	}
-
-	of_node_put(ep);
 	of_node_put(remote);
-
-	return false;
+	return true;
 }
 
 int meson_venc_cvbs_create(struct meson_drm *priv)
@@ -248,7 +244,7 @@ int meson_venc_cvbs_create(struct meson_drm *priv)
 
 	if (!meson_venc_cvbs_connector_is_available(priv)) {
 		dev_info(drm->dev, "CVBS Output connector not available\n");
-		return -ENODEV;
+		return 0;
 	}
 
 	meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs),

+ 5 - 1
drivers/gpu/drm/meson/meson_viu.c

@@ -28,9 +28,12 @@
 #include "meson_canvas.h"
 #include "meson_registers.h"
 
-/*
+/**
+ * DOC: Video Input Unit
+ *
  * VIU Handles the Pixel scanout and the basic Colorspace conversions
  * We handle the following features :
+ *
  * - OSD1 RGB565/RGB888/xRGB8888 scanout
  * - RGB conversion to x/cb/cr
  * - Progressive or Interlace buffer scanout
@@ -38,6 +41,7 @@
  * - HDR OSD matrix for GXL/GXM
  *
  * What is missing :
+ *
  * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
  * - YUV4:2:2 Y0CbY1Cr scanout
  * - Conversion to YUV 4:4:4 from 4:2:2 input

+ 6 - 2
drivers/gpu/drm/meson/meson_vpp.c

@@ -25,16 +25,20 @@
 #include "meson_vpp.h"
 #include "meson_registers.h"
 
-/*
+/**
+ * DOC: Video Post Processing
+ *
  * VPP Handles all the Post Processing after the Scanout from the VIU
  * We handle the following post processings :
- * - Postblend : Blends the OSD1 only
+ *
+ * - Postblend, Blends the OSD1 only
  *	We exclude OSD2, VS1, VS1 and Preblend output
  * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
  *	use it only for interlace scanout
  * - Intermediate FIFO with default Amlogic values
  *
  * What is missing :
+ *
  * - Preblend for video overlay pre-scaling
  * - OSD2 support for cursor framebuffer
  * - Video pre-scaling before postblend

+ 2 - 0
drivers/gpu/drm/meson/meson_vpp.h

@@ -23,6 +23,8 @@
 
 /* Mux VIU/VPP to ENCI */
 #define MESON_VIU_VPP_MUX_ENCI	0x5
+/* Mux VIU/VPP to ENCP */
+#define MESON_VIU_VPP_MUX_ENCP	0xA
 
 void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux);
 

+ 2 - 1
drivers/gpu/drm/mgag200/mgag200_mode.c

@@ -1393,7 +1393,8 @@ static void mga_crtc_commit(struct drm_crtc *crtc)
  * but it's a requirement that we provide the function
  */
 static int mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-			      u16 *blue, uint32_t size)
+			      u16 *blue, uint32_t size,
+			      struct drm_modeset_acquire_ctx *ctx)
 {
 	struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
 	int i;

+ 1 - 1
drivers/gpu/drm/msm/dsi/dsi_host.c

@@ -1635,7 +1635,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 	}
 
 	/* Get panel node from the output port's endpoint data */
-	device_node = of_graph_get_remote_port_parent(endpoint);
+	device_node = of_graph_get_remote_node(np, 1, 0);
 	if (!device_node) {
 		dev_dbg(dev, "%s: no valid device\n", __func__);
 		goto err;

+ 1 - 27
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c

@@ -225,32 +225,6 @@ int mdp4_enable(struct mdp4_kms *mdp4_kms)
 	return 0;
 }
 
-static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev)
-{
-	struct device_node *endpoint, *panel_node;
-	struct device_node *np = dev->dev->of_node;
-
-	/*
-	 * LVDS/LCDC is the first port described in the list of ports in the
-	 * MDP4 DT node.
-	 */
-	endpoint = of_graph_get_endpoint_by_regs(np, 0, -1);
-	if (!endpoint) {
-		DBG("no LVDS remote endpoint\n");
-		return NULL;
-	}
-
-	panel_node = of_graph_get_remote_port_parent(endpoint);
-	if (!panel_node) {
-		DBG("no valid panel node in LVDS endpoint\n");
-		of_node_put(endpoint);
-		return NULL;
-	}
-
-	of_node_put(endpoint);
-
-	return panel_node;
-}
 
 static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
 				  int intf_type)
@@ -269,7 +243,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
 		 * bail out early if there is no panel node (no need to
 		 * initialize LCDC encoder and LVDS connector)
 		 */
-		panel_node = mdp4_detect_lcdc_panel(dev);
+		panel_node = of_graph_get_remote_node(dev->dev->of_node, 0, 0);
 		if (!panel_node)
 			return 0;
 

+ 6 - 34
drivers/gpu/drm/mxsfb/mxsfb_out.c

@@ -19,6 +19,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_simple_kms_helper.h>
@@ -82,20 +83,15 @@ static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
 
-static int mxsfb_attach_endpoint(struct drm_device *drm,
-				 const struct of_endpoint *ep)
+int mxsfb_create_output(struct drm_device *drm)
 {
 	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	struct device_node *np;
 	struct drm_panel *panel;
-	int ret = -EPROBE_DEFER;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-	panel = of_drm_find_panel(np);
-	of_node_put(np);
+	int ret;
 
-	if (!panel)
-		return -EPROBE_DEFER;
+	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL);
+	if (ret)
+		return ret;
 
 	mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
 	mxsfb->connector.polled = 0;
@@ -109,27 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,
 
 	return ret;
 }
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	struct device_node *ep_np = NULL;
-	struct of_endpoint ep;
-	int ret;
-
-	for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = mxsfb_attach_endpoint(drm, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
-			return ret;
-		}
-	}
-
-	if (!mxsfb->panel)
-		return -EPROBE_DEFER;
-
-	return 0;
-}

+ 2 - 1
drivers/gpu/drm/nouveau/dispnv04/crtc.c

@@ -788,7 +788,8 @@ nv_crtc_disable(struct drm_crtc *crtc)
 
 static int
 nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
-		  uint32_t size)
+		  uint32_t size,
+		  struct drm_modeset_acquire_ctx *ctx)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	int i;

+ 2 - 11
drivers/gpu/drm/nouveau/nv50_display.c

@@ -2210,25 +2210,16 @@ nv50_head_lut_load(struct drm_crtc *crtc)
 	}
 }
 
-static int
-nv50_head_mode_set_base_atomic(struct drm_crtc *crtc,
-			       struct drm_framebuffer *fb, int x, int y,
-			       enum mode_set_atomic state)
-{
-	WARN_ON(1);
-	return 0;
-}
-
 static const struct drm_crtc_helper_funcs
 nv50_head_help = {
-	.mode_set_base_atomic = nv50_head_mode_set_base_atomic,
 	.load_lut = nv50_head_lut_load,
 	.atomic_check = nv50_head_atomic_check,
 };
 
 static int
 nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
-		    uint32_t size)
+		    uint32_t size,
+		    struct drm_modeset_acquire_ctx *ctx)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	u32 i;

+ 1 - 1
drivers/gpu/drm/omapdrm/dss/dpi.c

@@ -877,7 +877,7 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port)
 	if (!dpi)
 		return -ENOMEM;
 
-	ep = omapdss_of_get_next_endpoint(port, NULL);
+	ep = of_get_next_child(port, NULL);
 	if (!ep)
 		return 0;
 

+ 2 - 1
drivers/gpu/drm/omapdrm/dss/dsi.c

@@ -39,6 +39,7 @@
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/of_platform.h>
 #include <linux/component.h>
 
@@ -5090,7 +5091,7 @@ static int dsi_probe_of(struct platform_device *pdev)
 	struct device_node *ep;
 	struct omap_dsi_pin_config pin_cfg;
 
-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;
 

+ 3 - 99
drivers/gpu/drm/omapdrm/dss/dss-of.c

@@ -16,76 +16,11 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/seq_file.h>
 
 #include "omapdss.h"
 
-struct device_node *
-omapdss_of_get_next_port(const struct device_node *parent,
-			 struct device_node *prev)
-{
-	struct device_node *port = NULL;
-
-	if (!parent)
-		return NULL;
-
-	if (!prev) {
-		struct device_node *ports;
-		/*
-		 * It's the first call, we have to find a port subnode
-		 * within this node or within an optional 'ports' node.
-		 */
-		ports = of_get_child_by_name(parent, "ports");
-		if (ports)
-			parent = ports;
-
-		port = of_get_child_by_name(parent, "port");
-
-		/* release the 'ports' node */
-		of_node_put(ports);
-	} else {
-		struct device_node *ports;
-
-		ports = of_get_parent(prev);
-		if (!ports)
-			return NULL;
-
-		do {
-			port = of_get_next_child(ports, prev);
-			if (!port) {
-				of_node_put(ports);
-				return NULL;
-			}
-			prev = port;
-		} while (of_node_cmp(port->name, "port") != 0);
-
-		of_node_put(ports);
-	}
-
-	return port;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_next_port);
-
-struct device_node *
-omapdss_of_get_next_endpoint(const struct device_node *parent,
-			     struct device_node *prev)
-{
-	struct device_node *ep = NULL;
-
-	if (!parent)
-		return NULL;
-
-	do {
-		ep = of_get_next_child(parent, prev);
-		if (!ep)
-			return NULL;
-		prev = ep;
-	} while (of_node_cmp(ep->name, "endpoint") != 0);
-
-	return ep;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
-
 struct device_node *dss_of_port_get_parent_device(struct device_node *port)
 {
 	struct device_node *np;
@@ -124,37 +59,6 @@ u32 dss_of_port_get_port_number(struct device_node *port)
 }
 EXPORT_SYMBOL_GPL(dss_of_port_get_port_number);
 
-static struct device_node *omapdss_of_get_remote_port(const struct device_node *node)
-{
-	struct device_node *np;
-
-	np = of_parse_phandle(node, "remote-endpoint", 0);
-	if (!np)
-		return NULL;
-
-	np = of_get_next_parent(np);
-
-	return np;
-}
-
-struct device_node *
-omapdss_of_get_first_endpoint(const struct device_node *parent)
-{
-	struct device_node *port, *ep;
-
-	port = omapdss_of_get_next_port(parent, NULL);
-
-	if (!port)
-		return NULL;
-
-	ep = omapdss_of_get_next_endpoint(port, NULL);
-
-	of_node_put(port);
-
-	return ep;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint);
-
 struct omap_dss_device *
 omapdss_of_find_source_for_first_ep(struct device_node *node)
 {
@@ -162,11 +66,11 @@ omapdss_of_find_source_for_first_ep(struct device_node *node)
 	struct device_node *src_port;
 	struct omap_dss_device *src;
 
-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return ERR_PTR(-EINVAL);
 
-	src_port = omapdss_of_get_remote_port(ep);
+	src_port = of_graph_get_remote_port(ep);
 	if (!src_port) {
 		of_node_put(ep);
 		return ERR_PTR(-EINVAL);

+ 13 - 48
drivers/gpu/drm/omapdrm/dss/dss.c

@@ -38,6 +38,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 #include <linux/suspend.h>
 #include <linux/component.h>
@@ -1035,32 +1036,14 @@ static int dss_init_ports(struct platform_device *pdev)
 {
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
-	int r;
-
-	if (parent == NULL)
-		return 0;
+	int i;
 
-	port = omapdss_of_get_next_port(parent, NULL);
-	if (!port)
-		return 0;
-
-	if (dss.feat->num_ports == 0)
-		return 0;
-
-	do {
-		enum omap_display_type port_type;
-		u32 reg;
-
-		r = of_property_read_u32(port, "reg", &reg);
-		if (r)
-			reg = 0;
-
-		if (reg >= dss.feat->num_ports)
+	for (i = 0; i < dss.feat->num_ports; i++) {
+		port = of_graph_get_port_by_id(parent, i);
+		if (!port)
 			continue;
 
-		port_type = dss.feat->ports[reg];
-
-		switch (port_type) {
+		switch (dss.feat->ports[i]) {
 		case OMAP_DISPLAY_TYPE_DPI:
 			dpi_init_port(pdev, port);
 			break;
@@ -1070,7 +1053,7 @@ static int dss_init_ports(struct platform_device *pdev)
 		default:
 			break;
 		}
-	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+	}
 
 	return 0;
 }
@@ -1079,32 +1062,14 @@ static void dss_uninit_ports(struct platform_device *pdev)
 {
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
+	int i;
 
-	if (parent == NULL)
-		return;
-
-	port = omapdss_of_get_next_port(parent, NULL);
-	if (!port)
-		return;
-
-	if (dss.feat->num_ports == 0)
-		return;
-
-	do {
-		enum omap_display_type port_type;
-		u32 reg;
-		int r;
-
-		r = of_property_read_u32(port, "reg", &reg);
-		if (r)
-			reg = 0;
-
-		if (reg >= dss.feat->num_ports)
+	for (i = 0; i < dss.feat->num_ports; i++) {
+		port = of_graph_get_port_by_id(parent, i);
+		if (!port)
 			continue;
 
-		port_type = dss.feat->ports[reg];
-
-		switch (port_type) {
+		switch (dss.feat->ports[i]) {
 		case OMAP_DISPLAY_TYPE_DPI:
 			dpi_uninit_port(port);
 			break;
@@ -1114,7 +1079,7 @@ static void dss_uninit_ports(struct platform_device *pdev)
 		default:
 			break;
 		}
-	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+	}
 }
 
 static int dss_video_pll_probe(struct platform_device *pdev)

+ 2 - 1
drivers/gpu/drm/omapdrm/dss/hdmi4.c

@@ -34,6 +34,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <sound/omap-hdmi-audio.h>
 
 #include "omapdss.h"
@@ -546,7 +547,7 @@ static int hdmi_probe_of(struct platform_device *pdev)
 	struct device_node *ep;
 	int r;
 
-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;
 

+ 2 - 1
drivers/gpu/drm/omapdrm/dss/hdmi5.c

@@ -39,6 +39,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <sound/omap-hdmi-audio.h>
 
 #include "omapdss.h"
@@ -572,7 +573,7 @@ static int hdmi_probe_of(struct platform_device *pdev)
 	struct device_node *ep;
 	int r;
 
-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;
 

+ 0 - 11
drivers/gpu/drm/omapdrm/dss/omapdss.h

@@ -830,17 +830,6 @@ static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
 	return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
 }
 
-struct device_node *
-omapdss_of_get_next_port(const struct device_node *parent,
-			 struct device_node *prev);
-
-struct device_node *
-omapdss_of_get_next_endpoint(const struct device_node *parent,
-			     struct device_node *prev);
-
-struct device_node *
-omapdss_of_get_first_endpoint(const struct device_node *parent);
-
 struct omap_dss_device *
 omapdss_of_find_source_for_first_ep(struct device_node *node);
 

+ 1 - 1
drivers/gpu/drm/omapdrm/dss/sdi.c

@@ -414,7 +414,7 @@ int sdi_init_port(struct platform_device *pdev, struct device_node *port)
 	u32 datapairs;
 	int r;
 
-	ep = omapdss_of_get_next_endpoint(port, NULL);
+	ep = of_get_next_child(port, NULL);
 	if (!ep)
 		return 0;
 

+ 2 - 1
drivers/gpu/drm/omapdrm/dss/venc.c

@@ -35,6 +35,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/component.h>
 
 #include "omapdss.h"
@@ -818,7 +819,7 @@ static int venc_probe_of(struct platform_device *pdev)
 	u32 channels;
 	int r;
 
-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;
 

+ 2 - 1
drivers/gpu/drm/radeon/radeon_display.c

@@ -232,7 +232,8 @@ void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 }
 
 static int radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				 u16 *blue, uint32_t size)
+				 u16 *blue, uint32_t size,
+				 struct drm_modeset_acquire_ctx *ctx)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	int i;

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