Skip to contentSkip to conversation

Add Synopsys DesignWare HDMI RX Controller and PHY drivers

PATCH In review Nelson Costa 4 participants 31 messages Jun 2, 2021 – Jun 23, 2021 Page 1 of 2

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover Add Synopsys DesignWare HDMI RX Controller and PHY drivers

This series implements support for the Synopsys DesignWare HDMI RX Controller and PHYs e405/e406 drivers, being compliant with standard HDMI 1.4 and HDMI 2.0.

The Controller + PHY pipeline can be integrated into a fully featured system that can be able to receive video up to 4k@60Hz with basic audio.

This solution is mainly composed by two modules: phy-dw-hdmi-e40x and dw-hdmi-rx.

phy-dw-hdmi-e40x: it's the PHY (Physical Layer) driver that implements support for Synopsys DesignWare e405 and e406 PHYs. It is responsible to configure the PHY and equalize it for the best settings, in order to receive and decode video to be delivered to the Controller. This driver is integrated in the PHY subsystem.
The main features of this module are:
- Equalizer algorithm that chooses the phy best settings according to the detected HDMI cable characteristics
- Support for scrambling
- Support for color depth up to 48bpp
- Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz).

dw-hdmi-rx: it's the Controller driver that implements support for Synopsys DesignWare HDMI RX Controller. It is responsible to manage and handle the PHY (through the PHY API) and the Controller configurations in order to configure the video and audio pipeline.
This driver is implemented as a standard V4L2 subdevice.
The main features of this module are:
- Support for scrambling
- Support for color depth up to 48bpp
- Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz)
- Support for RGB, YCC444, YCC422 and YCC420
- Support for basic audio (LPCM 2ch, 32KHz/44.1KHz/48KHz, 16bit)
- Support for Aspect Ratio
- Support for CEC
- Internal state machine that reconfigures phy and controller
- JTAG communication with phy
- Inter-module communication with phy driver:
* through the PHY API using the phy reference "hdmi-phy"
* through the callbacks that phy dwc driver needs.
- Debug write/read ioctls

NOTES: This patch series has two specific patches (Patch [4/8] and [7/8]) one for the PHY API and the other for v4l2-dv-timings.

Patch [4/8] adds phy standard HDMI opts to the phy API that contributes for the PHY subsystem, which allows to integrate the PHY driver in the PHY subsystem using this new HDMI opts structure, because there are hdmi options that are needed to pass between the Controller and PHY drivers using the standard API.

Patch [7/8] adds more CEA/CTA-861 video format timings that contributes to the v4l2 media subsystem, which in our case is needed to provide information about the Aspect Ratio.

PATCH v1:
- Fix "undefined reference to `hdmi_infoframe_unpack'", adding config HDMI selectable for config VIDEO_DWC_HDMI_RX.

- Add MEDIA_CONTROLLER and VIDEO_V4L2_SUBDEV_API also selectable for config VIDEO_DWC_HDMI_RX.

RFC v2:
- The original media Device Tree bindings was divided in two independent Device Trees:
* Device tree for PHYs e405/e406 in PHY dt bindings
* Device tree for HDMI RX Controller in media dt bindings
- Add OF graph ports connection model in the Device Trees (Thanks to Laurent Pinchart <[email protected]>)
- The HDMI RX Controller was adjusted in order to work with the new Device Trees Model:
* the "input-count" field was removed from original Device Tree and now the count is done based on port child count.
* Changed the way to get the phy node, removing the dependency as child node of Controller node
- Fix reported kernel test robot issues:
* Fix "warning: no previous prototype for 'dw_phy_eq_settings'"
* Fix "warning: integer literal is too large to be represented in type 'long', interpreting as 'unsigned long' per C89; this literal will have type 'long long' in C99 onwards [-Wc99-compat]"

- Fix phy power off/on issue when the system startups without the cable connected.
- Fix "CHECK: Comparison to NULL could be written "of_device_get_match_data"".

Nelson Costa (9):
dt-bindings: phy: Document Synopsys DesignWare HDMI RX PHYs e405 and

    e406

dt-bindings: media: Document Synopsys DesignWare HDMI RX
MAINTAINERS: Add entry for Synopsys DesignWare HDMI drivers
phy: Add PHY standard HDMI opts to the PHY API
phy: dwc: Add Synopsys DesignWare HDMI RX PHYs e405 and e406 Driver
media: platform: Add Synopsys DesignWare HDMI RX Controller Driver
media: v4l2-dv-timings: Add more CEA/CTA-861 video format timings
media: dwc: dw-hdmi-rx: Add support for Aspect Ratio
media: dwc: dw-hdmi-rx: Add support for CEC

 .../devicetree/bindings/media/snps,dw-hdmi-rx.yaml |   98 +
 .../bindings/phy/snps,phy-dw-hdmi-e40x.yaml        |   93 +
 MAINTAINERS                                        |   11 +
 drivers/media/platform/Kconfig                     |    2 +
 drivers/media/platform/Makefile                    |    1 +
 drivers/media/platform/dwc/Kconfig                 |   23 +
 drivers/media/platform/dwc/Makefile                |    3 +
 drivers/media/platform/dwc/dw-hdmi-rx.c            | 3542 ++++++++++++++++++++
 drivers/media/platform/dwc/dw-hdmi-rx.h            |  533 +++
 drivers/media/v4l2-core/v4l2-dv-timings.c          |  139 +
 drivers/phy/Kconfig                                |    1 +
 drivers/phy/Makefile                               |    1 +
 drivers/phy/dwc/Kconfig                            |   20 +
 drivers/phy/dwc/Makefile                           |    9 +
 drivers/phy/dwc/phy-dw-hdmi-e405.c                 |  497 +++
 drivers/phy/dwc/phy-dw-hdmi-e406.c                 |  475 +++
 drivers/phy/dwc/phy-dw-hdmi-e40x-core.c            |  514 +++
 drivers/phy/dwc/phy-dw-hdmi-e40x.h                 |  219 ++
 include/linux/phy/dwc/dw-hdmi-phy-pdata.h          |   73 +
 include/linux/phy/phy-hdmi.h                       |  102 +
 include/linux/phy/phy.h                            |    7 +-
 include/media/dwc/dw-hdmi-rx-pdata.h               |  126 +
 include/uapi/linux/v4l2-dv-timings.h               | 1595 ++++++++-
 23 files changed, 8082 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/snps,phy-dw-hdmi-e40x.yaml
 create mode 100644 drivers/media/platform/dwc/Kconfig
 create mode 100644 drivers/media/platform/dwc/Makefile
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.c
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.h
 create mode 100644 drivers/phy/dwc/Kconfig
 create mode 100644 drivers/phy/dwc/Makefile
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e405.c
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e406.c
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e40x-core.c
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e40x.h
 create mode 100644 include/linux/phy/dwc/dw-hdmi-phy-pdata.h
 create mode 100644 include/linux/phy/phy-hdmi.h
 create mode 100644 include/media/dwc/dw-hdmi-rx-pdata.h
Signature · 1 line
2.7.4
#1 lore raw

PATCH 1/9 dt-bindings: phy: Document Synopsys DesignWare HDMI RX PHYs e405 and e406

Document the device tree bindings for the Synopsys DesignWare HDMI RX PHYs e405 and e406.

---
 .../bindings/phy/snps,phy-dw-hdmi-e40x.yaml        | 93 ++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/snps,phy-dw-hdmi-e40x.yaml
Documentation/devicetree/bindings/phy/snps,phy-dw-hdmi-e40x.yaml new file +93 -0
new file mode 100644
index 0000000..25bece5
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/snps,phy-dw-hdmi-e40x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare HDMI PHYs e405/e406 Device Tree Bindings
+
+maintainers:
+  - Jose Abreu <[email protected]>
+  - Nelson Costa <[email protected]>
+
+description: |
+  The Synopsys DesignWare HDMI PHYs e405/e406 are HDMI 2.0 PHY Receivers that
+  receive video and audio, and send to the HDMI RX Controller.
+
+properties:
+  compatible:
+    oneOf:
+      - const: snps,dw-hdmi-phy-e405
+      - const: snps,dw-hdmi-phy-e406
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: |
+      phandle to the configuration clock
+
+  clock-names:
+    const: cfg
+
+  "#phy-cells":
+    const: 0
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+    description: |
+      Output port node, multiple endpoints describing the PHY HDMI inputs data
+      connected to the HDMI RX Controller.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - "#phy-cells"
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    parent {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+        hdmi_e406_phy: hdmi-phy@fc {
+            compatible = "snps,dw-hdmi-phy-e406";
+            reg = <0xfc>;
+
+            clocks = <&dw_hdmi_refclk>;
+            clock-names = "cfg";
+
+            #phy-cells = <0>;
+
+            port {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                hdmi_e406_phy_0: endpoint@0 {
+                    reg = <0>;
+                    remote-endpoint = <&hdmi_rx_0>;
+                };
+
+                hdmi_e406_phy_1: endpoint@1 {
+                    reg = <1>;
+                    remote-endpoint = <&hdmi_rx_1>;
+                };
+
+                hdmi_e406_phy_2: endpoint@2 {
+                    reg = <2>;
+                    remote-endpoint = <&hdmi_rx_2>;
+                };
+
+                hdmi_e406_phy_3: endpoint@3 {
+                    reg = <3>;
+                    remote-endpoint = <&hdmi_rx_3>;
+                };
+            };
+        };
+    };
Signature · 1 line
2.7.4
maintainer Reviewed-by on v1 1/9
#2 lore raw

Re: [PATCH 1/9] dt-bindings: phy: Document Synopsys DesignWare HDMI RX PHYs e405 and e406

Quoted 9 lines · Nelson Costa

Document the device tree bindings for the Synopsys DesignWare HDMI RX PHYs e405 and e406.

---
 .../bindings/phy/snps,phy-dw-hdmi-e40x.yaml        | 93 ++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/snps,phy-dw-hdmi-e40x.yaml
#3 lore raw

PATCH 2/9 dt-bindings: media: Document Synopsys DesignWare HDMI RX

In reply to Nelson Costa

Document the device tree bindings for the Synopsys DesignWare HDMI RX Controller.

---
 .../devicetree/bindings/media/snps,dw-hdmi-rx.yaml | 98 ++++++++++++++++++++++
 1 file changed, 98 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +98 -0
new file mode 100644
index 0000000..4f2169e
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/snps,dw-hdmi-rx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare HDMI RX Controller Device Tree Bindings
+
+maintainers:
+  - Jose Abreu <[email protected]>
+  - Nelson Costa <[email protected]>
+
+description: |
+  The Synopsys DesignWare HDMI RX Controller and PHYs e405/e406 is an HDMI 2.0
+  Receiver solution that is able to decode video and audio.
+
+properties:
+  compatible:
+    const: snps,dw-hdmi-rx
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: |
+      phandle to the configuration clock
+
+  clock-names:
+    const: cfg
+
+  phys:
+    maxItems: 1
+    description: |
+      phandle for the HDMI RX PHY
+
+  phy-names:
+    const: hdmi-phy
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+    description: |
+      Input port node, multiple endpoints describing the HDMI RX data connected
+      to the HDMI PHY receiver.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - phys
+  - phy-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi_rx: hdmi-rx@0 {
+        compatible = "snps,dw-hdmi-rx";
+        reg = <0x0 0x10000>;
+        interrupts = <1 2>;
+
+        clocks = <&dw_hdmi_refclk>;
+        clock-names = "cfg";
+
+        phys = <&hdmi_e406_phy>;
+        phy-names = "hdmi-phy";
+
+        port {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            hdmi_rx_0: endpoint@0 {
+                reg = <0>;
+                remote-endpoint = <&hdmi_e406_phy_0>;
+            };
+
+            hdmi_rx_1: endpoint@1 {
+                reg = <1>;
+                remote-endpoint = <&hdmi_e406_phy_1>;
+            };
+
+            hdmi_rx_2: endpoint@2 {
+                reg = <2>;
+                remote-endpoint = <&hdmi_e406_phy_2>;
+            };
+
+            hdmi_rx_3: endpoint@3 {
+                reg = <3>;
+                remote-endpoint = <&hdmi_e406_phy_3>;
+            };
+        };
+    };
Signature · 1 line
2.7.4
maintainer
#4 lore raw

Re: [PATCH 2/9] dt-bindings: media: Document Synopsys DesignWare HDMI RX

Quoted 47 lines · Nelson Costa

Document the device tree bindings for the Synopsys DesignWare HDMI RX Controller.

---
 .../devicetree/bindings/media/snps,dw-hdmi-rx.yaml | 98 ++++++++++++++++++++++
 1 file changed, 98 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +31 -0
new file mode 100644
index 0000000..4f2169e
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/snps,dw-hdmi-rx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare HDMI RX Controller Device Tree Bindings
+
+maintainers:
+  - Jose Abreu <[email protected]>
+  - Nelson Costa <[email protected]>
+
+description: |
+  The Synopsys DesignWare HDMI RX Controller and PHYs e405/e406 is an HDMI 2.0
+  Receiver solution that is able to decode video and audio.
+
+properties:
+  compatible:
+    const: snps,dw-hdmi-rx
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: |
+      phandle to the configuration clock
+

Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml line 41

Quoted 10 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +10 -0
+  clock-names:
+    const: cfg
+
+  phys:
+    maxItems: 1
+    description: |
+      phandle for the HDMI RX PHY
+
+  phy-names:
+    const: hdmi-phy

You don't need *-names when there is only one generally.

Quoted 30 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +30 -0
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+    description: |
+      Input port node, multiple endpoints describing the HDMI RX data connected
+      to the HDMI PHY receiver.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - phys
+  - phy-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi_rx: hdmi-rx@0 {
+        compatible = "snps,dw-hdmi-rx";
+        reg = <0x0 0x10000>;
+        interrupts = <1 2>;
+
+        clocks = <&dw_hdmi_refclk>;
+        clock-names = "cfg";
+
+        phys = <&hdmi_e406_phy>;

Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml line 81

Quoted 10 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +10 -0
+        phy-names = "hdmi-phy";
+
+        port {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            hdmi_rx_0: endpoint@0 {
+                reg = <0>;
+                remote-endpoint = <&hdmi_e406_phy_0>;
+            };

I don't get why you have a connection to the phy with 'phys' and OF graph? The connection should be to the remote device generating the HDMI data with a PHY being somewhat transparent to that data flow.

Quoted 19 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +17 -0
+
+            hdmi_rx_1: endpoint@1 {
+                reg = <1>;
+                remote-endpoint = <&hdmi_e406_phy_1>;
+            };
+
+            hdmi_rx_2: endpoint@2 {
+                reg = <2>;
+                remote-endpoint = <&hdmi_e406_phy_2>;
+            };
+
+            hdmi_rx_3: endpoint@3 {
+                reg = <3>;
+                remote-endpoint = <&hdmi_e406_phy_3>;
+            };
+        };
+    };
Signature · 1 line
2.7.4
#5 lore raw

RE: [PATCH 2/9] dt-bindings: media: Document Synopsys DesignWare HDMI RX

Hi Rob,

Thanks for your initial comments and feedback!

From: Rob Herring <[email protected]>
Date: qua, jun 16, 2021 at 00:40:48

Quoted 52 lines · Nelson Costa
Quoted 51 lines

Document the device tree bindings for the Synopsys DesignWare HDMI RX Controller.

---
 .../devicetree/bindings/media/snps,dw-hdmi-rx.yaml | 98 ++++++++++++++++++++++
 1 file changed, 98 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +35 -0
new file mode 100644
index 0000000..4f2169e
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: https://urldefense.com/v3/__http://devicetree.org/schemas/media/snps,dw-hdmi-rx.yaml*__;Iw!!A4F2R9G_pg!PXFG6mDuYYepSE77ynbfBUqpXfgW5g0UdVsjQ5p0CEVGkNknkcWScmrRWLFWmhWsFl4$ 
+$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!A4F2R9G_pg!PXFG6mDuYYepSE77ynbfBUqpXfgW5g0UdVsjQ5p0CEVGkNknkcWScmrRWLFWXz21yII$ 
+
+title: Synopsys DesignWare HDMI RX Controller Device Tree Bindings
+
+maintainers:
+  - Jose Abreu <[email protected]>
+  - Nelson Costa <[email protected]>
+
+description: |
+  The Synopsys DesignWare HDMI RX Controller and PHYs e405/e406 is an HDMI 2.0
+  Receiver solution that is able to decode video and audio.
+
+properties:
+  compatible:
+    const: snps,dw-hdmi-rx
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: |
+      phandle to the configuration clock
+
+  clock-names:
+    const: cfg
+
+  phys:
Quoted 9 lines

Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml line 41

Quoted 6 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +6 -0
+    maxItems: 1
+    description: |
+      phandle for the HDMI RX PHY
+
+  phy-names:
+    const: hdmi-phy

You don't need *-names when there is only one generally.

But we are using the PHY API function "devm_phy_get(dw_dev->dev, "hdmi-phy")" in the controller driver in order to get the reference for the PHY.
And looking at the PHY API internal implementation (function "phy_get()" that is called by "devm_phy_get()") seems that this 'phy-names' property is required to get that PHY reference.

Quoted 36 lines
Quoted 36 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +36 -0
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+    description: |
+      Input port node, multiple endpoints describing the HDMI RX data connected
+      to the HDMI PHY receiver.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - phys
+  - phy-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi_rx: hdmi-rx@0 {
+        compatible = "snps,dw-hdmi-rx";
+        reg = <0x0 0x10000>;
+        interrupts = <1 2>;
+
+        clocks = <&dw_hdmi_refclk>;
+        clock-names = "cfg";
+
+        phys = <&hdmi_e406_phy>;
+        phy-names = "hdmi-phy";
+
+        port {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
Quoted 9 lines

Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml line 81

Quoted 4 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +4 -0
+            hdmi_rx_0: endpoint@0 {
+                reg = <0>;
+                remote-endpoint = <&hdmi_e406_phy_0>;
+            };

I don't get why you have a connection to the phy with 'phys' and OF graph? The connection should be to the remote device generating the HDMI data with a PHY being somewhat transparent to that data flow.

Would be possible to give an example for our specific use case? Or there is any good example, similar to this use case, that we can take a look?
Having in mind that we have two drivers one for the PHY e405/e406 and other for the Controller HDMI RX and a device tree specified for each one (patches [1/9] and [2/9]).

The pipeline is something like this:
HDMI Source (which is an external hot pluggable device) -> PHY e405/e406 -> CTRL HDMI RX

Thanks a lot,

BR,

Nelson Costa

Quoted 19 lines
Quoted 19 lines
Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml new file +17 -0
+
+            hdmi_rx_1: endpoint@1 {
+                reg = <1>;
+                remote-endpoint = <&hdmi_e406_phy_1>;
+            };
+
+            hdmi_rx_2: endpoint@2 {
+                reg = <2>;
+                remote-endpoint = <&hdmi_e406_phy_2>;
+            };
+
+            hdmi_rx_3: endpoint@3 {
+                reg = <3>;
+                remote-endpoint = <&hdmi_e406_phy_3>;
+            };
+        };
+    };
Signature · 1 line
2.7.4
#6 lore raw

PATCH 3/9 MAINTAINERS: Add entry for Synopsys DesignWare HDMI drivers

In reply to Nelson Costa

Add an entry for Synopsys DesignWare HDMI Receivers drivers and PHYs.

---
 MAINTAINERS | 11 +++++++++++
 1 file changed, 11 insertions(+)
MAINTAINERS +11 -0
index 04e6df9..e0e7b41 100644
@@ -17304,6 +17304,17 @@ S:	Supported
 F:	drivers/net/pcs/pcs-xpcs.c
 F:	include/linux/pcs/pcs-xpcs.h
 
+SYNOPSYS DESIGNWARE HDMI RECEIVERS AND PHY DRIVERS
+M:	Jose Abreu <[email protected]>
+M:	Nelson Costa <[email protected]>
+L:	[email protected]
+S:	Odd Fixes
+F:	Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml
+F:	drivers/media/platform/dwc/*
+F:	drivers/phy/dwc/*
+F:	include/linux/phy/dwc/*
+F:	include/media/dwc/*
+
 SYNOPSYS DESIGNWARE I2C DRIVER
 M:	Jarkko Nikula <[email protected]>
 R:	Andy Shevchenko <[email protected]>
Signature · 1 line
2.7.4
#7 lore raw

PATCH 4/9 phy: Add PHY standard HDMI opts to the PHY API

In reply to Nelson Costa

This adds the new options to give support for HDMI PHYs in a standard way. This is mainly useful when the HDMI PHY requires parameters to be passed by "phy_configure" function.

For this, the new struct phy_configure_opts_hdmi
was added with the required generic and standard
parameters.

---
 include/linux/phy/phy-hdmi.h | 102 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/phy/phy.h      |   7 ++-
 2 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/phy/phy-hdmi.h
include/linux/phy/phy-hdmi.h new file +102 -0
new file mode 100644
index 0000000..62334f4
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 - present Synopsys, Inc. and/or its affiliates.
+ * HDMI generic PHY options.
+ *
+ * Author: Nelson Costa <[email protected]>
+ */
+#ifndef __PHY_HDMI_H_
+#define __PHY_HDMI_H_
+
+#include <linux/types.h>
+
+/**
+ * struct phy_configure_opts_hdmi - HDMI PHY configuration set
+ *
+ * This structure is used to represent the configuration state of an
+ * HDMI PHY.
+ */
+struct phy_configure_opts_hdmi {
+	/**
+	 * @color_depth:
+	 *
+	 * Color depth, as specified by HDMI specification, represents the
+	 * number of bits per pixel.
+	 *
+	 * Allowed values: 24, 30, 36, 48
+	 *
+	 */
+	u8 color_depth;
+
+	/**
+	 * @tmds_bit_clock_ratio:
+	 *
+	 * Flag indicating, as specified by HDMI specification, the relation
+	 * between TMDS Clock Rate and TMDS Character Rate.
+	 *
+	 * As specified by HDMI specification:
+	 *
+	 * tmds_bit_clock_ratio = 0, for TMDS Character Rates <= 340 Mcsc
+	 * (TMDS Clock Rate = TMDS Character Rate)
+	 *
+	 * tmds_bit_clock_ratio = 1, for TMDS Character Rates > 340 Mcsc
+	 * (TMDS Clock Rate = TMDS Character Rate / 4)
+	 *
+	 */
+	u8 tmds_bit_clock_ratio;
+
+	/**
+	 * @scrambling:
+	 *
+	 * Scrambling, as specified by HDMI specification, enables the technique
+	 * to reduce the EMI/RFI.
+	 *
+	 */
+	u8 scrambling;
+
+	/**
+	 * @calibration_acq:
+	 *
+	 * Calibration acquisitions number for the calibration algorithm.
+	 *
+	 */
+	unsigned int calibration_acq;
+
+	/**
+	 * @calibration_force:
+	 *
+	 * Flag indicating, to force calibration algorithm even if the MPLL
+	 * status didn't change from previous run calibration.
+	 *
+	 */
+	u8 calibration_force;
+
+	/**
+	 * @set_color_depth:
+	 *
+	 * Flag indicating, whether or not reconfigure deep_color
+	 * to requested values.
+	 *
+	 */
+	u8 set_color_depth : 1;
+
+	/**
+	 * @set_tmds_bit_clock_ratio:
+	 *
+	 * Flag indicating, whether or not reconfigure tmds_bit_clock_ratio
+	 * to requested values.
+	 *
+	 */
+	u8 set_tmds_bit_clock_ratio : 1;
+
+	/**
+	 * @set_scrambling:
+	 *
+	 * Flag indicating, whether or not reconfigure scrambling
+	 * to requested values.
+	 *
+	 */
+	u8 set_scrambling : 1;
+};
+
+#endif /* __PHY_HDMI_H_ */
include/linux/phy/phy.h +6 -1
index e435bdb..8b1aaa4 100644
@@ -18,6 +18,7 @@
 
 #include <linux/phy/phy-dp.h>
 #include <linux/phy/phy-mipi-dphy.h>
+#include <linux/phy/phy-hdmi.h>
 
 struct phy;
 
@@ -41,7 +42,8 @@ enum phy_mode {
 	PHY_MODE_MIPI_DPHY,
 	PHY_MODE_SATA,
 	PHY_MODE_LVDS,
-	PHY_MODE_DP
+	PHY_MODE_DP,
+	PHY_MODE_HDMI
 };
 
 /**
@@ -51,10 +53,13 @@ enum phy_mode {
  *		the MIPI_DPHY phy mode.
  * @dp:		Configuration set applicable for phys supporting
  *		the DisplayPort protocol.
+ * @hdmi	Configuration set applicable for phys supporting
+ *		the HDMI protocol.
  */
 union phy_configure_opts {
 	struct phy_configure_opts_mipi_dphy	mipi_dphy;
 	struct phy_configure_opts_dp		dp;
+	struct phy_configure_opts_hdmi		hdmi;
 };
 
 /**
Signature · 1 line
2.7.4
#8 lore raw

PATCH 5/9 phy: dwc: Add Synopsys DesignWare HDMI RX PHYs e405 and e406 Driver

In reply to Nelson Costa

This adds support for the Synopsys DesignWare HDMI RX PHYs e405 and e406. The PHY receives and decodes HDMI video that is delivered to a controller.

Main features included in this driver are:
- Equalizer algorithm that chooses the PHY best settings according to the detected HDMI cable characteristics.
- Support for scrambling
- Support for color depth up to 48bpp
- Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz).

The driver was implemented using the standard PHY API in order to provide a standard access to the required callbacks to be handled by the controller through the phy_ops.

There is a bidirectional communication between controller and PHY:
- controller -> PHY : communication is done using the PHY API
- controller <- PHY : communication is done using the callbacks, provided by the controller, which are required to handle the PHY such as: read/write, pddq, reset, etc.
This callback functions are specified in struct dw_phy_pdata from 'include/linux/phy/dwc/dw-hdmi-phy-pdata.h'.

---
 drivers/phy/Kconfig                       |   1 +
 drivers/phy/Makefile                      |   1 +
 drivers/phy/dwc/Kconfig                   |  20 ++
 drivers/phy/dwc/Makefile                  |   9 +
 drivers/phy/dwc/phy-dw-hdmi-e405.c        | 497 +++++++++++++++++++++++++++++
 drivers/phy/dwc/phy-dw-hdmi-e406.c        | 475 +++++++++++++++++++++++++++
 drivers/phy/dwc/phy-dw-hdmi-e40x-core.c   | 514 ++++++++++++++++++++++++++++++
 drivers/phy/dwc/phy-dw-hdmi-e40x.h        | 219 +++++++++++++
 include/linux/phy/dwc/dw-hdmi-phy-pdata.h |  73 +++++
 9 files changed, 1809 insertions(+)
 create mode 100644 drivers/phy/dwc/Kconfig
 create mode 100644 drivers/phy/dwc/Makefile
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e405.c
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e406.c
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e40x-core.c
 create mode 100644 drivers/phy/dwc/phy-dw-hdmi-e40x.h
 create mode 100644 include/linux/phy/dwc/dw-hdmi-phy-pdata.h
drivers/phy/Kconfig +1 -0
index 68d9c2f..db7c4b1 100644
@@ -65,6 +65,7 @@ source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/broadcom/Kconfig"
 source "drivers/phy/cadence/Kconfig"
+source "drivers/phy/dwc/Kconfig"
 source "drivers/phy/freescale/Kconfig"
 source "drivers/phy/hisilicon/Kconfig"
 source "drivers/phy/ingenic/Kconfig"
drivers/phy/Makefile +1 -0
index 32261e1..ac63979 100644
@@ -13,6 +13,7 @@ obj-y					+= allwinner/	\
 					   amlogic/	\
 					   broadcom/	\
 					   cadence/	\
+					   dwc/		\
 					   freescale/	\
 					   hisilicon/	\
 					   ingenic/	\
drivers/phy/dwc/Kconfig new file +20 -0
new file mode 100644
index 0000000..ab451d8
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_DWC_HDMI_PHY_E40X
+	tristate "Synopsys DesignWare HDMI RX PHYs e405 and e406 driver"
+	select GENERIC_PHY
+	help
+	  Support for Synopsys DesignWare HDMI RX PHYs versions
+	  e405 and e406.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called phy-dw-hdmi-e40x.
+
+config VIDEO_DWC_HDMI_PHY_E40X_SUPPORT_TESTCHIP
+	bool "Synopsys DesignWare HDMI RX PHYs e405/e406 Test Chip Support"
+	depends on VIDEO_DWC_HDMI_PHY_E40X
+	help
+	  Support for Synopsys DesignWare HDMI RX PHYs e405/e406 with Test Chip.
+
+	  To have support for HDMI RX PHYs e405/e406 Test Chip, choose Y here.
+	  It will enable Test Chip additional requirements, for example enable
+	  the z calibration requirement during the PHY configuration.
drivers/phy/dwc/Makefile new file +9 -0
new file mode 100644
index 0000000..52a5b6b
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the PHY drivers.
+#
+
+phy-dw-hdmi-e40x-y			:= phy-dw-hdmi-e40x-core.o
+phy-dw-hdmi-e40x-y			+= phy-dw-hdmi-e405.o
+phy-dw-hdmi-e40x-y			+= phy-dw-hdmi-e406.o
+obj-$(CONFIG_VIDEO_DWC_HDMI_PHY_E40X)	+= phy-dw-hdmi-e40x.o
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +497 -0

497 lines not on this page · raw message

drivers/phy/dwc/phy-dw-hdmi-e406.c new file +475 -0

475 lines not on this page · raw message

drivers/phy/dwc/phy-dw-hdmi-e40x-core.c new file +514 -0

514 lines not on this page · raw message

drivers/phy/dwc/phy-dw-hdmi-e40x.h new file +219 -0

219 lines not on this page · raw message

include/linux/phy/dwc/dw-hdmi-phy-pdata.h new file +73 -0

73 lines not on this page · raw message

Signature · 1 line
2.7.4
maintainer
#9 lore raw

Re: [PATCH 5/9] phy: dwc: Add Synopsys DesignWare HDMI RX PHYs e405 and e406 Driver

drivers/phy/dwc/Makefile line 8

Quoted 6 lines · Nelson Costa
drivers/phy/dwc/Makefile new file +6 -0
+# Makefile for the PHY drivers.
+#
+
+phy-dw-hdmi-e40x-y			:= phy-dw-hdmi-e40x-core.o
+phy-dw-hdmi-e40x-y			+= phy-dw-hdmi-e405.o
+phy-dw-hdmi-e40x-y			+= phy-dw-hdmi-e406.o

why not:
phy-dw-hdmi-e40x-y := phy-dw-hdmi-e40x-core.o phy-dw-hdmi-e405.o phy-dw-hdmi-e406.o ?

drivers/phy/dwc/phy-dw-hdmi-e405.c line 4

Quoted 11 lines
drivers/phy/dwc/Makefile new file +1 -0
+obj-$(CONFIG_VIDEO_DWC_HDMI_PHY_E40X)	+= phy-dw-hdmi-e40x.o
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +4 -0
new file mode 100644
index 0000000..5078a86
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - present Synopsys, Inc. and/or its affiliates.
+ * Synopsys DesignWare HDMI PHY e405

2018 - 2021 ?

drivers/phy/dwc/phy-dw-hdmi-e405.c line 43

Quoted 3 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +3 -0
+/* PHY e405 mpll configuration */
+static const struct dw_phy_mpll_config dw_phy_e405_mpll_cfg[] = {
+	{ 0x27, 0x1B94 },

Lowercase please

Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+	{ 0x28, 0x16D2 },
+	{ 0x29, 0x12D9 },
+	{ 0x2A, 0x3249 },
+	{ 0x2B, 0x3653 },
+	{ 0x2C, 0x3436 },
+	{ 0x2D, 0x124D },

drivers/phy/dwc/phy-dw-hdmi-e405.c line 59

Quoted 10 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +10 -0
+	{ 0x2E, 0x0001 },
+	{ 0xCE, 0x0505 },
+	{ 0xCF, 0x0505 },
+	{ 0xD0, 0x0000 },
+	{ 0x00, 0x0000 },
+};
+
+/* PHY e405 equalization functions */
+static int dw_phy_eq_test(struct dw_phy_dev *dw_dev,
+			  u16 *fat_bit_mask, int *min_max_length)

Please align this to preceding line open brace (checkpatch with --strict would warn you about this)

drivers/phy/dwc/phy-dw-hdmi-e405.c line 72

Quoted 13 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +13 -0
+{
+	u16 main_fsm_status, val;
+	unsigned int i;
+
+	for (i = 0; i < DW_PHY_EQ_WAIT_TIME_START; i++) {
+		main_fsm_status = dw_phy_read(dw_dev, DW_PHY_MAINFSM_STATUS1);
+		if (main_fsm_status & DW_PHY_CLOCK_STABLE)
+			break;
+		mdelay(DW_PHY_EQ_SLEEP_TIME_CDR);
+	}
+
+	if (i == DW_PHY_EQ_WAIT_TIME_START) {
+		dev_dbg(dw_dev->dev, "PHY start conditions not achieved\n");

not error?

drivers/phy/dwc/phy-dw-hdmi-e405.c line 77

Quoted 5 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +5 -0
+		return -ETIMEDOUT;
+	}
+
+	if (main_fsm_status & DW_PHY_PLL_RATE_BIT1) {
+		dev_dbg(dw_dev->dev, "invalid pll rate\n");

error?

drivers/phy/dwc/phy-dw-hdmi-e405.c line 82

Quoted 5 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +5 -0
+		return -EINVAL;
+	}
+
+	val = dw_phy_read(dw_dev, DW_PHY_CDR_CTRL_CNT) &
+		DW_PHY_HDMI_MHL_MODE_MASK;

can be single line

drivers/phy/dwc/phy-dw-hdmi-e405.c line 214

Quoted 7 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +7 -0
+static void dw_phy_eq_init_vars(struct dw_phy_eq_ch *ch)
+{
+	ch->acc = 0;
+	ch->acq = 0;
+	ch->last_acq = 0;
+	ch->valid_long_setting = 0;
+	ch->valid_short_setting = 0;

memset() ?

Quoted 29 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +29 -0
+static bool dw_phy_eq_acquire_early_cnt(struct dw_phy_dev *dw_dev,
+					u16 setting, u16 acq,
+					struct dw_phy_eq_ch *ch0,
+					struct dw_phy_eq_ch *ch1,
+					struct dw_phy_eq_ch *ch2)
+{
+	u16 lock_vector = 0x1 << setting;
+	unsigned int i;
+
+	ch0->out_bound_acq = 0;
+	ch1->out_bound_acq = 0;
+	ch2->out_bound_acq = 0;
+	ch0->acq = 0;
+	ch1->acq = 0;
+	ch2->acq = 0;
+
+	dw_phy_eq_equal_setting(dw_dev, lock_vector);
+	dw_phy_eq_auto_calib(dw_dev);
+
+	mdelay(DW_PHY_EQ_SLEEP_TIME_CDR);
+	if (!dw_phy_tmds_valid(dw_dev))
+		dev_dbg(dw_dev->dev, "TMDS is NOT valid\n");
+
+	ch0->read_acq = dw_phy_read(dw_dev, DW_PHY_CH0_EQ_STATUS3);
+	ch1->read_acq = dw_phy_read(dw_dev, DW_PHY_CH1_EQ_STATUS3);
+	ch2->read_acq = dw_phy_read(dw_dev, DW_PHY_CH2_EQ_STATUS3);
+
+	ch0->acq += ch0->read_acq;
+	ch1->acq += ch1->read_acq;

drivers/phy/dwc/phy-dw-hdmi-e405.c line 256

Quoted 10 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +10 -0
+	ch2->acq += ch2->read_acq;
+
+	ch0->upper_bound_acq = ch0->read_acq + DW_PHY_EQ_BOUNDSPREAD;
+	ch0->lower_bound_acq = ch0->read_acq - DW_PHY_EQ_BOUNDSPREAD;
+	ch1->upper_bound_acq = ch1->read_acq + DW_PHY_EQ_BOUNDSPREAD;
+	ch1->lower_bound_acq = ch1->read_acq - DW_PHY_EQ_BOUNDSPREAD;
+	ch2->upper_bound_acq = ch2->read_acq + DW_PHY_EQ_BOUNDSPREAD;
+	ch2->lower_bound_acq = ch2->read_acq - DW_PHY_EQ_BOUNDSPREAD;
+
+	for (i = 1; i < acq; i++) {

why do we start from 1 here..?

drivers/phy/dwc/phy-dw-hdmi-e405.c line 102

Quoted 10 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +10 -0
+static const struct dw_phy_mpll_config dw_phy_e406_mpll_cfg[] = {
+	{ 0x27, 0x1C94 },
+	{ 0x28, 0x3713 },
+	{ 0x29, 0x24DA },
+	{ 0x2A, 0x5492 },
+	{ 0x2B, 0x4B0D },
+	{ 0x2C, 0x4760 },
+	{ 0x2D, 0x008C },
+	{ 0x2E, 0x0010 },
+	{ 0x00, 0x0000 },

lower case here too please

drivers/phy/dwc/phy-dw-hdmi-e405.c line 216

Quoted 9 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +9 -0
+static void dw_phy_eq_init_vars(struct dw_phy_eq_ch *ch)
+{
+	ch->acc = 0;
+	ch->acq = 0;
+	ch->last_acq = 0;
+	ch->valid_long_setting = 0;
+	ch->valid_short_setting = 0;
+	ch->best_setting = DW_PHY_EQ_SHORT_CABLE_SETTING;
+}

duplicate, it would make sense to create a common lib of such functions and use them across these files

drivers/phy/dwc/phy-dw-hdmi-e405.c line 123

Quoted 12 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +12 -0
+static int dw_phy_set_data(struct dw_phy_dev *dw_dev)
+{
+	const struct dw_hdmi_phy_data *of_data;
+
+	of_data = of_device_get_match_data(dw_dev->dev);
+
+	if (of_data) {
+		dw_dev->phy_data = (struct dw_hdmi_phy_data *)of_data;
+	} else if (dw_dev->config->version == dw_phy_e405_data.version) {
+		dw_dev->phy_data = &dw_phy_e405_data;
+	} else if (dw_dev->config->version == dw_phy_e406_data.version) {
+		dw_dev->phy_data = &dw_phy_e406_data;

Driver supports only of, where will these else cases get triggered?

Signature · 1 line
~Vinod
#10 lore raw

RE: [PATCH 5/9] phy: dwc: Add Synopsys DesignWare HDMI RX PHYs e405 and e406 Driver

Hi Vinod,

Thanks for your initial comments and feedback!

From: Vinod Koul <[email protected]>
Date: seg, jun 21, 2021 at 06:53:29

Quoted 12 lines · Nelson Costa

drivers/phy/dwc/Makefile line 8

Quoted 7 lines
drivers/phy/dwc/Makefile new file +6 -0
+# Makefile for the PHY drivers.
+#
+
+phy-dw-hdmi-e40x-y			:= phy-dw-hdmi-e40x-core.o
+phy-dw-hdmi-e40x-y			+= phy-dw-hdmi-e405.o
+phy-dw-hdmi-e40x-y			+= phy-dw-hdmi-e406.o

why not:
phy-dw-hdmi-e40x-y := phy-dw-hdmi-e40x-core.o phy-dw-hdmi-e405.o phy-dw-hdmi-e406.o ?

I agree! It will be addressed in v2.

Quoted 5 lines
Quoted 5 lines
drivers/phy/dwc/Makefile new file +1 -0
+obj-$(CONFIG_VIDEO_DWC_HDMI_PHY_E40X)	+= phy-dw-hdmi-e40x.o
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +0 -1
new file mode 100644
index 0000000..5078a86
--- /dev/null
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 4

Quoted 6 lines

+++ b/drivers/phy/dwc/phy-dw-hdmi-e405.c

drivers/phy/dwc/phy-dw-hdmi-e405.c new file +4 -0
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - present Synopsys, Inc. and/or its affiliates.
+ * Synopsys DesignWare HDMI PHY e405

2018 - 2021 ?

It will be addressed in v2.

Quoted 6 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 43

Quoted 3 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +3 -0
+/* PHY e405 mpll configuration */
+static const struct dw_phy_mpll_config dw_phy_e405_mpll_cfg[] = {
+	{ 0x27, 0x1B94 },

Lowercase please

It will be addressed in v2.

Quoted 10 lines
Quoted 10 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +10 -0
+	{ 0x28, 0x16D2 },
+	{ 0x29, 0x12D9 },
+	{ 0x2A, 0x3249 },
+	{ 0x2B, 0x3653 },
+	{ 0x2C, 0x3436 },
+	{ 0x2D, 0x124D },
+	{ 0x2E, 0x0001 },
+	{ 0xCE, 0x0505 },
+	{ 0xCF, 0x0505 },
+	{ 0xD0, 0x0000 },
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 59

Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+	{ 0x00, 0x0000 },
+};
+
+/* PHY e405 equalization functions */
+static int dw_phy_eq_test(struct dw_phy_dev *dw_dev,
+			  u16 *fat_bit_mask, int *min_max_length)

Please align this to preceding line open brace (checkpatch with --strict would warn you about this)

This is aligned in the original source code, and checkpatch clean. :) Seems that only in patch format due the char '+' gives that effect.

Quoted 7 lines
Quoted 7 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +7 -0
+{
+	u16 main_fsm_status, val;
+	unsigned int i;
+
+	for (i = 0; i < DW_PHY_EQ_WAIT_TIME_START; i++) {
+		main_fsm_status = dw_phy_read(dw_dev, DW_PHY_MAINFSM_STATUS1);
+		if (main_fsm_status & DW_PHY_CLOCK_STABLE)
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 72

Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+			break;
+		mdelay(DW_PHY_EQ_SLEEP_TIME_CDR);
+	}
+
+	if (i == DW_PHY_EQ_WAIT_TIME_START) {
+		dev_dbg(dw_dev->dev, "PHY start conditions not achieved\n");

not error?

In the reality this is not an error scenario.
The 'ETIMEDOUT' return code is used by the HDMI RX Controller driver to know that the equalization was not performed due the lack of Clock Stable, and in this case the driver will keep forcing the equalization.

This scenario is something that can happen during HDMI Source Video transitions, or even in scenarios that the Source is not sending video at all.

That's why the message is not an error but instead only useful for debug purposes.

BTW, the print message will be changed in v2 to make more clear it's not an error scenario:
"PHY start conditions not achieved\n" -> "Clock received is not stable yet\n"

Quoted 8 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 77

Quoted 5 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +5 -0
+		return -ETIMEDOUT;
+	}
+
+	if (main_fsm_status & DW_PHY_PLL_RATE_BIT1) {
+		dev_dbg(dw_dev->dev, "invalid pll rate\n");

error?

This is not an error scenario also.
The 'EINVAL' return code is used by the HDMI RX Controller driver to know that the Equalization is not required and only needs to wait for tmds valid to proceed.

BTW, the print message will be changed in v2 to make more clear it's not an error scenario:
"invalid pll rate\n" -> "Equalization not required\n"

Quoted 8 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 82

Quoted 5 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +5 -0
+		return -EINVAL;
+	}
+
+	val = dw_phy_read(dw_dev, DW_PHY_CDR_CTRL_CNT) &
+		DW_PHY_HDMI_MHL_MODE_MASK;

can be single line

But in single line seems that would not fit in the 80 chars.

Quoted 10 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 214

Quoted 7 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +7 -0
+static void dw_phy_eq_init_vars(struct dw_phy_eq_ch *ch)
+{
+	ch->acc = 0;
+	ch->acq = 0;
+	ch->last_acq = 0;
+	ch->valid_long_setting = 0;
+	ch->valid_short_setting = 0;

memset() ?

In this function we only initialize some fields of 'ch' with 0. There are other fields that are not supposed to be zeroed.

Quoted 33 lines
Quoted 33 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +33 -0
+static bool dw_phy_eq_acquire_early_cnt(struct dw_phy_dev *dw_dev,
+					u16 setting, u16 acq,
+					struct dw_phy_eq_ch *ch0,
+					struct dw_phy_eq_ch *ch1,
+					struct dw_phy_eq_ch *ch2)
+{
+	u16 lock_vector = 0x1 << setting;
+	unsigned int i;
+
+	ch0->out_bound_acq = 0;
+	ch1->out_bound_acq = 0;
+	ch2->out_bound_acq = 0;
+	ch0->acq = 0;
+	ch1->acq = 0;
+	ch2->acq = 0;
+
+	dw_phy_eq_equal_setting(dw_dev, lock_vector);
+	dw_phy_eq_auto_calib(dw_dev);
+
+	mdelay(DW_PHY_EQ_SLEEP_TIME_CDR);
+	if (!dw_phy_tmds_valid(dw_dev))
+		dev_dbg(dw_dev->dev, "TMDS is NOT valid\n");
+
+	ch0->read_acq = dw_phy_read(dw_dev, DW_PHY_CH0_EQ_STATUS3);
+	ch1->read_acq = dw_phy_read(dw_dev, DW_PHY_CH1_EQ_STATUS3);
+	ch2->read_acq = dw_phy_read(dw_dev, DW_PHY_CH2_EQ_STATUS3);
+
+	ch0->acq += ch0->read_acq;
+	ch1->acq += ch1->read_acq;
+	ch2->acq += ch2->read_acq;
+
+	ch0->upper_bound_acq = ch0->read_acq + DW_PHY_EQ_BOUNDSPREAD;
+	ch0->lower_bound_acq = ch0->read_acq - DW_PHY_EQ_BOUNDSPREAD;
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 256

Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+	ch1->upper_bound_acq = ch1->read_acq + DW_PHY_EQ_BOUNDSPREAD;
+	ch1->lower_bound_acq = ch1->read_acq - DW_PHY_EQ_BOUNDSPREAD;
+	ch2->upper_bound_acq = ch2->read_acq + DW_PHY_EQ_BOUNDSPREAD;
+	ch2->lower_bound_acq = ch2->read_acq - DW_PHY_EQ_BOUNDSPREAD;
+
+	for (i = 1; i < acq; i++) {

why do we start from 1 here..?

Because the first acquisition is required to be done before and out of the for loop.

Quoted 4 lines
Quoted 4 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +4 -0
+static const struct dw_phy_mpll_config dw_phy_e406_mpll_cfg[] = {
+	{ 0x27, 0x1C94 },
+	{ 0x28, 0x3713 },
+	{ 0x29, 0x24DA },
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 102

Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+	{ 0x2A, 0x5492 },
+	{ 0x2B, 0x4B0D },
+	{ 0x2C, 0x4760 },
+	{ 0x2D, 0x008C },
+	{ 0x2E, 0x0010 },
+	{ 0x00, 0x0000 },

lower case here too please

It will be addressed in v2.

Quoted 4 lines
Quoted 4 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +4 -0
+static void dw_phy_eq_init_vars(struct dw_phy_eq_ch *ch)
+{
+	ch->acc = 0;
+	ch->acq = 0;
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 216

Quoted 5 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +5 -0
+	ch->last_acq = 0;
+	ch->valid_long_setting = 0;
+	ch->valid_short_setting = 0;
+	ch->best_setting = DW_PHY_EQ_SHORT_CABLE_SETTING;
+}

duplicate, it would make sense to create a common lib of such functions and use them across these files

This function initializes the 'ch->best_setting = DW_PHY_EQ_SHORT_CABLE_SETTING' where the define can be tuned independently for each PHY.

Regarding the other fields, we can create a common function '_dw_phy_eq_init_vars()' in the common files phy-dw-hdmi-e40x.h/c and call it inside the original function.

Quoted 6 lines
Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+static int dw_phy_set_data(struct dw_phy_dev *dw_dev)
+{
+	const struct dw_hdmi_phy_data *of_data;
+
+	of_data = of_device_get_match_data(dw_dev->dev);
+
Quoted 9 lines

drivers/phy/dwc/phy-dw-hdmi-e405.c line 123

Quoted 6 lines
drivers/phy/dwc/phy-dw-hdmi-e405.c new file +6 -0
+	if (of_data) {
+		dw_dev->phy_data = (struct dw_hdmi_phy_data *)of_data;
+	} else if (dw_dev->config->version == dw_phy_e405_data.version) {
+		dw_dev->phy_data = &dw_phy_e405_data;
+	} else if (dw_dev->config->version == dw_phy_e406_data.version) {
+		dw_dev->phy_data = &dw_phy_e406_data;

Driver supports only of, where will these else cases get triggered?

The driver supports the following two use cases:
1. Device Tree support: where the configuration data is supported by the
DT itself
2. Non Device Tree support: where the configuration data is passed
through the platform_data

So, the "else cases" are used for the second use case (Non Device Tree support).

Quoted 2 lines
Signature · 1 line
~Vinod

Thanks,

BR,

Nelson Costa

#11 lore raw

PATCH 6/9 media: platform: Add Synopsys DesignWare HDMI RX Controller Driver

In reply to Nelson Costa

This is an initial submission for the Synopsys DesignWare HDMI RX Controller Driver. It is responsible to manage and handle the PHY (through the PHY API) and the Controller configurations in order to configure the video and audio pipeline.

This driver is implemented as a standard V4L2 subdevice. The main features of this module are:
- Support for scrambling
- Support for color depth up to 48bpp
- Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz)
- Support for RGB, YCC444, YCC422 and YCC420
- Support for basic audio (LPCM 2ch, 32KHz/44.1KHz/48KHz, 16bit)
- Support for Aspect Ratio
- Support for CEC
- Internal state machine that reconfigures PHY and controller
- JTAG communication with PHY
- Inter-module communication with PHY driver:
* through the PHY API using the PHY reference "hdmi-phy"
* through the callbacks that PHY DWC driver needs.
- Debug write/read ioctls.

---
 drivers/media/platform/Kconfig          |    2 +
 drivers/media/platform/Makefile         |    1 +
 drivers/media/platform/dwc/Kconfig      |   13 +
 drivers/media/platform/dwc/Makefile     |    3 +
 drivers/media/platform/dwc/dw-hdmi-rx.c | 3237 +++++++++++++++++++++++++++++++
 drivers/media/platform/dwc/dw-hdmi-rx.h |  476 +++++
 include/media/dwc/dw-hdmi-rx-pdata.h    |  126 ++
 7 files changed, 3858 insertions(+)
 create mode 100644 drivers/media/platform/dwc/Kconfig
 create mode 100644 drivers/media/platform/dwc/Makefile
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.c
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.h
 create mode 100644 include/media/dwc/dw-hdmi-rx-pdata.h
drivers/media/platform/Kconfig +2 -0
index b238a92..20db68d 100644
@@ -29,6 +29,8 @@ source "drivers/media/platform/cadence/Kconfig"
 
 source "drivers/media/platform/davinci/Kconfig"
 
+source "drivers/media/platform/dwc/Kconfig"
+
 source "drivers/media/platform/omap/Kconfig"
 
 config VIDEO_ASPEED
drivers/media/platform/Makefile +1 -0
index eedc14a..955aae6 100644
@@ -6,6 +6,7 @@
 obj-$(CONFIG_VIDEO_ALLEGRO_DVT)		+= allegro-dvt/
 obj-$(CONFIG_VIDEO_ASPEED)		+= aspeed-video.o
 obj-$(CONFIG_VIDEO_CADENCE)		+= cadence/
+obj-y					+= dwc/
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
 obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
drivers/media/platform/dwc/Kconfig new file +13 -0
new file mode 100644
index 0000000..e915ca6
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_DWC_HDMI_RX
+	tristate "Synopsys DesignWare HDMI Receiver driver"
+	depends on VIDEO_V4L2
+	select MEDIA_CONTROLLER
+	select VIDEO_V4L2_SUBDEV_API
+	select HDMI
+	help
+	  Support for Synopsys DesignWare HDMI RX Controller.
+	  This driver supports HDMI 2.0 version.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called dw-hdmi-rx.
drivers/media/platform/dwc/Makefile new file +3 -0
new file mode 100644
index 0000000..fddd30c
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_VIDEO_DWC_HDMI_RX) += dw-hdmi-rx.o
drivers/media/platform/dwc/dw-hdmi-rx.c new file +3237 -0

2,969 lines not on this page · raw message

drivers/media/platform/dwc/dw-hdmi-rx.h new file +476 -0

476 lines not on this page · raw message

include/media/dwc/dw-hdmi-rx-pdata.h new file +126 -0

126 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.7.4

Part of the diff is not shown here. View the raw message.

#12 lore raw

Re: [PATCH 6/9] media: platform: Add Synopsys DesignWare HDMI RX Controller Driver

Hi Nelson,

Thank you for this patch. Some initial comments below, I will need to go over this another time for some of the colorimetry related functions.

BTW, if you are interested in HDCP support, let me know. Cisco worked on an API for this, but due to various reasons we have not been able to upstream it. But we do use it in our products.

Quoted 151 lines · Nelson Costa

This is an initial submission for the Synopsys DesignWare HDMI RX Controller Driver. It is responsible to manage and handle the PHY (through the PHY API) and the Controller configurations in order to configure the video and audio pipeline.

This driver is implemented as a standard V4L2 subdevice. The main features of this module are:
- Support for scrambling
- Support for color depth up to 48bpp
- Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz)
- Support for RGB, YCC444, YCC422 and YCC420
- Support for basic audio (LPCM 2ch, 32KHz/44.1KHz/48KHz, 16bit)
- Support for Aspect Ratio
- Support for CEC
- Internal state machine that reconfigures PHY and controller
- JTAG communication with PHY
- Inter-module communication with PHY driver:
* through the PHY API using the PHY reference "hdmi-phy"
* through the callbacks that PHY DWC driver needs.
- Debug write/read ioctls.

---
 drivers/media/platform/Kconfig          |    2 +
 drivers/media/platform/Makefile         |    1 +
 drivers/media/platform/dwc/Kconfig      |   13 +
 drivers/media/platform/dwc/Makefile     |    3 +
 drivers/media/platform/dwc/dw-hdmi-rx.c | 3237 +++++++++++++++++++++++++++++++
 drivers/media/platform/dwc/dw-hdmi-rx.h |  476 +++++
 include/media/dwc/dw-hdmi-rx-pdata.h    |  126 ++
 7 files changed, 3858 insertions(+)
 create mode 100644 drivers/media/platform/dwc/Kconfig
 create mode 100644 drivers/media/platform/dwc/Makefile
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.c
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.h
 create mode 100644 include/media/dwc/dw-hdmi-rx-pdata.h
drivers/media/platform/Kconfig +2 -0
index b238a92..20db68d 100644
@@ -29,6 +29,8 @@ source "drivers/media/platform/cadence/Kconfig"
 
 source "drivers/media/platform/davinci/Kconfig"
 
+source "drivers/media/platform/dwc/Kconfig"
+
 source "drivers/media/platform/omap/Kconfig"
 
 config VIDEO_ASPEED
drivers/media/platform/Makefile +1 -0
index eedc14a..955aae6 100644
@@ -6,6 +6,7 @@
 obj-$(CONFIG_VIDEO_ALLEGRO_DVT)		+= allegro-dvt/
 obj-$(CONFIG_VIDEO_ASPEED)		+= aspeed-video.o
 obj-$(CONFIG_VIDEO_CADENCE)		+= cadence/
+obj-y					+= dwc/
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
 obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
drivers/media/platform/dwc/Kconfig new file +13 -0
new file mode 100644
index 0000000..e915ca6
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_DWC_HDMI_RX
+	tristate "Synopsys DesignWare HDMI Receiver driver"
+	depends on VIDEO_V4L2
+	select MEDIA_CONTROLLER
+	select VIDEO_V4L2_SUBDEV_API
+	select HDMI
+	help
+	  Support for Synopsys DesignWare HDMI RX Controller.
+	  This driver supports HDMI 2.0 version.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called dw-hdmi-rx.
drivers/media/platform/dwc/Makefile new file +3 -0
new file mode 100644
index 0000000..fddd30c
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_VIDEO_DWC_HDMI_RX) += dw-hdmi-rx.o
drivers/media/platform/dwc/dw-hdmi-rx.c new file +54 -0
new file mode 100644
index 0000000..b20eccc
@@ -0,0 +1,3237 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - present Synopsys, Inc. and/or its affiliates.
+ * Synopsys DesignWare HDMI Receiver controller driver
+ *
+ * Author: Jose Abreu <[email protected]>
+ * Author: Nelson Costa <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/dwc/dw-hdmi-phy-pdata.h>
+#include <linux/v4l2-dv-timings.h>
+#include <linux/workqueue.h>
+#include <linux/rational.h>
+#include <linux/hdmi.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dv-timings.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+#include <media/dwc/dw-hdmi-rx-pdata.h>
+
+#include "dw-hdmi-rx.h"
+
+#define DW_HDMI_DEFAULT_TIMING		V4L2_DV_BT_CEA_640X480P59_94
+#define DW_HDMI_JTAG_TAP_ADDR_CMD	0
+#define DW_HDMI_JTAG_TAP_WRITE_CMD	1
+#define DW_HDMI_JTAG_TAP_READ_CMD	3
+#define DW_HDMI_AUDIO_FREQ_RANGE	1000
+
+/* EDID for HDMI RX */
+static u32 dw_hdmi_edid[] = {
+	/* V2 Support for                           */
+	/*  - Video modes up-to 2.97Gbps            */
+	/*  - RGB, Ycc444/422/420                   */
+	/*  - Audio 2Ch L-PCM                       */
+	/*  - SCDC CED                              */
+	0x00FFFFFF, 0xFFFFFF00, 0x4F2E4A21, 0x00000000,
+	0x331E0103, 0x80462878, 0x0A0DC9A0, 0x57479827,
+	0x12484C20, 0x00000101, 0x01010101, 0x01010101,
+	0x01010101, 0x0101023A, 0x80187138, 0x2D40582C,
+	0x450020C2, 0x3100001E, 0x011D0072, 0x51D01E20,
+	0x6E285500, 0x20C23100, 0x001E0000, 0x00FC0053,
+	0x4E505320, 0x48444D49, 0x2052580A, 0x000000FD,
+	0x0017780F, 0x871E000A, 0x20202020, 0x20200160,

drivers/media/platform/dwc/dw-hdmi-rx.c line 64

Quoted 10 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +10 -0
+
+	0x02035771, 0x83010000, 0x57696867, 0x6463625F,
+	0x5E5D901F, 0x04131211, 0x0302015A, 0x59585756,
+	0x55555453, 0x5251504F, 0x4E4D4C4B, 0x4A494847,
+	0x46454443, 0x42412309, 0x07076E03, 0x0C001000,
+	0xF83B2000, 0x80010203, 0x0467D85D, 0xC4010080,
+	0x00E50E66, 0x65616000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x000000B6,
+};

This won't work, it's a bad idea to have a default EDID since it is almost certainly wrong anyway. Userspace has to set the EDID since userspace knows the capabilities of the device as a whole. I.e., while this receiver supports up to 2.97 Gbps, there might other contraints that would lower this value. And the EDID contains vendor and model information, and addition blocks and capabilities might have to be set.

So keep the EDID empty and the HPD low at start up, and leave it to userspace to write the EDID (for testing the v4l2-ctl utility comes with a bunch of predefined EDIDs).

Quoted 2,471 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +2471 -0
+
+static const struct v4l2_dv_timings_cap dw_hdmi_timings_cap = {
+	.type = V4L2_DV_BT_656_1120,
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(640, 4096,			/* min/max width */
+			     480, 4455,			/* min/max height */
+			     20000000, 600000000,	/* min/max pixelclock */
+			     /* standards */
+			     V4L2_DV_BT_STD_CEA861,
+			     /* capabilities */
+			     V4L2_DV_BT_CAP_PROGRESSIVE)
+};
+
+static const struct v4l2_event dw_hdmi_event_fmt = {
+	.type = V4L2_EVENT_SOURCE_CHANGE,
+	.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+};
+
+enum dw_hdmi_state {
+	HDMI_STATE_NO_INIT = 0,
+	HDMI_STATE_POWER_OFF,
+	HDMI_STATE_POWER_UP,
+	HDMI_STATE_PHY_CONFIG,
+	HDMI_STATE_HPD,
+	HDMI_STATE_EQUALIZER,
+	HDMI_STATE_DATAPATH,
+	HDMI_STATE_VIDEO_UNSTABLE,
+	HDMI_STATE_AUDIO,
+	HDMI_STATE_POWER_ON,
+};
+
+struct dw_hdmi_infoframe_cfg {
+	const char *desc;
+	u8 header[3];
+	u32 header_addr;
+	u32 payload_addr;
+	u32 payload_len;
+	void *frame;
+	unsigned int frame_size;
+};
+
+struct dw_hdmi_dev {
+	struct device *dev;
+	struct device_node *of_node;
+	void __iomem *regs;
+	struct clk *clk;
+
+	/* Platform Data configuration */
+	struct dw_hdmi_rx_pdata *config;
+
+	/* Phy info */
+	struct platform_device *phy_pdev;
+	struct dw_phy_pdata phy_config;
+	struct phy *phy;
+
+	/*
+	 * Used to prevent race conditions between multiple
+	 * concurrent calls to handle the state machine changes
+	 * and pending configurations.
+	 */
+	spinlock_t lock;
+	/*
+	 * Used to prevent race conditions between multiple
+	 * concurrent calls to notify the audio changes.
+	 */
+	spinlock_t event_lock;
+
+	/* Work queue to handle the state machine */
+	struct workqueue_struct *wq;
+	struct work_struct work;
+
+	/* State machine variables */
+	enum dw_hdmi_state state;
+	u32 mbus_code;
+	u32 old_mbus;
+	u8 *curr_edid_blocks;
+	u8 current_vic;
+	bool current_vic_is_4k;
+	bool registered;
+	bool pending_config;
+	bool force_off;
+	bool is_hdmi2;
+	bool is_scrambled;
+	bool phy_eq_force;
+	bool phy_eq_on;
+	bool hw_reset_on_hot_plug;
+	bool *input_connected;
+	unsigned int selected_input;
+	unsigned int configured_input;
+	unsigned int input_stat;
+	unsigned int audio_sf;
+	unsigned int tmds_valid_wait_count;
+	unsigned int has_clock_wait_ms;
+	unsigned int video_stable_wait_ms;
+	unsigned int reset_datapath_enable;
+
+	/* Infoframes */
+	union hdmi_infoframe aviif;
+	union hdmi_infoframe spdif;
+	union hdmi_infoframe audioif;
+	union hdmi_infoframe vsif;
+
+	/* v4l2 device */
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *detect_tx_5v_ctrl;
+	struct v4l2_dv_timings timings;
+};
+
+static const char *get_state_name(enum dw_hdmi_state state)
+{
+	switch (state) {
+	case HDMI_STATE_NO_INIT:
+		return "NO_INIT";
+	case HDMI_STATE_POWER_OFF:
+		return "POWER_OFF";
+	case HDMI_STATE_POWER_UP:
+		return "POWER_UP";
+	case HDMI_STATE_PHY_CONFIG:
+		return "PHY_CONFIG";
+	case HDMI_STATE_HPD:
+		return "HPD";
+	case HDMI_STATE_EQUALIZER:
+		return "EQUALIZER";
+	case HDMI_STATE_DATAPATH:
+		return "DATAPATH";
+	case HDMI_STATE_VIDEO_UNSTABLE:
+		return "VIDEO_UNSTABLE";
+	case HDMI_STATE_AUDIO:
+		return "AUDIO";
+	case HDMI_STATE_POWER_ON:
+		return "POWER_ON";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static inline void dw_hdmi_set_state(struct dw_hdmi_dev *dw_dev,
+				     enum dw_hdmi_state new_state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dev_dbg(dw_dev->dev, "old_state=%s, new_state=%s\n",
+		get_state_name(dw_dev->state),
+		get_state_name(new_state));
+	dw_dev->state = new_state;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+}
+
+static inline struct dw_hdmi_dev *to_dw_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct dw_hdmi_dev, sd);
+}
+
+static inline void hdmi_writel(struct dw_hdmi_dev *dw_dev, u32 val, int reg)
+{
+	writel(val, dw_dev->regs + reg);
+}
+
+static inline u32 hdmi_readl(struct dw_hdmi_dev *dw_dev, int reg)
+{
+	return readl(dw_dev->regs + reg);
+}
+
+static void hdmi_modl(struct dw_hdmi_dev *dw_dev, u32 data, u32 mask, int reg)
+{
+	u32 val = hdmi_readl(dw_dev, reg) & ~mask;
+
+	val |= data & mask;
+	hdmi_writel(dw_dev, val, reg);
+}
+
+static void hdmi_mask_writel(struct dw_hdmi_dev *dw_dev, u32 data, int reg,
+			     u32 shift, u32 mask)
+{
+	hdmi_modl(dw_dev, data << shift, mask, reg);
+}
+
+static u32 hdmi_mask_readl(struct dw_hdmi_dev *dw_dev, int reg, u32 shift,
+			   u32 mask)
+{
+	return (hdmi_readl(dw_dev, reg) & mask) >> shift;
+}
+
+static bool dw_hdmi_5v_status(struct dw_hdmi_dev *dw_dev, int input)
+{
+	void __iomem *arg = dw_dev->config->dw_5v_arg;
+
+	if (dw_dev->config->dw_5v_status)
+		return dw_dev->config->dw_5v_status(arg, input);
+
+	return false;
+}
+
+static void dw_hdmi_5v_disable(struct dw_hdmi_dev *dw_dev, int input)
+{
+	void __iomem *arg = dw_dev->config->dw_5v_arg;
+
+	if (!dw_dev->config->dw_5v_disable)
+		return;
+
+	dw_dev->config->dw_5v_disable(arg, input);
+}
+
+static void dw_hdmi_5v_enable(struct dw_hdmi_dev *dw_dev, int input)
+{
+	void __iomem *arg = dw_dev->config->dw_5v_arg;
+
+	if (!dw_dev->config->dw_5v_enable)
+		return;
+
+	dw_dev->config->dw_5v_enable(arg, input);
+}
+
+static u32 dw_hdmi_edid_read(struct dw_hdmi_dev *dw_dev, int input, u32 offset)
+{
+	void __iomem *arg = dw_dev->config->dw_edid_arg;
+
+	if (!dw_dev->config->dw_edid_read)
+		return 0x0;
+
+	return dw_dev->config->dw_edid_read(arg, input, offset);
+}
+
+static int dw_hdmi_edid_write(struct dw_hdmi_dev *dw_dev, int input, u32 *edid,
+			      int size)
+{
+	void __iomem *arg = dw_dev->config->dw_edid_arg;
+
+	if (!dw_dev->config->dw_edid_write)
+		return 0;
+
+	return dw_dev->config->dw_edid_write(arg, input, edid, size);
+}
+
+static u32 dw_hdmi_edid_4blocks_le(struct dw_hdmi_dev *dw_dev)
+{
+	void __iomem *arg = dw_dev->config->dw_edid_arg;
+
+	if (!dw_dev->config->dw_edid_4blocks_le)
+		return 0x0;
+
+	return dw_dev->config->dw_edid_4blocks_le(arg);
+}
+
+static int dw_hdmi_update_edid(struct dw_hdmi_dev *dw_dev, int input,
+			       u8 *edid, int size, u8 invert_bytes)
+{
+	unsigned int i, j;
+	u32 *w_edid_srt;
+	int ret;
+
+	if (invert_bytes) {
+		/* invert the order of bytes to register 32bit */
+		w_edid_srt = devm_kzalloc(dw_dev->dev, size, GFP_KERNEL);
+		if (!w_edid_srt) {
+			devm_kfree(dw_dev->dev, w_edid_srt);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < size / sizeof(u32); i++) {
+			for (j = 0; j < 4; j++) {
+				w_edid_srt[i] |=
+					edid[i * 4 + j] << (8 * (3 - j));
+			}
+		}
+
+		ret = dw_hdmi_edid_write(dw_dev, input, (u32 *)w_edid_srt,
+					 size / sizeof(u32));
+		devm_kfree(dw_dev->dev, w_edid_srt);
+	} else {
+		/* no need to invert bytes */
+		ret = dw_hdmi_edid_write(dw_dev, input, (u32 *)edid,
+					 size / sizeof(u32));
+	}
+	dw_dev->curr_edid_blocks[input] = size / 128;
+
+	return ret;
+}
+
+static void dw_hdmi_main_reset(struct dw_hdmi_dev *dw_dev)
+{
+	void __iomem *arg = dw_dev->config->dw_reset_arg;
+
+	if (!dw_dev->config->dw_reset_all)
+		return;
+
+	dev_dbg(dw_dev->dev, "%s: main reset\n", __func__);
+
+	dw_dev->config->dw_reset_all(arg);
+}
+
+static void dw_hdmi_disable_hpd(struct dw_hdmi_dev *dw_dev);
+
+static void dw_hdmi_reset(struct dw_hdmi_dev *dw_dev)
+{
+	dev_dbg(dw_dev->dev, "%s: reset\n", __func__);
+
+	/* perform main reset */
+	dw_hdmi_main_reset(dw_dev);
+
+	dw_hdmi_disable_hpd(dw_dev);
+}
+
+static inline bool is_off(struct dw_hdmi_dev *dw_dev)
+{
+	return dw_dev->state <= HDMI_STATE_POWER_OFF;
+}
+
+static inline bool is_on(struct dw_hdmi_dev *dw_dev)
+{
+	return dw_dev->state == HDMI_STATE_POWER_ON;
+}
+
+static bool has_signal(struct dw_hdmi_dev *dw_dev, unsigned int input)
+{
+	return dw_dev->input_connected[input];
+}
+
+static inline bool is_hdmi2(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_readl(dw_dev, DW_HDMI_SCDC_REGS0) &
+			DW_HDMI_SCDC_TMDSBITCLKRATIO_MASK;
+}
+
+static inline bool is_scrambled(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_readl(dw_dev, DW_HDMI_SCDC_REGS0) &
+			DW_HDMI_SCDC_SCRAMBSTATUS_MASK;
+}
+
+static void hdmi_phy_jtag_send_pulse(struct dw_hdmi_dev *dw_dev, u8 tms, u8 tdi)
+{
+	u8 val;
+
+	val = tms ? DW_HDMI_JTAG_TMS : 0;
+	val |= tdi ? DW_HDMI_JTAG_TDI : 0;
+
+	hdmi_writel(dw_dev, 0, DW_HDMI_JTAG_TAP_TCLK);
+	hdmi_writel(dw_dev, val, DW_HDMI_JTAG_TAP_IN);
+	hdmi_writel(dw_dev, 1, DW_HDMI_JTAG_TAP_TCLK);
+}
+
+static void hdmi_phy_jtag_shift_dr(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+}
+
+static void hdmi_phy_jtag_shift_ir(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+}
+
+static u16 hdmi_phy_jtag_send(struct dw_hdmi_dev *dw_dev, u8 cmd, u16 val)
+{
+	u32 in = (cmd << 16) | val;
+	u16 out = 0;
+	u8 i;
+
+	for (i = 0; i < 16; i++) {
+		hdmi_phy_jtag_send_pulse(dw_dev, 0, in & 0x1);
+		out |= (hdmi_readl(dw_dev, DW_HDMI_JTAG_TAP_OUT) & 0x1) << i;
+		in >>= 1;
+	}
+
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, in & 0x1);
+	in >>= 1;
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, in & 0x1);
+
+	out |= (hdmi_readl(dw_dev, DW_HDMI_JTAG_TAP_OUT) & 0x1) << ++i;
+	return out;
+}
+
+static void hdmi_phy_jtag_idle(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+}
+
+static void hdmi_phy_jtag_init(struct dw_hdmi_dev *dw_dev, u8 addr)
+{
+	u8 i;
+
+	hdmi_writel(dw_dev, addr, DW_HDMI_JTAG_ADDR);
+
+	/* reset */
+	hdmi_writel(dw_dev, 0x10, DW_HDMI_JTAG_TAP_IN);
+	hdmi_writel(dw_dev, 0x0, DW_HDMI_JTAG_CONF);
+	hdmi_writel(dw_dev, 0x1, DW_HDMI_JTAG_CONF);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+
+	/* soft reset */
+	for (i = 0; i < 5; i++)
+		hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+
+	/* set slave address */
+	hdmi_phy_jtag_shift_ir(dw_dev);
+	for (i = 0; i < 7; i++) {
+		hdmi_phy_jtag_send_pulse(dw_dev, 0, addr & 0x1);
+		addr >>= 1;
+	}
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, addr & 0x1);
+	hdmi_phy_jtag_idle(dw_dev);
+}
+
+static void hdmi_phy_jtag_write(struct dw_hdmi_dev *dw_dev, u16 val, u16 addr)
+{
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_ADDR_CMD, addr << 8);
+	hdmi_phy_jtag_idle(dw_dev);
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_WRITE_CMD, val);
+	hdmi_phy_jtag_idle(dw_dev);
+}
+
+static u16 hdmi_phy_jtag_read(struct dw_hdmi_dev *dw_dev, u16 addr)
+{
+	u16 val;
+
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_ADDR_CMD, addr << 8);
+	hdmi_phy_jtag_idle(dw_dev);
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	val = hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_READ_CMD, 0xFFFF);
+	hdmi_phy_jtag_idle(dw_dev);
+
+	return val;
+}
+
+static void dw_hdmi_phy_write(void *arg, u16 val, u16 addr)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+	u16 rval;
+
+	hdmi_phy_jtag_init(dw_dev, dw_dev->config->phy->jtag_addr);
+	hdmi_phy_jtag_write(dw_dev, val, addr);
+	rval = hdmi_phy_jtag_read(dw_dev, addr);
+
+	if (rval != val) {
+		dev_err(dw_dev->dev,
+			"JTAG read-back failed: expected=0x%x, got=0x%x\n",
+			val, rval);
+	}
+}
+
+static u16 dw_hdmi_phy_read(void *arg, u16 addr)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_phy_jtag_init(dw_dev, dw_dev->config->phy->jtag_addr);
+	return hdmi_phy_jtag_read(dw_dev, addr);
+}
+
+static void dw_hdmi_phy_reset(void *arg, int enable)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PHYRESET_OFFSET,
+			 DW_HDMI_PHYRESET_MASK);
+}
+
+static void dw_hdmi_phy_pddq(void *arg, int enable)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PHYPDDQ_OFFSET,
+			 DW_HDMI_PHYPDDQ_MASK);
+}
+
+static void dw_hdmi_phy_svsmode(void *arg, int enable)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PHYSVSRETMODEZ_OFFSET,
+			 DW_HDMI_PHYSVSRETMODEZ_MASK);
+}
+
+static void dw_hdmi_zcal_reset(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	if (dw_dev->config->dw_zcal_reset)
+		dw_dev->config->dw_zcal_reset(dw_dev->config->dw_zcal_arg);
+}
+
+static bool dw_hdmi_zcal_done(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+	void __iomem *zcal_arg = dw_dev->config->dw_zcal_arg;
+
+	if (dw_dev->config->dw_zcal_done)
+		return dw_dev->config->dw_zcal_done(zcal_arg);
+
+	return false;
+}
+
+static bool dw_hdmi_tmds_valid(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	return (hdmi_readl(dw_dev, DW_HDMI_PLL_LCK_STS) & DW_HDMI_PLL_LOCKED);
+}
+
+static bool dw_hdmi_audio_valid(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	return ((hdmi_readl(dw_dev, DW_HDMI_AUD_PLL_CTRL) &
+			DW_HDMI_PLL_LOCK_STABLE_MASK) != 0);
+}
+
+static const struct dw_phy_funcs dw_hdmi_phy_funcs = {
+	.write = dw_hdmi_phy_write,
+	.read = dw_hdmi_phy_read,
+	.reset = dw_hdmi_phy_reset,
+	.pddq = dw_hdmi_phy_pddq,
+	.svsmode = dw_hdmi_phy_svsmode,
+	.zcal_reset = dw_hdmi_zcal_reset,
+	.zcal_done = dw_hdmi_zcal_done,
+	.tmds_valid = dw_hdmi_tmds_valid,
+};
+
+static const struct of_device_id dw_hdmi_supported_phys[] = {
+	{ .compatible = "snps,dw-hdmi-phy-e405", .data = DW_PHY_E40X_DRVNAME, },
+	{ .compatible = "snps,dw-hdmi-phy-e406", .data = DW_PHY_E40X_DRVNAME, },
+	{ },
+};
+
+static struct device_node *
+dw_hdmi_get_phy_of_node(struct dw_hdmi_dev *dw_dev,
+			const struct of_device_id **found_id)
+{
+	const struct of_device_id *id = NULL;
+	struct device_node *np = NULL;
+
+	np = of_find_matching_node_and_match(NULL, dw_hdmi_supported_phys, &id);
+
+	if (!id)
+		return NULL;
+
+	if (found_id)
+		*found_id = id;
+
+	return np;
+}
+
+static bool dw_hdmi_has_dt(struct dw_hdmi_dev *dw_dev)
+{
+	const struct of_device_id *of_id;
+
+	if (!dw_dev->of_node ||
+	    !dw_hdmi_get_phy_of_node(dw_dev, &of_id) ||
+	    !of_id || !of_id->data) {
+		return false;
+	}
+
+	return true;
+}
+
+static const struct dw_hdmi_phy_cfg {
+	const char *drvname;
+	const struct dw_phy_funcs *funcs;
+	int (*extra_init)(struct dw_hdmi_dev *dw_dev);
+} dw_hdmi_phys[] = {
+	{
+		.drvname = DW_PHY_E40X_DRVNAME,
+		.funcs = &dw_hdmi_phy_funcs,
+	},
+};
+
+static int dw_hdmi_phy_init_dt(struct dw_hdmi_dev *dw_dev)
+{
+	const struct dw_hdmi_phy_cfg *phy_config = NULL;
+	struct dw_phy_pdata *phy = &dw_dev->phy_config;
+	struct of_dev_auxdata lookup = { };
+	const struct of_device_id *of_id;
+	struct device_node *child;
+	const char *drvname;
+	unsigned int i;
+	int ret;
+
+	child = dw_hdmi_get_phy_of_node(dw_dev, &of_id);
+	if (!child || !of_id || !of_id->data) {
+		dev_err(dw_dev->dev, "no supported PHY found in DT\n");
+		return -EINVAL;
+	}
+
+	drvname = of_id->data;
+	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); i++) {
+		if (!strcmp(dw_hdmi_phys[i].drvname, drvname))
+			phy_config = &dw_hdmi_phys[i];
+	}
+
+	if (!phy_config) {
+		dev_err(dw_dev->dev, "failed to find PHY configuration\n");
+		return -EINVAL;
+	}
+
+	if (phy_config->extra_init) {
+		ret = phy_config->extra_init(dw_dev);
+		if (ret)
+			return ret;
+	}
+
+	phy->funcs = phy_config->funcs;
+	phy->funcs_arg = dw_dev;
+
+	lookup.compatible = (char *)of_id->compatible;
+	lookup.platform_data = phy;
+
+	request_module(drvname);
+
+	ret = of_platform_populate(dw_dev->of_node, NULL, &lookup, dw_dev->dev);
+	if (ret) {
+		dev_err(dw_dev->dev, "failed to populate PHY driver\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_phy_init_pd(struct dw_hdmi_dev *dw_dev)
+{
+	const char *drv_name = dw_dev->config->phy->drv_name;
+	const struct dw_hdmi_phy_cfg *phy_config = NULL;
+	struct platform_device_info pdevinfo;
+	unsigned int i;
+	int ret;
+
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); i++) {
+		if (!strcmp(dw_hdmi_phys[i].drvname, drv_name))
+			phy_config = &dw_hdmi_phys[i];
+	}
+
+	if (!phy_config) {
+		dev_err(dw_dev->dev, "failed to find PHY configuration\n");
+		return -EINVAL;
+	}
+
+	if (phy_config->extra_init) {
+		ret = phy_config->extra_init(dw_dev);
+		if (ret)
+			return ret;
+	}
+
+	dw_dev->phy_config.version = dw_dev->config->phy->version;
+	dw_dev->phy_config.cfg_clk = dw_dev->config->phy->cfg_clk;
+	dw_dev->phy_config.funcs = phy_config->funcs;
+	dw_dev->phy_config.funcs_arg = dw_dev;
+
+	pdevinfo.parent = dw_dev->dev;
+	pdevinfo.id = PLATFORM_DEVID_NONE;
+	pdevinfo.name = drv_name;
+	pdevinfo.data = &dw_dev->phy_config;
+	pdevinfo.size_data = sizeof(dw_dev->phy_config);
+	pdevinfo.dma_mask = DMA_BIT_MASK(32);
+
+	request_module(pdevinfo.name);
+
+	dw_dev->phy_pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(dw_dev->phy_pdev)) {
+		dev_err(dw_dev->dev, "failed to register PHY device\n");
+		return PTR_ERR(dw_dev->phy_pdev);
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_phy_init(struct dw_hdmi_dev *dw_dev)
+{
+	int ret;
+
+	if (dw_hdmi_has_dt(dw_dev)) {
+		/* init PHY based on device tree */
+		ret = dw_hdmi_phy_init_dt(dw_dev);
+	} else {
+		/* init PHY based on platform device */
+		ret = dw_hdmi_phy_init_pd(dw_dev);
+	}
+
+	/* get the HDMI PHY reference */
+	dw_dev->phy = devm_phy_get(dw_dev->dev, "hdmi-phy");
+	if (IS_ERR(dw_dev->phy)) {
+		if (PTR_ERR(dw_dev->phy) != -EPROBE_DEFER)
+			dev_err(dw_dev->dev, "Couldn't get the HDMI PHY\n");
+		return PTR_ERR(dw_dev->phy);
+	}
+
+	return ret;
+}
+
+static void dw_hdmi_phy_exit(struct dw_hdmi_dev *dw_dev)
+{
+	if (dw_hdmi_has_dt(dw_dev)) {
+		/* exit PHY based on device tree */
+		of_platform_depopulate(dw_dev->dev);
+	} else {
+		/* exit PHY based on platform device */
+		if (!IS_ERR(dw_dev->phy_pdev))
+			platform_device_unregister(dw_dev->phy_pdev);
+	}
+}
+
+static int dw_hdmi_phy_eq_init(struct dw_hdmi_dev *dw_dev, u16 acq, bool force)
+{
+	union phy_configure_opts opts;
+	struct phy_configure_opts_hdmi *hdmi_opts = &opts.hdmi;
+	int ret = 0;
+
+	/* load the required options for calibration */
+	hdmi_opts->calibration_acq = acq;
+	hdmi_opts->calibration_force = force;
+	/* to avoid other reconfigurations when is to calibrate */
+	hdmi_opts->set_color_depth = 0;
+	hdmi_opts->set_tmds_bit_clock_ratio = 0;
+	hdmi_opts->set_scrambling = 0;
+
+	/* set PHY configuration */
+	ret = phy_configure(dw_dev->phy, &opts);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY configure (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+	/* call PHY calibrate */
+	ret = phy_calibrate(dw_dev->phy);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY calibrate (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int dw_hdmi_phy_config(struct dw_hdmi_dev *dw_dev,
+			      unsigned char color_depth, bool hdmi2,
+			      bool scrambling)
+{
+	union phy_configure_opts opts;
+	struct phy_configure_opts_hdmi *hdmi_opts = &opts.hdmi;
+	int ret = 0;
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_DATAPATH_CBUSZ_OFFSET,
+			 DW_HDMI_DATAPATH_CBUSZ_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_CBUS_SVSRETMODEZ_OFFSET,
+			 DW_HDMI_CBUS_SVSRETMODEZ_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_CBUS_PDDQ_OFFSET,
+			 DW_HDMI_CBUS_PDDQ_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_CBUS_RESET_OFFSET,
+			 DW_HDMI_CBUS_RESET_MASK);
+
+	/* load the required options for power on */
+	hdmi_opts->color_depth = color_depth;
+	hdmi_opts->tmds_bit_clock_ratio = hdmi2;
+	hdmi_opts->scrambling = scrambling;
+	/* to avoid color depth reconfiguration before the power on */
+	hdmi_opts->set_color_depth = 0;
+
+	/* set PHY configuration */
+	ret = phy_configure(dw_dev->phy, &opts);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY configure (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+	/* call PHY power off if needed */
+	if (dw_dev->phy->power_count > 0) {
+		ret = phy_power_off(dw_dev->phy);
+		if (ret) {
+			dev_err(dw_dev->dev, "%s: Couldn't PHY power off (err: %d)\n",
+				__func__, ret);
+		}
+	}
+
+	/* call PHY power on */
+	ret = phy_power_on(dw_dev->phy);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY power on (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int dw_hdmi_phy_set_color_depth(struct dw_hdmi_dev *dw_dev,
+				       u8 color_depth)
+{
+	union phy_configure_opts opts;
+	struct phy_configure_opts_hdmi *hdmi_opts = &opts.hdmi;
+	int ret = 0;
+
+	/* load the required options for color depth reconfiguration */
+	hdmi_opts->color_depth = color_depth;
+	/* to avoid other reconfigurations when is to set only color depth */
+	hdmi_opts->set_tmds_bit_clock_ratio = 0;
+	hdmi_opts->set_scrambling = 0;
+
+	/* set PHY configuration */
+	ret = phy_configure(dw_dev->phy, &opts);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY configure (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static void dw_hdmi_event_source_change(struct dw_hdmi_dev *dw_dev)
+{
+	if (dw_dev->registered)
+		v4l2_subdev_notify_event(&dw_dev->sd, &dw_hdmi_event_fmt);
+}
+
+static int dw_hdmi_reset_ceavid(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_RST_OFFSET,
+			 DW_HDMI_CEAVID_RST_MASK);
+	msleep(100);
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_RST_OFFSET,
+			 DW_HDMI_CEAVID_RST_MASK);
+
+	return 0;
+}
+
+static void dw_hdmi_update_avmute(struct dw_hdmi_dev *dw_dev, u32 mbus_code)
+{
+	u32 val_l = 0x0, val_h = 0x0;
+
+	switch (mbus_code) {
+	case MEDIA_BUS_FMT_YUYV8_1X16: /* YCbCr 4:2:2 */
+		val_h = 0x00008000;
+		val_l = 0x00008000;
+		break;
+	case MEDIA_BUS_FMT_YUYV12_1X24: /* YCbCr 4:4:4 */
+		val_h = 0x00008000;
+		val_l = 0x00008000;
+		break;
+	case MEDIA_BUS_FMT_YVYU8_1X16: /* YCbCr 4:2:0 */
+		val_h = 0x00000f00;
+		val_l = 0x0f007f00;
+		break;
+	case MEDIA_BUS_FMT_RGB888_2X12_BE: /* RGB */
+	default:
+		break;
+	}
+
+	hdmi_writel(dw_dev, val_l, DW_HDMI_VM_CFG_CH_0_1);
+	hdmi_mask_writel(dw_dev, val_h, DW_HDMI_VM_CFG_CH2,
+			 DW_HDMI_VM_CH2_COL_VALUE_OFFSET,
+			 DW_HDMI_VM_CH2_COL_VALUE_MASK);
+}
+
+static u32 dw_hdmi_get_mbus_code(struct dw_hdmi_dev *dw_dev)
+{
+	enum hdmi_colorspace cs = dw_dev->aviif.avi.colorspace;
+
+	switch (cs) {
+	case HDMI_COLORSPACE_RGB: /* RGB */
+		return MEDIA_BUS_FMT_RGB888_2X12_BE;
+	case HDMI_COLORSPACE_YUV422: /* YCbCr 4:2:2 */
+		return MEDIA_BUS_FMT_YUYV8_1X16;
+	case HDMI_COLORSPACE_YUV444: /* YCbCr 4:4:4 */
+		return MEDIA_BUS_FMT_YUYV12_1X24;
+	case HDMI_COLORSPACE_YUV420: /* YCbCr 4:2:0 */
+		return MEDIA_BUS_FMT_YVYU8_1X16;
+	default:
+		return MEDIA_BUS_FMT_RGB888_2X12_BE;
+	}
+}
+
+static u8 dw_hdmi_infoframe_checksum(u8 *ptr, size_t size)
+{
+	u8 csum = 0;
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		csum += ptr[i];
+	return 256 - csum;
+}
+
+static void dw_hdmi_get_raw_infoframe_avi(struct dw_hdmi_dev *dw_dev,
+					  struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	u32 pb, ph = hdmi_readl(dw_dev, fcfg->header_addr);
+	union hdmi_infoframe *frame = fcfg->frame;
+	u8 packet_hlen = sizeof(fcfg->header);
+	u8 packet_len = (ph >> 8) & 0xff;
+	unsigned int i, j, pos = 0;
+	u8 packet[35] = {0};
+
+	dev_dbg(dw_dev->dev, "%s[%s]: packet_header=0x%x\n", __func__,
+		fcfg->desc, ph);
+
+	if (!ph) /* Fail silently if there is no packet */
+		return;
+
+	if ((packet_len + packet_hlen + 1) > sizeof(packet)) {
+		dev_dbg(dw_dev->dev, "%s: invalid length\n", __func__);
+		goto out;
+	}
+
+	memcpy(packet, fcfg->header, packet_hlen);
+	packet[2] = packet_len; /* Replace fake header size by real header */
+	pos += packet_hlen + 1;
+
+	for (i = 0; i < fcfg->payload_len; i++) {
+		j = 0;
+
+		/* specific for AVI */
+		if (fcfg->header[0] == HDMI_INFOFRAME_TYPE_AVI && i == 1) {
+			/* read YQx, CNx, PRx from AVI PH register */
+			u32 offset = DW_HDMI_PIX_REP_FACTOR_OFFSET;
+			u32 mask = DW_HDMI_QUANT_RANGE_MASK |
+				DW_HDMI_CONTENT_TYPE_MASK |
+				DW_HDMI_PIX_REP_FACTOR_MASK;
+
+			pb = hdmi_mask_readl(dw_dev, fcfg->header_addr, offset,
+					     mask);
+			packet[pos++] = pb & 0xff;
+			j = 1;
+		}
+
+		/* the registers are aligned with the standard raw packet */
+		pb = hdmi_readl(dw_dev, fcfg->payload_addr + 4 * i);
+		for (; j < 4; j++) {
+			if (pos >= (packet_len + packet_hlen + 1))
+				break;
+			packet[pos++] = (pb >> (8 * j)) & 0xff;
+		}
+	}
+
+	packet[3] = dw_hdmi_infoframe_checksum(packet, packet_len +
+			packet_hlen + 1);
+
+	/*print all packet bytes */
+	for (j = 0; j < pos; j++) {
+		dev_dbg(dw_dev->dev, "%s[%s]: packet=0x%x\n", __func__,
+			fcfg->desc, packet[j]);
+	}
+
+	if (hdmi_infoframe_unpack(frame, packet, sizeof(packet))) {
+		dev_dbg(dw_dev->dev, "%s[%s]: failed to unpack\n",
+			__func__, fcfg->desc);
+		goto out;
+	}
+
+	return;
+out:
+	dev_err(dw_dev->dev, "[INVALID INFOFRAME]\n");
+}
+
+static void dw_hdmi_get_raw_infoframe_aud(struct dw_hdmi_dev *dw_dev,
+					  struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	u32 pb, ph = hdmi_readl(dw_dev, fcfg->header_addr);
+	union hdmi_infoframe *frame = fcfg->frame;
+	u8 packet_hlen = sizeof(fcfg->header);
+	u8 packet_len = (ph >> 8) & 0xff;
+	unsigned int i, j, pos = 0;
+	u8 packet[35] = {0};
+
+	dev_dbg(dw_dev->dev, "%s[%s]: packet_header=0x%x\n", __func__,
+		fcfg->desc, ph);
+
+	if (!ph) /* Fail silently if there is no packet */
+		return;
+
+	if ((packet_len + packet_hlen + 1) > sizeof(packet)) {
+		dev_dbg(dw_dev->dev, "%s: invalid length\n", __func__);
+		goto out;
+	}
+
+	memcpy(packet, fcfg->header, packet_hlen);
+	packet[2] = packet_len; /* Replace fake header size by real header */
+	pos += packet_hlen + 1;
+
+	for (i = 0; i < fcfg->payload_len; i++) {
+		j = 0;
+
+		/* specific for audio */
+		if (fcfg->header[0] == HDMI_INFOFRAME_TYPE_AUDIO && i == 1) {
+			pb = hdmi_readl(dw_dev, fcfg->payload_addr + 4 * i);
+			packet[pos++] = (pb |
+			    ((pb & DW_HDMI_LFE_PLAYBACK_LEVEL_MASK)
+			    >> DW_HDMI_LFE_PLAYBACK_LEVEL_OFFSET)) &
+			    0xff;
+			break;
+		}
+
+		/* the registers are aligned with the standard raw packet */
+		pb = hdmi_readl(dw_dev, fcfg->payload_addr + 4 * i);
+		for (; j < 4; j++) {
+			if (pos >= (packet_len + packet_hlen + 1))
+				break;
+			packet[pos++] = (pb >> (8 * j)) & 0xff;
+		}
+	}
+
+	packet[3] = dw_hdmi_infoframe_checksum(packet, packet_len +
+			packet_hlen + 1);
+
+	/*print all packet bytes */
+	for (j = 0; j < pos; j++) {
+		dev_dbg(dw_dev->dev, "%s[%s]: packet=0x%x\n", __func__,
+			fcfg->desc, packet[j]);
+	}
+
+	if (hdmi_infoframe_unpack(frame, packet, sizeof(packet))) {
+		dev_dbg(dw_dev->dev, "%s[%s]: failed to unpack\n",
+			__func__, fcfg->desc);
+		goto out;
+	}
+
+	return;
+out:
+	dev_err(dw_dev->dev, "[INVALID INFOFRAME]\n");
+}
+
+static void dw_hdmi_get_raw_infoframe_vs(struct dw_hdmi_dev *dw_dev,
+					 struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	u32 pb, ph = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+				     DW_HDMI_LENGTH_OFFSET,
+				     DW_HDMI_LENGTH_MASK);
+	union hdmi_infoframe *frame = fcfg->frame;
+	u8 packet_hlen = sizeof(fcfg->header);
+	unsigned int j, pos = 0;
+	u8 packet[35] = {0};
+	u8 packet_len = ph;
+
+	dev_dbg(dw_dev->dev, "%s[%s]: packet_header=0x%x\n", __func__,
+		fcfg->desc, ph);
+
+	if (!ph) /* Fail silently if there is no packet */
+		return;
+
+	if ((packet_len + packet_hlen + 1) > sizeof(packet)) {
+		dev_dbg(dw_dev->dev, "%s: invalid length\n", __func__);
+		goto out;
+	}
+
+	memcpy(packet, fcfg->header, packet_hlen);
+	packet[2] = packet_len; /* Replace fake header size by real header */
+	pos += packet_hlen + 1;
+
+	/* 24bit IEEE Registration identifier */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST0,
+			     DW_HDMI_IEEE_REG_ID_OFFSET,
+			     DW_HDMI_IEEE_REG_ID_MASK);
+	for (j = 0; j < 3; j++) {
+		if (pos >= (packet_len + packet_hlen + 1))
+			break;
+		packet[pos++] = (pb >> (8 * j)) & 0xff;
+	}
+
+	/* HDMI video format */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_HDMI_VIDEO_FORMAT_OFFSET,
+			     DW_HDMI_HDMI_VIDEO_FORMAT_MASK);
+	packet[pos++] = (pb << DW_HDMI_HDMI_VIDEO_FORMAT_OFFSET) &
+			0xff;
+
+	/* HDMI vic */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_HDMI_VIC_OFFSET,
+			     DW_HDMI_HDMI_VIC_MASK);
+	packet[pos++] = pb & 0xff;
+
+	/* 3d structure */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_H3D_STRUCTURE_OFFSET,
+			     DW_HDMI_H3D_STRUCTURE_MASK);
+	packet[pos++] = (pb << 4) & 0xff;
+
+	/* 3d ext data */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_H3D_EXT_DATA_OFFSET,
+			     DW_HDMI_H3D_EXT_DATA_MASK);
+	packet[pos++] = (pb << 4) & 0xff;
+
+	packet[3] = dw_hdmi_infoframe_checksum(packet, packet_len +
+			packet_hlen + 1);
+
+	/*print all packet bytes */
+	for (j = 0; j < pos; j++) {
+		dev_dbg(dw_dev->dev, "%s[%s]: packet=0x%x\n", __func__,
+			fcfg->desc, packet[j]);
+	}
+
+	if (hdmi_infoframe_unpack(frame, packet, sizeof(packet))) {
+		dev_dbg(dw_dev->dev, "%s[%s]: failed to unpack\n",
+			__func__, fcfg->desc);
+		goto out;
+	}
+
+	return;
+out:
+	dev_err(dw_dev->dev, "[INVALID INFOFRAME]\n");
+}
+
+static void dw_hdmi_get_raw_infoframe(struct dw_hdmi_dev *dw_dev,
+				      struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	switch (fcfg->header[0]) {
+	case HDMI_INFOFRAME_TYPE_AVI:
+		dw_hdmi_get_raw_infoframe_avi(dw_dev, fcfg);
+		break;
+	case HDMI_INFOFRAME_TYPE_SPD:
+		dev_dbg(dw_dev->dev,
+			"%s[%s]: not processed infoframe packet type %d\n",
+			__func__, fcfg->desc, fcfg->header[0]);
+		break;
+	case HDMI_INFOFRAME_TYPE_AUDIO:
+		dw_hdmi_get_raw_infoframe_aud(dw_dev, fcfg);
+		break;
+	case HDMI_INFOFRAME_TYPE_VENDOR:
+		dw_hdmi_get_raw_infoframe_vs(dw_dev, fcfg);
+		break;
+	case HDMI_INFOFRAME_TYPE_DRM:
+		dev_dbg(dw_dev->dev,
+			"%s[%s]: not processed infoframe packet type %d\n",
+			__func__, fcfg->desc, fcfg->header[0]);
+		break;
+	default:
+		dev_dbg(dw_dev->dev,
+			"%s[%s]: invalid infoframe packet type %d\n",
+			__func__, fcfg->desc, fcfg->header[0]);
+		break;
+	}
+}
+
+/* Forward declaration needed because of color encoding change */
+static void dw_hdmi_power_off(struct dw_hdmi_dev *dw_dev);
+static void dw_hdmi_controller_power_off(struct dw_hdmi_dev *dw_dev);
+static int dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, unsigned int input);
+
+static void dw_hdmi_get_infoframes(struct dw_hdmi_dev *dw_dev)
+{
+	struct dw_hdmi_infoframe_cfg ifs[] = {
+		{
+			.desc = "AVI",
+			.header = {HDMI_INFOFRAME_TYPE_AVI, 2,
+				   HDMI_AVI_INFOFRAME_SIZE},
+			.header_addr = DW_HDMI_PDEC_AVI_HB,
+			.payload_addr = DW_HDMI_PDEC_AVI_PB,
+			.payload_len = DW_HDMI_PDEC_AVI_PBLEN,
+			.frame = &dw_dev->aviif,
+			.frame_size = sizeof(dw_dev->aviif),
+		}, {
+			.desc = "Audio",
+			.header = {HDMI_INFOFRAME_TYPE_AUDIO, 1,
+				   HDMI_AUDIO_INFOFRAME_SIZE},
+			.header_addr = DW_HDMI_PDEC_AIF_HB,
+			.payload_addr = DW_HDMI_PDEC_AIF_PB0,
+			.payload_len = DW_HDMI_PDEC_AIF_PBLEN,
+			.frame = &dw_dev->audioif,
+			.frame_size = sizeof(dw_dev->audioif),
+		}, {
+			.desc = "Vendor Specific",
+			.header = {HDMI_INFOFRAME_TYPE_VENDOR, 1,
+				   HDMI_VENDOR_INFOFRAME_SIZE},
+			.frame = &dw_dev->vsif,
+			.frame_size = sizeof(dw_dev->vsif),
+		},
+	};
+	union hdmi_vendor_any_infoframe *vendor;
+	struct hdmi_avi_infoframe *avi;
+	unsigned int i;
+	u32 old_mbus;
+
+	for (i = 0; i < ARRAY_SIZE(ifs); i++) {
+		memset(ifs[i].frame, 0, ifs[i].frame_size);
+		dw_hdmi_get_raw_infoframe(dw_dev, &ifs[i]);
+	}
+
+	/* Update color space */
+	old_mbus = dw_dev->mbus_code;
+	dw_dev->mbus_code = dw_hdmi_get_mbus_code(dw_dev);
+	if (dw_dev->mbus_code != old_mbus && is_on(dw_dev)) {
+		dw_hdmi_power_off(dw_dev);
+		if (has_signal(dw_dev, dw_dev->configured_input))
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+	}
+
+	/* Update AVMute value */
+	dw_hdmi_update_avmute(dw_dev, dw_dev->mbus_code);
+
+	vendor = &dw_dev->vsif.vendor;
+	avi = &dw_dev->aviif.avi;
+
+	/*
+	 * Update current VIC: When transmitting any extended video format
+	 * indicated through use of the HDMI_VIC field in the HDMI Vendor
+	 * Specific InfoFrame or any other format which is not described in
+	 * the above cases, an HDMI Source shall set the AVI InfoFrame VIC
+	 * field to zero.
+	 */
+	if (vendor->hdmi.vic && !avi->video_code) {
+		dw_dev->current_vic = vendor->hdmi.vic;
+		dw_dev->current_vic_is_4k = true;
+	} else {
+		dw_dev->current_vic = avi->video_code;
+		dw_dev->current_vic_is_4k = false;
+	}
+}
+
+static int dw_hdmi_wait_phy_lock_poll(struct dw_hdmi_dev *dw_dev)
+{
+	int timeout = dw_dev->tmds_valid_wait_count;
+
+	while (!dw_hdmi_tmds_valid(dw_dev) && timeout-- && !dw_dev->force_off)
+		usleep_range(5000, 10000);
+
+	if (!dw_hdmi_tmds_valid(dw_dev))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static void dw_hdmi_reset_datapath(struct dw_hdmi_dev *dw_dev)
+{
+	u32 val = DW_HDMI_TMDS_SWRESET |
+		DW_HDMI_HDCP_SWRESET |
+		DW_HDMI_VID_SWRESET |
+		DW_HDMI_PIXEL_SWRESET |
+		DW_HDMI_CEC_SWRESET |
+		DW_HDMI_AUD_SWRESET |
+		DW_HDMI_BUS_SWRESET |
+		DW_HDMI_HDMI_SWRESET |
+		DW_HDMI_MODET_SWRESET;
+
+	hdmi_writel(dw_dev, val & dw_dev->reset_datapath_enable,
+		    DW_HDMI_DMI_SW_RST);
+}
+
+static void dw_hdmi_reset_audio(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_writel(dw_dev, DW_HDMI_AUD_SWRESET, DW_HDMI_DMI_SW_RST);
+}
+
+static void dw_hdmi_restart_audio_fifo(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_AUD_FIFO_CTRL,
+			 DW_HDMI_AFIF_INIT_OFFSET,
+			 DW_HDMI_AFIF_INIT_MASK);
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_AUD_FIFO_CTRL,
+			 DW_HDMI_AFIF_INIT_OFFSET,
+			 DW_HDMI_AFIF_INIT_MASK);
+}
+
+static int dw_hdmi_wait_audio_lock_poll(struct dw_hdmi_dev *dw_dev)
+{
+	int timeout = 10;
+
+	while (!dw_hdmi_audio_valid(dw_dev) && timeout-- && !dw_dev->force_off)
+		usleep_range(5000, 10000);
+
+	if (!dw_hdmi_audio_valid(dw_dev))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int dw_hdmi_config_audio(struct dw_hdmi_dev *dw_dev)
+{
+	int ret;
+
+	ret = dw_hdmi_wait_audio_lock_poll(dw_dev);
+	if (ret) {
+		dev_err(dw_dev->dev, "failed to wait for audio pll lock\n");
+		return ret;
+	}
+
+	/* trigger offset for N and CTS interrupts */
+	hdmi_mask_writel(dw_dev, 0x05, DW_HDMI_PDEC_ACRM_CTRL,
+			 DW_HDMI_DELTACTS_IRQTRIG_OFFSET,
+			 DW_HDMI_DELTACTS_IRQTRIG_MASK);
+
+	/* Config */
+	hdmi_mask_writel(dw_dev, 0x01, DW_HDMI_AUD_MUTE_CTRL,
+			 DW_HDMI_AUD_MUTE_SEL_OFFSET,
+			 DW_HDMI_AUD_MUTE_SEL_MASK);
+
+	/* enable all outputs and select 16-bit for I2S */
+	hdmi_writel(dw_dev, 0x00, DW_HDMI_AUD_SAO_CTRL);
+
+	/* Start */
+	dw_hdmi_restart_audio_fifo(dw_dev);
+	return 0;
+}
+
+static void dw_hdmi_config_packet(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_CTRL,
+			 DW_HDMI_PFIFO_STORE_FILTER_EN_OFFSET,
+			 DW_HDMI_PFIFO_STORE_FILTER_EN_MASK);
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_ASP_CTRL,
+			 DW_HDMI_AUTO_VMUTE_OFFSET,
+			 DW_HDMI_AUTO_VMUTE_MASK);
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_ASP_CTRL,
+			 DW_HDMI_AUTO_SPFLAT_MUTE_OFFSET,
+			 DW_HDMI_AUTO_SPFLAT_MUTE_MASK);
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_CTRL,
+			 DW_HDMI_PD_FIFO_CLR_OFFSET,
+			 DW_HDMI_PD_FIFO_CLR_MASK);
+}
+
+static void dw_hdmi_wait_video_stable(struct dw_hdmi_dev *dw_dev)
+{
+	/*
+	 * Empiric value. Video should be stable way longer before the
+	 * end of this sleep time. Though, we can have some video change
+	 * interrupts before the video is stable so filter them by sleeping.
+	 */
+	msleep(dw_dev->video_stable_wait_ms);
+}
+
+static void dw_hdmi_enable_ints(struct dw_hdmi_dev *dw_dev)
+{
+	u32 pdec_ints = 0;
+
+	/* video interrupts */
+	hdmi_writel(dw_dev, DW_HDMI_CLK_CHANGE_ISTS | DW_HDMI_PLL_LCK_CHG_ISTS |
+			DW_HDMI_DCM_CURRENT_MODE_CHG_ISTS, DW_HDMI_IEN_SET);
+	hdmi_writel(dw_dev, (DW_HDMI_VACT_LIN_ISTS | DW_HDMI_HACT_PIX_ISTS),
+		    DW_HDMI_MD_IEN_SET);
+
+	/* infoframes interrupts */
+	pdec_ints = (DW_HDMI_VSI_CKS_CHG_ISTS |
+		     DW_HDMI_DRM_CKS_CHG_ISTS |
+		     DW_HDMI_AVI_CKS_CHG_ISTS);
+
+	/* audio interrupts */
+	pdec_ints |= (DW_HDMI_AUD_TYPE_CHG_ISTS |
+		      DW_HDMI_AIF_CKS_CHG_ISTS |
+		      DW_HDMI_ACR_N_CHG_ISTS |
+		      DW_HDMI_ACR_CTS_CHG_ISTS |
+		      DW_HDMI_GCP_AV_MUTE_CHG_ISTS);
+
+	hdmi_writel(dw_dev, pdec_ints, DW_HDMI_PDEC_IEN_SET);
+	hdmi_writel(dw_dev, (DW_HDMI_AFIF_OVERFL_ISTS |
+			DW_HDMI_AFIF_UNDERFL_ISTS |
+			DW_HDMI_AFIF_THS_PASS_ISTS),
+		    DW_HDMI_AUD_FIFO_IEN_SET);
+}
+
+static void dw_hdmi_disable_ints(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_IEN_CLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_MD_IEN_CLR);
+
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_PDEC_IEN_CLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_AUD_FIFO_IEN_CLR);
+}
+
+static void dw_hdmi_clear_ints(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_ICLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_MD_ICLR);
+
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_PDEC_ICLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_AUD_FIFO_ICLR);
+}
+
+static u32 dw_hdmi_get_int_val(struct dw_hdmi_dev *dw_dev, u32 ists, u32 ien)
+{
+	return hdmi_readl(dw_dev, ists) & hdmi_readl(dw_dev, ien);
+}
+
+static u8 dw_hdmi_get_curr_vic(struct dw_hdmi_dev *dw_dev, bool *is_hdmi_vic)
+{
+	u8 vic = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_AVI_PB,
+				 DW_HDMI_VID_IDENT_CODE_OFFSET,
+				 DW_HDMI_VID_IDENT_CODE_MASK);
+
+	if (!vic) {
+		vic = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_PAYLOAD0,
+				      DW_HDMI_VSI_PAYLOAD1_HDMI_VIC_OFFSET,
+				      DW_HDMI_VSI_PAYLOAD1_HDMI_VIC_MASK);
+		if (is_hdmi_vic)
+			*is_hdmi_vic = true;
+	} else {
+		if (is_hdmi_vic)
+			*is_hdmi_vic = false;
+	}
+
+	return vic;
+}
+
+static u32 dw_hdmi_get_evaltime(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_CKM_EVLTM,
+			       DW_HDMI_EVAL_TIME_OFFSET,
+			       DW_HDMI_EVAL_TIME_MASK);
+}
+
+static u32 dw_hdmi_get_clkrate(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_CKM_RESULT,
+			       DW_HDMI_CLKRATE_OFFSET,
+			       DW_HDMI_CLKRATE_MASK);
+}
+
+static u32 dw_hdmi_get_cts(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_ACR_CTS,
+			       DW_HDMI_CTS_DECODED_OFFSET,
+			       DW_HDMI_CTS_DECODED_MASK);
+}
+
+static u32 dw_hdmi_get_n(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_ACR_N,
+			       DW_HDMI_N_DECODED_OFFSET,
+			       DW_HDMI_N_DECODED_MASK);
+}
+
+static u32 dw_hdmi_get_tmds_clk(struct dw_hdmi_dev *dw_dev)
+{
+	u32 rate = dw_hdmi_get_clkrate(dw_dev);
+	u64 tmp = (u64)rate * (u64)dw_dev->config->iref_clk * 1000000;
+	u32 evaltime = dw_hdmi_get_evaltime(dw_dev);
+
+	do_div(tmp, evaltime);
+	return tmp;
+}
+
+static u32 dw_hdmi_get_colordepth(struct dw_hdmi_dev *dw_dev)
+{
+	u32 dcm = hdmi_mask_readl(dw_dev, DW_HDMI_STS,
+				  DW_HDMI_DCM_CURRENT_MODE_OFFSET,
+				  DW_HDMI_DCM_CURRENT_MODE_MASK);
+
+	switch (dcm) {
+	case 0x4:
+		return 24;
+	case 0x5:
+		return 30;
+	case 0x6:
+		return 36;
+	case 0x7:
+		return 48;
+	default:
+		return 24;
+	}
+}
+
+static u64 dw_hdmi_get_pixelclk(struct dw_hdmi_dev *dw_dev)
+{
+	u32 tmds_clk = dw_hdmi_get_tmds_clk(dw_dev);
+	u32 cd = dw_hdmi_get_colordepth(dw_dev);
+	u32 pix_clk = 0;
+
+	switch (cd) {
+	case 24:
+		pix_clk = tmds_clk;
+		break;
+	case 30:
+		pix_clk = (tmds_clk * 100) / 125;
+		break;
+	case 36:
+		pix_clk = (tmds_clk * 10) / 15;
+		break;
+	case 48:
+		pix_clk = tmds_clk / 2;
+		break;
+	default:
+		break;
+	}
+
+	return pix_clk;
+}
+
+static void dw_hdmi_set_input(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	hdmi_mask_writel(dw_dev, input, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PORTSELECT_OFFSET,
+			 DW_HDMI_PORTSELECT_MASK);
+	dw_dev->configured_input = input;
+	dw_dev->selected_input = input;
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_INPUT_CHANGED,
+			   &dw_dev->configured_input);
+}
+
+static void dw_hdmi_enable_hpd(struct dw_hdmi_dev *dw_dev, u32 input_mask)
+{
+	hdmi_mask_writel(dw_dev, input_mask, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_MASK);
+}
+
+static void dw_hdmi_disable_hpd(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_MASK);
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_MASK);
+}
+
+static void dw_hdmi_enable_scdc(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_SCDC_CONFIG,
+			 DW_HDMI_POWERPROVIDED_OFFSET,
+			 DW_HDMI_POWERPROVIDED_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_IEN_SET,
+			 DW_HDMI_SCDCTMDSCFGCHANGE_ISTS_OFFSET,
+			 DW_HDMI_SCDCTMDSCFGCHANGE_ISTS_MASK);
+}
+
+static void dw_hdmi_disable_scdc(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_SCDC_CONFIG,
+			 DW_HDMI_POWERPROVIDED_OFFSET,
+			 DW_HDMI_POWERPROVIDED_MASK);
+}
+
+static void dw_hdmi_handle_audio_mute_change(struct dw_hdmi_dev *dw_dev);
+
+static void dw_hdmi_enable_hdmi_domain(struct dw_hdmi_dev *dw_dev, bool enable)
+{
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_DMI_DISABLE_IF,
+			 DW_HDMI_HDMI_ENABLE_OFFSET,
+			 DW_HDMI_HDMI_ENABLE_MASK);
+}
+
+static int dw_hdmi_initial_config(struct dw_hdmi_dev *dw_dev, u32 input);
+
+static int dw_hdmi_config(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	u32 in_state = dw_dev->state;
+	u32 cd1 = 0, cd2 = 0;
+	int eqret, ret = 0;
+
+	while (1) {
+		/* Give up silently if we are forcing off */
+		if (dw_dev->force_off) {
+			ret = 0;
+			goto out;
+		}
+		/* Give up silently if input has disconnected */
+		if (!has_signal(dw_dev, input)) {
+			ret = 0;
+			goto out;
+		}
+
+		switch (dw_dev->state) {
+		case HDMI_STATE_POWER_OFF:
+			dw_hdmi_disable_ints(dw_dev);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_PHY_CONFIG);
+			break;
+		case HDMI_STATE_POWER_UP:
+			/* when connect the cable */
+			dw_hdmi_disable_ints(dw_dev);
+			/* reset */
+			if (dw_dev->hw_reset_on_hot_plug)
+				dw_hdmi_reset(dw_dev);
+			/* initial configuration */
+			dw_hdmi_initial_config(dw_dev, input);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_PHY_CONFIG);
+			break;
+		case HDMI_STATE_PHY_CONFIG:
+			cd1 = 24;
+			dw_dev->is_hdmi2 = is_hdmi2(dw_dev);
+			dw_dev->is_scrambled = is_scrambled(dw_dev);
+			dw_hdmi_phy_config(dw_dev, cd1, dw_dev->is_hdmi2,
+					   dw_dev->is_scrambled);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_HPD);
+			break;
+		case HDMI_STATE_HPD:
+			/* disable HDMI domain to avoid the DCM INTs */
+			dw_hdmi_enable_hdmi_domain(dw_dev, false);
+			dw_hdmi_enable_scdc(dw_dev);
+			dw_hdmi_enable_hpd(dw_dev, dw_dev->input_stat);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_EQUALIZER);
+			break;
+		case HDMI_STATE_EQUALIZER:
+			if (dw_dev->phy_eq_on) {
+				bool phy_eq_force = dw_dev->phy_eq_force;
+
+				eqret = dw_hdmi_phy_eq_init(dw_dev, 5,
+							    phy_eq_force);
+			} else {
+				/* Clear equalizer error status if not on */
+				eqret = 0;
+			}
+
+			ret = dw_hdmi_wait_phy_lock_poll(dw_dev);
+
+			/* Do not force equalizer */
+			dw_dev->phy_eq_force = false;
+
+			if (ret || eqret) {
+				if (ret || eqret == -ETIMEDOUT) {
+					/* No TMDSVALID signal:
+					 * - force equalizer
+					 */
+					dw_dev->phy_eq_force = true;
+				}
+				break;
+			}
+
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_DATAPATH);
+			break;
+		case HDMI_STATE_DATAPATH:
+			dw_hdmi_reset_datapath(dw_dev);
+			/* reenable HDMI domain */
+			dw_hdmi_enable_hdmi_domain(dw_dev, true);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_VIDEO_UNSTABLE);
+			break;
+		case HDMI_STATE_VIDEO_UNSTABLE:
+			dw_hdmi_wait_video_stable(dw_dev);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_AUDIO);
+			break;
+		case HDMI_STATE_AUDIO:
+			ret = dw_hdmi_config_audio(dw_dev);
+			dw_hdmi_config_packet(dw_dev);
+
+			if (in_state != HDMI_STATE_EQUALIZER)
+				dw_hdmi_clear_ints(dw_dev);
+
+			dw_hdmi_get_infoframes(dw_dev);
+
+			/* check if there was deep color changes */
+			if (cd1) {
+				cd2 = dw_hdmi_get_colordepth(dw_dev);
+				if (cd1 != cd2)
+					dw_hdmi_phy_set_color_depth(dw_dev,
+								    cd2);
+			}
+
+			/* reset CEA video */
+			dw_hdmi_reset_ceavid(dw_dev);
+
+			dw_hdmi_enable_ints(dw_dev);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_POWER_ON);
+			break;
+		case HDMI_STATE_POWER_ON:
+			break;
+		default:
+			dev_err(dw_dev->dev, "%s called with state (%d)\n",
+				__func__, dw_dev->state);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (dw_dev->state == HDMI_STATE_POWER_ON) {
+			dev_info(dw_dev->dev, "HDMI-RX configured\n");
+			dw_hdmi_event_source_change(dw_dev);
+			dw_hdmi_handle_audio_mute_change(dw_dev);
+			return 0;
+		}
+	}
+
+out:
+	dw_hdmi_set_state(dw_dev, HDMI_STATE_POWER_OFF);
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_IS_OFF, NULL);
+	return ret;
+}
+
+static int __dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	unsigned long flags;
+	int ret;
+
+	ret = dw_hdmi_config(dw_dev, input);
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dw_dev->pending_config = false;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+
+	return ret;
+}
+
+static void dw_hdmi_work_handler(struct work_struct *work)
+{
+	struct dw_hdmi_dev *dw_dev = container_of(work, struct dw_hdmi_dev,
+						  work);
+
+	__dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+}
+
+static int dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	if (dw_dev->pending_config) {
+		spin_unlock_irqrestore(&dw_dev->lock, flags);
+		return 0;
+	}
+
+	INIT_WORK(&dw_dev->work, dw_hdmi_work_handler);
+	dw_dev->configured_input = input;
+	dw_dev->pending_config = true;
+	queue_work(dw_dev->wq, &dw_dev->work);
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+	return 0;
+}
+
+static void dw_hdmi_power_off(struct dw_hdmi_dev *dw_dev)
+{
+	unsigned long flags;
+
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_IS_OFF, NULL);
+
+	dw_dev->force_off = true;
+	flush_workqueue(dw_dev->wq);
+	dw_dev->force_off = false;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dw_dev->pending_config = false;
+	dw_dev->state = HDMI_STATE_POWER_OFF;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+
+	/* Reset variables */
+	dw_dev->phy_eq_force = true;
+	dw_dev->audio_sf = 0;
+}
+
+static void dw_hdmi_force_off(struct dw_hdmi_dev *dw_dev)
+{
+	unsigned long flags;
+
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_IS_OFF, NULL);
+
+	dw_dev->force_off = true;
+	flush_workqueue(dw_dev->wq);
+	dw_dev->force_off = false;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dw_dev->pending_config = false;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+}
+
+static void dw_hdmi_power_up(struct dw_hdmi_dev *dw_dev)
+{
+	dw_hdmi_force_off(dw_dev);
+	dw_hdmi_set_state(dw_dev, HDMI_STATE_POWER_UP);
+
+	/* Reset variables */
+	dw_dev->phy_eq_force = true;
+	dw_dev->audio_sf = 0;
+}
+
+static void dw_hdmi_controller_power_off(struct dw_hdmi_dev *dw_dev)
+{
+	dw_hdmi_force_off(dw_dev);
+	dw_hdmi_set_state(dw_dev, HDMI_STATE_EQUALIZER);
+
+	dw_dev->phy_eq_force = false;
+	dw_dev->audio_sf = 0;
+}
+
+static int dw_hdmi_query_dv_timings(struct v4l2_subdev *sd,
+				    struct v4l2_dv_timings *timings);
+
+static void dw_hdmi_handle_video_change(struct dw_hdmi_dev *dw_dev)
+{
+	struct v4l2_dv_timings timings;
+
+	if (is_on(dw_dev)) {
+		dev_dbg(dw_dev->dev, "[VIDEO] video change interrupt\n");
+		dw_hdmi_query_dv_timings(&dw_dev->sd, &timings);
+		dw_hdmi_controller_power_off(dw_dev);
+		dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+	}
+}
+
+static u32 dw_hdmi_round_freq(int freq)
+{
+	static const u32 base_freqs[] = { 32000, 44100, 48000, 0 };
+	unsigned int i;
+
+	for (i = 0; base_freqs[i]; i++) {
+		if ((freq <= (base_freqs[i] + DW_HDMI_AUDIO_FREQ_RANGE)) &&
+		    (freq >= (base_freqs[i] - DW_HDMI_AUDIO_FREQ_RANGE))) {
+			return base_freqs[i];
+		}
+	}
+
+	return 0;
+}
+
+static unsigned int dw_hdmi_get_sample_freq(struct dw_hdmi_dev *dw_dev)
+{
+	u64 tmp;
+	u32 cts;
+	u32 sf;
+	u32 n;
+
+	n = dw_hdmi_get_n(dw_dev);
+	cts = dw_hdmi_get_cts(dw_dev);
+
+	if (!n || !cts) {
+		dev_dbg(dw_dev->dev, "%s: cts: %d, n: %d\n", __func__, cts, n);
+		return 0;
+	}
+
+	dev_dbg(dw_dev->dev, "%s: tmds_clk: %d\n",
+		__func__, dw_hdmi_get_tmds_clk(dw_dev));
+
+	/* regenerate the audio clock from tmds clock */
+	tmp = (u64)dw_hdmi_get_tmds_clk(dw_dev) * (u64)n;
+	do_div(tmp, cts);
+	do_div(tmp, 128);
+	sf = tmp;
+
+	dev_dbg(dw_dev->dev, "%s: sf: %d\n", __func__, sf);
+	sf = dw_hdmi_round_freq(sf);
+	dev_dbg(dw_dev->dev, "%s: sf(round): %d\n", __func__, sf);
+
+	return sf;
+}
+
+static void dw_hdmi_handle_audio_mute_change(struct dw_hdmi_dev *dw_dev)
+{
+	unsigned long flags;
+	unsigned int sf;
+
+	spin_lock_irqsave(&dw_dev->event_lock, flags);
+	sf = dw_hdmi_get_sample_freq(dw_dev);
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_AUDIO_CHANGED, &sf);
+	dw_dev->audio_sf = sf;
+	spin_unlock_irqrestore(&dw_dev->event_lock, flags);
+}
+
+static void dw_hdmi_handle_audio_change(struct dw_hdmi_dev *dw_dev,
+					u32 afif_stat, u32 pdec_stat)
+{
+	bool restart = true;
+
+	if (pdec_stat & DW_HDMI_GCP_AV_MUTE_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] AV Mute change\n");
+		dw_hdmi_handle_audio_mute_change(dw_dev);
+		restart = false;
+	}
+
+	if (pdec_stat & DW_HDMI_AUD_TYPE_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] type change\n");
+		restart = true;
+	}
+	if (pdec_stat & DW_HDMI_AIF_CKS_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] aif change\n");
+		restart = true;
+	}
+	if (pdec_stat & DW_HDMI_ACR_N_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] N change\n");
+		restart = true;
+	}
+	if (pdec_stat & DW_HDMI_ACR_CTS_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] CTS change\n");
+		restart = true;
+	}
+	if (afif_stat & DW_HDMI_AFIF_UNDERFL_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] fifo underflow\n");
+		restart = true;
+	}
+	if (afif_stat & DW_HDMI_AFIF_OVERFL_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] fifo overflow\n");
+		restart = true;
+	}
+	if (afif_stat & DW_HDMI_AFIF_THS_PASS_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] TRH Pass\n");
+		dw_hdmi_handle_audio_mute_change(dw_dev);
+		restart = false;
+	}
+
+	if (restart) {
+		dw_hdmi_handle_audio_mute_change(dw_dev);
+		dw_hdmi_wait_audio_lock_poll(dw_dev);
+		dw_hdmi_reset_audio(dw_dev);
+		dw_hdmi_restart_audio_fifo(dw_dev);
+	}
+}
+
+static irqreturn_t dw_hdmi_irq_handler(int irq, void *dev_data)
+{
+	struct dw_hdmi_dev *dw_dev = dev_data;
+	u32 hdmi_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_ISTS, DW_HDMI_IEN);
+	u32 md_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_MD_ISTS,
+					  DW_HDMI_MD_IEN);
+	u32 pdec_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_PDEC_ISTS,
+					    DW_HDMI_PDEC_IEN);
+	u32 afif_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_AUD_FIFO_ISTS,
+					    DW_HDMI_AUD_FIFO_IEN);
+	u32 cd = 0;
+
+	dw_hdmi_clear_ints(dw_dev);
+
+	/* video handling */
+	if (hdmi_ists & DW_HDMI_CLK_CHANGE_ISTS) {
+		dev_dbg(dw_dev->dev, "[HDMI] clock rate change\n");
+		dw_hdmi_power_off(dw_dev);
+		if (has_signal(dw_dev, dw_dev->configured_input))
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+
+		return IRQ_HANDLED;
+	}
+	if (hdmi_ists & DW_HDMI_PLL_LCK_CHG_ISTS) {
+		dev_dbg(dw_dev->dev,
+			"[PHY] PLL lock state changed (tmds_valid: %d)\n",
+			dw_hdmi_tmds_valid(dw_dev));
+		dw_hdmi_power_off(dw_dev);
+
+		if (has_signal(dw_dev, dw_dev->configured_input))
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+
+		return IRQ_HANDLED;
+	}
+	if (hdmi_ists & DW_HDMI_DCM_CURRENT_MODE_CHG_ISTS) {
+		dev_dbg(dw_dev->dev,
+			"[HDMI] deep color changed\n");
+
+		cd = dw_hdmi_get_colordepth(dw_dev);
+		if (cd)
+			dw_hdmi_phy_set_color_depth(dw_dev, cd);
+
+		/* reset CEA video */
+		dw_hdmi_reset_ceavid(dw_dev);
+
+		return IRQ_HANDLED;
+	}
+	if (md_ists || pdec_ists &
+	    (DW_HDMI_VSI_CKS_CHG_ISTS |
+	     DW_HDMI_DRM_CKS_CHG_ISTS |
+	     DW_HDMI_AVI_CKS_CHG_ISTS)) {
+		dw_hdmi_handle_video_change(dw_dev);
+		dev_dbg(dw_dev->dev,
+			"   md_ists: 0x%x, pdec_ists: 0x%x\n",
+			md_ists, pdec_ists);
+	}
+
+	/* infoframes */
+	if (pdec_ists & DW_HDMI_AIF_CKS_CHG_ISTS)
+		dw_hdmi_get_infoframes(dw_dev);
+
+	/* audio handling */
+	if (pdec_ists & (DW_HDMI_AUD_TYPE_CHG_ISTS |
+			 DW_HDMI_AIF_CKS_CHG_ISTS |
+			 DW_HDMI_ACR_N_CHG_ISTS |
+			 DW_HDMI_ACR_CTS_CHG_ISTS |
+			 DW_HDMI_GCP_AV_MUTE_CHG_ISTS) ||
+	    afif_ists & (DW_HDMI_AFIF_UNDERFL_ISTS |
+			 DW_HDMI_AFIF_OVERFL_ISTS |
+			 DW_HDMI_AFIF_THS_PASS_ISTS)) {
+		dw_hdmi_handle_audio_change(dw_dev, afif_ists, pdec_ists);
+	}
+
+	/* scdc */
+	if (hdmi_ists & DW_HDMI_SCDCTMDSCFGCHANGE_ISTS_MASK) {
+		dev_dbg(dw_dev->dev, "[SCDC] hdmi2=%d->%d, scrambling=%d->%d\n",
+			dw_dev->is_hdmi2, is_hdmi2(dw_dev),
+			dw_dev->is_scrambled, is_scrambled(dw_dev));
+		if (dw_dev->is_hdmi2 != is_hdmi2(dw_dev) ||
+		    dw_dev->is_scrambled != is_scrambled(dw_dev)) {
+			dw_dev->is_hdmi2 = is_hdmi2(dw_dev);
+			dw_dev->is_scrambled = is_scrambled(dw_dev);
+			dw_hdmi_power_off(dw_dev);
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int dw_hdmi_detect_tx_5v_ctrl(struct dw_hdmi_dev *dw_dev)
+{
+	bool current_on = dw_hdmi_5v_status(dw_dev, dw_dev->configured_input);
+	unsigned int input_count = dw_dev->config->phy->input_count;
+	unsigned int old_input = dw_dev->configured_input;
+	unsigned int new_input = old_input;
+	bool pending_config = false;
+	unsigned int stat = 0;
+	unsigned int i;
+
+	for (i = 0; i < input_count; i++) {
+		bool on = dw_hdmi_5v_status(dw_dev, i);
+
+		stat |= on << i;
+
+		if (on && on != dw_dev->input_connected[i]) {
+			dw_hdmi_disable_ints(dw_dev);
+			dw_hdmi_power_off(dw_dev);
+			dw_hdmi_power_up(dw_dev);
+			dw_dev->input_connected[i] = true;
+			dw_hdmi_power_on(dw_dev, i);
+			dw_hdmi_set_input(dw_dev, i);
+			new_input = i;
+			pending_config = true;
+		} else {
+			dw_dev->input_connected[i] = on;
+		}
+	}
+
+	dw_dev->input_stat = stat;
+
+	if (!pending_config && !current_on) {
+		dw_hdmi_disable_ints(dw_dev);
+		dw_hdmi_disable_hpd(dw_dev);
+		dw_hdmi_disable_scdc(dw_dev);
+		dw_hdmi_power_off(dw_dev);
+		if (dw_dev->phy->power_count > 0)
+			phy_power_off(dw_dev->phy);
+	}
+
+	dev_dbg(dw_dev->dev, "%s: stat=0x%x, input=%d->%d\n", __func__,
+		stat, old_input, new_input);
+	return v4l2_ctrl_s_ctrl(dw_dev->detect_tx_5v_ctrl, stat);
+}
+
+static irqreturn_t dw_hdmi_5v_irq_handler(int irq, void *dev_data)
+{
+	struct dw_hdmi_dev *dw_dev = dev_data;
+
+	dw_hdmi_detect_tx_5v_ctrl(dw_dev);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_hdmi_5v_hard_irq_handler(int irq, void *dev_data)
+{
+	struct dw_hdmi_dev *dw_dev = dev_data;
+	unsigned int input_count = dw_dev->config->phy->input_count;
+	u32 stat = 0x0;
+	unsigned int i;
+
+	/* Clear interrupts */
+	for (i = 0; i < input_count; i++) {
+		dw_hdmi_5v_disable(dw_dev, i);
+		dw_hdmi_5v_enable(dw_dev, i);
+		stat |= dw_hdmi_5v_status(dw_dev, i) << i;
+	}
+
+	if (!stat) {
+		/*
+		 * If there are no connected ports disable whole HPD and SCDC
+		 * also.
+		 */
+		dw_hdmi_disable_hpd(dw_dev);
+		dw_hdmi_disable_scdc(dw_dev);
+	}
+
+	return IRQ_WAKE_THREAD;
+}
+
+static int dw_hdmi_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+			     u32 config)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	int ret;
+
+	if (!has_signal(dw_dev, input))
+		return -EINVAL;
+
+	dw_dev->selected_input = input;
+	if (input == dw_dev->configured_input)
+		return 0;
+
+	dw_hdmi_power_off(dw_dev);
+	ret = dw_hdmi_power_on(dw_dev, input);
+	dw_hdmi_set_input(dw_dev, input);
+	return ret;
+}
+
+static int dw_hdmi_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	*status = 0;
+	if (!has_signal(dw_dev, dw_dev->selected_input))
+		*status |= V4L2_IN_ST_NO_POWER;
+	if (!is_on(dw_dev))
+		*status |= V4L2_IN_ST_NO_SIGNAL;
+
+	dev_dbg(dw_dev->dev, "%s: status=0x%x\n", __func__, *status);
+	return 0;
+}
+
+static int dw_hdmi_g_frame_interval(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_frame_interval *ival)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	u32 htot, vtot, fps;
+	unsigned long n, d;
+	u64 pclk;
+
+	htot = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT1,
+			       DW_HDMI_HTOT_PIX_OFFSET,
+			       DW_HDMI_HTOT_PIX_MASK);
+	vtot = hdmi_readl(dw_dev, DW_HDMI_MD_VTL);
+	pclk = dw_hdmi_get_pixelclk(dw_dev);
+
+	fps = (htot * vtot) > 0 ? div_u64((100 * pclk), (htot * vtot)) : 0;
+	if (!fps)
+		return 0;
+
+	rational_best_approximation(fps, 100, fps, 100, &n, &d);
+
+	ival->interval.numerator = d;
+	ival->interval.denominator = n;
+
+	dev_dbg(dw_dev->dev, "%s: %lu / %lu\n", __func__, d, n);
+
+	return 0;
+}
+
+static int dw_hdmi_s_dv_timings(struct v4l2_subdev *sd,
+				struct v4l2_dv_timings *timings)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	if (!v4l2_valid_dv_timings(timings, &dw_hdmi_timings_cap, NULL, NULL))
+		return -EINVAL;
+	if (v4l2_match_dv_timings(timings, &dw_dev->timings, 0, false))
+		return 0;
+
+	dw_dev->timings = *timings;
+	return 0;
+}
+
+static int dw_hdmi_g_dv_timings(struct v4l2_subdev *sd,
+				struct v4l2_dv_timings *timings)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	*timings = dw_dev->timings;
+	return 0;
+}
+
+static u32 dw_hdmi_get_width(struct dw_hdmi_dev *dw_dev)
+{
+	u32 width = hdmi_readl(dw_dev, DW_HDMI_MD_HACT_PX);
+	u32 cd = dw_hdmi_get_colordepth(dw_dev);
+
+	switch (cd) {
+	case 30:
+		width = (width * 100) / 125;
+		break;
+	case 36:
+		width = (width * 10) / 15;
+		break;
+	case 48:
+		width /= 2;
+		break;
+	case 24:
+	default:
+		break;
+	}
+
+	if (dw_hdmi_get_mbus_code(dw_dev) == MEDIA_BUS_FMT_YVYU8_1X16)
+		width *= 2;
+
+	return width;
+}
+
+static int dw_hdmi_query_dv_timings(struct v4l2_subdev *sd,
+				    struct v4l2_dv_timings *timings)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	struct v4l2_bt_timings *bt = &timings->bt;
+	bool is_hdmi_vic;
+	u32 htot, hofs;
+	u32 vtot;
+	u8 vic;
+
+	memset(timings, 0, sizeof(*timings));
+
+	if (is_off(dw_dev)) {
+		dev_dbg(dw_dev->dev, "%s: controller is off\n", __func__);
+		return -ENOLINK;
+	}
+
+	if (!is_on(dw_dev)) {
+		dev_dbg(dw_dev->dev, "%s: controller is being configured\n",
+			__func__);
+		return -EAGAIN;
+	}
+
+	timings->type = V4L2_DV_BT_656_1120;
+	bt->width = dw_hdmi_get_width(dw_dev);
+	bt->height = hdmi_readl(dw_dev, DW_HDMI_MD_VAL);
+	bt->interlaced =
+		hdmi_readl(dw_dev, DW_HDMI_MD_STS) & DW_HDMI_ILACE_STS ?
+			V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (hdmi_readl(dw_dev, DW_HDMI_ISTS) & DW_HDMI_VS_POL_ADJ_ISTS)
+		bt->polarities |= V4L2_DV_VSYNC_POS_POL;
+	if (hdmi_readl(dw_dev, DW_HDMI_ISTS) & DW_HDMI_HS_POL_ADJ_ISTS)
+		bt->polarities |= V4L2_DV_HSYNC_POS_POL;
+
+	bt->pixelclock = dw_hdmi_get_pixelclk(dw_dev);
+
+	/* HTOT = HACT + HFRONT + HSYNC + HBACK */
+	htot = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT1,
+			       DW_HDMI_HTOT_PIX_OFFSET,
+			       DW_HDMI_HTOT_PIX_MASK);
+	/* HOFS = HSYNC + HBACK */
+	hofs = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT1,
+			       DW_HDMI_HOFS_PIX_OFFSET,
+			       DW_HDMI_HOFS_PIX_MASK);
+
+	bt->hfrontporch = htot - hofs - bt->width;
+	bt->hsync = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT0,
+				    DW_HDMI_HS_CLK_OFFSET,
+				    DW_HDMI_HS_CLK_MASK);
+	bt->hbackporch = hofs - bt->hsync;
+
+	/* VTOT = VACT + VFRONT + VSYNC + VBACK */
+	vtot = hdmi_readl(dw_dev, DW_HDMI_MD_VTL);
+
+	bt->vsync = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+
+	bt->vbackporch = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+	bt->vfrontporch = vtot - bt->height - bt->vsync - bt->vbackporch;
+
+	if (bt->interlaced == V4L2_DV_INTERLACED) {
+		hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_MODE_OFFSET,
+				 DW_HDMI_V_MODE_MASK);
+		msleep(100); /* Wait for 2 fields */
+
+		vtot = hdmi_readl(dw_dev, DW_HDMI_MD_VTL);
+		hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_OFFS_LIN_MODE_OFFSET,
+				 DW_HDMI_V_OFFS_LIN_MODE_MASK);
+		msleep(50); /* Wait for 1 field */
+		bt->il_vsync = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+
+		hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_OFFS_LIN_MODE_OFFSET,
+				 DW_HDMI_V_OFFS_LIN_MODE_MASK);
+		msleep(50);
+		bt->il_vbackporch = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+		bt->il_vfrontporch = vtot - bt->height - bt->il_vsync -
+			bt->il_vbackporch;
+
+		hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_MODE_OFFSET,
+				 DW_HDMI_V_MODE_MASK);
+	}
+
+	bt->standards = V4L2_DV_BT_STD_CEA861;
+
+	vic = dw_hdmi_get_curr_vic(dw_dev, &is_hdmi_vic);
+	if (vic) {
+		if (is_hdmi_vic) {
+			bt->flags |= V4L2_DV_FL_HAS_HDMI_VIC;
+			bt->hdmi_vic = vic;
+			bt->cea861_vic = 0;
+		} else {
+			bt->flags |= V4L2_DV_FL_HAS_CEA861_VIC;
+			bt->hdmi_vic = 0;
+			bt->cea861_vic = vic;
+		}
+	}
+
+	dev_dbg(dw_dev->dev, "%s: width=%u, height=%u, mbuscode=%u\n", __func__,
+		bt->width, bt->height, dw_hdmi_get_mbus_code(dw_dev));
+
+	return 0;
+}
+
+static int dw_hdmi_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	if (code->index != 0)
+		return -EINVAL;
+
+	code->code = dw_dev->mbus_code;
+	return 0;
+}
+
+static int dw_hdmi_fill_format(struct dw_hdmi_dev *dw_dev,
+			       struct v4l2_mbus_framefmt *format)
+{
+	enum hdmi_extended_colorimetry extcol;
+	enum hdmi_colorimetry col;
+	int ret;
+
+	memset(format, 0, sizeof(*format));
+
+	/* Update timings */
+	ret = dw_hdmi_query_dv_timings(&dw_dev->sd, &dw_dev->timings);
+	if (ret)
+		return ret;
+
+	/* Update infoframe contents */
+	dw_hdmi_get_infoframes(dw_dev);
+
+	col = dw_dev->aviif.avi.colorimetry;
+	extcol = dw_dev->aviif.avi.extended_colorimetry;
+
+	switch (col) {
+	case HDMI_COLORIMETRY_ITU_601:
+		format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+		break;
+	case HDMI_COLORIMETRY_EXTENDED:
+		switch (extcol) {
+		case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
+			format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+			break;
+		case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
+		case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
+		case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
+		case HDMI_EXTENDED_COLORIMETRY_OPRGB:
+		case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
+		case HDMI_EXTENDED_COLORIMETRY_BT2020:
+		case HDMI_EXTENDED_COLORIMETRY_RESERVED:
+		default:
+			format->colorspace = V4L2_COLORSPACE_REC709;
+			break;
+		}
+
+		break;
+	case HDMI_COLORIMETRY_NONE:
+	case HDMI_COLORIMETRY_ITU_709:
+	default:
+		format->colorspace = V4L2_COLORSPACE_REC709;
+		break;
+	}
+
+	format->width = dw_dev->timings.bt.width;
+	format->height = dw_dev->timings.bt.height;
+	format->code = dw_dev->mbus_code;
+	if (dw_dev->timings.bt.interlaced)
+		format->field = V4L2_FIELD_ALTERNATE;
+	else
+		format->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int dw_hdmi_get_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *format)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	return dw_hdmi_fill_format(dw_dev, &format->format);
+}
+
+static int dw_hdmi_set_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *format)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	if (format->format.code != dw_dev->mbus_code) {
+		dev_dbg(dw_dev->dev, "invalid format\n");
+		return -EINVAL;
+	}
+
+	return dw_hdmi_get_fmt(sd, cfg, format);
+}
+
+static int dw_hdmi_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	unsigned int input_count = dw_dev->config->phy->input_count;
+	unsigned int i, j, start, end;
+	u8 *ptr = edid->edid;
+	u8 blocks;
+
+	memset(edid->reserved, 0, sizeof(edid->reserved));
+
+	if (edid->pad >= input_count || !ptr)
+		return -EINVAL;
+
+	blocks = dw_dev->curr_edid_blocks[edid->pad];
+
+	if (!edid->start_block && !edid->blocks) {
+		edid->blocks = blocks;
+		return 0;
+	}
+	if (!blocks)
+		return -ENODATA;
+	if (edid->start_block >= blocks)
+		return -EINVAL;
+	if ((edid->start_block + edid->blocks) > blocks)
+		edid->blocks = blocks - edid->start_block;
+
+	start = (edid->start_block * 128) / sizeof(u32);
+	end = start + (edid->blocks * 128) / sizeof(u32);
+
+	for (i = start; i < end; i++) {
+		u32 raw = dw_hdmi_edid_read(dw_dev, edid->pad, i * sizeof(u32));
+
+		if (!dw_hdmi_edid_4blocks_le(dw_dev)) {
+			u32 raw_srt = 0;
+			/* little endian representation, need to invert */
+			for (j = 0; j < 4; j++) {
+				raw_srt |= ((raw >> (8 * (3 - j))) & 0xff)
+					<< (j * 8);
+			}
+			raw = raw_srt;
+		}
+		memcpy(ptr, &raw, sizeof(u32));
+		ptr += sizeof(u32);
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	int input_count = dw_dev->config->phy->input_count;
+	int size, ret;
+	u32 *tmp;
+
+	memset(edid->reserved, 0, sizeof(edid->reserved));
+
+	if (edid->pad >= input_count || !edid->edid || !edid->blocks)
+		return -EINVAL;
+	if (edid->start_block != 0)
+		return -EINVAL;
+
+	/* Clear old EDID */
+	size = dw_dev->curr_edid_blocks[edid->pad] * 128;
+	tmp = devm_kzalloc(dw_dev->dev, size, GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	ret = dw_hdmi_edid_write(dw_dev, edid->pad, tmp, size / sizeof(u32));
+	devm_kfree(dw_dev->dev, tmp);
+
+	if (ret)
+		return ret;
+
+	dw_dev->curr_edid_blocks[edid->pad] = 0;
+
+	/* Set new EDID */
+	if (dw_hdmi_edid_4blocks_le(dw_dev)) {
+		/* little endian representation, no need to invert bytes */
+		ret = dw_hdmi_update_edid(dw_dev, edid->pad, (u8 *)edid->edid,

drivers/media/platform/dwc/dw-hdmi-rx.c line 2545

Quoted 10 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +10 -0
+					  (edid->blocks * 128), false);
+	} else {
+		/* invert the order of bytes to register 32bit */
+		ret = dw_hdmi_update_edid(dw_dev, edid->pad, (u8 *)edid->edid,
+					  (edid->blocks * 128), true);
+	}
+	if (ret)
+		return ret;
+
+	dw_dev->curr_edid_blocks[edid->pad] = edid->blocks;

I don't see any checks on edid->blocks: that can't be right. The typical max number of blocks for an EDID is 2 or 4, I haven't seen any implementations for more than 4 blocks.

I also don't see any signaling of the HPD: it must be pulled low before you start writing the EDID, and pulled high again at least 100ms later (150 ms or so is recommended to keep a margin).

Quoted 533 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +533 -0
+	return 0;
+}
+
+static int dw_hdmi_dv_timings_cap(struct v4l2_subdev *sd,
+				  struct v4l2_dv_timings_cap *cap)
+{
+	unsigned int pad = cap->pad;
+
+	*cap = dw_hdmi_timings_cap;
+	cap->pad = pad;
+	return 0;
+}
+
+static int dw_hdmi_enum_dv_timings(struct v4l2_subdev *sd,
+				   struct v4l2_enum_dv_timings *timings)
+{
+	return v4l2_enum_dv_timings_cap(timings, &dw_hdmi_timings_cap,
+					NULL, NULL);
+}
+
+static int dw_hdmi_log_status(struct v4l2_subdev *sd)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	struct v4l2_dv_timings timings;
+
+	v4l2_info(sd, "--- Chip configuration ---\n");
+	v4l2_info(sd, "iref_clk=%dMHz\n", dw_dev->config->iref_clk);
+	v4l2_info(sd, "phy_drv=%s, phy_jtag_addr=0x%x\n",
+		  dw_dev->phy ? "present" : "not present",
+		  dw_dev->config->phy->jtag_addr);
+
+	v4l2_info(sd, "--- Chip status ---\n");
+	v4l2_info(sd, "selected_input=%d: signal=%d\n", dw_dev->selected_input,
+		  has_signal(dw_dev, dw_dev->selected_input));
+	v4l2_info(sd, "configured_input=%d: signal=%d\n",
+		  dw_dev->configured_input,
+		  has_signal(dw_dev, dw_dev->configured_input));
+
+	v4l2_info(sd, "--- Video status ---\n");
+	v4l2_info(sd, "type=%s, color_depth=%dbits",
+		  hdmi_readl(dw_dev, DW_HDMI_PDEC_STS) &
+		  DW_HDMI_DVIDET ? "dvi" : "hdmi",
+		  dw_hdmi_get_colordepth(dw_dev));
+
+	v4l2_info(sd, "--- Video timings ---\n");
+	if (dw_hdmi_query_dv_timings(sd, &timings))
+		v4l2_info(sd, "No video detected\n");
+	else
+		v4l2_print_dv_timings(sd->name, "Detected format: ",
+				      &timings, true);
+	v4l2_print_dv_timings(sd->name, "Configured format: ",
+			      &dw_dev->timings, true);
+
+	v4l2_ctrl_subdev_log_status(sd);
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static void dw_hdmi_invalid_register(struct dw_hdmi_dev *dw_dev, u64 reg)
+{
+	dev_err(dw_dev->dev, "register 0x%llx not supported\n", reg);
+	dev_err(dw_dev->dev, "0x0000-0x7fff: Main controller map\n");
+	dev_err(dw_dev->dev, "0x8000-0x8fff: Debug registers\n");
+	dev_err(dw_dev->dev, "  0x8000: TMDSVALID wait count\n");
+	dev_err(dw_dev->dev, "  0x8001: SW state\n");
+	dev_err(dw_dev->dev, "  0x8002: Equalizer ON/OFF\n");
+	dev_err(dw_dev->dev, "  0x8003: PHY Version\n");
+	dev_err(dw_dev->dev, "  0x8004: Video Stable Wait Time (ms)\n");
+	dev_err(dw_dev->dev, "  0x8005: Clock wait time (ms)\n");
+	dev_err(dw_dev->dev, "  0x8006: iref_clk value\n");
+	dev_err(dw_dev->dev, "  0x8007: reset_datapath_enable mask value\n");
+	dev_err(dw_dev->dev, "  0x8008: audio sample frequency (read only)\n");
+	dev_err(dw_dev->dev, "  0x8009: hw_reset_on_hot_plug (1=enabled, 0=disabled)");
+	dev_err(dw_dev->dev, "0x10000-0x100ff: PHY map\n");
+}
+
+static bool dw_hdmi_is_reserved_register(struct dw_hdmi_dev *dw_dev, u32 reg)
+{
+	/*
+	 * NOTE: Some of the HDCP registers are write only. This means that
+	 * a read from these registers will never return and can block the bus
+	 * in some architectures. Disable the read to these registers and also
+	 * disable the write as a safety measure because userspace should not
+	 * be able to set HDCP registers.
+	 */
+	if (reg >= DW_HDMI_HDCP_CTRL && reg <= DW_HDMI_HDCP_STS)
+		return true;
+	if (reg == DW_HDMI_HDCP22_CONTROL)
+		return true;
+	if (reg == DW_HDMI_HDCP22_STATUS)
+		return true;
+	return false;
+}
+
+static int dw_hdmi_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	switch (reg->reg >> 15) {
+	case 0: /* Controller core read */
+		if (dw_hdmi_is_reserved_register(dw_dev, reg->reg & 0x7fff))
+			return -EINVAL;
+
+		reg->size = 4;
+		reg->val = hdmi_readl(dw_dev, reg->reg & 0x7fff);
+		return 0;
+	case 1: /* Debug registers */
+		reg->size = 4;
+
+		switch (reg->reg & GENMASK(14, 0)) {
+		case 0:
+			reg->val = dw_dev->tmds_valid_wait_count;
+			return 0;
+		case 1:
+			reg->val = dw_dev->state;
+			return 0;
+		case 2:
+			reg->val = dw_dev->phy_eq_on;
+			return 0;
+		case 3:
+			reg->val = dw_dev->config->phy->version;
+			return 0;
+		case 4:
+			reg->val = dw_dev->video_stable_wait_ms;
+			return 0;
+		case 5:
+			reg->val = dw_dev->has_clock_wait_ms;
+			return 0;
+		case 6:
+			reg->val = dw_dev->config->iref_clk;
+			return 0;
+		case 7:
+			reg->val = dw_dev->reset_datapath_enable;
+			return 0;
+		case 8:
+			reg->val = dw_hdmi_get_sample_freq(dw_dev);
+			return 0;
+		case 9:
+			reg->val = dw_dev->hw_reset_on_hot_plug;
+			return 0;
+		default:
+			break;
+		}
+		break;
+	case 2: /* PHY read */
+		if ((reg->reg & ~0xff) != BIT(16))
+			break;
+
+		reg->size = 2;
+		reg->val = dw_hdmi_phy_read(dw_dev, reg->reg & 0xff);
+		return 0;
+	default:
+		break;
+	}
+
+	dw_hdmi_invalid_register(dw_dev, reg->reg);
+	return 0;
+}
+
+static int dw_hdmi_s_register(struct v4l2_subdev *sd,
+			      const struct v4l2_dbg_register *reg)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	switch (reg->reg >> 15) {
+	case 0: /* Controller core write */
+		if (dw_hdmi_is_reserved_register(dw_dev, reg->reg & 0x7fff))
+			return -EINVAL;
+
+		hdmi_writel(dw_dev, reg->val & GENMASK(31, 0),
+			    reg->reg & 0x7fff);
+		return 0;
+	case 1: /* Debug registers */
+		switch (reg->reg & GENMASK(14, 0)) {
+		case 0:
+			dw_dev->tmds_valid_wait_count = reg->val;
+			return 0;
+		case 1:
+			dw_hdmi_set_state(dw_dev, reg->val & 0xff);
+			return 0;
+		case 2:
+			dw_dev->phy_eq_on = reg->val;
+			return 0;
+		case 4:
+			dw_dev->video_stable_wait_ms = reg->val;
+			return 0;
+		case 5:
+			dw_dev->has_clock_wait_ms = reg->val;
+			return 0;
+		case 7:
+			dw_dev->reset_datapath_enable = reg->val;
+			return 0;
+		/* case 8 is read-only */
+		case 9:
+			dw_dev->hw_reset_on_hot_plug = reg->val;
+			return 0;
+		case 400:
+			dev_warn(dw_dev->dev, "synmp debug select timeout\n");
+			return 0;
+		default:
+			break;
+		}
+		break;
+	case 2: /* PHY write */
+		if ((reg->reg & ~0xff) != BIT(16))
+			break;
+		dw_hdmi_phy_write(dw_dev, reg->val & 0xffff, reg->reg & 0xff);
+		return 0;
+	default:
+		break;
+	}
+
+	dw_hdmi_invalid_register(dw_dev, reg->reg);
+	return 0;
+}
+#endif
+
+static int dw_hdmi_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				   struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
+	default:
+		return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
+	}
+}
+
+static int dw_hdmi_registered(struct v4l2_subdev *sd)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	dw_dev->registered = true;
+	return 0;
+}
+
+static void dw_hdmi_unregistered(struct v4l2_subdev *sd)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	dw_dev->registered = false;
+}
+
+static const struct v4l2_subdev_core_ops dw_hdmi_sd_core_ops = {
+	.log_status = dw_hdmi_log_status,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = dw_hdmi_g_register,
+	.s_register = dw_hdmi_s_register,
+#endif
+	.subscribe_event = dw_hdmi_subscribe_event,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops dw_hdmi_sd_video_ops = {
+	.s_routing = dw_hdmi_s_routing,
+	.g_input_status = dw_hdmi_g_input_status,
+	.g_frame_interval = dw_hdmi_g_frame_interval,
+	.s_dv_timings = dw_hdmi_s_dv_timings,
+	.g_dv_timings = dw_hdmi_g_dv_timings,
+	.query_dv_timings = dw_hdmi_query_dv_timings,
+};
+
+static const struct v4l2_subdev_pad_ops dw_hdmi_sd_pad_ops = {
+	.enum_mbus_code = dw_hdmi_enum_mbus_code,
+	.get_fmt = dw_hdmi_get_fmt,
+	.set_fmt = dw_hdmi_set_fmt,
+	.get_edid = dw_hdmi_get_edid,
+	.set_edid = dw_hdmi_set_edid,
+	.dv_timings_cap = dw_hdmi_dv_timings_cap,
+	.enum_dv_timings = dw_hdmi_enum_dv_timings,
+};
+
+static const struct v4l2_subdev_ops dw_hdmi_sd_ops = {
+	.core = &dw_hdmi_sd_core_ops,
+	.video = &dw_hdmi_sd_video_ops,
+	.pad = &dw_hdmi_sd_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops dw_hdmi_internal_ops = {
+	.registered = dw_hdmi_registered,
+	.unregistered = dw_hdmi_unregistered,
+};
+
+static int dw_hdmi_parse_pd(struct dw_hdmi_dev *dw_dev)
+{
+	/* PHY address already comes from platform data */
+	if (!dw_dev->config->phy->jtag_addr) {
+		dev_err(dw_dev->dev, "missing PHY jtag address in PD\n");
+		return -EINVAL;
+	}
+
+	/* clock already comes from platform data */
+	if (!dw_dev->config->iref_clk) {
+		dev_err(dw_dev->dev, "invalid cfg clock frequency in PD\n");
+		return -EINVAL;
+	}
+
+	/* PHY input count already comes from platform data */
+	if (!dw_dev->config->phy->input_count) {
+		dev_err(dw_dev->dev, "invalid PHY input count\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_parse_dt(struct dw_hdmi_dev *dw_dev)
+{
+	struct device_node *phy_node, *np = dw_dev->of_node;
+	struct device_node *port_node;
+	u32 tmp = 0;
+	int ret;
+
+	if (!np) {
+		dev_err(dw_dev->dev, "missing DT node\n");
+		return -EINVAL;
+	}
+
+	/* PHY properties parsing */
+	phy_node = dw_hdmi_get_phy_of_node(dw_dev, NULL);
+	ret = of_property_read_u32(phy_node, "reg", &tmp);
+	if (ret) {
+		dev_err(dw_dev->dev, "missing PHY jtag address in DT\n");
+		return ret;
+	}
+
+	dw_dev->config->phy->jtag_addr = tmp & 0xff;
+
+	/* Get config clock value */
+	dw_dev->clk = devm_clk_get(dw_dev->dev, "cfg");
+	if (IS_ERR(dw_dev->clk)) {
+		dev_err(dw_dev->dev, "failed to get cfg clock\n");
+		return PTR_ERR(dw_dev->clk);
+	}
+
+	ret = clk_prepare_enable(dw_dev->clk);
+	if (ret) {
+		dev_err(dw_dev->dev, "failed to enable cfg clock\n");
+		return ret;
+	}
+
+	dw_dev->config->iref_clk = clk_get_rate(dw_dev->clk) / 1000000U;
+	if (!dw_dev->config->iref_clk) {
+		dev_err(dw_dev->dev, "invalid cfg clock frequency\n");
+		ret = -EINVAL;
+		goto err_clk;
+	}
+
+	/* Get PHY input count through the port children count */
+	port_node = of_get_child_by_name(phy_node, "port");
+	dw_dev->config->phy->input_count = of_get_child_count(port_node);
+	if (!dw_dev->config->phy->input_count) {
+		dev_err(dw_dev->dev, "invalid PHY input count\n");
+		ret = -EINVAL;
+		goto err_clk;
+	}
+
+	return 0;
+
+err_clk:
+	clk_disable_unprepare(dw_dev->clk);
+	return ret;
+}
+
+static void dw_hdmi_config_ced(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1f, DW_HDMI_HDMI20_CONTROL,
+			 DW_HDMI_CTRLCHECKEN_OFFSET,
+			 DW_HDMI_VIDDATACHECKEN_MASK |
+			 DW_HDMI_DATAISCHECKEN_MASK |
+			 DW_HDMI_GBCHECKEN_MASK |
+			 DW_HDMI_PREAMBCHECKEN_MASK |
+			 DW_HDMI_CTRLCHECKEN_MASK);
+}
+
+static void dw_hdmi_config_mode_recover(struct dw_hdmi_dev *dw_dev)
+{
+	/*NOTE: avoid instability of md_ists interrupts */
+
+	/* set HDMI_MODE_HYST */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MODE_RECOVER,
+			 DW_HDMI_HDMI_MODE_HYST_OFFSET,
+			 DW_HDMI_HDMI_MODE_HYST_MASK);
+	/* set DVI_MODE_HYST */
+	hdmi_mask_writel(dw_dev, 0x8, DW_HDMI_MODE_RECOVER,
+			 DW_HDMI_DVI_MODE_HYST_OFFSET,
+			 DW_HDMI_DVI_MODE_HYST_MASK);
+	/* set SPIKE_FILTER_EN */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MODE_RECOVER,
+			 DW_HDMI_SPIKE_FILTER_EN_OFFSET,
+			 DW_HDMI_SPIKE_FILTER_EN_MASK);
+
+	/* enable BCH error correction */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_CTRL,
+			 DW_HDMI_PDEC_BCH_EN_OFFSET,
+			 DW_HDMI_PDEC_BCH_EN_MASK);
+}
+
+static void dw_hdmi_config_scdc(struct dw_hdmi_dev *dw_dev)
+{
+	u32 chlock = dw_dev->config->iref_clk * 1000;
+
+	/* set HDMI_CHLOCK_CONFIG */
+	hdmi_mask_writel(dw_dev, chlock, DW_HDMI_CHLOCK_CONFIG,
+			 DW_HDMI_MILISECTIMERLIMIT_OFFSET,
+			 DW_HDMI_MILISECTIMERLIMIT_MASK);
+}
+
+static void dw_hdmi_config_ceavid(struct dw_hdmi_dev *dw_dev)
+{
+	/* set CEA YCC 422 IPI Mapping */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_YCC422_IPIMAP_OFFSET,
[… more lines in the raw message]

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

drivers/media/platform/dwc/dw-hdmi-rx.c line 2969

Quoted 10 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +10 -0
+			 DW_HDMI_CEAVID_YCC422_IPIMAP_MASK);
+	/* set CEA YCC 420 IPI Mapping */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_YCC420_IPIMAP_OFFSET,
+			 DW_HDMI_CEAVID_YCC420_IPIMAP_MASK);
+}
+
+static int dw_hdmi_initial_config(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	/* disable interrupts */
[… more lines in the raw message]

This should be dropped, start with an empty EDID and pull the HPD low.

include/media/dwc/dw-hdmi-rx-pdata.h

Quoted 764 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +149 -0

Lines of this file are not shown. View the raw message.

drivers/media/platform/dwc/dw-hdmi-rx.h new file +476 -0
new file mode 100644
index 0000000..f0ea1d4

Lines of this file are not shown. View the raw message.

include/media/dwc/dw-hdmi-rx-pdata.h new file +126 -0
new file mode 100644
index 0000000..a2a5440

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Regards,

Hans

Part of the diff is not shown here. View the raw message.

#13 lore raw

RE: [PATCH 6/9] media: platform: Add Synopsys DesignWare HDMI RX Controller Driver

Hi Hans,

Thanks for your initial comments and feedback!

From: Hans Verkuil <[email protected]>
Date: qua, jun 02, 2021 at 12:54:38

Quoted 6 lines

Hi Nelson,

Thank you for this patch. Some initial comments below, I will need to go over this another time for some of the colorimetry related functions.

Ok.

Quoted 4 lines

BTW, if you are interested in HDCP support, let me know. Cisco worked on an API for this, but due to various reasons we have not been able to upstream it. But we do use it in our products.

Good to know! In that case if in the future we think to upstream something
related with HDCP we will let you know. :)
BTW, which versions of HDCP (1.4, 2.2, 2.3) the API supports?

Quoted 170 lines · Nelson Costa
Quoted 151 lines

This is an initial submission for the Synopsys DesignWare HDMI RX Controller Driver. It is responsible to manage and handle the PHY (through the PHY API) and the Controller configurations in order to configure the video and audio pipeline.

This driver is implemented as a standard V4L2 subdevice. The main features of this module are:
- Support for scrambling
- Support for color depth up to 48bpp
- Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz)
- Support for RGB, YCC444, YCC422 and YCC420
- Support for basic audio (LPCM 2ch, 32KHz/44.1KHz/48KHz, 16bit)
- Support for Aspect Ratio
- Support for CEC
- Internal state machine that reconfigures PHY and controller
- JTAG communication with PHY
- Inter-module communication with PHY driver:
* through the PHY API using the PHY reference "hdmi-phy"
* through the callbacks that PHY DWC driver needs.
- Debug write/read ioctls.

---
 drivers/media/platform/Kconfig          |    2 +
 drivers/media/platform/Makefile         |    1 +
 drivers/media/platform/dwc/Kconfig      |   13 +
 drivers/media/platform/dwc/Makefile     |    3 +
 drivers/media/platform/dwc/dw-hdmi-rx.c | 3237 +++++++++++++++++++++++++++++++
 drivers/media/platform/dwc/dw-hdmi-rx.h |  476 +++++
 include/media/dwc/dw-hdmi-rx-pdata.h    |  126 ++
 7 files changed, 3858 insertions(+)
 create mode 100644 drivers/media/platform/dwc/Kconfig
 create mode 100644 drivers/media/platform/dwc/Makefile
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.c
 create mode 100644 drivers/media/platform/dwc/dw-hdmi-rx.h
 create mode 100644 include/media/dwc/dw-hdmi-rx-pdata.h
drivers/media/platform/Kconfig +2 -0
index b238a92..20db68d 100644
@@ -29,6 +29,8 @@ source "drivers/media/platform/cadence/Kconfig"
 
 source "drivers/media/platform/davinci/Kconfig"
 
+source "drivers/media/platform/dwc/Kconfig"
+
 source "drivers/media/platform/omap/Kconfig"
 
 config VIDEO_ASPEED
drivers/media/platform/Makefile +1 -0
index eedc14a..955aae6 100644
@@ -6,6 +6,7 @@
 obj-$(CONFIG_VIDEO_ALLEGRO_DVT)		+= allegro-dvt/
 obj-$(CONFIG_VIDEO_ASPEED)		+= aspeed-video.o
 obj-$(CONFIG_VIDEO_CADENCE)		+= cadence/
+obj-y					+= dwc/
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
 obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
drivers/media/platform/dwc/Kconfig new file +13 -0
new file mode 100644
index 0000000..e915ca6
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_DWC_HDMI_RX
+	tristate "Synopsys DesignWare HDMI Receiver driver"
+	depends on VIDEO_V4L2
+	select MEDIA_CONTROLLER
+	select VIDEO_V4L2_SUBDEV_API
+	select HDMI
+	help
+	  Support for Synopsys DesignWare HDMI RX Controller.
+	  This driver supports HDMI 2.0 version.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called dw-hdmi-rx.
drivers/media/platform/dwc/Makefile new file +3 -0
new file mode 100644
index 0000000..fddd30c
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_VIDEO_DWC_HDMI_RX) += dw-hdmi-rx.o
drivers/media/platform/dwc/dw-hdmi-rx.c new file +54 -0
new file mode 100644
index 0000000..b20eccc
@@ -0,0 +1,3237 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - present Synopsys, Inc. and/or its affiliates.
+ * Synopsys DesignWare HDMI Receiver controller driver
+ *
+ * Author: Jose Abreu <[email protected]>
+ * Author: Nelson Costa <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/dwc/dw-hdmi-phy-pdata.h>
+#include <linux/v4l2-dv-timings.h>
+#include <linux/workqueue.h>
+#include <linux/rational.h>
+#include <linux/hdmi.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dv-timings.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+#include <media/dwc/dw-hdmi-rx-pdata.h>
+
+#include "dw-hdmi-rx.h"
+
+#define DW_HDMI_DEFAULT_TIMING		V4L2_DV_BT_CEA_640X480P59_94
+#define DW_HDMI_JTAG_TAP_ADDR_CMD	0
+#define DW_HDMI_JTAG_TAP_WRITE_CMD	1
+#define DW_HDMI_JTAG_TAP_READ_CMD	3
+#define DW_HDMI_AUDIO_FREQ_RANGE	1000
+
+/* EDID for HDMI RX */
+static u32 dw_hdmi_edid[] = {
+	/* V2 Support for                           */
+	/*  - Video modes up-to 2.97Gbps            */
+	/*  - RGB, Ycc444/422/420                   */
+	/*  - Audio 2Ch L-PCM                       */
+	/*  - SCDC CED                              */
+	0x00FFFFFF, 0xFFFFFF00, 0x4F2E4A21, 0x00000000,
+	0x331E0103, 0x80462878, 0x0A0DC9A0, 0x57479827,
+	0x12484C20, 0x00000101, 0x01010101, 0x01010101,
+	0x01010101, 0x0101023A, 0x80187138, 0x2D40582C,
+	0x450020C2, 0x3100001E, 0x011D0072, 0x51D01E20,
+	0x6E285500, 0x20C23100, 0x001E0000, 0x00FC0053,
+	0x4E505320, 0x48444D49, 0x2052580A, 0x000000FD,
+	0x0017780F, 0x871E000A, 0x20202020, 0x20200160,

drivers/media/platform/dwc/dw-hdmi-rx.c line 64

Quoted 10 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +10 -0
+
+	0x02035771, 0x83010000, 0x57696867, 0x6463625F,
+	0x5E5D901F, 0x04131211, 0x0302015A, 0x59585756,
+	0x55555453, 0x5251504F, 0x4E4D4C4B, 0x4A494847,
+	0x46454443, 0x42412309, 0x07076E03, 0x0C001000,
+	0xF83B2000, 0x80010203, 0x0467D85D, 0xC4010080,
+	0x00E50E66, 0x65616000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x000000B6,
+};

This won't work, it's a bad idea to have a default EDID since it is almost certainly wrong anyway. Userspace has to set the EDID since userspace knows the capabilities of the device as a whole. I.e., while this receiver supports up to 2.97 Gbps, there might other contraints that would lower this value. And the EDID contains vendor and model information, and addition blocks and capabilities might have to be set.

Quoted 4 lines

So keep the EDID empty and the HPD low at start up, and leave it to userspace to write the EDID (for testing the v4l2-ctl utility comes with a bunch of predefined EDIDs).

I agree! This will be addressed in the next patch series.

Quoted 2,477 lines
Quoted 2,477 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +2477 -0
+
+static const struct v4l2_dv_timings_cap dw_hdmi_timings_cap = {
+	.type = V4L2_DV_BT_656_1120,
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(640, 4096,			/* min/max width */
+			     480, 4455,			/* min/max height */
+			     20000000, 600000000,	/* min/max pixelclock */
+			     /* standards */
+			     V4L2_DV_BT_STD_CEA861,
+			     /* capabilities */
+			     V4L2_DV_BT_CAP_PROGRESSIVE)
+};
+
+static const struct v4l2_event dw_hdmi_event_fmt = {
+	.type = V4L2_EVENT_SOURCE_CHANGE,
+	.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+};
+
+enum dw_hdmi_state {
+	HDMI_STATE_NO_INIT = 0,
+	HDMI_STATE_POWER_OFF,
+	HDMI_STATE_POWER_UP,
+	HDMI_STATE_PHY_CONFIG,
+	HDMI_STATE_HPD,
+	HDMI_STATE_EQUALIZER,
+	HDMI_STATE_DATAPATH,
+	HDMI_STATE_VIDEO_UNSTABLE,
+	HDMI_STATE_AUDIO,
+	HDMI_STATE_POWER_ON,
+};
+
+struct dw_hdmi_infoframe_cfg {
+	const char *desc;
+	u8 header[3];
+	u32 header_addr;
+	u32 payload_addr;
+	u32 payload_len;
+	void *frame;
+	unsigned int frame_size;
+};
+
+struct dw_hdmi_dev {
+	struct device *dev;
+	struct device_node *of_node;
+	void __iomem *regs;
+	struct clk *clk;
+
+	/* Platform Data configuration */
+	struct dw_hdmi_rx_pdata *config;
+
+	/* Phy info */
+	struct platform_device *phy_pdev;
+	struct dw_phy_pdata phy_config;
+	struct phy *phy;
+
+	/*
+	 * Used to prevent race conditions between multiple
+	 * concurrent calls to handle the state machine changes
+	 * and pending configurations.
+	 */
+	spinlock_t lock;
+	/*
+	 * Used to prevent race conditions between multiple
+	 * concurrent calls to notify the audio changes.
+	 */
+	spinlock_t event_lock;
+
+	/* Work queue to handle the state machine */
+	struct workqueue_struct *wq;
+	struct work_struct work;
+
+	/* State machine variables */
+	enum dw_hdmi_state state;
+	u32 mbus_code;
+	u32 old_mbus;
+	u8 *curr_edid_blocks;
+	u8 current_vic;
+	bool current_vic_is_4k;
+	bool registered;
+	bool pending_config;
+	bool force_off;
+	bool is_hdmi2;
+	bool is_scrambled;
+	bool phy_eq_force;
+	bool phy_eq_on;
+	bool hw_reset_on_hot_plug;
+	bool *input_connected;
+	unsigned int selected_input;
+	unsigned int configured_input;
+	unsigned int input_stat;
+	unsigned int audio_sf;
+	unsigned int tmds_valid_wait_count;
+	unsigned int has_clock_wait_ms;
+	unsigned int video_stable_wait_ms;
+	unsigned int reset_datapath_enable;
+
+	/* Infoframes */
+	union hdmi_infoframe aviif;
+	union hdmi_infoframe spdif;
+	union hdmi_infoframe audioif;
+	union hdmi_infoframe vsif;
+
+	/* v4l2 device */
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *detect_tx_5v_ctrl;
+	struct v4l2_dv_timings timings;
+};
+
+static const char *get_state_name(enum dw_hdmi_state state)
+{
+	switch (state) {
+	case HDMI_STATE_NO_INIT:
+		return "NO_INIT";
+	case HDMI_STATE_POWER_OFF:
+		return "POWER_OFF";
+	case HDMI_STATE_POWER_UP:
+		return "POWER_UP";
+	case HDMI_STATE_PHY_CONFIG:
+		return "PHY_CONFIG";
+	case HDMI_STATE_HPD:
+		return "HPD";
+	case HDMI_STATE_EQUALIZER:
+		return "EQUALIZER";
+	case HDMI_STATE_DATAPATH:
+		return "DATAPATH";
+	case HDMI_STATE_VIDEO_UNSTABLE:
+		return "VIDEO_UNSTABLE";
+	case HDMI_STATE_AUDIO:
+		return "AUDIO";
+	case HDMI_STATE_POWER_ON:
+		return "POWER_ON";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static inline void dw_hdmi_set_state(struct dw_hdmi_dev *dw_dev,
+				     enum dw_hdmi_state new_state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dev_dbg(dw_dev->dev, "old_state=%s, new_state=%s\n",
+		get_state_name(dw_dev->state),
+		get_state_name(new_state));
+	dw_dev->state = new_state;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+}
+
+static inline struct dw_hdmi_dev *to_dw_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct dw_hdmi_dev, sd);
+}
+
+static inline void hdmi_writel(struct dw_hdmi_dev *dw_dev, u32 val, int reg)
+{
+	writel(val, dw_dev->regs + reg);
+}
+
+static inline u32 hdmi_readl(struct dw_hdmi_dev *dw_dev, int reg)
+{
+	return readl(dw_dev->regs + reg);
+}
+
+static void hdmi_modl(struct dw_hdmi_dev *dw_dev, u32 data, u32 mask, int reg)
+{
+	u32 val = hdmi_readl(dw_dev, reg) & ~mask;
+
+	val |= data & mask;
+	hdmi_writel(dw_dev, val, reg);
+}
+
+static void hdmi_mask_writel(struct dw_hdmi_dev *dw_dev, u32 data, int reg,
+			     u32 shift, u32 mask)
+{
+	hdmi_modl(dw_dev, data << shift, mask, reg);
+}
+
+static u32 hdmi_mask_readl(struct dw_hdmi_dev *dw_dev, int reg, u32 shift,
+			   u32 mask)
+{
+	return (hdmi_readl(dw_dev, reg) & mask) >> shift;
+}
+
+static bool dw_hdmi_5v_status(struct dw_hdmi_dev *dw_dev, int input)
+{
+	void __iomem *arg = dw_dev->config->dw_5v_arg;
+
+	if (dw_dev->config->dw_5v_status)
+		return dw_dev->config->dw_5v_status(arg, input);
+
+	return false;
+}
+
+static void dw_hdmi_5v_disable(struct dw_hdmi_dev *dw_dev, int input)
+{
+	void __iomem *arg = dw_dev->config->dw_5v_arg;
+
+	if (!dw_dev->config->dw_5v_disable)
+		return;
+
+	dw_dev->config->dw_5v_disable(arg, input);
+}
+
+static void dw_hdmi_5v_enable(struct dw_hdmi_dev *dw_dev, int input)
+{
+	void __iomem *arg = dw_dev->config->dw_5v_arg;
+
+	if (!dw_dev->config->dw_5v_enable)
+		return;
+
+	dw_dev->config->dw_5v_enable(arg, input);
+}
+
+static u32 dw_hdmi_edid_read(struct dw_hdmi_dev *dw_dev, int input, u32 offset)
+{
+	void __iomem *arg = dw_dev->config->dw_edid_arg;
+
+	if (!dw_dev->config->dw_edid_read)
+		return 0x0;
+
+	return dw_dev->config->dw_edid_read(arg, input, offset);
+}
+
+static int dw_hdmi_edid_write(struct dw_hdmi_dev *dw_dev, int input, u32 *edid,
+			      int size)
+{
+	void __iomem *arg = dw_dev->config->dw_edid_arg;
+
+	if (!dw_dev->config->dw_edid_write)
+		return 0;
+
+	return dw_dev->config->dw_edid_write(arg, input, edid, size);
+}
+
+static u32 dw_hdmi_edid_4blocks_le(struct dw_hdmi_dev *dw_dev)
+{
+	void __iomem *arg = dw_dev->config->dw_edid_arg;
+
+	if (!dw_dev->config->dw_edid_4blocks_le)
+		return 0x0;
+
+	return dw_dev->config->dw_edid_4blocks_le(arg);
+}
+
+static int dw_hdmi_update_edid(struct dw_hdmi_dev *dw_dev, int input,
+			       u8 *edid, int size, u8 invert_bytes)
+{
+	unsigned int i, j;
+	u32 *w_edid_srt;
+	int ret;
+
+	if (invert_bytes) {
+		/* invert the order of bytes to register 32bit */
+		w_edid_srt = devm_kzalloc(dw_dev->dev, size, GFP_KERNEL);
+		if (!w_edid_srt) {
+			devm_kfree(dw_dev->dev, w_edid_srt);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < size / sizeof(u32); i++) {
+			for (j = 0; j < 4; j++) {
+				w_edid_srt[i] |=
+					edid[i * 4 + j] << (8 * (3 - j));
+			}
+		}
+
+		ret = dw_hdmi_edid_write(dw_dev, input, (u32 *)w_edid_srt,
+					 size / sizeof(u32));
+		devm_kfree(dw_dev->dev, w_edid_srt);
+	} else {
+		/* no need to invert bytes */
+		ret = dw_hdmi_edid_write(dw_dev, input, (u32 *)edid,
+					 size / sizeof(u32));
+	}
+	dw_dev->curr_edid_blocks[input] = size / 128;
+
+	return ret;
+}
+
+static void dw_hdmi_main_reset(struct dw_hdmi_dev *dw_dev)
+{
+	void __iomem *arg = dw_dev->config->dw_reset_arg;
+
+	if (!dw_dev->config->dw_reset_all)
+		return;
+
+	dev_dbg(dw_dev->dev, "%s: main reset\n", __func__);
+
+	dw_dev->config->dw_reset_all(arg);
+}
+
+static void dw_hdmi_disable_hpd(struct dw_hdmi_dev *dw_dev);
+
+static void dw_hdmi_reset(struct dw_hdmi_dev *dw_dev)
+{
+	dev_dbg(dw_dev->dev, "%s: reset\n", __func__);
+
+	/* perform main reset */
+	dw_hdmi_main_reset(dw_dev);
+
+	dw_hdmi_disable_hpd(dw_dev);
+}
+
+static inline bool is_off(struct dw_hdmi_dev *dw_dev)
+{
+	return dw_dev->state <= HDMI_STATE_POWER_OFF;
+}
+
+static inline bool is_on(struct dw_hdmi_dev *dw_dev)
+{
+	return dw_dev->state == HDMI_STATE_POWER_ON;
+}
+
+static bool has_signal(struct dw_hdmi_dev *dw_dev, unsigned int input)
+{
+	return dw_dev->input_connected[input];
+}
+
+static inline bool is_hdmi2(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_readl(dw_dev, DW_HDMI_SCDC_REGS0) &
+			DW_HDMI_SCDC_TMDSBITCLKRATIO_MASK;
+}
+
+static inline bool is_scrambled(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_readl(dw_dev, DW_HDMI_SCDC_REGS0) &
+			DW_HDMI_SCDC_SCRAMBSTATUS_MASK;
+}
+
+static void hdmi_phy_jtag_send_pulse(struct dw_hdmi_dev *dw_dev, u8 tms, u8 tdi)
+{
+	u8 val;
+
+	val = tms ? DW_HDMI_JTAG_TMS : 0;
+	val |= tdi ? DW_HDMI_JTAG_TDI : 0;
+
+	hdmi_writel(dw_dev, 0, DW_HDMI_JTAG_TAP_TCLK);
+	hdmi_writel(dw_dev, val, DW_HDMI_JTAG_TAP_IN);
+	hdmi_writel(dw_dev, 1, DW_HDMI_JTAG_TAP_TCLK);
+}
+
+static void hdmi_phy_jtag_shift_dr(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+}
+
+static void hdmi_phy_jtag_shift_ir(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+}
+
+static u16 hdmi_phy_jtag_send(struct dw_hdmi_dev *dw_dev, u8 cmd, u16 val)
+{
+	u32 in = (cmd << 16) | val;
+	u16 out = 0;
+	u8 i;
+
+	for (i = 0; i < 16; i++) {
+		hdmi_phy_jtag_send_pulse(dw_dev, 0, in & 0x1);
+		out |= (hdmi_readl(dw_dev, DW_HDMI_JTAG_TAP_OUT) & 0x1) << i;
+		in >>= 1;
+	}
+
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, in & 0x1);
+	in >>= 1;
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, in & 0x1);
+
+	out |= (hdmi_readl(dw_dev, DW_HDMI_JTAG_TAP_OUT) & 0x1) << ++i;
+	return out;
+}
+
+static void hdmi_phy_jtag_idle(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+}
+
+static void hdmi_phy_jtag_init(struct dw_hdmi_dev *dw_dev, u8 addr)
+{
+	u8 i;
+
+	hdmi_writel(dw_dev, addr, DW_HDMI_JTAG_ADDR);
+
+	/* reset */
+	hdmi_writel(dw_dev, 0x10, DW_HDMI_JTAG_TAP_IN);
+	hdmi_writel(dw_dev, 0x0, DW_HDMI_JTAG_CONF);
+	hdmi_writel(dw_dev, 0x1, DW_HDMI_JTAG_CONF);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+
+	/* soft reset */
+	for (i = 0; i < 5; i++)
+		hdmi_phy_jtag_send_pulse(dw_dev, 1, 0);
+	hdmi_phy_jtag_send_pulse(dw_dev, 0, 0);
+
+	/* set slave address */
+	hdmi_phy_jtag_shift_ir(dw_dev);
+	for (i = 0; i < 7; i++) {
+		hdmi_phy_jtag_send_pulse(dw_dev, 0, addr & 0x1);
+		addr >>= 1;
+	}
+	hdmi_phy_jtag_send_pulse(dw_dev, 1, addr & 0x1);
+	hdmi_phy_jtag_idle(dw_dev);
+}
+
+static void hdmi_phy_jtag_write(struct dw_hdmi_dev *dw_dev, u16 val, u16 addr)
+{
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_ADDR_CMD, addr << 8);
+	hdmi_phy_jtag_idle(dw_dev);
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_WRITE_CMD, val);
+	hdmi_phy_jtag_idle(dw_dev);
+}
+
+static u16 hdmi_phy_jtag_read(struct dw_hdmi_dev *dw_dev, u16 addr)
+{
+	u16 val;
+
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_ADDR_CMD, addr << 8);
+	hdmi_phy_jtag_idle(dw_dev);
+	hdmi_phy_jtag_shift_dr(dw_dev);
+	val = hdmi_phy_jtag_send(dw_dev, DW_HDMI_JTAG_TAP_READ_CMD, 0xFFFF);
+	hdmi_phy_jtag_idle(dw_dev);
+
+	return val;
+}
+
+static void dw_hdmi_phy_write(void *arg, u16 val, u16 addr)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+	u16 rval;
+
+	hdmi_phy_jtag_init(dw_dev, dw_dev->config->phy->jtag_addr);
+	hdmi_phy_jtag_write(dw_dev, val, addr);
+	rval = hdmi_phy_jtag_read(dw_dev, addr);
+
+	if (rval != val) {
+		dev_err(dw_dev->dev,
+			"JTAG read-back failed: expected=0x%x, got=0x%x\n",
+			val, rval);
+	}
+}
+
+static u16 dw_hdmi_phy_read(void *arg, u16 addr)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_phy_jtag_init(dw_dev, dw_dev->config->phy->jtag_addr);
+	return hdmi_phy_jtag_read(dw_dev, addr);
+}
+
+static void dw_hdmi_phy_reset(void *arg, int enable)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PHYRESET_OFFSET,
+			 DW_HDMI_PHYRESET_MASK);
+}
+
+static void dw_hdmi_phy_pddq(void *arg, int enable)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PHYPDDQ_OFFSET,
+			 DW_HDMI_PHYPDDQ_MASK);
+}
+
+static void dw_hdmi_phy_svsmode(void *arg, int enable)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PHYSVSRETMODEZ_OFFSET,
+			 DW_HDMI_PHYSVSRETMODEZ_MASK);
+}
+
+static void dw_hdmi_zcal_reset(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	if (dw_dev->config->dw_zcal_reset)
+		dw_dev->config->dw_zcal_reset(dw_dev->config->dw_zcal_arg);
+}
+
+static bool dw_hdmi_zcal_done(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+	void __iomem *zcal_arg = dw_dev->config->dw_zcal_arg;
+
+	if (dw_dev->config->dw_zcal_done)
+		return dw_dev->config->dw_zcal_done(zcal_arg);
+
+	return false;
+}
+
+static bool dw_hdmi_tmds_valid(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	return (hdmi_readl(dw_dev, DW_HDMI_PLL_LCK_STS) & DW_HDMI_PLL_LOCKED);
+}
+
+static bool dw_hdmi_audio_valid(void *arg)
+{
+	struct dw_hdmi_dev *dw_dev = arg;
+
+	return ((hdmi_readl(dw_dev, DW_HDMI_AUD_PLL_CTRL) &
+			DW_HDMI_PLL_LOCK_STABLE_MASK) != 0);
+}
+
+static const struct dw_phy_funcs dw_hdmi_phy_funcs = {
+	.write = dw_hdmi_phy_write,
+	.read = dw_hdmi_phy_read,
+	.reset = dw_hdmi_phy_reset,
+	.pddq = dw_hdmi_phy_pddq,
+	.svsmode = dw_hdmi_phy_svsmode,
+	.zcal_reset = dw_hdmi_zcal_reset,
+	.zcal_done = dw_hdmi_zcal_done,
+	.tmds_valid = dw_hdmi_tmds_valid,
+};
+
+static const struct of_device_id dw_hdmi_supported_phys[] = {
+	{ .compatible = "snps,dw-hdmi-phy-e405", .data = DW_PHY_E40X_DRVNAME, },
+	{ .compatible = "snps,dw-hdmi-phy-e406", .data = DW_PHY_E40X_DRVNAME, },
+	{ },
+};
+
+static struct device_node *
+dw_hdmi_get_phy_of_node(struct dw_hdmi_dev *dw_dev,
+			const struct of_device_id **found_id)
+{
+	const struct of_device_id *id = NULL;
+	struct device_node *np = NULL;
+
+	np = of_find_matching_node_and_match(NULL, dw_hdmi_supported_phys, &id);
+
+	if (!id)
+		return NULL;
+
+	if (found_id)
+		*found_id = id;
+
+	return np;
+}
+
+static bool dw_hdmi_has_dt(struct dw_hdmi_dev *dw_dev)
+{
+	const struct of_device_id *of_id;
+
+	if (!dw_dev->of_node ||
+	    !dw_hdmi_get_phy_of_node(dw_dev, &of_id) ||
+	    !of_id || !of_id->data) {
+		return false;
+	}
+
+	return true;
+}
+
+static const struct dw_hdmi_phy_cfg {
+	const char *drvname;
+	const struct dw_phy_funcs *funcs;
+	int (*extra_init)(struct dw_hdmi_dev *dw_dev);
+} dw_hdmi_phys[] = {
+	{
+		.drvname = DW_PHY_E40X_DRVNAME,
+		.funcs = &dw_hdmi_phy_funcs,
+	},
+};
+
+static int dw_hdmi_phy_init_dt(struct dw_hdmi_dev *dw_dev)
+{
+	const struct dw_hdmi_phy_cfg *phy_config = NULL;
+	struct dw_phy_pdata *phy = &dw_dev->phy_config;
+	struct of_dev_auxdata lookup = { };
+	const struct of_device_id *of_id;
+	struct device_node *child;
+	const char *drvname;
+	unsigned int i;
+	int ret;
+
+	child = dw_hdmi_get_phy_of_node(dw_dev, &of_id);
+	if (!child || !of_id || !of_id->data) {
+		dev_err(dw_dev->dev, "no supported PHY found in DT\n");
+		return -EINVAL;
+	}
+
+	drvname = of_id->data;
+	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); i++) {
+		if (!strcmp(dw_hdmi_phys[i].drvname, drvname))
+			phy_config = &dw_hdmi_phys[i];
+	}
+
+	if (!phy_config) {
+		dev_err(dw_dev->dev, "failed to find PHY configuration\n");
+		return -EINVAL;
+	}
+
+	if (phy_config->extra_init) {
+		ret = phy_config->extra_init(dw_dev);
+		if (ret)
+			return ret;
+	}
+
+	phy->funcs = phy_config->funcs;
+	phy->funcs_arg = dw_dev;
+
+	lookup.compatible = (char *)of_id->compatible;
+	lookup.platform_data = phy;
+
+	request_module(drvname);
+
+	ret = of_platform_populate(dw_dev->of_node, NULL, &lookup, dw_dev->dev);
+	if (ret) {
+		dev_err(dw_dev->dev, "failed to populate PHY driver\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_phy_init_pd(struct dw_hdmi_dev *dw_dev)
+{
+	const char *drv_name = dw_dev->config->phy->drv_name;
+	const struct dw_hdmi_phy_cfg *phy_config = NULL;
+	struct platform_device_info pdevinfo;
+	unsigned int i;
+	int ret;
+
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); i++) {
+		if (!strcmp(dw_hdmi_phys[i].drvname, drv_name))
+			phy_config = &dw_hdmi_phys[i];
+	}
+
+	if (!phy_config) {
+		dev_err(dw_dev->dev, "failed to find PHY configuration\n");
+		return -EINVAL;
+	}
+
+	if (phy_config->extra_init) {
+		ret = phy_config->extra_init(dw_dev);
+		if (ret)
+			return ret;
+	}
+
+	dw_dev->phy_config.version = dw_dev->config->phy->version;
+	dw_dev->phy_config.cfg_clk = dw_dev->config->phy->cfg_clk;
+	dw_dev->phy_config.funcs = phy_config->funcs;
+	dw_dev->phy_config.funcs_arg = dw_dev;
+
+	pdevinfo.parent = dw_dev->dev;
+	pdevinfo.id = PLATFORM_DEVID_NONE;
+	pdevinfo.name = drv_name;
+	pdevinfo.data = &dw_dev->phy_config;
+	pdevinfo.size_data = sizeof(dw_dev->phy_config);
+	pdevinfo.dma_mask = DMA_BIT_MASK(32);
+
+	request_module(pdevinfo.name);
+
+	dw_dev->phy_pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(dw_dev->phy_pdev)) {
+		dev_err(dw_dev->dev, "failed to register PHY device\n");
+		return PTR_ERR(dw_dev->phy_pdev);
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_phy_init(struct dw_hdmi_dev *dw_dev)
+{
+	int ret;
+
+	if (dw_hdmi_has_dt(dw_dev)) {
+		/* init PHY based on device tree */
+		ret = dw_hdmi_phy_init_dt(dw_dev);
+	} else {
+		/* init PHY based on platform device */
+		ret = dw_hdmi_phy_init_pd(dw_dev);
+	}
+
+	/* get the HDMI PHY reference */
+	dw_dev->phy = devm_phy_get(dw_dev->dev, "hdmi-phy");
+	if (IS_ERR(dw_dev->phy)) {
+		if (PTR_ERR(dw_dev->phy) != -EPROBE_DEFER)
+			dev_err(dw_dev->dev, "Couldn't get the HDMI PHY\n");
+		return PTR_ERR(dw_dev->phy);
+	}
+
+	return ret;
+}
+
+static void dw_hdmi_phy_exit(struct dw_hdmi_dev *dw_dev)
+{
+	if (dw_hdmi_has_dt(dw_dev)) {
+		/* exit PHY based on device tree */
+		of_platform_depopulate(dw_dev->dev);
+	} else {
+		/* exit PHY based on platform device */
+		if (!IS_ERR(dw_dev->phy_pdev))
+			platform_device_unregister(dw_dev->phy_pdev);
+	}
+}
+
+static int dw_hdmi_phy_eq_init(struct dw_hdmi_dev *dw_dev, u16 acq, bool force)
+{
+	union phy_configure_opts opts;
+	struct phy_configure_opts_hdmi *hdmi_opts = &opts.hdmi;
+	int ret = 0;
+
+	/* load the required options for calibration */
+	hdmi_opts->calibration_acq = acq;
+	hdmi_opts->calibration_force = force;
+	/* to avoid other reconfigurations when is to calibrate */
+	hdmi_opts->set_color_depth = 0;
+	hdmi_opts->set_tmds_bit_clock_ratio = 0;
+	hdmi_opts->set_scrambling = 0;
+
+	/* set PHY configuration */
+	ret = phy_configure(dw_dev->phy, &opts);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY configure (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+	/* call PHY calibrate */
+	ret = phy_calibrate(dw_dev->phy);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY calibrate (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int dw_hdmi_phy_config(struct dw_hdmi_dev *dw_dev,
+			      unsigned char color_depth, bool hdmi2,
+			      bool scrambling)
+{
+	union phy_configure_opts opts;
+	struct phy_configure_opts_hdmi *hdmi_opts = &opts.hdmi;
+	int ret = 0;
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_DATAPATH_CBUSZ_OFFSET,
+			 DW_HDMI_DATAPATH_CBUSZ_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_CBUS_SVSRETMODEZ_OFFSET,
+			 DW_HDMI_CBUS_SVSRETMODEZ_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_CBUS_PDDQ_OFFSET,
+			 DW_HDMI_CBUS_PDDQ_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CBUSIOCTRL,
+			 DW_HDMI_CBUS_RESET_OFFSET,
+			 DW_HDMI_CBUS_RESET_MASK);
+
+	/* load the required options for power on */
+	hdmi_opts->color_depth = color_depth;
+	hdmi_opts->tmds_bit_clock_ratio = hdmi2;
+	hdmi_opts->scrambling = scrambling;
+	/* to avoid color depth reconfiguration before the power on */
+	hdmi_opts->set_color_depth = 0;
+
+	/* set PHY configuration */
+	ret = phy_configure(dw_dev->phy, &opts);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY configure (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+	/* call PHY power off if needed */
+	if (dw_dev->phy->power_count > 0) {
+		ret = phy_power_off(dw_dev->phy);
+		if (ret) {
+			dev_err(dw_dev->dev, "%s: Couldn't PHY power off (err: %d)\n",
+				__func__, ret);
+		}
+	}
+
+	/* call PHY power on */
+	ret = phy_power_on(dw_dev->phy);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY power on (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int dw_hdmi_phy_set_color_depth(struct dw_hdmi_dev *dw_dev,
+				       u8 color_depth)
+{
+	union phy_configure_opts opts;
+	struct phy_configure_opts_hdmi *hdmi_opts = &opts.hdmi;
+	int ret = 0;
+
+	/* load the required options for color depth reconfiguration */
+	hdmi_opts->color_depth = color_depth;
+	/* to avoid other reconfigurations when is to set only color depth */
+	hdmi_opts->set_tmds_bit_clock_ratio = 0;
+	hdmi_opts->set_scrambling = 0;
+
+	/* set PHY configuration */
+	ret = phy_configure(dw_dev->phy, &opts);
+	if (ret) {
+		dev_err(dw_dev->dev, "%s: Couldn't PHY configure (err: %d)\n",
+			__func__, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static void dw_hdmi_event_source_change(struct dw_hdmi_dev *dw_dev)
+{
+	if (dw_dev->registered)
+		v4l2_subdev_notify_event(&dw_dev->sd, &dw_hdmi_event_fmt);
+}
+
+static int dw_hdmi_reset_ceavid(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_RST_OFFSET,
+			 DW_HDMI_CEAVID_RST_MASK);
+	msleep(100);
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_RST_OFFSET,
+			 DW_HDMI_CEAVID_RST_MASK);
+
+	return 0;
+}
+
+static void dw_hdmi_update_avmute(struct dw_hdmi_dev *dw_dev, u32 mbus_code)
+{
+	u32 val_l = 0x0, val_h = 0x0;
+
+	switch (mbus_code) {
+	case MEDIA_BUS_FMT_YUYV8_1X16: /* YCbCr 4:2:2 */
+		val_h = 0x00008000;
+		val_l = 0x00008000;
+		break;
+	case MEDIA_BUS_FMT_YUYV12_1X24: /* YCbCr 4:4:4 */
+		val_h = 0x00008000;
+		val_l = 0x00008000;
+		break;
+	case MEDIA_BUS_FMT_YVYU8_1X16: /* YCbCr 4:2:0 */
+		val_h = 0x00000f00;
+		val_l = 0x0f007f00;
+		break;
+	case MEDIA_BUS_FMT_RGB888_2X12_BE: /* RGB */
+	default:
+		break;
+	}
+
+	hdmi_writel(dw_dev, val_l, DW_HDMI_VM_CFG_CH_0_1);
+	hdmi_mask_writel(dw_dev, val_h, DW_HDMI_VM_CFG_CH2,
+			 DW_HDMI_VM_CH2_COL_VALUE_OFFSET,
+			 DW_HDMI_VM_CH2_COL_VALUE_MASK);
+}
+
+static u32 dw_hdmi_get_mbus_code(struct dw_hdmi_dev *dw_dev)
+{
+	enum hdmi_colorspace cs = dw_dev->aviif.avi.colorspace;
+
+	switch (cs) {
+	case HDMI_COLORSPACE_RGB: /* RGB */
+		return MEDIA_BUS_FMT_RGB888_2X12_BE;
+	case HDMI_COLORSPACE_YUV422: /* YCbCr 4:2:2 */
+		return MEDIA_BUS_FMT_YUYV8_1X16;
+	case HDMI_COLORSPACE_YUV444: /* YCbCr 4:4:4 */
+		return MEDIA_BUS_FMT_YUYV12_1X24;
+	case HDMI_COLORSPACE_YUV420: /* YCbCr 4:2:0 */
+		return MEDIA_BUS_FMT_YVYU8_1X16;
+	default:
+		return MEDIA_BUS_FMT_RGB888_2X12_BE;
+	}
+}
+
+static u8 dw_hdmi_infoframe_checksum(u8 *ptr, size_t size)
+{
+	u8 csum = 0;
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		csum += ptr[i];
+	return 256 - csum;
+}
+
+static void dw_hdmi_get_raw_infoframe_avi(struct dw_hdmi_dev *dw_dev,
+					  struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	u32 pb, ph = hdmi_readl(dw_dev, fcfg->header_addr);
+	union hdmi_infoframe *frame = fcfg->frame;
+	u8 packet_hlen = sizeof(fcfg->header);
+	u8 packet_len = (ph >> 8) & 0xff;
+	unsigned int i, j, pos = 0;
+	u8 packet[35] = {0};
+
+	dev_dbg(dw_dev->dev, "%s[%s]: packet_header=0x%x\n", __func__,
+		fcfg->desc, ph);
+
+	if (!ph) /* Fail silently if there is no packet */
+		return;
+
+	if ((packet_len + packet_hlen + 1) > sizeof(packet)) {
+		dev_dbg(dw_dev->dev, "%s: invalid length\n", __func__);
+		goto out;
+	}
+
+	memcpy(packet, fcfg->header, packet_hlen);
+	packet[2] = packet_len; /* Replace fake header size by real header */
+	pos += packet_hlen + 1;
+
+	for (i = 0; i < fcfg->payload_len; i++) {
+		j = 0;
+
+		/* specific for AVI */
+		if (fcfg->header[0] == HDMI_INFOFRAME_TYPE_AVI && i == 1) {
+			/* read YQx, CNx, PRx from AVI PH register */
+			u32 offset = DW_HDMI_PIX_REP_FACTOR_OFFSET;
+			u32 mask = DW_HDMI_QUANT_RANGE_MASK |
+				DW_HDMI_CONTENT_TYPE_MASK |
+				DW_HDMI_PIX_REP_FACTOR_MASK;
+
+			pb = hdmi_mask_readl(dw_dev, fcfg->header_addr, offset,
+					     mask);
+			packet[pos++] = pb & 0xff;
+			j = 1;
+		}
+
+		/* the registers are aligned with the standard raw packet */
+		pb = hdmi_readl(dw_dev, fcfg->payload_addr + 4 * i);
+		for (; j < 4; j++) {
+			if (pos >= (packet_len + packet_hlen + 1))
+				break;
+			packet[pos++] = (pb >> (8 * j)) & 0xff;
+		}
+	}
+
+	packet[3] = dw_hdmi_infoframe_checksum(packet, packet_len +
+			packet_hlen + 1);
+
+	/*print all packet bytes */
+	for (j = 0; j < pos; j++) {
+		dev_dbg(dw_dev->dev, "%s[%s]: packet=0x%x\n", __func__,
+			fcfg->desc, packet[j]);
+	}
+
+	if (hdmi_infoframe_unpack(frame, packet, sizeof(packet))) {
+		dev_dbg(dw_dev->dev, "%s[%s]: failed to unpack\n",
+			__func__, fcfg->desc);
+		goto out;
+	}
+
+	return;
+out:
+	dev_err(dw_dev->dev, "[INVALID INFOFRAME]\n");
+}
+
+static void dw_hdmi_get_raw_infoframe_aud(struct dw_hdmi_dev *dw_dev,
+					  struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	u32 pb, ph = hdmi_readl(dw_dev, fcfg->header_addr);
+	union hdmi_infoframe *frame = fcfg->frame;
+	u8 packet_hlen = sizeof(fcfg->header);
+	u8 packet_len = (ph >> 8) & 0xff;
+	unsigned int i, j, pos = 0;
+	u8 packet[35] = {0};
+
+	dev_dbg(dw_dev->dev, "%s[%s]: packet_header=0x%x\n", __func__,
+		fcfg->desc, ph);
+
+	if (!ph) /* Fail silently if there is no packet */
+		return;
+
+	if ((packet_len + packet_hlen + 1) > sizeof(packet)) {
+		dev_dbg(dw_dev->dev, "%s: invalid length\n", __func__);
+		goto out;
+	}
+
+	memcpy(packet, fcfg->header, packet_hlen);
+	packet[2] = packet_len; /* Replace fake header size by real header */
+	pos += packet_hlen + 1;
+
+	for (i = 0; i < fcfg->payload_len; i++) {
+		j = 0;
+
+		/* specific for audio */
+		if (fcfg->header[0] == HDMI_INFOFRAME_TYPE_AUDIO && i == 1) {
+			pb = hdmi_readl(dw_dev, fcfg->payload_addr + 4 * i);
+			packet[pos++] = (pb |
+			    ((pb & DW_HDMI_LFE_PLAYBACK_LEVEL_MASK)
+			    >> DW_HDMI_LFE_PLAYBACK_LEVEL_OFFSET)) &
+			    0xff;
+			break;
+		}
+
+		/* the registers are aligned with the standard raw packet */
+		pb = hdmi_readl(dw_dev, fcfg->payload_addr + 4 * i);
+		for (; j < 4; j++) {
+			if (pos >= (packet_len + packet_hlen + 1))
+				break;
+			packet[pos++] = (pb >> (8 * j)) & 0xff;
+		}
+	}
+
+	packet[3] = dw_hdmi_infoframe_checksum(packet, packet_len +
+			packet_hlen + 1);
+
+	/*print all packet bytes */
+	for (j = 0; j < pos; j++) {
+		dev_dbg(dw_dev->dev, "%s[%s]: packet=0x%x\n", __func__,
+			fcfg->desc, packet[j]);
+	}
+
+	if (hdmi_infoframe_unpack(frame, packet, sizeof(packet))) {
+		dev_dbg(dw_dev->dev, "%s[%s]: failed to unpack\n",
+			__func__, fcfg->desc);
+		goto out;
+	}
+
+	return;
+out:
+	dev_err(dw_dev->dev, "[INVALID INFOFRAME]\n");
+}
+
+static void dw_hdmi_get_raw_infoframe_vs(struct dw_hdmi_dev *dw_dev,
+					 struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	u32 pb, ph = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+				     DW_HDMI_LENGTH_OFFSET,
+				     DW_HDMI_LENGTH_MASK);
+	union hdmi_infoframe *frame = fcfg->frame;
+	u8 packet_hlen = sizeof(fcfg->header);
+	unsigned int j, pos = 0;
+	u8 packet[35] = {0};
+	u8 packet_len = ph;
+
+	dev_dbg(dw_dev->dev, "%s[%s]: packet_header=0x%x\n", __func__,
+		fcfg->desc, ph);
+
+	if (!ph) /* Fail silently if there is no packet */
+		return;
+
+	if ((packet_len + packet_hlen + 1) > sizeof(packet)) {
+		dev_dbg(dw_dev->dev, "%s: invalid length\n", __func__);
+		goto out;
+	}
+
+	memcpy(packet, fcfg->header, packet_hlen);
+	packet[2] = packet_len; /* Replace fake header size by real header */
+	pos += packet_hlen + 1;
+
+	/* 24bit IEEE Registration identifier */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST0,
+			     DW_HDMI_IEEE_REG_ID_OFFSET,
+			     DW_HDMI_IEEE_REG_ID_MASK);
+	for (j = 0; j < 3; j++) {
+		if (pos >= (packet_len + packet_hlen + 1))
+			break;
+		packet[pos++] = (pb >> (8 * j)) & 0xff;
+	}
+
+	/* HDMI video format */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_HDMI_VIDEO_FORMAT_OFFSET,
+			     DW_HDMI_HDMI_VIDEO_FORMAT_MASK);
+	packet[pos++] = (pb << DW_HDMI_HDMI_VIDEO_FORMAT_OFFSET) &
+			0xff;
+
+	/* HDMI vic */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_HDMI_VIC_OFFSET,
+			     DW_HDMI_HDMI_VIC_MASK);
+	packet[pos++] = pb & 0xff;
+
+	/* 3d structure */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_H3D_STRUCTURE_OFFSET,
+			     DW_HDMI_H3D_STRUCTURE_MASK);
+	packet[pos++] = (pb << 4) & 0xff;
+
+	/* 3d ext data */
+	pb = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_ST1,
+			     DW_HDMI_H3D_EXT_DATA_OFFSET,
+			     DW_HDMI_H3D_EXT_DATA_MASK);
+	packet[pos++] = (pb << 4) & 0xff;
+
+	packet[3] = dw_hdmi_infoframe_checksum(packet, packet_len +
+			packet_hlen + 1);
+
+	/*print all packet bytes */
+	for (j = 0; j < pos; j++) {
+		dev_dbg(dw_dev->dev, "%s[%s]: packet=0x%x\n", __func__,
+			fcfg->desc, packet[j]);
+	}
+
+	if (hdmi_infoframe_unpack(frame, packet, sizeof(packet))) {
+		dev_dbg(dw_dev->dev, "%s[%s]: failed to unpack\n",
+			__func__, fcfg->desc);
+		goto out;
+	}
+
+	return;
+out:
+	dev_err(dw_dev->dev, "[INVALID INFOFRAME]\n");
+}
+
+static void dw_hdmi_get_raw_infoframe(struct dw_hdmi_dev *dw_dev,
+				      struct dw_hdmi_infoframe_cfg *fcfg)
+{
+	switch (fcfg->header[0]) {
+	case HDMI_INFOFRAME_TYPE_AVI:
+		dw_hdmi_get_raw_infoframe_avi(dw_dev, fcfg);
+		break;
+	case HDMI_INFOFRAME_TYPE_SPD:
+		dev_dbg(dw_dev->dev,
+			"%s[%s]: not processed infoframe packet type %d\n",
+			__func__, fcfg->desc, fcfg->header[0]);
+		break;
+	case HDMI_INFOFRAME_TYPE_AUDIO:
+		dw_hdmi_get_raw_infoframe_aud(dw_dev, fcfg);
+		break;
+	case HDMI_INFOFRAME_TYPE_VENDOR:
+		dw_hdmi_get_raw_infoframe_vs(dw_dev, fcfg);
+		break;
+	case HDMI_INFOFRAME_TYPE_DRM:
+		dev_dbg(dw_dev->dev,
+			"%s[%s]: not processed infoframe packet type %d\n",
+			__func__, fcfg->desc, fcfg->header[0]);
+		break;
+	default:
+		dev_dbg(dw_dev->dev,
+			"%s[%s]: invalid infoframe packet type %d\n",
+			__func__, fcfg->desc, fcfg->header[0]);
+		break;
+	}
+}
+
+/* Forward declaration needed because of color encoding change */
+static void dw_hdmi_power_off(struct dw_hdmi_dev *dw_dev);
+static void dw_hdmi_controller_power_off(struct dw_hdmi_dev *dw_dev);
+static int dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, unsigned int input);
+
+static void dw_hdmi_get_infoframes(struct dw_hdmi_dev *dw_dev)
+{
+	struct dw_hdmi_infoframe_cfg ifs[] = {
+		{
+			.desc = "AVI",
+			.header = {HDMI_INFOFRAME_TYPE_AVI, 2,
+				   HDMI_AVI_INFOFRAME_SIZE},
+			.header_addr = DW_HDMI_PDEC_AVI_HB,
+			.payload_addr = DW_HDMI_PDEC_AVI_PB,
+			.payload_len = DW_HDMI_PDEC_AVI_PBLEN,
+			.frame = &dw_dev->aviif,
+			.frame_size = sizeof(dw_dev->aviif),
+		}, {
+			.desc = "Audio",
+			.header = {HDMI_INFOFRAME_TYPE_AUDIO, 1,
+				   HDMI_AUDIO_INFOFRAME_SIZE},
+			.header_addr = DW_HDMI_PDEC_AIF_HB,
+			.payload_addr = DW_HDMI_PDEC_AIF_PB0,
+			.payload_len = DW_HDMI_PDEC_AIF_PBLEN,
+			.frame = &dw_dev->audioif,
+			.frame_size = sizeof(dw_dev->audioif),
+		}, {
+			.desc = "Vendor Specific",
+			.header = {HDMI_INFOFRAME_TYPE_VENDOR, 1,
+				   HDMI_VENDOR_INFOFRAME_SIZE},
+			.frame = &dw_dev->vsif,
+			.frame_size = sizeof(dw_dev->vsif),
+		},
+	};
+	union hdmi_vendor_any_infoframe *vendor;
+	struct hdmi_avi_infoframe *avi;
+	unsigned int i;
+	u32 old_mbus;
+
+	for (i = 0; i < ARRAY_SIZE(ifs); i++) {
+		memset(ifs[i].frame, 0, ifs[i].frame_size);
+		dw_hdmi_get_raw_infoframe(dw_dev, &ifs[i]);
+	}
+
+	/* Update color space */
+	old_mbus = dw_dev->mbus_code;
+	dw_dev->mbus_code = dw_hdmi_get_mbus_code(dw_dev);
+	if (dw_dev->mbus_code != old_mbus && is_on(dw_dev)) {
+		dw_hdmi_power_off(dw_dev);
+		if (has_signal(dw_dev, dw_dev->configured_input))
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+	}
+
+	/* Update AVMute value */
+	dw_hdmi_update_avmute(dw_dev, dw_dev->mbus_code);
+
+	vendor = &dw_dev->vsif.vendor;
+	avi = &dw_dev->aviif.avi;
+
+	/*
+	 * Update current VIC: When transmitting any extended video format
+	 * indicated through use of the HDMI_VIC field in the HDMI Vendor
+	 * Specific InfoFrame or any other format which is not described in
+	 * the above cases, an HDMI Source shall set the AVI InfoFrame VIC
+	 * field to zero.
+	 */
+	if (vendor->hdmi.vic && !avi->video_code) {
+		dw_dev->current_vic = vendor->hdmi.vic;
+		dw_dev->current_vic_is_4k = true;
+	} else {
+		dw_dev->current_vic = avi->video_code;
+		dw_dev->current_vic_is_4k = false;
+	}
+}
+
+static int dw_hdmi_wait_phy_lock_poll(struct dw_hdmi_dev *dw_dev)
+{
+	int timeout = dw_dev->tmds_valid_wait_count;
+
+	while (!dw_hdmi_tmds_valid(dw_dev) && timeout-- && !dw_dev->force_off)
+		usleep_range(5000, 10000);
+
+	if (!dw_hdmi_tmds_valid(dw_dev))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static void dw_hdmi_reset_datapath(struct dw_hdmi_dev *dw_dev)
+{
+	u32 val = DW_HDMI_TMDS_SWRESET |
+		DW_HDMI_HDCP_SWRESET |
+		DW_HDMI_VID_SWRESET |
+		DW_HDMI_PIXEL_SWRESET |
+		DW_HDMI_CEC_SWRESET |
+		DW_HDMI_AUD_SWRESET |
+		DW_HDMI_BUS_SWRESET |
+		DW_HDMI_HDMI_SWRESET |
+		DW_HDMI_MODET_SWRESET;
+
+	hdmi_writel(dw_dev, val & dw_dev->reset_datapath_enable,
+		    DW_HDMI_DMI_SW_RST);
+}
+
+static void dw_hdmi_reset_audio(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_writel(dw_dev, DW_HDMI_AUD_SWRESET, DW_HDMI_DMI_SW_RST);
+}
+
+static void dw_hdmi_restart_audio_fifo(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_AUD_FIFO_CTRL,
+			 DW_HDMI_AFIF_INIT_OFFSET,
+			 DW_HDMI_AFIF_INIT_MASK);
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_AUD_FIFO_CTRL,
+			 DW_HDMI_AFIF_INIT_OFFSET,
+			 DW_HDMI_AFIF_INIT_MASK);
+}
+
+static int dw_hdmi_wait_audio_lock_poll(struct dw_hdmi_dev *dw_dev)
+{
+	int timeout = 10;
+
+	while (!dw_hdmi_audio_valid(dw_dev) && timeout-- && !dw_dev->force_off)
+		usleep_range(5000, 10000);
+
+	if (!dw_hdmi_audio_valid(dw_dev))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int dw_hdmi_config_audio(struct dw_hdmi_dev *dw_dev)
+{
+	int ret;
+
+	ret = dw_hdmi_wait_audio_lock_poll(dw_dev);
+	if (ret) {
+		dev_err(dw_dev->dev, "failed to wait for audio pll lock\n");
+		return ret;
+	}
+
+	/* trigger offset for N and CTS interrupts */
+	hdmi_mask_writel(dw_dev, 0x05, DW_HDMI_PDEC_ACRM_CTRL,
+			 DW_HDMI_DELTACTS_IRQTRIG_OFFSET,
+			 DW_HDMI_DELTACTS_IRQTRIG_MASK);
+
+	/* Config */
+	hdmi_mask_writel(dw_dev, 0x01, DW_HDMI_AUD_MUTE_CTRL,
+			 DW_HDMI_AUD_MUTE_SEL_OFFSET,
+			 DW_HDMI_AUD_MUTE_SEL_MASK);
+
+	/* enable all outputs and select 16-bit for I2S */
+	hdmi_writel(dw_dev, 0x00, DW_HDMI_AUD_SAO_CTRL);
+
+	/* Start */
+	dw_hdmi_restart_audio_fifo(dw_dev);
+	return 0;
+}
+
+static void dw_hdmi_config_packet(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_CTRL,
+			 DW_HDMI_PFIFO_STORE_FILTER_EN_OFFSET,
+			 DW_HDMI_PFIFO_STORE_FILTER_EN_MASK);
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_ASP_CTRL,
+			 DW_HDMI_AUTO_VMUTE_OFFSET,
+			 DW_HDMI_AUTO_VMUTE_MASK);
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_ASP_CTRL,
+			 DW_HDMI_AUTO_SPFLAT_MUTE_OFFSET,
+			 DW_HDMI_AUTO_SPFLAT_MUTE_MASK);
+
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_CTRL,
+			 DW_HDMI_PD_FIFO_CLR_OFFSET,
+			 DW_HDMI_PD_FIFO_CLR_MASK);
+}
+
+static void dw_hdmi_wait_video_stable(struct dw_hdmi_dev *dw_dev)
+{
+	/*
+	 * Empiric value. Video should be stable way longer before the
+	 * end of this sleep time. Though, we can have some video change
+	 * interrupts before the video is stable so filter them by sleeping.
+	 */
+	msleep(dw_dev->video_stable_wait_ms);
+}
+
+static void dw_hdmi_enable_ints(struct dw_hdmi_dev *dw_dev)
+{
+	u32 pdec_ints = 0;
+
+	/* video interrupts */
+	hdmi_writel(dw_dev, DW_HDMI_CLK_CHANGE_ISTS | DW_HDMI_PLL_LCK_CHG_ISTS |
+			DW_HDMI_DCM_CURRENT_MODE_CHG_ISTS, DW_HDMI_IEN_SET);
+	hdmi_writel(dw_dev, (DW_HDMI_VACT_LIN_ISTS | DW_HDMI_HACT_PIX_ISTS),
+		    DW_HDMI_MD_IEN_SET);
+
+	/* infoframes interrupts */
+	pdec_ints = (DW_HDMI_VSI_CKS_CHG_ISTS |
+		     DW_HDMI_DRM_CKS_CHG_ISTS |
+		     DW_HDMI_AVI_CKS_CHG_ISTS);
+
+	/* audio interrupts */
+	pdec_ints |= (DW_HDMI_AUD_TYPE_CHG_ISTS |
+		      DW_HDMI_AIF_CKS_CHG_ISTS |
+		      DW_HDMI_ACR_N_CHG_ISTS |
+		      DW_HDMI_ACR_CTS_CHG_ISTS |
+		      DW_HDMI_GCP_AV_MUTE_CHG_ISTS);
+
+	hdmi_writel(dw_dev, pdec_ints, DW_HDMI_PDEC_IEN_SET);
+	hdmi_writel(dw_dev, (DW_HDMI_AFIF_OVERFL_ISTS |
+			DW_HDMI_AFIF_UNDERFL_ISTS |
+			DW_HDMI_AFIF_THS_PASS_ISTS),
+		    DW_HDMI_AUD_FIFO_IEN_SET);
+}
+
+static void dw_hdmi_disable_ints(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_IEN_CLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_MD_IEN_CLR);
+
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_PDEC_IEN_CLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_AUD_FIFO_IEN_CLR);
+}
+
+static void dw_hdmi_clear_ints(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_ICLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_MD_ICLR);
+
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_PDEC_ICLR);
+	hdmi_writel(dw_dev, ~0x0, DW_HDMI_AUD_FIFO_ICLR);
+}
+
+static u32 dw_hdmi_get_int_val(struct dw_hdmi_dev *dw_dev, u32 ists, u32 ien)
+{
+	return hdmi_readl(dw_dev, ists) & hdmi_readl(dw_dev, ien);
+}
+
+static u8 dw_hdmi_get_curr_vic(struct dw_hdmi_dev *dw_dev, bool *is_hdmi_vic)
+{
+	u8 vic = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_AVI_PB,
+				 DW_HDMI_VID_IDENT_CODE_OFFSET,
+				 DW_HDMI_VID_IDENT_CODE_MASK);
+
+	if (!vic) {
+		vic = hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_VSI_PAYLOAD0,
+				      DW_HDMI_VSI_PAYLOAD1_HDMI_VIC_OFFSET,
+				      DW_HDMI_VSI_PAYLOAD1_HDMI_VIC_MASK);
+		if (is_hdmi_vic)
+			*is_hdmi_vic = true;
+	} else {
+		if (is_hdmi_vic)
+			*is_hdmi_vic = false;
+	}
+
+	return vic;
+}
+
+static u32 dw_hdmi_get_evaltime(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_CKM_EVLTM,
+			       DW_HDMI_EVAL_TIME_OFFSET,
+			       DW_HDMI_EVAL_TIME_MASK);
+}
+
+static u32 dw_hdmi_get_clkrate(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_CKM_RESULT,
+			       DW_HDMI_CLKRATE_OFFSET,
+			       DW_HDMI_CLKRATE_MASK);
+}
+
+static u32 dw_hdmi_get_cts(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_ACR_CTS,
+			       DW_HDMI_CTS_DECODED_OFFSET,
+			       DW_HDMI_CTS_DECODED_MASK);
+}
+
+static u32 dw_hdmi_get_n(struct dw_hdmi_dev *dw_dev)
+{
+	return hdmi_mask_readl(dw_dev, DW_HDMI_PDEC_ACR_N,
+			       DW_HDMI_N_DECODED_OFFSET,
+			       DW_HDMI_N_DECODED_MASK);
+}
+
+static u32 dw_hdmi_get_tmds_clk(struct dw_hdmi_dev *dw_dev)
+{
+	u32 rate = dw_hdmi_get_clkrate(dw_dev);
+	u64 tmp = (u64)rate * (u64)dw_dev->config->iref_clk * 1000000;
+	u32 evaltime = dw_hdmi_get_evaltime(dw_dev);
+
+	do_div(tmp, evaltime);
+	return tmp;
+}
+
+static u32 dw_hdmi_get_colordepth(struct dw_hdmi_dev *dw_dev)
+{
+	u32 dcm = hdmi_mask_readl(dw_dev, DW_HDMI_STS,
+				  DW_HDMI_DCM_CURRENT_MODE_OFFSET,
+				  DW_HDMI_DCM_CURRENT_MODE_MASK);
+
+	switch (dcm) {
+	case 0x4:
+		return 24;
+	case 0x5:
+		return 30;
+	case 0x6:
+		return 36;
+	case 0x7:
+		return 48;
+	default:
+		return 24;
+	}
+}
+
+static u64 dw_hdmi_get_pixelclk(struct dw_hdmi_dev *dw_dev)
+{
+	u32 tmds_clk = dw_hdmi_get_tmds_clk(dw_dev);
+	u32 cd = dw_hdmi_get_colordepth(dw_dev);
+	u32 pix_clk = 0;
+
+	switch (cd) {
+	case 24:
+		pix_clk = tmds_clk;
+		break;
+	case 30:
+		pix_clk = (tmds_clk * 100) / 125;
+		break;
+	case 36:
+		pix_clk = (tmds_clk * 10) / 15;
+		break;
+	case 48:
+		pix_clk = tmds_clk / 2;
+		break;
+	default:
+		break;
+	}
+
+	return pix_clk;
+}
+
+static void dw_hdmi_set_input(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	hdmi_mask_writel(dw_dev, input, DW_HDMI_PHY_CTRL,
+			 DW_HDMI_PORTSELECT_OFFSET,
+			 DW_HDMI_PORTSELECT_MASK);
+	dw_dev->configured_input = input;
+	dw_dev->selected_input = input;
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_INPUT_CHANGED,
+			   &dw_dev->configured_input);
+}
+
+static void dw_hdmi_enable_hpd(struct dw_hdmi_dev *dw_dev, u32 input_mask)
+{
+	hdmi_mask_writel(dw_dev, input_mask, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_MASK);
+}
+
+static void dw_hdmi_disable_hpd(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_INPUT_X_MASK);
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_SETUP_CTRL,
+			 DW_HDMI_HOT_PLUG_DETECT_OFFSET,
+			 DW_HDMI_HOT_PLUG_DETECT_MASK);
+}
+
+static void dw_hdmi_enable_scdc(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_SCDC_CONFIG,
+			 DW_HDMI_POWERPROVIDED_OFFSET,
+			 DW_HDMI_POWERPROVIDED_MASK);
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_IEN_SET,
+			 DW_HDMI_SCDCTMDSCFGCHANGE_ISTS_OFFSET,
+			 DW_HDMI_SCDCTMDSCFGCHANGE_ISTS_MASK);
+}
+
+static void dw_hdmi_disable_scdc(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_SCDC_CONFIG,
+			 DW_HDMI_POWERPROVIDED_OFFSET,
+			 DW_HDMI_POWERPROVIDED_MASK);
+}
+
+static void dw_hdmi_handle_audio_mute_change(struct dw_hdmi_dev *dw_dev);
+
+static void dw_hdmi_enable_hdmi_domain(struct dw_hdmi_dev *dw_dev, bool enable)
+{
+	hdmi_mask_writel(dw_dev, enable, DW_HDMI_DMI_DISABLE_IF,
+			 DW_HDMI_HDMI_ENABLE_OFFSET,
+			 DW_HDMI_HDMI_ENABLE_MASK);
+}
+
+static int dw_hdmi_initial_config(struct dw_hdmi_dev *dw_dev, u32 input);
+
+static int dw_hdmi_config(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	u32 in_state = dw_dev->state;
+	u32 cd1 = 0, cd2 = 0;
+	int eqret, ret = 0;
+
+	while (1) {
+		/* Give up silently if we are forcing off */
+		if (dw_dev->force_off) {
+			ret = 0;
+			goto out;
+		}
+		/* Give up silently if input has disconnected */
+		if (!has_signal(dw_dev, input)) {
+			ret = 0;
+			goto out;
+		}
+
+		switch (dw_dev->state) {
+		case HDMI_STATE_POWER_OFF:
+			dw_hdmi_disable_ints(dw_dev);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_PHY_CONFIG);
+			break;
+		case HDMI_STATE_POWER_UP:
+			/* when connect the cable */
+			dw_hdmi_disable_ints(dw_dev);
+			/* reset */
+			if (dw_dev->hw_reset_on_hot_plug)
+				dw_hdmi_reset(dw_dev);
+			/* initial configuration */
+			dw_hdmi_initial_config(dw_dev, input);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_PHY_CONFIG);
+			break;
+		case HDMI_STATE_PHY_CONFIG:
+			cd1 = 24;
+			dw_dev->is_hdmi2 = is_hdmi2(dw_dev);
+			dw_dev->is_scrambled = is_scrambled(dw_dev);
+			dw_hdmi_phy_config(dw_dev, cd1, dw_dev->is_hdmi2,
+					   dw_dev->is_scrambled);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_HPD);
+			break;
+		case HDMI_STATE_HPD:
+			/* disable HDMI domain to avoid the DCM INTs */
+			dw_hdmi_enable_hdmi_domain(dw_dev, false);
+			dw_hdmi_enable_scdc(dw_dev);
+			dw_hdmi_enable_hpd(dw_dev, dw_dev->input_stat);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_EQUALIZER);
+			break;
+		case HDMI_STATE_EQUALIZER:
+			if (dw_dev->phy_eq_on) {
+				bool phy_eq_force = dw_dev->phy_eq_force;
+
+				eqret = dw_hdmi_phy_eq_init(dw_dev, 5,
+							    phy_eq_force);
+			} else {
+				/* Clear equalizer error status if not on */
+				eqret = 0;
+			}
+
+			ret = dw_hdmi_wait_phy_lock_poll(dw_dev);
+
+			/* Do not force equalizer */
+			dw_dev->phy_eq_force = false;
+
+			if (ret || eqret) {
+				if (ret || eqret == -ETIMEDOUT) {
+					/* No TMDSVALID signal:
+					 * - force equalizer
+					 */
+					dw_dev->phy_eq_force = true;
+				}
+				break;
+			}
+
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_DATAPATH);
+			break;
+		case HDMI_STATE_DATAPATH:
+			dw_hdmi_reset_datapath(dw_dev);
+			/* reenable HDMI domain */
+			dw_hdmi_enable_hdmi_domain(dw_dev, true);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_VIDEO_UNSTABLE);
+			break;
+		case HDMI_STATE_VIDEO_UNSTABLE:
+			dw_hdmi_wait_video_stable(dw_dev);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_AUDIO);
+			break;
+		case HDMI_STATE_AUDIO:
+			ret = dw_hdmi_config_audio(dw_dev);
+			dw_hdmi_config_packet(dw_dev);
+
+			if (in_state != HDMI_STATE_EQUALIZER)
+				dw_hdmi_clear_ints(dw_dev);
+
+			dw_hdmi_get_infoframes(dw_dev);
+
+			/* check if there was deep color changes */
+			if (cd1) {
+				cd2 = dw_hdmi_get_colordepth(dw_dev);
+				if (cd1 != cd2)
+					dw_hdmi_phy_set_color_depth(dw_dev,
+								    cd2);
+			}
+
+			/* reset CEA video */
+			dw_hdmi_reset_ceavid(dw_dev);
+
+			dw_hdmi_enable_ints(dw_dev);
+			dw_hdmi_set_state(dw_dev, HDMI_STATE_POWER_ON);
+			break;
+		case HDMI_STATE_POWER_ON:
+			break;
+		default:
+			dev_err(dw_dev->dev, "%s called with state (%d)\n",
+				__func__, dw_dev->state);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (dw_dev->state == HDMI_STATE_POWER_ON) {
+			dev_info(dw_dev->dev, "HDMI-RX configured\n");
+			dw_hdmi_event_source_change(dw_dev);
+			dw_hdmi_handle_audio_mute_change(dw_dev);
+			return 0;
+		}
+	}
+
+out:
+	dw_hdmi_set_state(dw_dev, HDMI_STATE_POWER_OFF);
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_IS_OFF, NULL);
+	return ret;
+}
+
+static int __dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	unsigned long flags;
+	int ret;
+
+	ret = dw_hdmi_config(dw_dev, input);
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dw_dev->pending_config = false;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+
+	return ret;
+}
+
+static void dw_hdmi_work_handler(struct work_struct *work)
+{
+	struct dw_hdmi_dev *dw_dev = container_of(work, struct dw_hdmi_dev,
+						  work);
+
+	__dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+}
+
+static int dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	if (dw_dev->pending_config) {
+		spin_unlock_irqrestore(&dw_dev->lock, flags);
+		return 0;
+	}
+
+	INIT_WORK(&dw_dev->work, dw_hdmi_work_handler);
+	dw_dev->configured_input = input;
+	dw_dev->pending_config = true;
+	queue_work(dw_dev->wq, &dw_dev->work);
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+	return 0;
+}
+
+static void dw_hdmi_power_off(struct dw_hdmi_dev *dw_dev)
+{
+	unsigned long flags;
+
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_IS_OFF, NULL);
+
+	dw_dev->force_off = true;
+	flush_workqueue(dw_dev->wq);
+	dw_dev->force_off = false;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dw_dev->pending_config = false;
+	dw_dev->state = HDMI_STATE_POWER_OFF;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+
+	/* Reset variables */
+	dw_dev->phy_eq_force = true;
+	dw_dev->audio_sf = 0;
+}
+
+static void dw_hdmi_force_off(struct dw_hdmi_dev *dw_dev)
+{
+	unsigned long flags;
+
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_IS_OFF, NULL);
+
+	dw_dev->force_off = true;
+	flush_workqueue(dw_dev->wq);
+	dw_dev->force_off = false;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	dw_dev->pending_config = false;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+}
+
+static void dw_hdmi_power_up(struct dw_hdmi_dev *dw_dev)
+{
+	dw_hdmi_force_off(dw_dev);
+	dw_hdmi_set_state(dw_dev, HDMI_STATE_POWER_UP);
+
+	/* Reset variables */
+	dw_dev->phy_eq_force = true;
+	dw_dev->audio_sf = 0;
+}
+
+static void dw_hdmi_controller_power_off(struct dw_hdmi_dev *dw_dev)
+{
+	dw_hdmi_force_off(dw_dev);
+	dw_hdmi_set_state(dw_dev, HDMI_STATE_EQUALIZER);
+
+	dw_dev->phy_eq_force = false;
+	dw_dev->audio_sf = 0;
+}
+
+static int dw_hdmi_query_dv_timings(struct v4l2_subdev *sd,
+				    struct v4l2_dv_timings *timings);
+
+static void dw_hdmi_handle_video_change(struct dw_hdmi_dev *dw_dev)
+{
+	struct v4l2_dv_timings timings;
+
+	if (is_on(dw_dev)) {
+		dev_dbg(dw_dev->dev, "[VIDEO] video change interrupt\n");
+		dw_hdmi_query_dv_timings(&dw_dev->sd, &timings);
+		dw_hdmi_controller_power_off(dw_dev);
+		dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+	}
+}
+
+static u32 dw_hdmi_round_freq(int freq)
+{
+	static const u32 base_freqs[] = { 32000, 44100, 48000, 0 };
+	unsigned int i;
+
+	for (i = 0; base_freqs[i]; i++) {
+		if ((freq <= (base_freqs[i] + DW_HDMI_AUDIO_FREQ_RANGE)) &&
+		    (freq >= (base_freqs[i] - DW_HDMI_AUDIO_FREQ_RANGE))) {
+			return base_freqs[i];
+		}
+	}
+
+	return 0;
+}
+
+static unsigned int dw_hdmi_get_sample_freq(struct dw_hdmi_dev *dw_dev)
+{
+	u64 tmp;
+	u32 cts;
+	u32 sf;
+	u32 n;
+
+	n = dw_hdmi_get_n(dw_dev);
+	cts = dw_hdmi_get_cts(dw_dev);
+
+	if (!n || !cts) {
+		dev_dbg(dw_dev->dev, "%s: cts: %d, n: %d\n", __func__, cts, n);
+		return 0;
+	}
+
+	dev_dbg(dw_dev->dev, "%s: tmds_clk: %d\n",
+		__func__, dw_hdmi_get_tmds_clk(dw_dev));
+
+	/* regenerate the audio clock from tmds clock */
+	tmp = (u64)dw_hdmi_get_tmds_clk(dw_dev) * (u64)n;
+	do_div(tmp, cts);
+	do_div(tmp, 128);
+	sf = tmp;
+
+	dev_dbg(dw_dev->dev, "%s: sf: %d\n", __func__, sf);
+	sf = dw_hdmi_round_freq(sf);
+	dev_dbg(dw_dev->dev, "%s: sf(round): %d\n", __func__, sf);
+
+	return sf;
+}
+
+static void dw_hdmi_handle_audio_mute_change(struct dw_hdmi_dev *dw_dev)
+{
+	unsigned long flags;
+	unsigned int sf;
+
+	spin_lock_irqsave(&dw_dev->event_lock, flags);
+	sf = dw_hdmi_get_sample_freq(dw_dev);
+	v4l2_subdev_notify(&dw_dev->sd, DW_HDMI_NOTIFY_AUDIO_CHANGED, &sf);
+	dw_dev->audio_sf = sf;
+	spin_unlock_irqrestore(&dw_dev->event_lock, flags);
+}
+
+static void dw_hdmi_handle_audio_change(struct dw_hdmi_dev *dw_dev,
+					u32 afif_stat, u32 pdec_stat)
+{
+	bool restart = true;
+
+	if (pdec_stat & DW_HDMI_GCP_AV_MUTE_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] AV Mute change\n");
+		dw_hdmi_handle_audio_mute_change(dw_dev);
+		restart = false;
+	}
+
+	if (pdec_stat & DW_HDMI_AUD_TYPE_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] type change\n");
+		restart = true;
+	}
+	if (pdec_stat & DW_HDMI_AIF_CKS_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] aif change\n");
+		restart = true;
+	}
+	if (pdec_stat & DW_HDMI_ACR_N_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] N change\n");
+		restart = true;
+	}
+	if (pdec_stat & DW_HDMI_ACR_CTS_CHG_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] CTS change\n");
+		restart = true;
+	}
+	if (afif_stat & DW_HDMI_AFIF_UNDERFL_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] fifo underflow\n");
+		restart = true;
+	}
+	if (afif_stat & DW_HDMI_AFIF_OVERFL_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] fifo overflow\n");
+		restart = true;
+	}
+	if (afif_stat & DW_HDMI_AFIF_THS_PASS_ISTS) {
+		dev_dbg(dw_dev->dev, "[interrupt:audio] TRH Pass\n");
+		dw_hdmi_handle_audio_mute_change(dw_dev);
+		restart = false;
+	}
+
+	if (restart) {
+		dw_hdmi_handle_audio_mute_change(dw_dev);
+		dw_hdmi_wait_audio_lock_poll(dw_dev);
+		dw_hdmi_reset_audio(dw_dev);
+		dw_hdmi_restart_audio_fifo(dw_dev);
+	}
+}
+
+static irqreturn_t dw_hdmi_irq_handler(int irq, void *dev_data)
+{
+	struct dw_hdmi_dev *dw_dev = dev_data;
+	u32 hdmi_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_ISTS, DW_HDMI_IEN);
+	u32 md_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_MD_ISTS,
+					  DW_HDMI_MD_IEN);
+	u32 pdec_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_PDEC_ISTS,
+					    DW_HDMI_PDEC_IEN);
+	u32 afif_ists = dw_hdmi_get_int_val(dw_dev, DW_HDMI_AUD_FIFO_ISTS,
+					    DW_HDMI_AUD_FIFO_IEN);
+	u32 cd = 0;
+
+	dw_hdmi_clear_ints(dw_dev);
+
+	/* video handling */
+	if (hdmi_ists & DW_HDMI_CLK_CHANGE_ISTS) {
+		dev_dbg(dw_dev->dev, "[HDMI] clock rate change\n");
+		dw_hdmi_power_off(dw_dev);
+		if (has_signal(dw_dev, dw_dev->configured_input))
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+
+		return IRQ_HANDLED;
+	}
+	if (hdmi_ists & DW_HDMI_PLL_LCK_CHG_ISTS) {
+		dev_dbg(dw_dev->dev,
+			"[PHY] PLL lock state changed (tmds_valid: %d)\n",
+			dw_hdmi_tmds_valid(dw_dev));
+		dw_hdmi_power_off(dw_dev);
+
+		if (has_signal(dw_dev, dw_dev->configured_input))
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+
+		return IRQ_HANDLED;
+	}
+	if (hdmi_ists & DW_HDMI_DCM_CURRENT_MODE_CHG_ISTS) {
+		dev_dbg(dw_dev->dev,
+			"[HDMI] deep color changed\n");
+
+		cd = dw_hdmi_get_colordepth(dw_dev);
+		if (cd)
+			dw_hdmi_phy_set_color_depth(dw_dev, cd);
+
+		/* reset CEA video */
+		dw_hdmi_reset_ceavid(dw_dev);
+
+		return IRQ_HANDLED;
+	}
+	if (md_ists || pdec_ists &
+	    (DW_HDMI_VSI_CKS_CHG_ISTS |
+	     DW_HDMI_DRM_CKS_CHG_ISTS |
+	     DW_HDMI_AVI_CKS_CHG_ISTS)) {
+		dw_hdmi_handle_video_change(dw_dev);
+		dev_dbg(dw_dev->dev,
+			"   md_ists: 0x%x, pdec_ists: 0x%x\n",
+			md_ists, pdec_ists);
+	}
+
+	/* infoframes */
+	if (pdec_ists & DW_HDMI_AIF_CKS_CHG_ISTS)
+		dw_hdmi_get_infoframes(dw_dev);
+
+	/* audio handling */
+	if (pdec_ists & (DW_HDMI_AUD_TYPE_CHG_ISTS |
+			 DW_HDMI_AIF_CKS_CHG_ISTS |
+			 DW_HDMI_ACR_N_CHG_ISTS |
+			 DW_HDMI_ACR_CTS_CHG_ISTS |
+			 DW_HDMI_GCP_AV_MUTE_CHG_ISTS) ||
+	    afif_ists & (DW_HDMI_AFIF_UNDERFL_ISTS |
+			 DW_HDMI_AFIF_OVERFL_ISTS |
+			 DW_HDMI_AFIF_THS_PASS_ISTS)) {
+		dw_hdmi_handle_audio_change(dw_dev, afif_ists, pdec_ists);
+	}
+
+	/* scdc */
+	if (hdmi_ists & DW_HDMI_SCDCTMDSCFGCHANGE_ISTS_MASK) {
+		dev_dbg(dw_dev->dev, "[SCDC] hdmi2=%d->%d, scrambling=%d->%d\n",
+			dw_dev->is_hdmi2, is_hdmi2(dw_dev),
+			dw_dev->is_scrambled, is_scrambled(dw_dev));
+		if (dw_dev->is_hdmi2 != is_hdmi2(dw_dev) ||
+		    dw_dev->is_scrambled != is_scrambled(dw_dev)) {
+			dw_dev->is_hdmi2 = is_hdmi2(dw_dev);
+			dw_dev->is_scrambled = is_scrambled(dw_dev);
+			dw_hdmi_power_off(dw_dev);
+			dw_hdmi_power_on(dw_dev, dw_dev->configured_input);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int dw_hdmi_detect_tx_5v_ctrl(struct dw_hdmi_dev *dw_dev)
+{
+	bool current_on = dw_hdmi_5v_status(dw_dev, dw_dev->configured_input);
+	unsigned int input_count = dw_dev->config->phy->input_count;
+	unsigned int old_input = dw_dev->configured_input;
+	unsigned int new_input = old_input;
+	bool pending_config = false;
+	unsigned int stat = 0;
+	unsigned int i;
+
+	for (i = 0; i < input_count; i++) {
+		bool on = dw_hdmi_5v_status(dw_dev, i);
+
+		stat |= on << i;
+
+		if (on && on != dw_dev->input_connected[i]) {
+			dw_hdmi_disable_ints(dw_dev);
+			dw_hdmi_power_off(dw_dev);
+			dw_hdmi_power_up(dw_dev);
+			dw_dev->input_connected[i] = true;
+			dw_hdmi_power_on(dw_dev, i);
+			dw_hdmi_set_input(dw_dev, i);
+			new_input = i;
+			pending_config = true;
+		} else {
+			dw_dev->input_connected[i] = on;
+		}
+	}
+
+	dw_dev->input_stat = stat;
+
+	if (!pending_config && !current_on) {
+		dw_hdmi_disable_ints(dw_dev);
+		dw_hdmi_disable_hpd(dw_dev);
+		dw_hdmi_disable_scdc(dw_dev);
+		dw_hdmi_power_off(dw_dev);
+		if (dw_dev->phy->power_count > 0)
+			phy_power_off(dw_dev->phy);
+	}
+
+	dev_dbg(dw_dev->dev, "%s: stat=0x%x, input=%d->%d\n", __func__,
+		stat, old_input, new_input);
+	return v4l2_ctrl_s_ctrl(dw_dev->detect_tx_5v_ctrl, stat);
+}
+
+static irqreturn_t dw_hdmi_5v_irq_handler(int irq, void *dev_data)
+{
+	struct dw_hdmi_dev *dw_dev = dev_data;
+
+	dw_hdmi_detect_tx_5v_ctrl(dw_dev);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_hdmi_5v_hard_irq_handler(int irq, void *dev_data)
+{
+	struct dw_hdmi_dev *dw_dev = dev_data;
+	unsigned int input_count = dw_dev->config->phy->input_count;
+	u32 stat = 0x0;
+	unsigned int i;
+
+	/* Clear interrupts */
+	for (i = 0; i < input_count; i++) {
+		dw_hdmi_5v_disable(dw_dev, i);
+		dw_hdmi_5v_enable(dw_dev, i);
+		stat |= dw_hdmi_5v_status(dw_dev, i) << i;
+	}
+
+	if (!stat) {
+		/*
+		 * If there are no connected ports disable whole HPD and SCDC
+		 * also.
+		 */
+		dw_hdmi_disable_hpd(dw_dev);
+		dw_hdmi_disable_scdc(dw_dev);
+	}
+
+	return IRQ_WAKE_THREAD;
+}
+
+static int dw_hdmi_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+			     u32 config)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	int ret;
+
+	if (!has_signal(dw_dev, input))
+		return -EINVAL;
+
+	dw_dev->selected_input = input;
+	if (input == dw_dev->configured_input)
+		return 0;
+
+	dw_hdmi_power_off(dw_dev);
+	ret = dw_hdmi_power_on(dw_dev, input);
+	dw_hdmi_set_input(dw_dev, input);
+	return ret;
+}
+
+static int dw_hdmi_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	*status = 0;
+	if (!has_signal(dw_dev, dw_dev->selected_input))
+		*status |= V4L2_IN_ST_NO_POWER;
+	if (!is_on(dw_dev))
+		*status |= V4L2_IN_ST_NO_SIGNAL;
+
+	dev_dbg(dw_dev->dev, "%s: status=0x%x\n", __func__, *status);
+	return 0;
+}
+
+static int dw_hdmi_g_frame_interval(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_frame_interval *ival)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	u32 htot, vtot, fps;
+	unsigned long n, d;
+	u64 pclk;
+
+	htot = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT1,
+			       DW_HDMI_HTOT_PIX_OFFSET,
+			       DW_HDMI_HTOT_PIX_MASK);
+	vtot = hdmi_readl(dw_dev, DW_HDMI_MD_VTL);
+	pclk = dw_hdmi_get_pixelclk(dw_dev);
+
+	fps = (htot * vtot) > 0 ? div_u64((100 * pclk), (htot * vtot)) : 0;
+	if (!fps)
+		return 0;
+
+	rational_best_approximation(fps, 100, fps, 100, &n, &d);
+
+	ival->interval.numerator = d;
+	ival->interval.denominator = n;
+
+	dev_dbg(dw_dev->dev, "%s: %lu / %lu\n", __func__, d, n);
+
+	return 0;
+}
+
+static int dw_hdmi_s_dv_timings(struct v4l2_subdev *sd,
+				struct v4l2_dv_timings *timings)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	if (!v4l2_valid_dv_timings(timings, &dw_hdmi_timings_cap, NULL, NULL))
+		return -EINVAL;
+	if (v4l2_match_dv_timings(timings, &dw_dev->timings, 0, false))
+		return 0;
+
+	dw_dev->timings = *timings;
+	return 0;
+}
+
+static int dw_hdmi_g_dv_timings(struct v4l2_subdev *sd,
+				struct v4l2_dv_timings *timings)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	*timings = dw_dev->timings;
+	return 0;
+}
+
+static u32 dw_hdmi_get_width(struct dw_hdmi_dev *dw_dev)
+{
+	u32 width = hdmi_readl(dw_dev, DW_HDMI_MD_HACT_PX);
+	u32 cd = dw_hdmi_get_colordepth(dw_dev);
+
+	switch (cd) {
+	case 30:
+		width = (width * 100) / 125;
+		break;
+	case 36:
+		width = (width * 10) / 15;
+		break;
+	case 48:
+		width /= 2;
+		break;
+	case 24:
+	default:
+		break;
+	}
+
+	if (dw_hdmi_get_mbus_code(dw_dev) == MEDIA_BUS_FMT_YVYU8_1X16)
+		width *= 2;
+
+	return width;
+}
+
+static int dw_hdmi_query_dv_timings(struct v4l2_subdev *sd,
+				    struct v4l2_dv_timings *timings)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	struct v4l2_bt_timings *bt = &timings->bt;
+	bool is_hdmi_vic;
+	u32 htot, hofs;
+	u32 vtot;
+	u8 vic;
+
+	memset(timings, 0, sizeof(*timings));
+
+	if (is_off(dw_dev)) {
+		dev_dbg(dw_dev->dev, "%s: controller is off\n", __func__);
+		return -ENOLINK;
+	}
+
+	if (!is_on(dw_dev)) {
+		dev_dbg(dw_dev->dev, "%s: controller is being configured\n",
+			__func__);
+		return -EAGAIN;
+	}
+
+	timings->type = V4L2_DV_BT_656_1120;
+	bt->width = dw_hdmi_get_width(dw_dev);
+	bt->height = hdmi_readl(dw_dev, DW_HDMI_MD_VAL);
+	bt->interlaced =
+		hdmi_readl(dw_dev, DW_HDMI_MD_STS) & DW_HDMI_ILACE_STS ?
+			V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (hdmi_readl(dw_dev, DW_HDMI_ISTS) & DW_HDMI_VS_POL_ADJ_ISTS)
+		bt->polarities |= V4L2_DV_VSYNC_POS_POL;
+	if (hdmi_readl(dw_dev, DW_HDMI_ISTS) & DW_HDMI_HS_POL_ADJ_ISTS)
+		bt->polarities |= V4L2_DV_HSYNC_POS_POL;
+
+	bt->pixelclock = dw_hdmi_get_pixelclk(dw_dev);
+
+	/* HTOT = HACT + HFRONT + HSYNC + HBACK */
+	htot = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT1,
+			       DW_HDMI_HTOT_PIX_OFFSET,
+			       DW_HDMI_HTOT_PIX_MASK);
+	/* HOFS = HSYNC + HBACK */
+	hofs = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT1,
+			       DW_HDMI_HOFS_PIX_OFFSET,
+			       DW_HDMI_HOFS_PIX_MASK);
+
+	bt->hfrontporch = htot - hofs - bt->width;
+	bt->hsync = hdmi_mask_readl(dw_dev, DW_HDMI_MD_HT0,
+				    DW_HDMI_HS_CLK_OFFSET,
+				    DW_HDMI_HS_CLK_MASK);
+	bt->hbackporch = hofs - bt->hsync;
+
+	/* VTOT = VACT + VFRONT + VSYNC + VBACK */
+	vtot = hdmi_readl(dw_dev, DW_HDMI_MD_VTL);
+
+	bt->vsync = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+
+	bt->vbackporch = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+	bt->vfrontporch = vtot - bt->height - bt->vsync - bt->vbackporch;
+
+	if (bt->interlaced == V4L2_DV_INTERLACED) {
+		hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_MODE_OFFSET,
+				 DW_HDMI_V_MODE_MASK);
+		msleep(100); /* Wait for 2 fields */
+
+		vtot = hdmi_readl(dw_dev, DW_HDMI_MD_VTL);
+		hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_OFFS_LIN_MODE_OFFSET,
+				 DW_HDMI_V_OFFS_LIN_MODE_MASK);
+		msleep(50); /* Wait for 1 field */
+		bt->il_vsync = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+
+		hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_OFFS_LIN_MODE_OFFSET,
+				 DW_HDMI_V_OFFS_LIN_MODE_MASK);
+		msleep(50);
+		bt->il_vbackporch = hdmi_readl(dw_dev, DW_HDMI_MD_VOL);
+		bt->il_vfrontporch = vtot - bt->height - bt->il_vsync -
+			bt->il_vbackporch;
+
+		hdmi_mask_writel(dw_dev, 0x0, DW_HDMI_MD_VCTRL,
+				 DW_HDMI_V_MODE_OFFSET,
+				 DW_HDMI_V_MODE_MASK);
+	}
+
+	bt->standards = V4L2_DV_BT_STD_CEA861;
+
+	vic = dw_hdmi_get_curr_vic(dw_dev, &is_hdmi_vic);
+	if (vic) {
+		if (is_hdmi_vic) {
+			bt->flags |= V4L2_DV_FL_HAS_HDMI_VIC;
+			bt->hdmi_vic = vic;
+			bt->cea861_vic = 0;
+		} else {
+			bt->flags |= V4L2_DV_FL_HAS_CEA861_VIC;
+			bt->hdmi_vic = 0;
+			bt->cea861_vic = vic;
+		}
+	}
+
+	dev_dbg(dw_dev->dev, "%s: width=%u, height=%u, mbuscode=%u\n", __func__,
+		bt->width, bt->height, dw_hdmi_get_mbus_code(dw_dev));
+
+	return 0;
+}
+
+static int dw_hdmi_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	if (code->index != 0)
+		return -EINVAL;
+
+	code->code = dw_dev->mbus_code;
+	return 0;
+}
+
+static int dw_hdmi_fill_format(struct dw_hdmi_dev *dw_dev,
+			       struct v4l2_mbus_framefmt *format)
+{
+	enum hdmi_extended_colorimetry extcol;
+	enum hdmi_colorimetry col;
+	int ret;
+
+	memset(format, 0, sizeof(*format));
+
+	/* Update timings */
+	ret = dw_hdmi_query_dv_timings(&dw_dev->sd, &dw_dev->timings);
+	if (ret)
+		return ret;
+
+	/* Update infoframe contents */
+	dw_hdmi_get_infoframes(dw_dev);
+
+	col = dw_dev->aviif.avi.colorimetry;
+	extcol = dw_dev->aviif.avi.extended_colorimetry;
+
+	switch (col) {
+	case HDMI_COLORIMETRY_ITU_601:
+		format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+		break;
+	case HDMI_COLORIMETRY_EXTENDED:
+		switch (extcol) {
+		case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
+			format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+			break;
+		case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
+		case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
+		case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
+		case HDMI_EXTENDED_COLORIMETRY_OPRGB:
+		case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
+		case HDMI_EXTENDED_COLORIMETRY_BT2020:
+		case HDMI_EXTENDED_COLORIMETRY_RESERVED:
+		default:
+			format->colorspace = V4L2_COLORSPACE_REC709;
+			break;
+		}
+
+		break;
+	case HDMI_COLORIMETRY_NONE:
+	case HDMI_COLORIMETRY_ITU_709:
+	default:
+		format->colorspace = V4L2_COLORSPACE_REC709;
+		break;
+	}
+
+	format->width = dw_dev->timings.bt.width;
+	format->height = dw_dev->timings.bt.height;
+	format->code = dw_dev->mbus_code;
+	if (dw_dev->timings.bt.interlaced)
+		format->field = V4L2_FIELD_ALTERNATE;
+	else
+		format->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int dw_hdmi_get_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *format)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	return dw_hdmi_fill_format(dw_dev, &format->format);
+}
+
+static int dw_hdmi_set_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *format)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	if (format->format.code != dw_dev->mbus_code) {
+		dev_dbg(dw_dev->dev, "invalid format\n");
+		return -EINVAL;
+	}
+
+	return dw_hdmi_get_fmt(sd, cfg, format);
+}
+
+static int dw_hdmi_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	unsigned int input_count = dw_dev->config->phy->input_count;
+	unsigned int i, j, start, end;
+	u8 *ptr = edid->edid;
+	u8 blocks;
+
+	memset(edid->reserved, 0, sizeof(edid->reserved));
+
+	if (edid->pad >= input_count || !ptr)
+		return -EINVAL;
+
+	blocks = dw_dev->curr_edid_blocks[edid->pad];
+
+	if (!edid->start_block && !edid->blocks) {
+		edid->blocks = blocks;
+		return 0;
+	}
+	if (!blocks)
+		return -ENODATA;
+	if (edid->start_block >= blocks)
+		return -EINVAL;
+	if ((edid->start_block + edid->blocks) > blocks)
+		edid->blocks = blocks - edid->start_block;
+
+	start = (edid->start_block * 128) / sizeof(u32);
+	end = start + (edid->blocks * 128) / sizeof(u32);
+
+	for (i = start; i < end; i++) {
+		u32 raw = dw_hdmi_edid_read(dw_dev, edid->pad, i * sizeof(u32));
+
+		if (!dw_hdmi_edid_4blocks_le(dw_dev)) {
+			u32 raw_srt = 0;
+			/* little endian representation, need to invert */
+			for (j = 0; j < 4; j++) {
+				raw_srt |= ((raw >> (8 * (3 - j))) & 0xff)
+					<< (j * 8);
+			}
+			raw = raw_srt;
+		}
+		memcpy(ptr, &raw, sizeof(u32));
+		ptr += sizeof(u32);
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	int input_count = dw_dev->config->phy->input_count;
+	int size, ret;
+	u32 *tmp;
+
+	memset(edid->reserved, 0, sizeof(edid->reserved));
+
+	if (edid->pad >= input_count || !edid->edid || !edid->blocks)
+		return -EINVAL;
+	if (edid->start_block != 0)
+		return -EINVAL;
+
+	/* Clear old EDID */
+	size = dw_dev->curr_edid_blocks[edid->pad] * 128;
+	tmp = devm_kzalloc(dw_dev->dev, size, GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	ret = dw_hdmi_edid_write(dw_dev, edid->pad, tmp, size / sizeof(u32));
+	devm_kfree(dw_dev->dev, tmp);
+
+	if (ret)
+		return ret;
+
+	dw_dev->curr_edid_blocks[edid->pad] = 0;
+
+	/* Set new EDID */
+	if (dw_hdmi_edid_4blocks_le(dw_dev)) {
+		/* little endian representation, no need to invert bytes */
+		ret = dw_hdmi_update_edid(dw_dev, edid->pad, (u8 *)edid->edid,
+					  (edid->blocks * 128), false);
+	} else {
+		/* invert the order of bytes to register 32bit */
+		ret = dw_hdmi_update_edid(dw_dev, edid->pad, (u8 *)edid->edid,
+					  (edid->blocks * 128), true);
+	}
Quoted 9 lines

drivers/media/platform/dwc/dw-hdmi-rx.c line 2545

Quoted 4 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +4 -0
+	if (ret)
+		return ret;
+
+	dw_dev->curr_edid_blocks[edid->pad] = edid->blocks;

I don't see any checks on edid->blocks: that can't be right. The typical max number of blocks for an EDID is 2 or 4, I haven't seen any implementations for more than 4 blocks.

I agree! This will be addressed in the next patch series.

Quoted 4 lines

I also don't see any signaling of the HPD: it must be pulled low before you start writing the EDID, and pulled high again at least 100ms later (150 ms or so is recommended to keep a margin).

I agree! This will be addressed in the next patch series.

Quoted 537 lines
Quoted 537 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +537 -0
+	return 0;
+}
+
+static int dw_hdmi_dv_timings_cap(struct v4l2_subdev *sd,
+				  struct v4l2_dv_timings_cap *cap)
+{
+	unsigned int pad = cap->pad;
+
+	*cap = dw_hdmi_timings_cap;
+	cap->pad = pad;
+	return 0;
+}
+
+static int dw_hdmi_enum_dv_timings(struct v4l2_subdev *sd,
+				   struct v4l2_enum_dv_timings *timings)
+{
+	return v4l2_enum_dv_timings_cap(timings, &dw_hdmi_timings_cap,
+					NULL, NULL);
+}
+
+static int dw_hdmi_log_status(struct v4l2_subdev *sd)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+	struct v4l2_dv_timings timings;
+
+	v4l2_info(sd, "--- Chip configuration ---\n");
+	v4l2_info(sd, "iref_clk=%dMHz\n", dw_dev->config->iref_clk);
+	v4l2_info(sd, "phy_drv=%s, phy_jtag_addr=0x%x\n",
+		  dw_dev->phy ? "present" : "not present",
+		  dw_dev->config->phy->jtag_addr);
+
+	v4l2_info(sd, "--- Chip status ---\n");
+	v4l2_info(sd, "selected_input=%d: signal=%d\n", dw_dev->selected_input,
+		  has_signal(dw_dev, dw_dev->selected_input));
+	v4l2_info(sd, "configured_input=%d: signal=%d\n",
+		  dw_dev->configured_input,
+		  has_signal(dw_dev, dw_dev->configured_input));
+
+	v4l2_info(sd, "--- Video status ---\n");
+	v4l2_info(sd, "type=%s, color_depth=%dbits",
+		  hdmi_readl(dw_dev, DW_HDMI_PDEC_STS) &
+		  DW_HDMI_DVIDET ? "dvi" : "hdmi",
+		  dw_hdmi_get_colordepth(dw_dev));
+
+	v4l2_info(sd, "--- Video timings ---\n");
+	if (dw_hdmi_query_dv_timings(sd, &timings))
+		v4l2_info(sd, "No video detected\n");
+	else
+		v4l2_print_dv_timings(sd->name, "Detected format: ",
+				      &timings, true);
+	v4l2_print_dv_timings(sd->name, "Configured format: ",
+			      &dw_dev->timings, true);
+
+	v4l2_ctrl_subdev_log_status(sd);
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static void dw_hdmi_invalid_register(struct dw_hdmi_dev *dw_dev, u64 reg)
+{
+	dev_err(dw_dev->dev, "register 0x%llx not supported\n", reg);
+	dev_err(dw_dev->dev, "0x0000-0x7fff: Main controller map\n");
+	dev_err(dw_dev->dev, "0x8000-0x8fff: Debug registers\n");
+	dev_err(dw_dev->dev, "  0x8000: TMDSVALID wait count\n");
+	dev_err(dw_dev->dev, "  0x8001: SW state\n");
+	dev_err(dw_dev->dev, "  0x8002: Equalizer ON/OFF\n");
+	dev_err(dw_dev->dev, "  0x8003: PHY Version\n");
+	dev_err(dw_dev->dev, "  0x8004: Video Stable Wait Time (ms)\n");
+	dev_err(dw_dev->dev, "  0x8005: Clock wait time (ms)\n");
+	dev_err(dw_dev->dev, "  0x8006: iref_clk value\n");
+	dev_err(dw_dev->dev, "  0x8007: reset_datapath_enable mask value\n");
+	dev_err(dw_dev->dev, "  0x8008: audio sample frequency (read only)\n");
+	dev_err(dw_dev->dev, "  0x8009: hw_reset_on_hot_plug (1=enabled, 0=disabled)");
+	dev_err(dw_dev->dev, "0x10000-0x100ff: PHY map\n");
+}
+
+static bool dw_hdmi_is_reserved_register(struct dw_hdmi_dev *dw_dev, u32 reg)
+{
+	/*
+	 * NOTE: Some of the HDCP registers are write only. This means that
+	 * a read from these registers will never return and can block the bus
+	 * in some architectures. Disable the read to these registers and also
+	 * disable the write as a safety measure because userspace should not
+	 * be able to set HDCP registers.
+	 */
+	if (reg >= DW_HDMI_HDCP_CTRL && reg <= DW_HDMI_HDCP_STS)
+		return true;
+	if (reg == DW_HDMI_HDCP22_CONTROL)
+		return true;
+	if (reg == DW_HDMI_HDCP22_STATUS)
+		return true;
+	return false;
+}
+
+static int dw_hdmi_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	switch (reg->reg >> 15) {
+	case 0: /* Controller core read */
+		if (dw_hdmi_is_reserved_register(dw_dev, reg->reg & 0x7fff))
+			return -EINVAL;
+
+		reg->size = 4;
+		reg->val = hdmi_readl(dw_dev, reg->reg & 0x7fff);
+		return 0;
+	case 1: /* Debug registers */
+		reg->size = 4;
+
+		switch (reg->reg & GENMASK(14, 0)) {
+		case 0:
+			reg->val = dw_dev->tmds_valid_wait_count;
+			return 0;
+		case 1:
+			reg->val = dw_dev->state;
+			return 0;
+		case 2:
+			reg->val = dw_dev->phy_eq_on;
+			return 0;
+		case 3:
+			reg->val = dw_dev->config->phy->version;
+			return 0;
+		case 4:
+			reg->val = dw_dev->video_stable_wait_ms;
+			return 0;
+		case 5:
+			reg->val = dw_dev->has_clock_wait_ms;
+			return 0;
+		case 6:
+			reg->val = dw_dev->config->iref_clk;
+			return 0;
+		case 7:
+			reg->val = dw_dev->reset_datapath_enable;
+			return 0;
+		case 8:
+			reg->val = dw_hdmi_get_sample_freq(dw_dev);
+			return 0;
+		case 9:
+			reg->val = dw_dev->hw_reset_on_hot_plug;
+			return 0;
+		default:
+			break;
+		}
+		break;
+	case 2: /* PHY read */
+		if ((reg->reg & ~0xff) != BIT(16))
+			break;
+
+		reg->size = 2;
+		reg->val = dw_hdmi_phy_read(dw_dev, reg->reg & 0xff);
+		return 0;
+	default:
+		break;
+	}
+
+	dw_hdmi_invalid_register(dw_dev, reg->reg);
+	return 0;
+}
+
+static int dw_hdmi_s_register(struct v4l2_subdev *sd,
+			      const struct v4l2_dbg_register *reg)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	switch (reg->reg >> 15) {
+	case 0: /* Controller core write */
+		if (dw_hdmi_is_reserved_register(dw_dev, reg->reg & 0x7fff))
+			return -EINVAL;
+
+		hdmi_writel(dw_dev, reg->val & GENMASK(31, 0),
+			    reg->reg & 0x7fff);
+		return 0;
+	case 1: /* Debug registers */
+		switch (reg->reg & GENMASK(14, 0)) {
+		case 0:
+			dw_dev->tmds_valid_wait_count = reg->val;
+			return 0;
+		case 1:
+			dw_hdmi_set_state(dw_dev, reg->val & 0xff);
+			return 0;
+		case 2:
+			dw_dev->phy_eq_on = reg->val;
+			return 0;
+		case 4:
+			dw_dev->video_stable_wait_ms = reg->val;
+			return 0;
+		case 5:
+			dw_dev->has_clock_wait_ms = reg->val;
+			return 0;
+		case 7:
+			dw_dev->reset_datapath_enable = reg->val;
+			return 0;
+		/* case 8 is read-only */
+		case 9:
+			dw_dev->hw_reset_on_hot_plug = reg->val;
+			return 0;
+		case 400:
+			dev_warn(dw_dev->dev, "synmp debug select timeout\n");
+			return 0;
+		default:
+			break;
+		}
+		break;
+	case 2: /* PHY write */
+		if ((reg->reg & ~0xff) != BIT(16))
+			break;
+		dw_hdmi_phy_write(dw_dev, reg->val & 0xffff, reg->reg & 0xff);
+		return 0;
+	default:
+		break;
+	}
+
+	dw_hdmi_invalid_register(dw_dev, reg->reg);
+	return 0;
+}
+#endif
+
+static int dw_hdmi_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				   struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
+	default:
+		return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
+	}
+}
+
+static int dw_hdmi_registered(struct v4l2_subdev *sd)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	dw_dev->registered = true;
+	return 0;
+}
+
+static void dw_hdmi_unregistered(struct v4l2_subdev *sd)
+{
+	struct dw_hdmi_dev *dw_dev = to_dw_dev(sd);
+
+	dw_dev->registered = false;
+}
+
+static const struct v4l2_subdev_core_ops dw_hdmi_sd_core_ops = {
+	.log_status = dw_hdmi_log_status,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = dw_hdmi_g_register,
+	.s_register = dw_hdmi_s_register,
+#endif
+	.subscribe_event = dw_hdmi_subscribe_event,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops dw_hdmi_sd_video_ops = {
+	.s_routing = dw_hdmi_s_routing,
+	.g_input_status = dw_hdmi_g_input_status,
+	.g_frame_interval = dw_hdmi_g_frame_interval,
+	.s_dv_timings = dw_hdmi_s_dv_timings,
+	.g_dv_timings = dw_hdmi_g_dv_timings,
+	.query_dv_timings = dw_hdmi_query_dv_timings,
+};
+
+static const struct v4l2_subdev_pad_ops dw_hdmi_sd_pad_ops = {
+	.enum_mbus_code = dw_hdmi_enum_mbus_code,
+	.get_fmt = dw_hdmi_get_fmt,
+	.set_fmt = dw_hdmi_set_fmt,
+	.get_edid = dw_hdmi_get_edid,
+	.set_edid = dw_hdmi_set_edid,
+	.dv_timings_cap = dw_hdmi_dv_timings_cap,
+	.enum_dv_timings = dw_hdmi_enum_dv_timings,
+};
+
+static const struct v4l2_subdev_ops dw_hdmi_sd_ops = {
+	.core = &dw_hdmi_sd_core_ops,
+	.video = &dw_hdmi_sd_video_ops,
+	.pad = &dw_hdmi_sd_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops dw_hdmi_internal_ops = {
+	.registered = dw_hdmi_registered,
+	.unregistered = dw_hdmi_unregistered,
+};
+
+static int dw_hdmi_parse_pd(struct dw_hdmi_dev *dw_dev)
+{
+	/* PHY address already comes from platform data */
+	if (!dw_dev->config->phy->jtag_addr) {
+		dev_err(dw_dev->dev, "missing PHY jtag address in PD\n");
+		return -EINVAL;
+	}
+
+	/* clock already comes from platform data */
+	if (!dw_dev->config->iref_clk) {
+		dev_err(dw_dev->dev, "invalid cfg clock frequency in PD\n");
+		return -EINVAL;
+	}
+
+	/* PHY input count already comes from platform data */
+	if (!dw_dev->config->phy->input_count) {
+		dev_err(dw_dev->dev, "invalid PHY input count\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_parse_dt(struct dw_hdmi_dev *dw_dev)
+{
+	struct device_node *phy_node, *np = dw_dev->of_node;
+	struct device_node *port_node;
+	u32 tmp = 0;
+	int ret;
+
+	if (!np) {
+		dev_err(dw_dev->dev, "missing DT node\n");
+		return -EINVAL;
+	}
+
+	/* PHY properties parsing */
+	phy_node = dw_hdmi_get_phy_of_node(dw_dev, NULL);
+	ret = of_property_read_u32(phy_node, "reg", &tmp);
+	if (ret) {
+		dev_err(dw_dev->dev, "missing PHY jtag address in DT\n");
+		return ret;
+	}
+
+	dw_dev->config->phy->jtag_addr = tmp & 0xff;
+
+	/* Get config clock value */
+	dw_dev->clk = devm_clk_get(dw_dev->dev, "cfg");
+	if (IS_ERR(dw_dev->clk)) {
+		dev_err(dw_dev->dev, "failed to get cfg clock\n");
+		return PTR_ERR(dw_dev->clk);
+	}
+
+	ret = clk_prepare_enable(dw_dev->clk);
+	if (ret) {
+		dev_err(dw_dev->dev, "failed to enable cfg clock\n");
+		return ret;
+	}
+
+	dw_dev->config->iref_clk = clk_get_rate(dw_dev->clk) / 1000000U;
+	if (!dw_dev->config->iref_clk) {
+		dev_err(dw_dev->dev, "invalid cfg clock frequency\n");
+		ret = -EINVAL;
+		goto err_clk;
+	}
+
+	/* Get PHY input count through the port children count */
+	port_node = of_get_child_by_name(phy_node, "port");
+	dw_dev->config->phy->input_count = of_get_child_count(port_node);
+	if (!dw_dev->config->phy->input_count) {
+		dev_err(dw_dev->dev, "invalid PHY input count\n");
+		ret = -EINVAL;
+		goto err_clk;
+	}
+
+	return 0;
+
+err_clk:
+	clk_disable_unprepare(dw_dev->clk);
+	return ret;
+}
+
+static void dw_hdmi_config_ced(struct dw_hdmi_dev *dw_dev)
+{
+	hdmi_mask_writel(dw_dev, 0x1f, DW_HDMI_HDMI20_CONTROL,
+			 DW_HDMI_CTRLCHECKEN_OFFSET,
+			 DW_HDMI_VIDDATACHECKEN_MASK |
+			 DW_HDMI_DATAISCHECKEN_MASK |
+			 DW_HDMI_GBCHECKEN_MASK |
+			 DW_HDMI_PREAMBCHECKEN_MASK |
+			 DW_HDMI_CTRLCHECKEN_MASK);
+}
+
+static void dw_hdmi_config_mode_recover(struct dw_hdmi_dev *dw_dev)
+{
+	/*NOTE: avoid instability of md_ists interrupts */
+
+	/* set HDMI_MODE_HYST */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MODE_RECOVER,
+			 DW_HDMI_HDMI_MODE_HYST_OFFSET,
+			 DW_HDMI_HDMI_MODE_HYST_MASK);
+	/* set DVI_MODE_HYST */
+	hdmi_mask_writel(dw_dev, 0x8, DW_HDMI_MODE_RECOVER,
+			 DW_HDMI_DVI_MODE_HYST_OFFSET,
+			 DW_HDMI_DVI_MODE_HYST_MASK);
+	/* set SPIKE_FILTER_EN */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_MODE_RECOVER,
+			 DW_HDMI_SPIKE_FILTER_EN_OFFSET,
+			 DW_HDMI_SPIKE_FILTER_EN_MASK);
+
+	/* enable BCH error correction */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_PDEC_CTRL,
+			 DW_HDMI_PDEC_BCH_EN_OFFSET,
+			 DW_HDMI_PDEC_BCH_EN_MASK);
+}
+
+static void dw_hdmi_config_scdc(struct dw_hdmi_dev *dw_dev)
+{
+	u32 chlock = dw_dev->config->iref_clk * 1000;
+
+	/* set HDMI_CHLOCK_CONFIG */
+	hdmi_mask_writel(dw_dev, chlock, DW_HDMI_CHLOCK_CONFIG,
+			 DW_HDMI_MILISECTIMERLIMIT_OFFSET,
+			 DW_HDMI_MILISECTIMERLIMIT_MASK);
+}
+
+static void dw_hdmi_config_ceavid(struct dw_hdmi_dev *dw_dev)
+{
+	/* set CEA YCC 422 IPI Mapping */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_YCC422_IPIMAP_OFFSET,
+			 DW_HDMI_CEAVID_YCC422_IPIMAP_MASK);
+	/* set CEA YCC 420 IPI Mapping */
+	hdmi_mask_writel(dw_dev, 0x1, DW_HDMI_CEAVID_CONFIG,
+			 DW_HDMI_CEAVID_YCC420_IPIMAP_OFFSET,
+			 DW_HDMI_CEAVID_YCC420_IPIMAP_MASK);
+}
+
+static int dw_hdmi_initial_config(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	/* disable interrupts */
[… more lines in the raw message]

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Quoted 9 lines

drivers/media/platform/dwc/dw-hdmi-rx.c

Quoted 6 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +6 -0

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

This should be dropped, start with an empty EDID and pull the HPD low.

I agree! This will be addressed in the next patch series.

Quoted 767 lines

include/media/dwc/dw-hdmi-rx-pdata.h

Quoted 764 lines
drivers/media/platform/dwc/dw-hdmi-rx.c new file +149 -0

Lines of this file are not shown. View the raw message.

drivers/media/platform/dwc/dw-hdmi-rx.h new file +476 -0
new file mode 100644
index 0000000..f0ea1d4

Lines of this file are not shown. View the raw message.

include/media/dwc/dw-hdmi-rx-pdata.h new file +126 -0
new file mode 100644
index 0000000..a2a5440

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Regards,

Quoted 1 line

Hans

Thanks!

BR,

Nelson Costa

Part of the diff is not shown here. View the raw message.

#14 lore raw

Re: [PATCH 6/9] media: platform: Add Synopsys DesignWare HDMI RX Controller Driver

Hi Nelson,

Quoted 21 lines · Nelson Costa

Hi Hans,

Thanks for your initial comments and feedback!

From: Hans Verkuil <[email protected]>
Date: qua, jun 02, 2021 at 12:54:38

Quoted 6 lines

Hi Nelson,

Thank you for this patch. Some initial comments below, I will need to go over this another time for some of the colorimetry related functions.

Ok.

Quoted 4 lines

BTW, if you are interested in HDCP support, let me know. Cisco worked on an API for this, but due to various reasons we have not been able to upstream it. But we do use it in our products.

Quoted 4 lines

Good to know! In that case if in the future we think to upstream something
related with HDCP we will let you know. :)
BTW, which versions of HDCP (1.4, 2.2, 2.3) the API supports?

It's designed for all versions, but it has only been tested with 1.4 receivers.

You can find it here:

https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=tc358840

BTW, don't wait for the follow-up review w.r.t. colorimetry, it might take 1-2 weeks before I get around to that, I need to carve out time for that. Feel free to post a v2 based on the current review.

Regards,

Hans

#15 lore raw

RE: [PATCH 6/9] media: platform: Add Synopsys DesignWare HDMI RX Controller Driver

Hi Hans,

From: Hans Verkuil <[email protected]>
Date: qua, jun 02, 2021 at 18:04:18

Quoted 36 lines

Hi Nelson,

Quoted 21 lines · Nelson Costa

Hi Hans,

Thanks for your initial comments and feedback!

From: Hans Verkuil <[email protected]>
Date: qua, jun 02, 2021 at 12:54:38

Quoted 6 lines

Hi Nelson,

Thank you for this patch. Some initial comments below, I will need to go over this another time for some of the colorimetry related functions.

Ok.

Quoted 4 lines

BTW, if you are interested in HDCP support, let me know. Cisco worked on an API for this, but due to various reasons we have not been able to upstream it. But we do use it in our products.

Quoted 4 lines

Good to know! In that case if in the future we think to upstream something
related with HDCP we will let you know. :)
BTW, which versions of HDCP (1.4, 2.2, 2.3) the API supports?

It's designed for all versions, but it has only been tested with 1.4 receivers.

You can find it here:

https://urldefense.com/v3/__https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=tc358840__;!!A4F2R9G_pg!Pa7NKoq1ggxUQRZwHUgCTC1A36pJsSxICKeVRFWtPHMlf9xUEDjtTjrBV0h7A81zNDo$

Quoted 7 lines

BTW, don't wait for the follow-up review w.r.t. colorimetry, it might take 1-2 weeks before I get around to that, I need to carve out time for that. Feel free to post a v2 based on the current review.

Regards,

Hans

Thanks for the feedback and for providing the HDCP related link!

BR,

Nelson Costa

#16 lore raw

PATCH 7/9 media: v4l2-dv-timings: Add more CEA/CTA-861 video format timings

In reply to Nelson Costa

This extends the support for more video format timings based on SPECs CEA-861-F and CTA-861-G.

NOTE: For the newer SPECs the CEA was unified to the CTA. The CTA-861-G then includes the CEA-861-F timings besides the new timings that are specified.

CEA-861-F: Specifies the Video timings for VICs 1-107.
CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219.

With this patch, the array v4l2_dv_timings_presets has support for all video timings specified in CTA-861-G.

---
 drivers/media/v4l2-core/v4l2-dv-timings.c |  139 +++
 include/uapi/linux/v4l2-dv-timings.h      | 1595 ++++++++++++++++++++++++++++-
 2 files changed, 1733 insertions(+), 1 deletion(-)
drivers/media/v4l2-core/v4l2-dv-timings.c +139 -0
index 230d65a..0766e0c 100644
@@ -133,6 +133,145 @@ const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
 	V4L2_DV_BT_CEA_4096X2160P50,
 	V4L2_DV_BT_DMT_4096X2160P59_94_RB,
 	V4L2_DV_BT_CEA_4096X2160P60,
+	V4L2_DV_BT_CEA_720X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X480I60_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_2880X480I60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480I60_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_1440X480P60_PA4_3,
+	V4L2_DV_BT_CEA_1440X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_720X576I50_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_2880X576I50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576I50_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_1440X576P50_PA4_3,
+	V4L2_DV_BT_CEA_1440X576P50_PA16_9,
+	V4L2_DV_BT_CEA_2880X480P60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480P60_PA16_9,
+	V4L2_DV_BT_CEA_2880X576P50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P100_PA16_9,
+	V4L2_DV_BT_CEA_720X576P100_PA4_3,
+	V4L2_DV_BT_CEA_720X576P100_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I100_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I100_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I120_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P120_PA16_9,
+	V4L2_DV_BT_CEA_720X480P120_PA4_3,
+	V4L2_DV_BT_CEA_720X480P120_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I120_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I120_PA16_9,
+	V4L2_DV_BT_CEA_720X576P200_PA4_3,
+	V4L2_DV_BT_CEA_720X576P200_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I200_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I200_PA16_9,
+	V4L2_DV_BT_CEA_720X480P240_PA4_3,
+	V4L2_DV_BT_CEA_720X480P240_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I240_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I240_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P120_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P120_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P120_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P48_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P48_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P48_PA16_9,
+	V4L2_DV_BT_CEA_4096X2160P48_PA256_135,
+	V4L2_DV_BT_CEA_3840X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P100_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P120_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P24_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P25_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P30_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P48_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P50_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P60_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P100_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P120_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_4096X2160P100_PA256_135,
+	V4L2_DV_BT_CEA_4096X2160P120_PA256_135,
 	{ }
 };
 EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
include/uapi/linux/v4l2-dv-timings.h +1594 -1

1,607 lines not on this page · raw message

Signature · 1 line
2.7.4
#17 lore raw

Re: [PATCH 7/9] media: v4l2-dv-timings: Add more CEA/CTA-861 video format timings

Hi Nelson,

Quoted 10 lines · Nelson Costa

This extends the support for more video format timings based on SPECs CEA-861-F and CTA-861-G.

NOTE: For the newer SPECs the CEA was unified to the CTA. The CTA-861-G then includes the CEA-861-F timings besides the new timings that are specified.

CEA-861-F: Specifies the Video timings for VICs 1-107.
CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219.

Quoted 7 lines

With this patch, the array v4l2_dv_timings_presets has support for all video timings specified in CTA-861-G.

---
 drivers/media/v4l2-core/v4l2-dv-timings.c |  139 +++
 include/uapi/linux/v4l2-dv-timings.h      | 1595 ++++++++++++++++++++++++++++-

I prefer to split this up in two patches, one for each header.

The v4l2-dv-timings.h changes look good (my compliments for all the work you put into that!).

I am more concerned about adding all these timings to v4l2_dv_timings_presets.

There are really two different things going on here: the v4l2_dv_timings_presets array is used both by v4l2_enum_dv_timings_cap() to list supported commonly used timings, or to match against timings parameters (v4l2_find_dv_timings_cap()), and as a lookup table when receiving a specific VIC code (v4l2_find_dv_timings_cea861_vic()).

All the new timings you added are really only relevant in the last case when you have the vic code.

I think it is better to create a second array v4l2_dv_timings_non_square_vics[] (or a better name!) that contains these timings.

Then if v4l2_find_dv_timings_cea861_vic() can't find the vic in the presets table it will look for it in the new table.

For the 'variable vertical total lines timings' there probably should be a new arg added to the v4l2_find_dv_timings_cea861_vic() parameter list with the detected number of lines, and v4l2_find_dv_timings_cea861_vic() can use that to find the correct VTOT variant.

Another issue I have is that I am unsure about the pixel repetition support in current HDMI receiver drivers. I've never tested this, and so I am not sure what will happen if you transmit such a format. Have you tested this yourself?

I wonder if support for such VICs should be optional, perhaps again through an argument to v4l2_find_dv_timings_cea861_vic() so drivers can decide to support such formats or not.

Regards,

Hans

Quoted 1,766 lines
 2 files changed, 1733 insertions(+), 1 deletion(-)
drivers/media/v4l2-core/v4l2-dv-timings.c +139 -0
index 230d65a..0766e0c 100644
@@ -133,6 +133,145 @@ const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
 	V4L2_DV_BT_CEA_4096X2160P50,
 	V4L2_DV_BT_DMT_4096X2160P59_94_RB,
 	V4L2_DV_BT_CEA_4096X2160P60,
+	V4L2_DV_BT_CEA_720X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X480I60_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_2880X480I60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480I60_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_1440X480P60_PA4_3,
+	V4L2_DV_BT_CEA_1440X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_720X576I50_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_2880X576I50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576I50_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_1440X576P50_PA4_3,
+	V4L2_DV_BT_CEA_1440X576P50_PA16_9,
+	V4L2_DV_BT_CEA_2880X480P60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480P60_PA16_9,
+	V4L2_DV_BT_CEA_2880X576P50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P100_PA16_9,
+	V4L2_DV_BT_CEA_720X576P100_PA4_3,
+	V4L2_DV_BT_CEA_720X576P100_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I100_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I100_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I120_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P120_PA16_9,
+	V4L2_DV_BT_CEA_720X480P120_PA4_3,
+	V4L2_DV_BT_CEA_720X480P120_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I120_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I120_PA16_9,
+	V4L2_DV_BT_CEA_720X576P200_PA4_3,
+	V4L2_DV_BT_CEA_720X576P200_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I200_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I200_PA16_9,
+	V4L2_DV_BT_CEA_720X480P240_PA4_3,
+	V4L2_DV_BT_CEA_720X480P240_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I240_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I240_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P120_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P120_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P120_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P48_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P48_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P48_PA16_9,
+	V4L2_DV_BT_CEA_4096X2160P48_PA256_135,
+	V4L2_DV_BT_CEA_3840X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P100_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P120_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P24_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P25_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P30_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P48_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P50_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P60_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P100_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P120_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_4096X2160P100_PA256_135,
+	V4L2_DV_BT_CEA_4096X2160P120_PA256_135,
 	{ }
 };
 EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
include/uapi/linux/v4l2-dv-timings.h +1594 -1
index b52b67c..900530b 100644
@@ -29,7 +29,14 @@
 	.bt = { _width , ## args }
 #endif
 
-/* CEA-861-F timings (i.e. standard HDTV timings) */
+/* CEA-861-F timings (i.e. standard HDTV timings)
+ * NOTE: For the newer SPECs the CEA was unified to the CTA.
+ * The CTA-861-G includes the CEA-861-F timings besides the
+ * new timings that are specified.
+ *
+ * CEA-861-F: Specifies the Video timings for VICs 1-107
+ * CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219
+ */
 
 #define V4L2_DV_BT_CEA_640X480P59_94 { \
 	.type = V4L2_DV_BT_656_1120, \
@@ -297,6 +304,1592 @@
 		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 102) \
 }
 
+/* VIC=3 */
+#define V4L2_DV_BT_CEA_720X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		27000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 3) \
+}
+
+/* VIC=7 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X480I60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 1, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 7) \
+}
+
+/* VIC=8 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 8) \
+}
+
+/* VIC=8 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 8) \
+}
+
+/* VIC=9 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 9) \
+}
+
+/* VIC=9 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 9) \
+}
+
+/* VIC=10 */
+#define V4L2_DV_BT_CEA_2880X480I60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 1, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 10) \
+}
+
+/* VIC=11 */
+#define V4L2_DV_BT_CEA_2880X480I60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 1, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 11) \
+}
+
+/* VIC=12 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 12) \
+}
+
+/* VIC=12 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 12) \
+}
+
+/* VIC=13 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 13) \
+}
+
+/* VIC=13 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 13) \
+}
+
+/* VIC=14 */
+#define V4L2_DV_BT_CEA_1440X480P60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 0, 0, \
+		54000000, 32, 124, 120, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 14) \
+}
+
+/* VIC=15 */
+#define V4L2_DV_BT_CEA_1440X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 0, 0, \
+		54000000, 32, 124, 120, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 15) \
+}
+
+/* VIC=18 */
+#define V4L2_DV_BT_CEA_720X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		27000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 18) \
+}
+
+/* VIC=22 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X576I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 1, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 22) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=25 */
+#define V4L2_DV_BT_CEA_2880X576I50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 1, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 25) \
+}
+
+/* VIC=26 */
+#define V4L2_DV_BT_CEA_2880X576I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 1, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 26) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=29 */
+#define V4L2_DV_BT_CEA_1440X576P50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 0, 0, \
+		54000000, 24, 128, 136, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 29) \
+}
+
+/* VIC=30 */
+#define V4L2_DV_BT_CEA_1440X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 0, 0, \
+		54000000, 24, 128, 136, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 30) \
+}
+
+/* VIC=35 */
+#define V4L2_DV_BT_CEA_2880X480P60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 0, 0, \
+		108000000, 64, 248, 240, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 35) \
+}
+
+/* VIC=36 */
+#define V4L2_DV_BT_CEA_2880X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 0, 0, \
+		108000000, 64, 248, 240, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 36) \
+}
+
+/* VIC=37 */
+#define V4L2_DV_BT_CEA_2880X576P50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 0, 0, \
+		108000000, 48, 256, 272, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 37) \
+}
+
+/* VIC=38 */
+#define V4L2_DV_BT_CEA_2880X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 0, 0, \
+		108000000, 48, 256, 272, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 38) \
+}
+
+/* VIC=39 */
+#define V4L2_DV_BT_CEA_1920X1080I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, V4L2_DV_HSYNC_POS_POL, \
+		72000000, 32, 168, 184, 23, 5, 57, 23, 5, 58, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 39) \
+}
+
+/* VIC=40 */
+#define V4L2_DV_BT_CEA_1920X1080I100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 40) \
+}
+
+/* VIC=41 */
+#define V4L2_DV_BT_CEA_1280X720P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 41) \
+}
+
+/* VIC=42 */
+#define V4L2_DV_BT_CEA_720X576P100_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		54000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 42) \
+}
+
+/* VIC=43 */
+#define V4L2_DV_BT_CEA_720X576P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		54000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 43) \
+}
+
+/* VIC=44 */
+#define V4L2_DV_BT_CEA_1440X576I100_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		54000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 44) \
+}
+
+/* VIC=45 */
+#define V4L2_DV_BT_CEA_1440X576I100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		54000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 45) \
+}
+
+/* VIC=46 */
+#define V4L2_DV_BT_CEA_1920X1080I120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 46) \
+}
+
+/* VIC=47 */
+#define V4L2_DV_BT_CEA_1280X720P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 47) \
+}
+
+/* VIC=48 */
+#define V4L2_DV_BT_CEA_720X480P120_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		54000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 48) \
+}
+
+/* VIC=49 */
+#define V4L2_DV_BT_CEA_720X480P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		54000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 49) \
+}
+
+/* VIC=50 */
+#define V4L2_DV_BT_CEA_1440X480I120_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		54000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 50) \
+}
+
+/* VIC=51 */
+#define V4L2_DV_BT_CEA_1440X480I120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		54000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 51) \
+}
+
+/* VIC=52 */
+#define V4L2_DV_BT_CEA_720X576P200_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		108000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 52) \
+}
+
+/* VIC=53 */
+#define V4L2_DV_BT_CEA_720X576P200_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		108000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 53) \
+}
+
+/* VIC=54 */
+#define V4L2_DV_BT_CEA_1440X576I200_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		108000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 54) \
+}
+
+/* VIC=55 */
+#define V4L2_DV_BT_CEA_1440X576I200_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		108000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 55) \
+}
+
+/* VIC=56 */
+#define V4L2_DV_BT_CEA_720X480P240_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		108000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 56) \
+}
+
+/* VIC=57 */
+#define V4L2_DV_BT_CEA_720X480P240_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		108000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 57) \
+}
+
+/* VIC=58 */
+#define V4L2_DV_BT_CEA_1440X480I240_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		108000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 58) \
+}
+
+/* VIC=59 */
+#define V4L2_DV_BT_CEA_1440X480I240_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		108000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 59) \
+}
+
+/* VIC=63 */
+#define V4L2_DV_BT_CEA_1920X1080P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 63) \
+}
+
+/* VIC=64 */
+#define V4L2_DV_BT_CEA_1920X1080P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 64) \
+}
+
+/* VIC=65 */
+#define V4L2_DV_BT_CEA_1280X720P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 65) \
+}
+
+/* VIC=66 */
+#define V4L2_DV_BT_CEA_1280X720P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 2420, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 66) \
+}
+
+/* VIC=67 */
+#define V4L2_DV_BT_CEA_1280X720P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 67) \
+}
+
+/* VIC=68 */
+#define V4L2_DV_BT_CEA_1280X720P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 68) \
+}
+
+/* VIC=69 */
+#define V4L2_DV_BT_CEA_1280X720P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 69) \
+}
+
+/* VIC=70 */
+#define V4L2_DV_BT_CEA_1280X720P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 70) \
+}
+
+/* VIC=71 */
+#define V4L2_DV_BT_CEA_1280X720P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 71) \
+}
+
+/* VIC=72 */
+#define V4L2_DV_BT_CEA_1920X1080P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 72) \
+}
+
+/* VIC=73 */
+#define V4L2_DV_BT_CEA_1920X1080P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 73) \
+}
+
+/* VIC=74 */
+#define V4L2_DV_BT_CEA_1920X1080P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 74) \
+}
+
+/* VIC=75 */
+#define V4L2_DV_BT_CEA_1920X1080P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 75) \
+}
+
+/* VIC=76 */
+#define V4L2_DV_BT_CEA_1920X1080P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 76) \
+}
+
+/* VIC=77 */
+#define V4L2_DV_BT_CEA_1920X1080P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 77) \
+}
+
+/* VIC=78 */
+#define V4L2_DV_BT_CEA_1920X1080P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 78) \
+}
+
+/* VIC=79 */
+#define V4L2_DV_BT_CEA_1680X720P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1360, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 79) \
+}
+
+/* VIC=80 */
+#define V4L2_DV_BT_CEA_1680X720P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1228, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 80) \
+}
+
+/* VIC=81 */
+#define V4L2_DV_BT_CEA_1680X720P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 700, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 81) \
+}
+
+/* VIC=82 */
+#define V4L2_DV_BT_CEA_1680X720P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		82500000, 260, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 82) \
+}
+
+/* VIC=83 */
+#define V4L2_DV_BT_CEA_1680X720P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 260, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 83) \
+}
+
+/* VIC=84 */
+#define V4L2_DV_BT_CEA_1680X720P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		165000000, 60, 40, 220, 5, 5, 95, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 84) \
+}
+
+/* VIC=85 */
+#define V4L2_DV_BT_CEA_1680X720P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		198000000, 60, 40, 220, 5, 5, 95, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 85) \
+}
+
+/* VIC=86 */
+#define V4L2_DV_BT_CEA_2560X1080P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 998, 44, 148, 4, 5, 11, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 86) \
+}
+
+/* VIC=87 */
+#define V4L2_DV_BT_CEA_2560X1080P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 448, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 87) \
+}
+
+/* VIC=88 */
+#define V4L2_DV_BT_CEA_2560X1080P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		118800000, 768, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 88) \
+}
+
+/* VIC=89 */
+#define V4L2_DV_BT_CEA_2560X1080P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		185625000, 548, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 89) \
+}
+
+/* VIC=90 */
+#define V4L2_DV_BT_CEA_2560X1080P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		198000000, 248, 44, 148, 4, 5, 11, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 90) \
+}
+
+/* VIC=91 */
+#define V4L2_DV_BT_CEA_2560X1080P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		371250000, 218, 44, 148, 4, 5, 161, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 91) \
+}
+
+/* VIC=92 */
+#define V4L2_DV_BT_CEA_2560X1080P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		495000000, 548, 44, 148, 4, 5, 161, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 92) \
+}
+
+/* VIC=103 */
+#define V4L2_DV_BT_CEA_3840X2160P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 103) \
+}
+
+/* VIC=104 */
+#define V4L2_DV_BT_CEA_3840X2160P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 104) \
+}
+
+/* VIC=105 */
+#define V4L2_DV_BT_CEA_3840X2160P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 105) \
+}
+
+/* VIC=106 */
+#define V4L2_DV_BT_CEA_3840X2160P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 106) \
+}
+
+/* VIC=107 */
+#define V4L2_DV_BT_CEA_3840X2160P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 107) \
+}
+
+/* VIC=108 */
+#define V4L2_DV_BT_CEA_1280X720P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 960, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 108) \
+}
+
+/* VIC=109 */
+#define V4L2_DV_BT_CEA_1280X720P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 960, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 109) \
+}
+
+/* VIC=110 */
+#define V4L2_DV_BT_CEA_1680X720P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 810, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 110) \
+}
+
+/* VIC=111 */
+#define V4L2_DV_BT_CEA_1920X1080P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 111) \
+}
+
+/* VIC=112 */
+#define V4L2_DV_BT_CEA_1920X1080P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 112) \
+}
+
+/* VIC=114 */
+#define V4L2_DV_BT_CEA_3840X2160P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 114) \
+}
+
+/* VIC=115 */
+#define V4L2_DV_BT_CEA_4096X2160P48_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 256, 135 }, 115) \
+}
+
+/* VIC=116 */
+#define V4L2_DV_BT_CEA_3840X2160P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 116) \
+}
+
+/* VIC=117 */
+#define V4L2_DV_BT_CEA_3840X2160P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 117) \
+}
+
+/* VIC=118 */
+#define V4L2_DV_BT_CEA_3840X2160P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 118) \
+}
+
+/* VIC=119 */
+#define V4L2_DV_BT_CEA_3840X2160P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 119) \
+}
+
+/* VIC=120 */
+#define V4L2_DV_BT_CEA_3840X2160P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 120) \
+}
+
+/* VIC=121 */
+#define V4L2_DV_BT_CEA_5120X2160P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 1996, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 121) \
+}
+
+/* VIC=122 */
+#define V4L2_DV_BT_CEA_5120X2160P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 1696, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 122) \
+}
+
+/* VIC=123 */
+#define V4L2_DV_BT_CEA_5120X2160P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 664, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 123) \
+}
+
+/* VIC=124 */
+#define V4L2_DV_BT_CEA_5120X2160P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 746, 88, 296, 8, 10, 297, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 124) \
+}
+
+/* VIC=125 */
+#define V4L2_DV_BT_CEA_5120X2160P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 1096, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 125) \
+}
+
+/* VIC=126 */
+#define V4L2_DV_BT_CEA_5120X2160P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 164, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 126) \
+}
+
+/* VIC=127 */
+#define V4L2_DV_BT_CEA_5120X2160P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 1096, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 127) \
+}
+
+/* VIC=193 */
+#define V4L2_DV_BT_CEA_5120X2160P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 154, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 193) \
+}
+
+/* VIC=194 */
+#define V4L2_DV_BT_CEA_7680X4320P24_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 194) \
+}
+
+/* VIC=195 */
+#define V4L2_DV_BT_CEA_7680X4320P25_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 195) \
+}
+
+/* VIC=196 */
+#define V4L2_DV_BT_CEA_7680X4320P30_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 196) \
+}
+
+/* VIC=197 */
+#define V4L2_DV_BT_CEA_7680X4320P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 197) \
+}
+
+/* VIC=198 */
+#define V4L2_DV_BT_CEA_7680X4320P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 198) \
+}
+
+/* VIC=199 */
+#define V4L2_DV_BT_CEA_7680X4320P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 199) \
+}
+
+/* VIC=200 */
+#define V4L2_DV_BT_CEA_7680X4320P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 2112, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 200) \
+}
+
+/* VIC=201 */
+#define V4L2_DV_BT_CEA_7680X4320P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 352, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 201) \
+}
+
+/* VIC=202 */
+#define V4L2_DV_BT_CEA_7680X4320P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 202) \
+}
+
+/* VIC=203 */
+#define V4L2_DV_BT_CEA_7680X4320P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 203) \
+}
+
+/* VIC=204 */
+#define V4L2_DV_BT_CEA_7680X4320P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 204) \
+}
+
+/* VIC=205 */
+#define V4L2_DV_BT_CEA_7680X4320P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 205) \
+}
+
+/* VIC=206 */
+#define V4L2_DV_BT_CEA_7680X4320P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 206) \
+}
+
+/* VIC=207 */
+#define V4L2_DV_BT_CEA_7680X4320P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 207) \
+}
+
+/* VIC=208 */
+#define V4L2_DV_BT_CEA_7680X4320P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 2112, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 208) \
+}
+
+/* VIC=209 */
+#define V4L2_DV_BT_CEA_7680X4320P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 352, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 209) \
+}
+
+/* VIC=210 */
+#define V4L2_DV_BT_CEA_10240X4320P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 1492, 176, 592, 16, 20, 594, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 210) \
+}
+
+/* VIC=211 */
+#define V4L2_DV_BT_CEA_10240X4320P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 2492, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 211) \
+}
+
+/* VIC=212 */
+#define V4L2_DV_BT_CEA_10240X4320P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 212) \
+}
+
+/* VIC=213 */
+#define V4L2_DV_BT_CEA_10240X4320P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 1492, 176, 592, 16, 20, 594, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 213) \
+}
+
+/* VIC=214 */
+#define V4L2_DV_BT_CEA_10240X4320P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 2492, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 214) \
+}
+
+/* VIC=215 */
+#define V4L2_DV_BT_CEA_10240X4320P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 215) \
+}
+
+/* VIC=216 */
+#define V4L2_DV_BT_CEA_10240X4320P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		5940000000ULL, 2192, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 216) \
+}
+
+/* VIC=217 */
+#define V4L2_DV_BT_CEA_10240X4320P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		5940000000ULL, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 217) \
+}
+
+/* VIC=218 */
+#define V4L2_DV_BT_CEA_4096X2160P100_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 800, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 256, 135 }, 218) \
+}
+
+/* VIC=219 */
+#define V4L2_DV_BT_CEA_4096X2160P120_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 256, 135 }, 219) \
+}
 
 /* VESA Discrete Monitor Timings as per version 1.0, revision 12 */
 
#18 lore raw

RE: [PATCH 7/9] media: v4l2-dv-timings: Add more CEA/CTA-861 video format timings

Hi Hans,

Thanks for your comments and feedback!

From: Hans Verkuil <[email protected]>
Date: qua, jun 02, 2021 at 13:26:17

Quoted 16 lines

Hi Nelson,

Quoted 13 lines · Nelson Costa

This extends the support for more video format timings based on SPECs CEA-861-F and CTA-861-G.

NOTE: For the newer SPECs the CEA was unified to the CTA. The CTA-861-G then includes the CEA-861-F timings besides the new timings that are specified.

CEA-861-F: Specifies the Video timings for VICs 1-107.
CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219.

With this patch, the array v4l2_dv_timings_presets has support for all video timings specified in CTA-861-G.

Quoted 7 lines
Quoted 4 lines
---
 drivers/media/v4l2-core/v4l2-dv-timings.c |  139 +++
 include/uapi/linux/v4l2-dv-timings.h      | 1595 ++++++++++++++++++++++++++++-

I prefer to split this up in two patches, one for each header.

I agree! It will be addressed in the next patch series.

Quoted 3 lines

The v4l2-dv-timings.h changes look good (my compliments for all the work you put into that!).

Thanks!

Quoted 7 lines

I am more concerned about adding all these timings to v4l2_dv_timings_presets.

There are really two different things going on here: the v4l2_dv_timings_presets array is used both by v4l2_enum_dv_timings_cap() to list supported commonly used timings, or to match against timings parameters (v4l2_find_dv_timings_cap()), and as a lookup table when receiving a specific VIC code (v4l2_find_dv_timings_cea861_vic()).

Quoted 6 lines

All the new timings you added are really only relevant in the last case when you have the vic code.

I think it is better to create a second array v4l2_dv_timings_non_square_vics[] (or a better name!) that contains these timings.

I understood.

We can then create another array as you said. But when you say "non_square"
you mean that the vics have "Pixel Aspect Ratio != 1:1"?

Because the new vics added have both kind of vics with "Pixel Aspect Ratio != 1:1"
and also "Pixel Aspect Ratio == 1:1".

So, for the new vics should we create a second array with name v4l2_dv_timings_extended_vics[]?

Quoted 3 lines

Then if v4l2_find_dv_timings_cea861_vic() can't find the vic in the presets table it will look for it in the new table.

I agree.

Quoted 5 lines

For the 'variable vertical total lines timings' there probably should be a new arg added to the v4l2_find_dv_timings_cea861_vic() parameter list with the detected number of lines, and v4l2_find_dv_timings_cea861_vic() can use that to find the correct VTOT variant.

Makes sense, because we can have different timings with the same vic but with different VTOT.

Quoted 4 lines

Another issue I have is that I am unsure about the pixel repetition support in current HDMI receiver drivers. I've never tested this, and so I am not sure what will happen if you transmit such a format. Have you tested this yourself?

I'll try to test that. But in our driver we use these vics info mainly to get
the Picture Aspect info, and so some other fields are not used. So the test might
not be useful for this kind of validation.

Quoted 4 lines

I wonder if support for such VICs should be optional, perhaps again through an argument to v4l2_find_dv_timings_cea861_vic() so drivers can decide to support such formats or not.

You mean something like this below?

v4l2_find_dv_timings_cea861_vic(.., vic, bool check_extended, vtot_extended)

where:
- check_extended:
* if true means to check the vic in the second array?
* if false means to check the vic only in the presets array?
- vtot_extended: the value of VTOT variant

My concern here is the incompatibility that the change of this function would cause in other implementations.

Once the idea would be to create a second array, should we think to create a second function for that like v4l2_find_dv_timings_cea861_extended_vic()?
What do you think?

Thanks,

BR,

Nelson Costa

Quoted 1,770 lines

Regards,

Hans

Quoted 1,766 lines
 2 files changed, 1733 insertions(+), 1 deletion(-)
drivers/media/v4l2-core/v4l2-dv-timings.c +139 -0
index 230d65a..0766e0c 100644
@@ -133,6 +133,145 @@ const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
 	V4L2_DV_BT_CEA_4096X2160P50,
 	V4L2_DV_BT_DMT_4096X2160P59_94_RB,
 	V4L2_DV_BT_CEA_4096X2160P60,
+	V4L2_DV_BT_CEA_720X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X480I60_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_2880X480I60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480I60_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_1440X480P60_PA4_3,
+	V4L2_DV_BT_CEA_1440X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_720X576I50_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_2880X576I50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576I50_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_1440X576P50_PA4_3,
+	V4L2_DV_BT_CEA_1440X576P50_PA16_9,
+	V4L2_DV_BT_CEA_2880X480P60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480P60_PA16_9,
+	V4L2_DV_BT_CEA_2880X576P50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P100_PA16_9,
+	V4L2_DV_BT_CEA_720X576P100_PA4_3,
+	V4L2_DV_BT_CEA_720X576P100_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I100_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I100_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I120_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P120_PA16_9,
+	V4L2_DV_BT_CEA_720X480P120_PA4_3,
+	V4L2_DV_BT_CEA_720X480P120_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I120_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I120_PA16_9,
+	V4L2_DV_BT_CEA_720X576P200_PA4_3,
+	V4L2_DV_BT_CEA_720X576P200_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I200_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I200_PA16_9,
+	V4L2_DV_BT_CEA_720X480P240_PA4_3,
+	V4L2_DV_BT_CEA_720X480P240_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I240_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I240_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P120_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P120_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P120_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P48_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P48_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P48_PA16_9,
+	V4L2_DV_BT_CEA_4096X2160P48_PA256_135,
+	V4L2_DV_BT_CEA_3840X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P100_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P120_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P24_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P25_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P30_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P48_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P50_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P60_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P100_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P120_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_4096X2160P100_PA256_135,
+	V4L2_DV_BT_CEA_4096X2160P120_PA256_135,
 	{ }
 };
 EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
include/uapi/linux/v4l2-dv-timings.h +1594 -1
index b52b67c..900530b 100644
@@ -29,7 +29,14 @@
 	.bt = { _width , ## args }
 #endif
 
-/* CEA-861-F timings (i.e. standard HDTV timings) */
+/* CEA-861-F timings (i.e. standard HDTV timings)
+ * NOTE: For the newer SPECs the CEA was unified to the CTA.
+ * The CTA-861-G includes the CEA-861-F timings besides the
+ * new timings that are specified.
+ *
+ * CEA-861-F: Specifies the Video timings for VICs 1-107
+ * CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219
+ */
 
 #define V4L2_DV_BT_CEA_640X480P59_94 { \
 	.type = V4L2_DV_BT_656_1120, \
@@ -297,6 +304,1592 @@
 		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 102) \
 }
 
+/* VIC=3 */
+#define V4L2_DV_BT_CEA_720X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		27000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 3) \
+}
+
+/* VIC=7 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X480I60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 1, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 7) \
+}
+
+/* VIC=8 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 8) \
+}
+
+/* VIC=8 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 8) \
+}
+
+/* VIC=9 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 9) \
+}
+
+/* VIC=9 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 9) \
+}
+
+/* VIC=10 */
+#define V4L2_DV_BT_CEA_2880X480I60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 1, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 10) \
+}
+
+/* VIC=11 */
+#define V4L2_DV_BT_CEA_2880X480I60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 1, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 11) \
+}
+
+/* VIC=12 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 12) \
+}
+
+/* VIC=12 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 12) \
+}
+
+/* VIC=13 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 13) \
+}
+
+/* VIC=13 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 13) \
+}
+
+/* VIC=14 */
+#define V4L2_DV_BT_CEA_1440X480P60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 0, 0, \
+		54000000, 32, 124, 120, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 14) \
+}
+
+/* VIC=15 */
+#define V4L2_DV_BT_CEA_1440X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 0, 0, \
+		54000000, 32, 124, 120, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 15) \
+}
+
+/* VIC=18 */
+#define V4L2_DV_BT_CEA_720X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		27000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 18) \
+}
+
+/* VIC=22 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X576I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 1, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 22) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=25 */
+#define V4L2_DV_BT_CEA_2880X576I50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 1, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 25) \
+}
+
+/* VIC=26 */
+#define V4L2_DV_BT_CEA_2880X576I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 1, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 26) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=29 */
+#define V4L2_DV_BT_CEA_1440X576P50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 0, 0, \
+		54000000, 24, 128, 136, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 29) \
+}
+
+/* VIC=30 */
+#define V4L2_DV_BT_CEA_1440X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 0, 0, \
+		54000000, 24, 128, 136, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 30) \
+}
+
+/* VIC=35 */
+#define V4L2_DV_BT_CEA_2880X480P60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 0, 0, \
+		108000000, 64, 248, 240, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 35) \
+}
+
+/* VIC=36 */
+#define V4L2_DV_BT_CEA_2880X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 0, 0, \
+		108000000, 64, 248, 240, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 36) \
+}
+
+/* VIC=37 */
+#define V4L2_DV_BT_CEA_2880X576P50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 0, 0, \
+		108000000, 48, 256, 272, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 37) \
+}
+
+/* VIC=38 */
+#define V4L2_DV_BT_CEA_2880X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 0, 0, \
+		108000000, 48, 256, 272, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 38) \
+}
+
+/* VIC=39 */
+#define V4L2_DV_BT_CEA_1920X1080I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, V4L2_DV_HSYNC_POS_POL, \
+		72000000, 32, 168, 184, 23, 5, 57, 23, 5, 58, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 39) \
+}
+
+/* VIC=40 */
+#define V4L2_DV_BT_CEA_1920X1080I100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 40) \
+}
+
+/* VIC=41 */
+#define V4L2_DV_BT_CEA_1280X720P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 41) \
+}
+
+/* VIC=42 */
+#define V4L2_DV_BT_CEA_720X576P100_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		54000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 42) \
+}
+
+/* VIC=43 */
+#define V4L2_DV_BT_CEA_720X576P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		54000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 43) \
+}
+
+/* VIC=44 */
+#define V4L2_DV_BT_CEA_1440X576I100_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		54000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 44) \
+}
+
+/* VIC=45 */
+#define V4L2_DV_BT_CEA_1440X576I100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		54000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 45) \
+}
+
+/* VIC=46 */
+#define V4L2_DV_BT_CEA_1920X1080I120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 46) \
+}
+
+/* VIC=47 */
+#define V4L2_DV_BT_CEA_1280X720P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 47) \
+}
+
+/* VIC=48 */
+#define V4L2_DV_BT_CEA_720X480P120_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		54000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 48) \
+}
+
+/* VIC=49 */
+#define V4L2_DV_BT_CEA_720X480P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		54000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 49) \
+}
+
+/* VIC=50 */
+#define V4L2_DV_BT_CEA_1440X480I120_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		54000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 50) \
+}
+
+/* VIC=51 */
+#define V4L2_DV_BT_CEA_1440X480I120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		54000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 51) \
+}
+
+/* VIC=52 */
+#define V4L2_DV_BT_CEA_720X576P200_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		108000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 52) \
+}
+
+/* VIC=53 */
+#define V4L2_DV_BT_CEA_720X576P200_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		108000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 53) \
+}
+
+/* VIC=54 */
+#define V4L2_DV_BT_CEA_1440X576I200_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		108000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 54) \
+}
+
+/* VIC=55 */
+#define V4L2_DV_BT_CEA_1440X576I200_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		108000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 55) \
+}
+
+/* VIC=56 */
+#define V4L2_DV_BT_CEA_720X480P240_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		108000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 56) \
+}
+
+/* VIC=57 */
+#define V4L2_DV_BT_CEA_720X480P240_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		108000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 57) \
+}
+
+/* VIC=58 */
+#define V4L2_DV_BT_CEA_1440X480I240_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		108000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 58) \
+}
+
+/* VIC=59 */
+#define V4L2_DV_BT_CEA_1440X480I240_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		108000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 59) \
+}
+
+/* VIC=63 */
+#define V4L2_DV_BT_CEA_1920X1080P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 63) \
+}
+
+/* VIC=64 */
+#define V4L2_DV_BT_CEA_1920X1080P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 64) \
+}
+
+/* VIC=65 */
+#define V4L2_DV_BT_CEA_1280X720P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 65) \
+}
+
+/* VIC=66 */
+#define V4L2_DV_BT_CEA_1280X720P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 2420, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 66) \
+}
+
+/* VIC=67 */
+#define V4L2_DV_BT_CEA_1280X720P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 67) \
+}
+
+/* VIC=68 */
+#define V4L2_DV_BT_CEA_1280X720P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 68) \
+}
+
+/* VIC=69 */
+#define V4L2_DV_BT_CEA_1280X720P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 69) \
+}
+
+/* VIC=70 */
+#define V4L2_DV_BT_CEA_1280X720P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 70) \
+}
+
+/* VIC=71 */
+#define V4L2_DV_BT_CEA_1280X720P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 71) \
+}
+
+/* VIC=72 */
+#define V4L2_DV_BT_CEA_1920X1080P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 72) \
+}
+
+/* VIC=73 */
+#define V4L2_DV_BT_CEA_1920X1080P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 73) \
+}
+
+/* VIC=74 */
+#define V4L2_DV_BT_CEA_1920X1080P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 74) \
+}
+
+/* VIC=75 */
+#define V4L2_DV_BT_CEA_1920X1080P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 75) \
+}
+
+/* VIC=76 */
+#define V4L2_DV_BT_CEA_1920X1080P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 76) \
+}
+
+/* VIC=77 */
+#define V4L2_DV_BT_CEA_1920X1080P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 77) \
+}
+
+/* VIC=78 */
+#define V4L2_DV_BT_CEA_1920X1080P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 78) \
+}
+
+/* VIC=79 */
+#define V4L2_DV_BT_CEA_1680X720P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1360, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 79) \
+}
+
+/* VIC=80 */
+#define V4L2_DV_BT_CEA_1680X720P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1228, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 80) \
+}
+
+/* VIC=81 */
+#define V4L2_DV_BT_CEA_1680X720P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 700, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 81) \
+}
+
+/* VIC=82 */
+#define V4L2_DV_BT_CEA_1680X720P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		82500000, 260, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 82) \
+}
+
+/* VIC=83 */
+#define V4L2_DV_BT_CEA_1680X720P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 260, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 83) \
+}
+
+/* VIC=84 */
+#define V4L2_DV_BT_CEA_1680X720P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		165000000, 60, 40, 220, 5, 5, 95, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 84) \
+}
+
+/* VIC=85 */
+#define V4L2_DV_BT_CEA_1680X720P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		198000000, 60, 40, 220, 5, 5, 95, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 85) \
+}
+
+/* VIC=86 */
+#define V4L2_DV_BT_CEA_2560X1080P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 998, 44, 148, 4, 5, 11, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 86) \
+}
+
+/* VIC=87 */
+#define V4L2_DV_BT_CEA_2560X1080P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 448, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 87) \
+}
+
+/* VIC=88 */
+#define V4L2_DV_BT_CEA_2560X1080P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		118800000, 768, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 88) \
+}
+
+/* VIC=89 */
+#define V4L2_DV_BT_CEA_2560X1080P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		185625000, 548, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 89) \
+}
+
+/* VIC=90 */
+#define V4L2_DV_BT_CEA_2560X1080P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		198000000, 248, 44, 148, 4, 5, 11, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 90) \
+}
+
+/* VIC=91 */
+#define V4L2_DV_BT_CEA_2560X1080P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		371250000, 218, 44, 148, 4, 5, 161, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 91) \
+}
+
+/* VIC=92 */
+#define V4L2_DV_BT_CEA_2560X1080P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		495000000, 548, 44, 148, 4, 5, 161, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 92) \
+}
+
+/* VIC=103 */
+#define V4L2_DV_BT_CEA_3840X2160P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 103) \
+}
+
+/* VIC=104 */
+#define V4L2_DV_BT_CEA_3840X2160P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 104) \
+}
+
+/* VIC=105 */
+#define V4L2_DV_BT_CEA_3840X2160P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 105) \
+}
+
+/* VIC=106 */
+#define V4L2_DV_BT_CEA_3840X2160P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 106) \
+}
+
+/* VIC=107 */
+#define V4L2_DV_BT_CEA_3840X2160P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 107) \
+}
+
+/* VIC=108 */
+#define V4L2_DV_BT_CEA_1280X720P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 960, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 108) \
+}
+
+/* VIC=109 */
+#define V4L2_DV_BT_CEA_1280X720P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 960, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 109) \
+}
+
+/* VIC=110 */
+#define V4L2_DV_BT_CEA_1680X720P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 810, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 110) \
+}
+
+/* VIC=111 */
+#define V4L2_DV_BT_CEA_1920X1080P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 111) \
+}
+
+/* VIC=112 */
+#define V4L2_DV_BT_CEA_1920X1080P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 112) \
+}
+
+/* VIC=114 */
+#define V4L2_DV_BT_CEA_3840X2160P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 114) \
+}
+
+/* VIC=115 */
+#define V4L2_DV_BT_CEA_4096X2160P48_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 256, 135 }, 115) \
+}
+
+/* VIC=116 */
+#define V4L2_DV_BT_CEA_3840X2160P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 116) \
+}
+
+/* VIC=117 */
+#define V4L2_DV_BT_CEA_3840X2160P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 117) \
+}
+
+/* VIC=118 */
+#define V4L2_DV_BT_CEA_3840X2160P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 118) \
+}
+
+/* VIC=119 */
+#define V4L2_DV_BT_CEA_3840X2160P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 119) \
+}
+
+/* VIC=120 */
+#define V4L2_DV_BT_CEA_3840X2160P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 120) \
+}
+
+/* VIC=121 */
+#define V4L2_DV_BT_CEA_5120X2160P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 1996, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 121) \
+}
+
+/* VIC=122 */
+#define V4L2_DV_BT_CEA_5120X2160P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 1696, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 122) \
+}
+
+/* VIC=123 */
+#define V4L2_DV_BT_CEA_5120X2160P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 664, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 123) \
+}
+
+/* VIC=124 */
+#define V4L2_DV_BT_CEA_5120X2160P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 746, 88, 296, 8, 10, 297, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 124) \
+}
+
+/* VIC=125 */
+#define V4L2_DV_BT_CEA_5120X2160P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 1096, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 125) \
+}
+
+/* VIC=126 */
+#define V4L2_DV_BT_CEA_5120X2160P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 164, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 126) \
+}
+
+/* VIC=127 */
+#define V4L2_DV_BT_CEA_5120X2160P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 1096, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 127) \
+}
+
+/* VIC=193 */
+#define V4L2_DV_BT_CEA_5120X2160P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 154, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 193) \
+}
+
+/* VIC=194 */
+#define V4L2_DV_BT_CEA_7680X4320P24_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 194) \
+}
+
+/* VIC=195 */
+#define V4L2_DV_BT_CEA_7680X4320P25_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 195) \
+}
+
+/* VIC=196 */
+#define V4L2_DV_BT_CEA_7680X4320P30_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 196) \
+}
+
+/* VIC=197 */
+#define V4L2_DV_BT_CEA_7680X4320P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 197) \
+}
+
+/* VIC=198 */
+#define V4L2_DV_BT_CEA_7680X4320P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 198) \
+}
+
+/* VIC=199 */
+#define V4L2_DV_BT_CEA_7680X4320P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 199) \
+}
+
+/* VIC=200 */
+#define V4L2_DV_BT_CEA_7680X4320P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 2112, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 200) \
+}
+
+/* VIC=201 */
+#define V4L2_DV_BT_CEA_7680X4320P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 352, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 201) \
+}
+
+/* VIC=202 */
+#define V4L2_DV_BT_CEA_7680X4320P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 202) \
+}
+
+/* VIC=203 */
+#define V4L2_DV_BT_CEA_7680X4320P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 203) \
+}
+
+/* VIC=204 */
+#define V4L2_DV_BT_CEA_7680X4320P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 204) \
+}
+
+/* VIC=205 */
+#define V4L2_DV_BT_CEA_7680X4320P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 205) \
+}
+
+/* VIC=206 */
+#define V4L2_DV_BT_CEA_7680X4320P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 206) \
+}
+
+/* VIC=207 */
+#define V4L2_DV_BT_CEA_7680X4320P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 207) \
+}
+
+/* VIC=208 */
+#define V4L2_DV_BT_CEA_7680X4320P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 2112, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 208) \
+}
+
+/* VIC=209 */
+#define V4L2_DV_BT_CEA_7680X4320P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 352, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 209) \
+}
+
+/* VIC=210 */
+#define V4L2_DV_BT_CEA_10240X4320P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 1492, 176, 592, 16, 20, 594, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 210) \
+}
+
+/* VIC=211 */
+#define V4L2_DV_BT_CEA_10240X4320P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 2492, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 211) \
+}
+
+/* VIC=212 */
+#define V4L2_DV_BT_CEA_10240X4320P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 212) \
+}
+
+/* VIC=213 */
+#define V4L2_DV_BT_CEA_10240X4320P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 1492, 176, 592, 16, 20, 594, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 213) \
+}
+
+/* VIC=214 */
+#define V4L2_DV_BT_CEA_10240X4320P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 2492, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 214) \
+}
+
+/* VIC=215 */
+#define V4L2_DV_BT_CEA_10240X4320P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 215) \
+}
+
+/* VIC=216 */
+#define V4L2_DV_BT_CEA_10240X4320P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		5940000000ULL, 2192, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 216) \
+}
+
+/* VIC=217 */
+#define V4L2_DV_BT_CEA_10240X4320P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		5940000000ULL, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 217) \
+}
+
+/* VIC=218 */
+#define V4L2_DV_BT_CEA_4096X2160P100_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 800, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 256, 135 }, 218) \
+}
+
+/* VIC=219 */
+#define V4L2_DV_BT_CEA_4096X2160P120_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 256, 135 }, 219) \
+}
 
 /* VESA Discrete Monitor Timings as per version 1.0, revision 12 */
 
#19 lore raw

Re: [PATCH 7/9] media: v4l2-dv-timings: Add more CEA/CTA-861 video format timings

Quoted 55 lines · Nelson Costa

Hi Hans,

Thanks for your comments and feedback!

From: Hans Verkuil <[email protected]>
Date: qua, jun 02, 2021 at 13:26:17

Quoted 16 lines

Hi Nelson,

Quoted 13 lines · Nelson Costa

This extends the support for more video format timings based on SPECs CEA-861-F and CTA-861-G.

NOTE: For the newer SPECs the CEA was unified to the CTA. The CTA-861-G then includes the CEA-861-F timings besides the new timings that are specified.

CEA-861-F: Specifies the Video timings for VICs 1-107.
CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219.

With this patch, the array v4l2_dv_timings_presets has support for all video timings specified in CTA-861-G.

Quoted 7 lines
Quoted 4 lines
---
 drivers/media/v4l2-core/v4l2-dv-timings.c |  139 +++
 include/uapi/linux/v4l2-dv-timings.h      | 1595 ++++++++++++++++++++++++++++-

I prefer to split this up in two patches, one for each header.

I agree! It will be addressed in the next patch series.

Quoted 3 lines

The v4l2-dv-timings.h changes look good (my compliments for all the work you put into that!).

Thanks!

Quoted 7 lines

I am more concerned about adding all these timings to v4l2_dv_timings_presets.

There are really two different things going on here: the v4l2_dv_timings_presets array is used both by v4l2_enum_dv_timings_cap() to list supported commonly used timings, or to match against timings parameters (v4l2_find_dv_timings_cap()), and as a lookup table when receiving a specific VIC code (v4l2_find_dv_timings_cea861_vic()).

Quoted 6 lines

All the new timings you added are really only relevant in the last case when you have the vic code.

I think it is better to create a second array v4l2_dv_timings_non_square_vics[] (or a better name!) that contains these timings.

I understood.

Quoted 7 lines

We can then create another array as you said. But when you say "non_square"
you mean that the vics have "Pixel Aspect Ratio != 1:1"?

Because the new vics added have both kind of vics with "Pixel Aspect Ratio != 1:1"
and also "Pixel Aspect Ratio == 1:1".

There are? It's confusing since for 1:1 pixel aspect ratios I expect that the picture aspect ratio is set to { 0, 0 }, instead they are all filled in.

I think it will be clearer if I see a v2 where the picture aspect ratio and the V4L2_DV_FL_HAS_PICTURE_ASPECT flag are only set for the non-square pixel timings. Also, for the timings with 1:1 pixel aspect ratio you don't need to add the PA... suffix. That suffix only makes sense for non-square pixel aspect ratios. It's confusing otherwise.

Quoted 3 lines

So, for the new vics should we create a second array with name v4l2_dv_timings_extended_vics[]?

The new vics with non-square pixel aspect ratios, or with pixel repetition.

Quoted 21 lines
Quoted 4 lines

Then if v4l2_find_dv_timings_cea861_vic() can't find the vic in the presets table it will look for it in the new table.

I agree.

Quoted 5 lines

For the 'variable vertical total lines timings' there probably should be a new arg added to the v4l2_find_dv_timings_cea861_vic() parameter list with the detected number of lines, and v4l2_find_dv_timings_cea861_vic() can use that to find the correct VTOT variant.

Makes sense, because we can have different timings with the same vic but with different VTOT.

Quoted 4 lines

Another issue I have is that I am unsure about the pixel repetition support in current HDMI receiver drivers. I've never tested this, and so I am not sure what will happen if you transmit such a format. Have you tested this yourself?

Quoted 5 lines

I'll try to test that. But in our driver we use these vics info mainly to get
the Picture Aspect info, and so some other fields are not used. So the test might
not be useful for this kind of validation.

Well, you still have to be able to capture the video, right? That's really the question: can you capture it and does it look as expected?

Quoted 8 lines
Quoted 5 lines

I wonder if support for such VICs should be optional, perhaps again through an argument to v4l2_find_dv_timings_cea861_vic() so drivers can decide to support such formats or not.

You mean something like this below?

Quoted 8 lines

v4l2_find_dv_timings_cea861_vic(.., vic, bool check_extended, vtot_extended)

where:
- check_extended:
* if true means to check the vic in the second array?
* if false means to check the vic only in the presets array?
- vtot_extended: the value of VTOT variant

Something along those lines, yes. I don't really like 'extended', perhaps bool presets_only? So inverting the meaning. 'vtot_extended' can just be vtot.

Quoted 3 lines

My concern here is the incompatibility that the change of this function would cause in other implementations.

Why? It's only used in adv7604.c, and there you can set check_extended to false.

Quoted 5 lines

Once the idea would be to create a second array, should we think to create a second function for that like v4l2_find_dv_timings_cea861_extended_vic()?
What do you think?

Not really worth it to make a new function, it's easier to just update adv7604.

Regards,

Hans

Quoted 1,779 lines

Thanks,

BR,

Nelson Costa

Quoted 1,770 lines

Regards,

Hans

Quoted 1,766 lines
 2 files changed, 1733 insertions(+), 1 deletion(-)
drivers/media/v4l2-core/v4l2-dv-timings.c +139 -0
index 230d65a..0766e0c 100644
@@ -133,6 +133,145 @@ const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
 	V4L2_DV_BT_CEA_4096X2160P50,
 	V4L2_DV_BT_DMT_4096X2160P59_94_RB,
 	V4L2_DV_BT_CEA_4096X2160P60,
+	V4L2_DV_BT_CEA_720X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X480I60_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_2880X480I60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480I60_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9,
+	V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9,
+	V4L2_DV_BT_CEA_1440X480P60_PA4_3,
+	V4L2_DV_BT_CEA_1440X480P60_PA16_9,
+	V4L2_DV_BT_CEA_720X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_720X576I50_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_2880X576I50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576I50_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9,
+	V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9,
+	V4L2_DV_BT_CEA_1440X576P50_PA4_3,
+	V4L2_DV_BT_CEA_1440X576P50_PA16_9,
+	V4L2_DV_BT_CEA_2880X480P60_PA4_3,
+	V4L2_DV_BT_CEA_2880X480P60_PA16_9,
+	V4L2_DV_BT_CEA_2880X576P50_PA4_3,
+	V4L2_DV_BT_CEA_2880X576P50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I50_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P100_PA16_9,
+	V4L2_DV_BT_CEA_720X576P100_PA4_3,
+	V4L2_DV_BT_CEA_720X576P100_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I100_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I100_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080I120_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P120_PA16_9,
+	V4L2_DV_BT_CEA_720X480P120_PA4_3,
+	V4L2_DV_BT_CEA_720X480P120_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I120_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I120_PA16_9,
+	V4L2_DV_BT_CEA_720X576P200_PA4_3,
+	V4L2_DV_BT_CEA_720X576P200_PA16_9,
+	V4L2_DV_BT_CEA_1440X576I200_PA4_3,
+	V4L2_DV_BT_CEA_1440X576I200_PA16_9,
+	V4L2_DV_BT_CEA_720X480P240_PA4_3,
+	V4L2_DV_BT_CEA_720X480P240_PA16_9,
+	V4L2_DV_BT_CEA_1440X480I240_PA4_3,
+	V4L2_DV_BT_CEA_1440X480I240_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P120_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P100_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P120_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P24_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P25_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P30_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P50_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P60_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P100_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P120_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P24_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P25_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P30_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P50_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P60_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P100_PA64_27,
+	V4L2_DV_BT_CEA_2560X1080P120_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_1280X720P48_PA16_9,
+	V4L2_DV_BT_CEA_1280X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1680X720P48_PA64_27,
+	V4L2_DV_BT_CEA_1920X1080P48_PA16_9,
+	V4L2_DV_BT_CEA_1920X1080P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P48_PA16_9,
+	V4L2_DV_BT_CEA_4096X2160P48_PA256_135,
+	V4L2_DV_BT_CEA_3840X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P100_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P120_PA16_9,
+	V4L2_DV_BT_CEA_3840X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_3840X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P24_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P25_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P30_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P48_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P50_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P60_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P100_PA64_27,
+	V4L2_DV_BT_CEA_5120X2160P120_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P24_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P25_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P30_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P48_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P50_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P60_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P100_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P120_PA16_9,
+	V4L2_DV_BT_CEA_7680X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_7680X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P24_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P25_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P30_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P48_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P50_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P60_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P100_PA64_27,
+	V4L2_DV_BT_CEA_10240X4320P120_PA64_27,
+	V4L2_DV_BT_CEA_4096X2160P100_PA256_135,
+	V4L2_DV_BT_CEA_4096X2160P120_PA256_135,
 	{ }
 };
 EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
include/uapi/linux/v4l2-dv-timings.h +1594 -1
index b52b67c..900530b 100644
@@ -29,7 +29,14 @@
 	.bt = { _width , ## args }
 #endif
 
-/* CEA-861-F timings (i.e. standard HDTV timings) */
+/* CEA-861-F timings (i.e. standard HDTV timings)
+ * NOTE: For the newer SPECs the CEA was unified to the CTA.
+ * The CTA-861-G includes the CEA-861-F timings besides the
+ * new timings that are specified.
+ *
+ * CEA-861-F: Specifies the Video timings for VICs 1-107
+ * CTA-861-G: Specifies the Video timings for VICs 1-107, 108-127, 193-219
+ */
 
 #define V4L2_DV_BT_CEA_640X480P59_94 { \
 	.type = V4L2_DV_BT_656_1120, \
@@ -297,6 +304,1592 @@
 		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 102) \
 }
 
+/* VIC=3 */
+#define V4L2_DV_BT_CEA_720X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		27000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 3) \
+}
+
+/* VIC=7 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X480I60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 1, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 7) \
+}
+
+/* VIC=8 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT262_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 8) \
+}
+
+/* VIC=8 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT263_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 8) \
+}
+
+/* VIC=9 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT262_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 9) \
+}
+
+/* VIC=9 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X240P60_VTOT263_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 240, 0, 0, \
+		13500000, 19, 62, 57, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 9) \
+}
+
+/* VIC=10 */
+#define V4L2_DV_BT_CEA_2880X480I60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 1, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 10) \
+}
+
+/* VIC=11 */
+#define V4L2_DV_BT_CEA_2880X480I60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 1, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 11) \
+}
+
+/* VIC=12 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 12) \
+}
+
+/* VIC=12 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 12) \
+}
+
+/* VIC=13 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT262_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 4, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 13) \
+}
+
+/* VIC=13 */
+#define V4L2_DV_BT_CEA_2880X240P60_VTOT263_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 240, 0, 0, \
+		54000000, 76, 248, 228, 5, 3, 15, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 13) \
+}
+
+/* VIC=14 */
+#define V4L2_DV_BT_CEA_1440X480P60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 0, 0, \
+		54000000, 32, 124, 120, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 14) \
+}
+
+/* VIC=15 */
+#define V4L2_DV_BT_CEA_1440X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 0, 0, \
+		54000000, 32, 124, 120, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 15) \
+}
+
+/* VIC=18 */
+#define V4L2_DV_BT_CEA_720X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		27000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 18) \
+}
+
+/* VIC=22 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X576I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 1, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 22) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT312_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT313_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=23 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT314_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 23) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT312_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT313_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=24 */
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.
+ */
+#define V4L2_DV_BT_CEA_720X288P50_VTOT314_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 288, 0, 0, \
+		13500000, 12, 63, 69, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 24) \
+}
+
+/* VIC=25 */
+#define V4L2_DV_BT_CEA_2880X576I50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 1, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 25) \
+}
+
+/* VIC=26 */
+#define V4L2_DV_BT_CEA_2880X576I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 1, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 26) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=27 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 27) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT312_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 2, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT313_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 3, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=28 */
+#define V4L2_DV_BT_CEA_2880X288P50_VTOT314_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 288, 0, 0, \
+		54000000, 48, 252, 276, 4, 3, 19, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 28) \
+}
+
+/* VIC=29 */
+#define V4L2_DV_BT_CEA_1440X576P50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 0, 0, \
+		54000000, 24, 128, 136, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 29) \
+}
+
+/* VIC=30 */
+#define V4L2_DV_BT_CEA_1440X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 0, 0, \
+		54000000, 24, 128, 136, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 30) \
+}
+
+/* VIC=35 */
+#define V4L2_DV_BT_CEA_2880X480P60_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 0, 0, \
+		108000000, 64, 248, 240, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 35) \
+}
+
+/* VIC=36 */
+#define V4L2_DV_BT_CEA_2880X480P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 480, 0, 0, \
+		108000000, 64, 248, 240, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 36) \
+}
+
+/* VIC=37 */
+#define V4L2_DV_BT_CEA_2880X576P50_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 0, 0, \
+		108000000, 48, 256, 272, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 37) \
+}
+
+/* VIC=38 */
+#define V4L2_DV_BT_CEA_2880X576P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2880, 576, 0, 0, \
+		108000000, 48, 256, 272, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 38) \
+}
+
+/* VIC=39 */
+#define V4L2_DV_BT_CEA_1920X1080I50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, V4L2_DV_HSYNC_POS_POL, \
+		72000000, 32, 168, 184, 23, 5, 57, 23, 5, 58, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 39) \
+}
+
+/* VIC=40 */
+#define V4L2_DV_BT_CEA_1920X1080I100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 40) \
+}
+
+/* VIC=41 */
+#define V4L2_DV_BT_CEA_1280X720P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 41) \
+}
+
+/* VIC=42 */
+#define V4L2_DV_BT_CEA_720X576P100_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		54000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 42) \
+}
+
+/* VIC=43 */
+#define V4L2_DV_BT_CEA_720X576P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		54000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 43) \
+}
+
+/* VIC=44 */
+#define V4L2_DV_BT_CEA_1440X576I100_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		54000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 44) \
+}
+
+/* VIC=45 */
+#define V4L2_DV_BT_CEA_1440X576I100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		54000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 45) \
+}
+
+/* VIC=46 */
+#define V4L2_DV_BT_CEA_1920X1080I120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 46) \
+}
+
+/* VIC=47 */
+#define V4L2_DV_BT_CEA_1280X720P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 47) \
+}
+
+/* VIC=48 */
+#define V4L2_DV_BT_CEA_720X480P120_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		54000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 48) \
+}
+
+/* VIC=49 */
+#define V4L2_DV_BT_CEA_720X480P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		54000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 49) \
+}
+
+/* VIC=50 */
+#define V4L2_DV_BT_CEA_1440X480I120_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		54000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 50) \
+}
+
+/* VIC=51 */
+#define V4L2_DV_BT_CEA_1440X480I120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		54000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 51) \
+}
+
+/* VIC=52 */
+#define V4L2_DV_BT_CEA_720X576P200_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		108000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 52) \
+}
+
+/* VIC=53 */
+#define V4L2_DV_BT_CEA_720X576P200_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		108000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 53) \
+}
+
+/* VIC=54 */
+#define V4L2_DV_BT_CEA_1440X576I200_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		108000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 54) \
+}
+
+/* VIC=55 */
+#define V4L2_DV_BT_CEA_1440X576I200_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 576, 1, 0, \
+		108000000, 24, 126, 138, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 55) \
+}
+
+/* VIC=56 */
+#define V4L2_DV_BT_CEA_720X480P240_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		108000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 56) \
+}
+
+/* VIC=57 */
+#define V4L2_DV_BT_CEA_720X480P240_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		108000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 57) \
+}
+
+/* VIC=58 */
+#define V4L2_DV_BT_CEA_1440X480I240_PA4_3 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		108000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 58) \
+}
+
+/* VIC=59 */
+#define V4L2_DV_BT_CEA_1440X480I240_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 480, 1, 0, \
+		108000000, 38, 124, 114, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE | \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 59) \
+}
+
+/* VIC=63 */
+#define V4L2_DV_BT_CEA_1920X1080P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 63) \
+}
+
+/* VIC=64 */
+#define V4L2_DV_BT_CEA_1920X1080P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 64) \
+}
+
+/* VIC=65 */
+#define V4L2_DV_BT_CEA_1280X720P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 65) \
+}
+
+/* VIC=66 */
+#define V4L2_DV_BT_CEA_1280X720P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 2420, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 66) \
+}
+
+/* VIC=67 */
+#define V4L2_DV_BT_CEA_1280X720P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 67) \
+}
+
+/* VIC=68 */
+#define V4L2_DV_BT_CEA_1280X720P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 68) \
+}
+
+/* VIC=69 */
+#define V4L2_DV_BT_CEA_1280X720P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 69) \
+}
+
+/* VIC=70 */
+#define V4L2_DV_BT_CEA_1280X720P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 70) \
+}
+
+/* VIC=71 */
+#define V4L2_DV_BT_CEA_1280X720P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 71) \
+}
+
+/* VIC=72 */
+#define V4L2_DV_BT_CEA_1920X1080P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 72) \
+}
+
+/* VIC=73 */
+#define V4L2_DV_BT_CEA_1920X1080P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 73) \
+}
+
+/* VIC=74 */
+#define V4L2_DV_BT_CEA_1920X1080P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 74) \
+}
+
+/* VIC=75 */
+#define V4L2_DV_BT_CEA_1920X1080P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 75) \
+}
+
+/* VIC=76 */
+#define V4L2_DV_BT_CEA_1920X1080P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 76) \
+}
+
+/* VIC=77 */
+#define V4L2_DV_BT_CEA_1920X1080P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 77) \
+}
+
+/* VIC=78 */
+#define V4L2_DV_BT_CEA_1920X1080P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 78) \
+}
+
+/* VIC=79 */
+#define V4L2_DV_BT_CEA_1680X720P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1360, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 79) \
+}
+
+/* VIC=80 */
+#define V4L2_DV_BT_CEA_1680X720P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1228, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 80) \
+}
+
+/* VIC=81 */
+#define V4L2_DV_BT_CEA_1680X720P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 700, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 81) \
+}
+
+/* VIC=82 */
+#define V4L2_DV_BT_CEA_1680X720P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		82500000, 260, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 82) \
+}
+
+/* VIC=83 */
+#define V4L2_DV_BT_CEA_1680X720P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 260, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 83) \
+}
+
+/* VIC=84 */
+#define V4L2_DV_BT_CEA_1680X720P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		165000000, 60, 40, 220, 5, 5, 95, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 84) \
+}
+
+/* VIC=85 */
+#define V4L2_DV_BT_CEA_1680X720P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		198000000, 60, 40, 220, 5, 5, 95, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 85) \
+}
+
+/* VIC=86 */
+#define V4L2_DV_BT_CEA_2560X1080P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 998, 44, 148, 4, 5, 11, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 86) \
+}
+
+/* VIC=87 */
+#define V4L2_DV_BT_CEA_2560X1080P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 448, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 87) \
+}
+
+/* VIC=88 */
+#define V4L2_DV_BT_CEA_2560X1080P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		118800000, 768, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 88) \
+}
+
+/* VIC=89 */
+#define V4L2_DV_BT_CEA_2560X1080P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		185625000, 548, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 89) \
+}
+
+/* VIC=90 */
+#define V4L2_DV_BT_CEA_2560X1080P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		198000000, 248, 44, 148, 4, 5, 11, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 90) \
+}
+
+/* VIC=91 */
+#define V4L2_DV_BT_CEA_2560X1080P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		371250000, 218, 44, 148, 4, 5, 161, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 91) \
+}
+
+/* VIC=92 */
+#define V4L2_DV_BT_CEA_2560X1080P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		495000000, 548, 44, 148, 4, 5, 161, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 92) \
+}
+
+/* VIC=103 */
+#define V4L2_DV_BT_CEA_3840X2160P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 103) \
+}
+
+/* VIC=104 */
+#define V4L2_DV_BT_CEA_3840X2160P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 104) \
+}
+
+/* VIC=105 */
+#define V4L2_DV_BT_CEA_3840X2160P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 105) \
+}
+
+/* VIC=106 */
+#define V4L2_DV_BT_CEA_3840X2160P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 106) \
+}
+
+/* VIC=107 */
+#define V4L2_DV_BT_CEA_3840X2160P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 107) \
+}
+
+/* VIC=108 */
+#define V4L2_DV_BT_CEA_1280X720P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 960, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 108) \
+}
+
+/* VIC=109 */
+#define V4L2_DV_BT_CEA_1280X720P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		90000000, 960, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 109) \
+}
+
+/* VIC=110 */
+#define V4L2_DV_BT_CEA_1680X720P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		99000000, 810, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 110) \
+}
+
+/* VIC=111 */
+#define V4L2_DV_BT_CEA_1920X1080P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 111) \
+}
+
+/* VIC=112 */
+#define V4L2_DV_BT_CEA_1920X1080P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 112) \
+}
+
+/* VIC=114 */
+#define V4L2_DV_BT_CEA_3840X2160P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 114) \
+}
+
+/* VIC=115 */
+#define V4L2_DV_BT_CEA_4096X2160P48_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 256, 135 }, 115) \
+}
+
+/* VIC=116 */
+#define V4L2_DV_BT_CEA_3840X2160P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 116) \
+}
+
+/* VIC=117 */
+#define V4L2_DV_BT_CEA_3840X2160P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 117) \
+}
+
+/* VIC=118 */
+#define V4L2_DV_BT_CEA_3840X2160P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 118) \
+}
+
+/* VIC=119 */
+#define V4L2_DV_BT_CEA_3840X2160P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 119) \
+}
+
+/* VIC=120 */
+#define V4L2_DV_BT_CEA_3840X2160P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 120) \
+}
+
+/* VIC=121 */
+#define V4L2_DV_BT_CEA_5120X2160P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 1996, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 121) \
+}
+
+/* VIC=122 */
+#define V4L2_DV_BT_CEA_5120X2160P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 1696, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 122) \
+}
+
+/* VIC=123 */
+#define V4L2_DV_BT_CEA_5120X2160P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		396000000, 664, 88, 296, 8, 10, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 123) \
+}
+
+/* VIC=124 */
+#define V4L2_DV_BT_CEA_5120X2160P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 746, 88, 296, 8, 10, 297, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 124) \
+}
+
+/* VIC=125 */
+#define V4L2_DV_BT_CEA_5120X2160P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 1096, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 125) \
+}
+
+/* VIC=126 */
+#define V4L2_DV_BT_CEA_5120X2160P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		742500000, 164, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 126) \
+}
+
+/* VIC=127 */
+#define V4L2_DV_BT_CEA_5120X2160P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 1096, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 127) \
+}
+
+/* VIC=193 */
+#define V4L2_DV_BT_CEA_5120X2160P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(5120, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 154, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 193) \
+}
+
+/* VIC=194 */
+#define V4L2_DV_BT_CEA_7680X4320P24_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 194) \
+}
+
+/* VIC=195 */
+#define V4L2_DV_BT_CEA_7680X4320P25_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 195) \
+}
+
+/* VIC=196 */
+#define V4L2_DV_BT_CEA_7680X4320P30_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 196) \
+}
+
+/* VIC=197 */
+#define V4L2_DV_BT_CEA_7680X4320P48_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 197) \
+}
+
+/* VIC=198 */
+#define V4L2_DV_BT_CEA_7680X4320P50_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 198) \
+}
+
+/* VIC=199 */
+#define V4L2_DV_BT_CEA_7680X4320P60_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 199) \
+}
+
+/* VIC=200 */
+#define V4L2_DV_BT_CEA_7680X4320P100_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 2112, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 16, 9 }, 200) \
+}
+
+/* VIC=201 */
+#define V4L2_DV_BT_CEA_7680X4320P120_PA16_9 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 352, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 16, 9 }, 201) \
+}
+
+/* VIC=202 */
+#define V4L2_DV_BT_CEA_7680X4320P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 202) \
+}
+
+/* VIC=203 */
+#define V4L2_DV_BT_CEA_7680X4320P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 203) \
+}
+
+/* VIC=204 */
+#define V4L2_DV_BT_CEA_7680X4320P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 204) \
+}
+
+/* VIC=205 */
+#define V4L2_DV_BT_CEA_7680X4320P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2552, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 205) \
+}
+
+/* VIC=206 */
+#define V4L2_DV_BT_CEA_7680X4320P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 2352, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 206) \
+}
+
+/* VIC=207 */
+#define V4L2_DV_BT_CEA_7680X4320P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2376000000ULL, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 207) \
+}
+
+/* VIC=208 */
+#define V4L2_DV_BT_CEA_7680X4320P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 2112, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 208) \
+}
+
+/* VIC=209 */
+#define V4L2_DV_BT_CEA_7680X4320P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		4752000000ULL, 352, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 209) \
+}
+
+/* VIC=210 */
+#define V4L2_DV_BT_CEA_10240X4320P24_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 1492, 176, 592, 16, 20, 594, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 210) \
+}
+
+/* VIC=211 */
+#define V4L2_DV_BT_CEA_10240X4320P25_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 2492, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 211) \
+}
+
+/* VIC=212 */
+#define V4L2_DV_BT_CEA_10240X4320P30_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1485000000, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 212) \
+}
+
+/* VIC=213 */
+#define V4L2_DV_BT_CEA_10240X4320P48_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 1492, 176, 592, 16, 20, 594, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 213) \
+}
+
+/* VIC=214 */
+#define V4L2_DV_BT_CEA_10240X4320P50_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 2492, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 214) \
+}
+
+/* VIC=215 */
+#define V4L2_DV_BT_CEA_10240X4320P60_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		2970000000ULL, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 215) \
+}
+
+/* VIC=216 */
+#define V4L2_DV_BT_CEA_10240X4320P100_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		5940000000ULL, 2192, 176, 592, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 64, 27 }, 216) \
+}
+
+/* VIC=217 */
+#define V4L2_DV_BT_CEA_10240X4320P120_PA64_27 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(10240, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		5940000000ULL, 288, 176, 296, 16, 20, 144, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 64, 27 }, 217) \
+}
+
+/* VIC=218 */
+#define V4L2_DV_BT_CEA_4096X2160P100_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 800, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 256, 135 }, 218) \
+}
+
+/* VIC=219 */
+#define V4L2_DV_BT_CEA_4096X2160P120_PA256_135 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		1188000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 256, 135 }, 219) \
+}
 
 /* VESA Discrete Monitor Timings as per version 1.0, revision 12 */