* [PATCH v2] dt-bindings: mfd: twl: Reference converted schemas for subnodes
From: Jihed Chaibi @ 2026-03-27 8:23 UTC (permalink / raw)
To: andreas
Cc: lee, robh, krzk+dt, conor+dt, devicetree, linux-kernel,
jihed.chaibi.dev
Now that all TWL subnode bindings (audio, keypad, twl4030-usb, gpio,
usb-comparator) have been converted and merged into mainline, update the
parent ti,twl.yaml to properly reference them via $ref.
Replace the inline compatible definitions with $ref to the appropriate
schemas and unevaluatedProperties: false, matching the pattern already
used by the madc, gpadc, and charger subnodes.
Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
---
Changes in v2:
- Drop "YAML" from subject and commit message
- Remove incorrect claim that subnode properties were not being validated
.../devicetree/bindings/mfd/ti,twl.yaml | 50 ++++---------------
1 file changed, 10 insertions(+), 40 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/ti,twl.yaml b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
index 9cc3e4721612..a3af8e717ec7 100644
--- a/Documentation/devicetree/bindings/mfd/ti,twl.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
@@ -265,47 +265,23 @@ properties:
audio:
type: object
- additionalProperties: true
-
- properties:
- compatible:
- const: ti,twl4030-audio
-
- required:
- - compatible
+ $ref: /schemas/sound/ti,twl4030-audio.yaml
+ unevaluatedProperties: false
keypad:
type: object
- additionalProperties: true
-
- properties:
- compatible:
- const: ti,twl4030-keypad
-
- required:
- - compatible
+ $ref: /schemas/input/ti,twl4030-keypad.yaml
+ unevaluatedProperties: false
twl4030-usb:
type: object
- additionalProperties: true
-
- properties:
- compatible:
- const: ti,twl4030-usb
-
- required:
- - compatible
+ $ref: /schemas/usb/ti,twl4030-usb.yaml
+ unevaluatedProperties: false
gpio:
type: object
- additionalProperties: true
-
- properties:
- compatible:
- const: ti,twl4030-gpio
-
- required:
- - compatible
+ $ref: /schemas/gpio/ti,twl4030-gpio.yaml
+ unevaluatedProperties: false
power:
type: object
@@ -371,14 +347,8 @@ properties:
usb-comparator:
type: object
- additionalProperties: true
-
- properties:
- compatible:
- const: ti,twl6030-usb
-
- required:
- - compatible
+ $ref: /schemas/usb/ti,twl6030-usb.yaml
+ unevaluatedProperties: false
pwm:
type: object
--
2.47.3
^ permalink raw reply related
* Re: [PATCH 01/12] dt-bindings: i3c: Add mipi-i3c-static-method to support SETAASA
From: Akhil R @ 2026-03-27 8:18 UTC (permalink / raw)
To: alexandre.belloni
Cc: Frank.Li, acpica-devel, akhilrajeev, conor+dt, conor, devicetree,
ebiggers, fredrik.markstrom, jonathanh, krzk+dt, lenb, linux-acpi,
linux-hwmon, linux-i3c, linux-kernel, linux-tegra, linux,
miquel.raynal, p.zabel, rafael, robert.moore, robh, smangipudi,
thierry.reding
In-Reply-To: <202603261544313f63018c@mail.local>
On Thu, 26 Mar 2026 16:44:31 +0100, Alexandre Belloni wrote:
> On 26/03/2026 10:05:03-0500, Rob Herring wrote:
>> On Wed, Mar 18, 2026 at 05:31:50PM +0000, Conor Dooley wrote:
>> > On Wed, Mar 18, 2026 at 10:57:14PM +0530, Akhil R wrote:
>> > > Add the 'mipi-i3c-static-method' property mentioned in the MIPI I3C
>> > > Discovery and Configuration Specification [1] to specify which discovery
>> > > method an I3C device supports during bus initialization. The property is
>> > > a bitmap, where a bit value of 1 indicates support for that method, and 0
>> > > indicates lack of support.
>> > > Bit 0: SETDASA CCC (Direct)
>> > > Bit 1: SETAASA CCC (Broadcast)
>> > > Bit 2: Other CCC (vendor / standards extension)
>> > > All other bits are reserved.
>> > >
>> > > It is specifically needed when an I3C device requires SETAASA for the
>> > > address assignment. SETDASA will be supported by default if this property
>> > > is absent - which means for now the property just serves as a flag to
>> > > enable SETAASA, but keep the property as a bitmap to align with the
>> > > specifications.
>> > >
>> > > [1] https://www.mipi.org/specifications/disco
>> > >
>> > > Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
>> > > ---
>> > > .../devicetree/bindings/i3c/i3c.yaml | 30 ++++++++++++++++---
>> > > 1 file changed, 26 insertions(+), 4 deletions(-)
>> > >
>> > > diff --git a/Documentation/devicetree/bindings/i3c/i3c.yaml b/Documentation/devicetree/bindings/i3c/i3c.yaml
>> > > index e25fa72fd785..1705d90d4d79 100644
>> > > --- a/Documentation/devicetree/bindings/i3c/i3c.yaml
>> > > +++ b/Documentation/devicetree/bindings/i3c/i3c.yaml
>> > > @@ -31,10 +31,12 @@ properties:
>> > > described in the device tree, which in turn means we have to describe
>> > > I3C devices.
>> > >
>> > > - Another use case for describing an I3C device in the device tree is when
>> > > - this I3C device has a static I2C address and we want to assign it a
>> > > - specific I3C dynamic address before the DAA takes place (so that other
>> > > - devices on the bus can't take this dynamic address).
>> > > + Other use-cases for describing an I3C device in the device tree are:
>> > > + - When the I3C device has a static I2C address and we want to assign
>> > > + it a specific I3C dynamic address before the DAA takes place (so
>> > > + that other devices on the bus can't take this dynamic address).
>> > > + - When the I3C device requires SETAASA for its discovery and uses a
>> > > + pre-defined static address.
>> > >
>> > > "#size-cells":
>> > > const: 0
>> > > @@ -147,6 +149,26 @@ patternProperties:
>> > > through SETDASA. If static address is not present, this address is assigned
>> > > through SETNEWDA after assigning a temporary address via ENTDAA.
>> > >
>> > > + mipi-i3c-static-method:
>> > > + $ref: /schemas/types.yaml#/definitions/uint32
>> > > + minimum: 0x1
>> > > + maximum: 0xff
>> > > + default: 1
>> > > + description: |
>> > > + Bitmap describing which methods of Dynamic Address Assignment from a
>> > > + static address are supported by this I3C Target. A bit value of 1
>> > > + indicates support for that method, and 0 indicates lack of support.
>> >
>> > I really am not keen on properties that are bitmaps, why can't we just
>> > use the strings "setdasa", "setaasa" etc?
>>
>> If this comes from a specification, then I'd tend to just copy it rather
>> than invent our own thing. Obviously if is something structured
>> fundamentally different from how DT is designed, then we wouldn't. But
>> this is just a simple property.
>>
>
> The issue being that the specification is not public so it is difficult
> to take any decision.
There is a public version available in the same link, but you would still
have to provide them a name and an email ID. The document will be sent to
the mail ID.
Regards,
Akhil
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: thermal: st,thermal-spear1340: convert to dtschema
From: Krzysztof Kozlowski @ 2026-03-27 8:06 UTC (permalink / raw)
To: Gopi Krishna Menon
Cc: rafael, daniel.lezcano, rui.zhang, lukasz.luba, robh, krzk+dt,
vireshk, conor+dt, linux-pm, devicetree, linux-kernel,
linux-arm-kernel, soc, daniel.baluta, simona.toaca, d-gole,
m-chawdhry
In-Reply-To: <20260324-belligerent-armadillo-of-camouflage-e52f7b@quoll>
On 24/03/2026 10:30, Krzysztof Kozlowski wrote:
> On Mon, Mar 23, 2026 at 07:08:08PM +0530, Gopi Krishna Menon wrote:
>> +properties:
>> + compatible:
>> + const: st,thermal-spear1340
>> +
>> + reg:
>> + maxItems: 1
>> +
>> + st,thermal-flags:
>> + description: flags used to enable thermal sensor
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> +
>> +required:
>> + - compatible
>> + - reg
>> + - st,thermal-flags
>> +
>> +unevaluatedProperties: false
>
> additionalProperties: true
Thanks for pinging me on IRC about this - it should be:
additionalProperties: false
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v9 1/2] dt-bindings: display: Add ITE IT61620 MIPI DSI to HDMI bridge
From: Pet Weng @ 2026-03-27 8:02 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: dri-devel, devicetree, linux-kernel, Hermes Wu, Kenneth Hung,
Pet Weng, Jau-chih Tseng, Pin-yen Lin, Krzysztof Kozlowski
In-Reply-To: <20260327-it61620-0714-v9-0-032938cb9d85@ite.com.tw>
This chip receives MIPI DSI input and outputs HDMI, and is commonly
connected to SoCs via I2C and DSI.
IT61620 is a variant of IT6162.
The main differences are listed below
- IT61620 supports only a single MIPI DSI input port, while
IT6162 supports dual MIPI DSI ports.
- IT61620 does not include the internal MCU present in IT6162.
Because of these architectural differences, IT61620 uses a separate
compatible string even though the external interfaces and bindings
are largely similar.
Signed-off-by: Pet Weng <pet.weng@ite.com.tw>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../bindings/display/bridge/ite,it61620.yaml | 152 +++++++++++++++++++++
1 file changed, 152 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it61620.yaml b/Documentation/devicetree/bindings/display/bridge/ite,it61620.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d4f0edeecd0e22f3fa92c9f8e276ce0806c24790
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/ite,it61620.yaml
@@ -0,0 +1,152 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/ite,it61620.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ITE IT61620 MIPI DSI to HDMI Bridge
+
+maintainers:
+ - Pet Weng <pet.weng@ite.com.tw>
+
+description: |
+ The ITE IT61620 is a high-performance, low-power HDMI bridge that converts
+ MIPI DSI input to HDMI 1.4b TMDS output. It supports up to 4 lanes of MIPI
+ D-PHY 2.0 input at 2.5Gbps per lane (10Gbps total), compatible with DSI-2
+ v2.0.
+
+ The HDMI transmitter side supports up to 4Kx2K@30Hz resolutions, and is
+ compliant with HDMI 1.4b and HDCP 1.4.
+
+ For audio, the IT61620 supports up to 8-channel LPCM via I2S (multi-line or
+ TDM mode), with optional S/PDIF or DSD (for SACD). It supports audio
+ sampling rates up to 192kHz.
+
+ IT61620 is a variant of IT6162.
+ The main differences are listed below
+ - IT61620 supports only a single MIPI DSI input port, while IT6162 supports
+ dual MIPI DSI ports.
+ - IT61620 does not include the internal MCU present in IT6162.
+
+ Because of these architectural differences, IT61620 uses a separate
+ compatible string even though the external interfaces and bindings are
+ largely similar.
+
+allOf:
+ - $ref: /schemas/sound/dai-common.yaml#
+
+properties:
+ compatible:
+ const: ite,it61620
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ ivdd-supply:
+ description: core voltage
+
+ ovdd-supply:
+ description: I/O voltage
+
+ ovdd1833-supply:
+ description: flexible I/O voltage
+
+ "#sound-dai-cells":
+ const: 0
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Input port for MIPI DSI
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+ required:
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Output port for HDMI output
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Audio input port (I2S)
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - reset-gpios
+ - ivdd-supply
+ - ovdd-supply
+ - ovdd1833-supply
+ - ports
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bridge@58 {
+ compatible = "ite,it61620";
+ reg = <0x58>;
+ #sound-dai-cells = <0>;
+ interrupt-parent = <&pio>;
+ interrupts = <128 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&it61620_pins>;
+ reset-gpios = <&pio 127 GPIO_ACTIVE_LOW>;
+ ivdd-supply = <&pp1000_hdmi_x>;
+ ovdd-supply = <&pp3300_vio28_x>;
+ ovdd1833-supply = <&pp1800_vcamio_x>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ it61620_dsi_in: endpoint {
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ it61620_hdmi_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ it61620_audio_in: endpoint {
+ remote-endpoint = <&i2s0_out>;
+ };
+ };
+ };
+ };
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH v9 2/2] drm/bridge: Add ITE IT61620 MIPI DSI to HDMI bridge driver
From: Pet Weng @ 2026-03-27 8:02 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: dri-devel, devicetree, linux-kernel, Hermes Wu, Kenneth Hung,
Pet Weng, Jau-chih Tseng, Pin-yen Lin, Dmitry Baryshkov
In-Reply-To: <20260327-it61620-0714-v9-0-032938cb9d85@ite.com.tw>
This adds support for the ITE IT61620 bridge chip which converts
MIPI DSI input to HDMI output. The Driver implements the basic
bridge functions and integrates with the DRM bridge and connector
frameworks.
Supported features include:
MIPI DSI input handling
HDMI output setup
Basic mode configuration
I2C-based control and initialization
HDCP 1.4 handling
HPD handling clarification:
Although IT61620 has an HPD pin, hotplug detection is handled by the
system connector. The bridge only receives HPD notifications, and the
HPD pin is used solely for short pulses during HDCP authentication.
Therefore, this bridge does not implement OP_HPD or OP_DETECT, as it
does not originate or determine hotplug or connection status.
This driver will be used on platforms embedding the IT61620 for
video output via HDMI from SoCs with MIPI DSI output.
Add a MAINTAINERS entry for the IT61620 bridge driver.
Signed-off-by: Pet Weng <pet.weng@ite.com.tw>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
MAINTAINERS | 7 +
drivers/gpu/drm/bridge/Kconfig | 18 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/ite-it61620.c | 2592 ++++++++++++++++++++++++++++++++++
4 files changed, 2618 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0a508f217c964bf1c9002e77d17db250d283c8f6..176aa411645ef44146a41cd7d3cdebcbf428db2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13654,6 +13654,13 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
F: drivers/gpu/drm/bridge/ite-it6263.c
+ITE IT61620 MIPI DSI TO HDMI BRIDGE DRIVER
+M: Pet Weng <pet.weng@ite.com.tw>
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+F: Documentation/devicetree/bindings/display/bridge/ite,it61620.yaml
+F: drivers/gpu/drm/bridge/ite-it61620.c
+
ITE IT66121 HDMI BRIDGE DRIVER
M: Phong LE <ple@baylibre.com>
M: Neil Armstrong <neil.armstrong@linaro.org>
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index c3209b0f46786ec6f9a96c0466b57b0e4a96f44f..7d90010cc63d032b4f740b48d9b3bffe9cd2a9f7 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -118,6 +118,24 @@ config DRM_ITE_IT6263
help
ITE IT6263 LVDS to HDMI bridge chip driver.
+config DRM_ITE_IT61620
+ tristate "ITE IT61620 DSI/HDMI bridge"
+ depends on OF
+ select DRM_DISPLAY_CONNECTOR
+ select DRM_DISPLAY_HDMI_HELPER
+ select DRM_DISPLAY_HDCP_HELPER
+ select DRM_DISPLAY_HELPER
+ select DRM_MIPI_DSI
+ select DRM_KMS_HELPER
+ select DRM_HDMI_HELPER
+ select CRYPTO_LIB_SHA1
+ help
+ Driver for ITE IT61620 MIPI DSI to HDMI bridge
+ chip driver.
+
+ It enables display output through HDMI when connected to a MIPI
+ DSI source. The bridge translates the video signals for HDMI monitors.
+
config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index beab5b695a6e1f5a8c39c264567d2b2fff17d6e0..9c50a5420a741f16591633269bd1da06f91befed 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
obj-$(CONFIG_DRM_INNO_HDMI) += inno-hdmi.o
obj-$(CONFIG_DRM_ITE_IT6263) += ite-it6263.o
+obj-$(CONFIG_DRM_ITE_IT61620) += ite-it61620.o
obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o
diff --git a/drivers/gpu/drm/bridge/ite-it61620.c b/drivers/gpu/drm/bridge/ite-it61620.c
new file mode 100644
index 0000000000000000000000000000000000000000..95771e5a391141a7b4de6a77e4cdd03d75a9dc08
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ite-it61620.c
@@ -0,0 +1,2592 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 ITE Tech. Inc.
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_graph.h>
+#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_print.h>
+#include <drm/drm_of.h>
+#include <drm/display/drm_hdcp_helper.h>
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
+#include <video/videomode.h>
+#include <sound/hdmi-codec.h>
+#include <crypto/sha1.h>
+
+#define EDID_R_BURST_NUM 16
+#define DDC_FIFO_DEPTH 32
+
+#define MIPIRX_I2C_ADDRESS (0x78 >> 1)
+#define TX_I2C_ADDRESS (0xC0 >> 1)
+
+#define REG_CTRL_PW 0xFF
+
+#define REG_VENDER_ID_L 0x00
+#define REG_VENDER_ID_H 0x01
+#define REG_DEVICE_ID_L 0x02
+#define REG_DEVICE_ID_H 0x03
+#define REG_DEV_VERSION 0x04
+#define DEV_VERSION_A0 0xA0
+#define DEV_VERSION_C0 0xC0
+
+#define RX_REG_BANK 0x0F
+#define M_MIPIRX_BANK 0x01
+
+#define RX_REG_RESET_CTRL 0x05
+#define B_REF_CLOCK_RESET BIT(3)
+#define RX_REG_CLK_CTRL 0x10
+#define B_MIPI_INT_STATUS BIT(7)
+#define RX_REG_D_RST 0x1A
+#define B_D_RST BIT(0)
+#define RX_REG_INT_STATUS_01 0x0A
+#define B_INI_V_CHG BIT(0)
+#define RX_REG_INT_POL 0x11
+#define RX_REG_INT_MASK 0x114
+#define B_V_CHG BIT(0)
+#define RX_REG_INT_STATUS_02 0x22
+#define B_INI_V_STB BIT(5)
+#define RX_REG_MPPCLKI 0x12
+
+#define RX_REG_HFP_L 0x30
+#define RX_REG_HFP_H 0x31
+#define RX_REG_HSW_L 0x32
+#define RX_REG_HSW_H 0x33
+#define RX_REG_HBP_L 0x34
+#define RX_REG_HBP_H 0x35
+#define RX_REG_HDEW_L 0x36
+#define RX_REG_HDEW_H 0x37
+#define RX_REG_HTOTAL_L 0x48
+#define RX_REG_HTOTAL_H 0x49
+
+#define RX_REG_SELDCLK 0x24
+#define RX_REG_VFP_L 0x3A
+#define RX_REG_VFP_H 0x3B
+#define RX_REG_VSW_L 0x3C
+#define RX_REG_VSW_H 0x3D
+#define RX_REG_VBP_L 0x3E
+#define RX_REG_VBP_H 0x3F
+#define RX_REG_VDEW_L 0x40
+#define RX_REG_VDEW_H 0x41
+#define RX_REG_POL 0x4E
+#define B_MIPI_H_POL BIT(0)
+#define B_MIPI_V_POL BIT(1)
+
+#define RX_REG_DSCCTRL 0x25
+#define RX_REG_SYNC_NUM 0x4D
+#define RX_REG_BSP_SEL 0x1F
+#define RX_REG_PWD_CTRL 0xE0
+#define RX_REG_ENVRR 0x1AC
+#define RX_REG_ENVBLK 0x1AD
+
+#define RX_REG_D2P_RESET 0xA0
+#define RX_REG_D2P_CTRL 0xA1
+#define RX_REG_AUTO_D2P_RESET 0xA2
+#define RX_REG_TUNEOPT 0xA9
+#define RX_REG_TUNETHRE 0xAA
+#define RX_REG_DSC_RESET 0xAB
+#define RX_REG_DSC_VFRD 0xAC
+
+#define RX_REG_MIPI_CONFIG 0x112
+#define B_MIPI_LANE_NUM 0x03
+#define B_MIPI_PN_SWAP BIT(2)
+#define B_MIPI_LANE_SWAP BIT(3)
+#define RX_REG_HS_CTRL 0x118
+#define RX_REG_LP_CTRL 0x119
+#define RX_REG_MIPI_CTRL01 0x44
+#define RX_REG_AUTO_SYNC 0x144
+#define RX_REG_MV_MAX 0x146
+#define RX_REG_FORCE_M 0x147
+#define B_FORCE_MHT_STB BIT(0)
+#define B_FORCE_MVT_STB BIT(3)
+#define RX_REG_MIPI_CTRL02 0x14E
+#define B_FIFO_RST BIT(5)
+
+#define TX_REG_STATUS01 0x07
+#define B_INT_STATUS BIT(0)
+#define B_HPD_STATUS BIT(1)
+#define B_VIDEO_STB BIT(2)
+
+#define TX_REG_HDMITX_BANK 0x0F
+#define M_HDMITX_BANK 0x03
+#define B_INT_EVENT_HDMI BIT(4)
+#define TX_REG_RESET_1_CTRL 0x05
+#define B_REFERENCE_CLOCK_RESET BIT(0)
+#define B_VIDEO_RESET BIT(1)
+#define B_AUDIO_RESET BIT(2)
+#define B_AUX_RESET BIT(3)
+#define B_IPCLK_RESET BIT(4)
+#define B_SDM_RESET BIT(5)
+#define B_TCLK_RESET BIT(6)
+
+#define TX_REG_RESET_2_CTRL 0x06
+
+#define TX_REG_V_STS 0x09
+#define B_RXSEN BIT(1)
+#define B_V_STABLE BIT(2)
+#define B_TMDS_STABLE BIT(3)
+
+#define TX_REG_SYS_CONFIG 0x0C
+#define B_EN_HDMI BIT(6)
+#define B_INT_POL BIT(0)
+#define B_INT_MODE BIT(1)
+#define B_INT_OUT_STATUS BIT(2)
+#define B_INT_OUTPUT BIT(3)
+
+#define BIT_OFFSET(x) ((x) * BITS_PER_BYTE)
+
+#define TX_REG_INT1 0x10
+#define TX_REG_INT_MASK1 0x18
+#define INT_HPD_CHG 0
+#define B_HPD_CHG BIT(INT_HPD_CHG)
+#define BIT_HPD_CHG (BIT_OFFSET(0) + INT_HPD_CHG)
+#define INT_RXSEN_CHANGE 2
+#define B_RXSEN_CHANGE BIT(INT_RXSEN_CHANGE)
+#define BIT_RXSEN_CHANGE (BIT_OFFSET(0) + INT_RXSEN_CHANGE)
+#define INT_AUTH_F 3
+#define B_INT_AUTH_F BIT(INT_AUTH_F)
+#define BIT_INT_AUTH_F (BIT_OFFSET(0) + INT_AUTH_F)
+#define INT_AUTH_D 4
+#define B_INT_AUTH_D BIT(INT_AUTH_D)
+#define BIT_INT_AUTH_D (BIT_OFFSET(0) + INT_AUTH_D)
+
+#define TX_REG_INT2 0x11
+#define TX_REG_INT_MASK2 0x19
+#define INT_KSV_CHECK 1
+#define B_KSV_CHECK BIT(INT_KSV_CHECK)
+#define BIT_KSV_CHECK (BIT_OFFSET(1) + INT_KSV_CHECK)
+
+#define TX_REG_INT3 0x16
+#define TX_REG_INT_MASK3 0x1E
+#define INT_TMDS_STB_CHG 6
+#define B_TMDS_STB_CHG BIT(INT_TMDS_STB_CHG)
+#define BIT_TMDS_STB_CHG (BIT_OFFSET(2) + INT_TMDS_STB_CHG)
+
+#define REG_TX_INT_CTRL 0x21
+#define B_DIS_INT_OUTPUT BIT(5)
+#define TX_REG_CLOCK_PWD_CTRL 0x2B
+
+#define TX_REG_AFE0E 0x0E
+#define TX_REG_AFE30 0x30
+#define TX_REG_AFE33 0x33
+#define TX_REG_AFE34 0x34
+#define TX_REG_AFE35 0x35
+#define TX_REG_AFEE9 0xE9
+#define TX_REG_AFE_XP 0x219
+#define TX_REG_AFE_XLC1 0x220
+#define TX_REG_AFE_XLC2 0x223
+#define TX_REG_AFE_XLC3 0x226
+#define TX_REG_AFE_DRV 0x23B
+
+#define TX_REG_CR_1_CTRL 0x3A
+#define TX_REG_CR_2_CTRL 0x3F
+
+#define TX_REG_R0TM 0x5A
+#define TX_REG_SHA_SEL 0x5D
+
+#define TX_REG_HDCP_CTRL1 0x60
+#define B_CPDESIRED BIT(0)
+#define TX_REG_HDCP_PRO 0x61
+#define B_AUTH_FIRE BIT(0)
+#define B_LIST_CHK_DONE BIT(4)
+#define B_LIST_CHK_FAIL BIT(5)
+#define TX_REG_HDCP_CTRL2 0x62
+#define TX_REG_AUTOMUTE 0x65
+#define B_AN_SEL BIT(0)
+#define B_EN_AN_GEN BIT(1)
+#define B_EN_M0_RD BIT(5)
+#define TX_REG_HDCP_AUTH_CS 0x66
+#define M_AUTH_CH 0x7F
+#define CS_AUTH_DONE 0x4E
+#define CS_AUTH_FAIL 0x02
+#define CS_KSVLIST_CHK 0x19
+#define TX_REG_HDCP_CTRL3 0x1BA
+#define B_ENC_DIS BIT(6)
+#define B_PAUSE BIT(7)
+
+#define TX_REG_VD_CTRL1 0xA8
+#define TX_REG_VD_CTRL2 0xA4
+#define B_VIDEO_FIFO_REST BIT(0)
+#define TX_REG_VD_CTRL3 0xB7
+
+#define TX_REG_AUD_SPDIF 0x23
+#define TX_REG_AUD_CTRL 0xB8
+#define TX_REG_AUD_FMT 0xBA
+#define TX_REG_EN_AUDIO 0xBB
+#define TX_REG_AUD_FIFO1 0xBC
+#define TX_REG_AUD_FIFO2 0xBD
+#define TX_REG_AUD_CTS 0x1BC
+#define TX_REG_AUD_STS1 0x1F0
+#define B_EN_AUD_NLPCM BIT(1)
+#define TX_REG_AUD_STS2 0x1F3
+#define TX_REG_AUD_STS3 0x1F4
+
+#define TX_REG_LINK_CTRL0 0xD3
+#define B_EN_AUDIO_MUTE BIT(5)
+
+#define TX_REG_V_QUEUE 0xE7
+#define TX_REG_V_TU 0xEB
+
+#define TX_REG_HPD_CONFIG 0xF6
+
+#define TX_REG_CEC_CONFIG 0xFA
+#define B_EN_CEC BIT(0)
+
+#define TX_REG_DDC_CTRL1 0x1A0
+#define TX_REG_DDC_ADDR 0x1A1
+#define DDC_HDCP_ADDR (DRM_HDCP_DDC_ADDR << 1)
+#define DDC_EDID_ADDR (DDC_ADDR << 1)
+#define TX_REG_DDC_OFFSET 0x1A2
+#define TX_REG_DDC_NUM_L 0x1A3
+#define TX_REG_DDC_NUM_H 0x1A4
+#define TX_REG_DDC_SEGMENT 0x1A5
+#define TX_REG_DDC_COMMAND 0x1A6
+#define DDC_COMMAND_BURST_R 0X00
+#define DDC_COMMAND_BURST_W 0X01
+#define DDC_COMMAND_EDID_RD 0X03
+#define DDC_COMMAND_FIFO_CLR 0X09
+#define DDC_COMMAND_ABORT 0X0F
+#define TX_REG_DDC_CTRL2 0x1AD
+#define B_DDC_REST BIT(4)
+#define TX_REG_DDC_STATUS 0x1A7
+#define B_DDC_TX_DONE BIT(7)
+#define B_DDC_NOACK BIT(5)
+#define B_DDC_FULL BIT(2)
+#define TX_REG_DDC_FIFO 0x1A8
+#define TX_REG_DDC_FIFO_STS 0x1AE
+#define M_DDC_STAGE_NUM 0x3F
+
+#define TX_REG_HDMI_CTRL1 0x1B8
+#define B_EN_HDMI_MODE BIT(0)
+#define TX_REG_HDMI_CTRL2 0x1B9
+#define B_EN_AVMUTE BIT(0)
+#define TX_REG_EN_PKT1 0x1BF
+#define B_EN_AVI BIT(0)
+#define B_AVI_RP BIT(1)
+#define B_EN_AUD BIT(2)
+#define B_EN_AUD_RP BIT(3)
+#define B_EN_VSIF BIT(6)
+#define B_EN_VSIF_RP BIT(7)
+#define TX_REG_EN_PKT2 0x1C0
+#define B_EN_NULL BIT(0)
+#define B_EN_NULL_RP BIT(1)
+#define B_EN_GEN BIT(4)
+#define B_GEN_RP BIT(5)
+
+#define TX_REG_VH_TIME 0x165
+#define TX_REG_PG_HFP_L 0x150
+#define TX_REG_PG_HFP_H 0x151
+#define TX_REG_PG_HSW_L 0x152
+#define TX_REG_PG_HSW_H 0x153
+#define TX_REG_PG_HBP_L 0x154
+#define TX_REG_PG_HBP_H 0x155
+#define TX_REG_PG_DEW_L 0x156
+#define TX_REG_PG_DEW_H 0x157
+#define TX_REG_PG_HVR2_L 0x158
+#define TX_REG_PG_HVR2_H 0x159
+#define TX_REG_PG_VFP_L 0x15A
+#define TX_REG_PG_VFP_H 0x15B
+#define TX_REG_PG_VSW_L 0x15C
+#define TX_REG_PG_VSW_H 0x15D
+#define TX_REG_PG_VBP_L 0x15E
+#define TX_REG_PG_VBP_H 0x15F
+#define TX_REG_PG_VDEW_L 0x160
+#define TX_REG_PG_HDEW_H 0x161
+#define TX_REG_PG_VFP2_L 0x162
+#define TX_REG_PG_VFP2_H 0x163
+#define TX_REG_PG_POL 0x164
+
+#define TX_REG_AVIINFO_DB00 0x1D0
+#define TX_REG_AVIINFO_DB01 0x1D1
+#define TX_REG_AVIINFO_DB02 0x1D2
+#define TX_REG_AVIINFO_DB03 0x1D3
+#define TX_REG_AVIINFO_DB04 0x1D4
+#define TX_REG_AVIINFO_DB05 0x1D5
+#define TX_REG_AVIINFO_DB06 0x1D6
+#define TX_REG_AVIINFO_DB07 0x1D7
+#define TX_REG_AVIINFO_DB08 0x1D8
+#define TX_REG_AVIINFO_DB09 0x1D9
+#define TX_REG_AVIINFO_DB10 0x1DA
+#define TX_REG_AVIINFO_DB11 0x1DB
+#define TX_REG_AVIINFO_DB12 0x1DC
+#define TX_REG_AVIINFO_DB13 0x1DD
+#define TX_REG_AVIINFO_DB14 0x1DE
+
+#define TX_REG_AUDINFO_DB01 0x1E0
+#define TX_REG_AUDINFO_DB02 0x1E1
+#define TX_REG_AUDINFO_DB03 0x1E2
+#define TX_REG_AUDINFO_DB04 0x1E3
+#define TX_REG_AUDINFO_DB05 0x1E4
+#define TX_REG_AUDINFO_DB06 0x1E5
+#define TX_REG_AUDINFO_DB07 0x1E6
+#define TX_REG_AUDINFO_DB08 0x1E7
+#define TX_REG_AUDINFO_DB09 0x1E8
+#define TX_REG_AUDINFO_DB10 0x1E9
+
+#define TX_REG_NULLPKT_HB00 0x310
+#define TX_REG_NULLPKT_HB01 0x311
+#define TX_REG_NULLPKT_HB02 0x312
+#define TX_REG_NULLPKT_PB00 0x314
+#define TX_REG_NULLPKT_PB27 0x32F
+
+#define TX_REG_VSIFPKT_HB02 0x37E
+#define TX_REG_VSIFPKT_PB00 0x380
+#define TX_REG_VSIFPKT_PB01 0x381
+
+#define TX_REG_SSC_PD 0x211
+
+#define TX_REG_TXPLL_CTRL 0x218
+#define TX_REG_XLC_7_CTRL 0x227
+
+#define TX_REG_TXDRV_PD_CTRL 0x23D
+#define TX_REG_TXDRV_CTRL 0x240
+#define TX_REG_AUX_CTRL 0x244
+#define TX_REG_IPLL_CTRL 0x248
+#define TX_REG_RDROM_TRG 0x271
+
+#define TX_REG_HDCP_ARI_L 0x63
+#define TX_REG_HDCP_ARI_H 0x64
+
+#define TX_REG_HDCP_AUTH_STS 0x67
+
+#define TX_REG_HDCP_BKSV1 0x68
+#define TX_REG_HDCP_BKSV2 0x69
+#define TX_REG_HDCP_BKSV3 0x6A
+#define TX_REG_HDCP_BKSV4 0x6B
+#define TX_REG_HDCP_BKSV5 0x6C
+
+#define TX_REG_HDCP_BRI_L 0x6D
+#define TX_REG_HDCP_BRI_H 0x6E
+
+#define TX_REG_HDCP_AKSV1 0x6F
+#define TX_REG_HDCP_AKSV2 0x70
+#define TX_REG_HDCP_AKSV3 0x71
+#define TX_REG_HDCP_AKSV4 0x72
+#define TX_REG_HDCP_AKSV5 0x73
+
+#define TX_REG_ANM0V1 0x74
+#define TX_REG_ANM0V2 0x75
+#define TX_REG_ANM0V3 0x76
+#define TX_REG_HDCP_AN_M0_V4 0x77
+#define TX_REG_HDCP_AN_M05 0x78
+#define TX_REG_HDCP_AN_M06 0x79
+#define TX_REG_HDCP_AN_M07 0x7A
+#define TX_REG_HDCP_AN_M08 0x7B
+
+#define TX_REG_HDCP_BCAPS 0x7C
+#define B_KSV_READY BIT(5)
+#define TX_REG_HDCP_BSTS_L 0x7D
+#define TX_REG_HDCP_BSTS_H 0x7E
+
+#define TX_REG_AUDPKT_CTS_0 0x3A8
+#define TX_REG_AUDPKT_CTS_1 0x3A9
+#define TX_REG_AUDPKT_CTS_2 0x3AA
+
+#define TX_REG_AUDPKT_N_0 0x3AB
+#define TX_REG_AUDPKT_N_1 0x3AC
+#define TX_REG_AUDPKT_N_2 0x3AD
+
+#define SOFT_DDC_TIMEOUT_MS 100
+#define HDCP_KSV_LIST_TIMEOUT_MS 5000
+
+#define MAX_HDCP_DOWN_STREAM_COUNT 127
+#define HDCP_SHA1_FIFO_LEN (MAX_HDCP_DOWN_STREAM_COUNT * DRM_HDCP_KSV_LEN + 10)
+
+#define HI_BYTE(x) (((x) >> 8) & 0xFF)
+#define LO_BYTE(x) ((x) & 0xFF)
+
+enum video_state {
+ it61620_VIDEO_OFF = 0x00,
+ it61620_VIDEO_WAIT,
+ it61620_VIDEO_ON,
+};
+
+enum hdcp_state {
+ CP_NONE = 0x00,
+ CP_GOING = 0x01,
+};
+
+enum it61620_audio_select {
+ I2S = 0,
+ SPDIF,
+};
+
+enum it61620_audio_word_length {
+ WORD_LENGTH_16BIT = 0x0,
+ WORD_LENGTH_20BIT = 0x2,
+ WORD_LENGTH_24BIT = 0x3,
+};
+
+enum it61620_audio_sample_rate {
+ SAMPLE_RATE_32K = 0x3,
+ SAMPLE_RATE_48K = 0x2,
+ SAMPLE_RATE_64K = 0xb,
+ SAMPLE_RATE_96K = 0xa,
+ SAMPLE_RATE_192K = 0xe,
+ SAMPLE_RATE_44_1K = 0x0,
+ SAMPLE_RATE_88_2K = 0x8,
+ SAMPLE_RATE_176_4K = 0xc,
+};
+
+enum it61620_audio_type {
+ LPCM = 0,
+ NLPCM,
+};
+
+enum it61620_audio_i2s_input_format {
+ I2S_INPUT_FORMAT_STANDARD = 0,
+ I2S_INPUT_FORMAT_32BIT = 1,
+};
+
+struct it6162_chip_info {
+ u16 vid;
+ u16 pid;
+};
+
+struct it61620_mipirx {
+ u8 lane_num;
+ u8 pn_swap;
+ u8 lane_swap;
+};
+
+struct it61620_hdmi_afe_setting {
+ unsigned int clock;
+ unsigned int h2on_pll;
+ unsigned int hs;
+ unsigned int afe_val[24];
+};
+
+struct it61620 {
+ struct drm_bridge bridge;
+ struct drm_connector *connector;
+ struct device *dev;
+ enum drm_connector_status connector_status;
+ struct drm_device *drm;
+ struct drm_bridge *next_bridge;
+
+ struct i2c_client *it61620_i2c;
+ struct i2c_client *mipirx_i2c;
+ struct i2c_client *tx_i2c;
+ struct regmap *it61620_regmap;
+ struct regmap *mipirx_regmap;
+ struct regmap *tx_regmap;
+
+ struct delayed_work hdcp_work;
+ struct wait_queue_head wq;
+
+ struct regulator *ovdd1833;
+ struct regulator *ivdd;
+ struct regulator *ovdd33;
+ struct gpio_desc *gpiod_reset;
+
+ bool powered;
+ bool is_hdmi;
+ bool en_audio;
+ bool hpd;
+ u8 dev_ver;
+
+ /* operations can only be served one at the time */
+ struct mutex ddc_lock;
+
+ enum video_state video_state;
+ enum it61620_audio_i2s_input_format i2s_input_format;
+
+ /* it61620 DSI RX related params */
+ struct mipi_dsi_device *dsi;
+
+ struct it61620_mipirx mipirx_config;
+
+ unsigned long tmds_char_rate;
+
+ enum hdcp_state hdcp_state;
+ int hdcp_cp;
+ u8 sha1_input[HDCP_SHA1_FIFO_LEN];
+ const struct it6162_chip_info *chip_info;
+};
+
+static inline struct it61620 *bridge_to_it61620(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct it61620, bridge);
+}
+
+static const struct regmap_config it61620_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_range it61620_tx_volatile_ranges[] = {
+ { .range_min = 0, .range_max = 0x3ff},
+};
+
+static const struct regmap_access_table it61620_tx_volatile_table = {
+ .yes_ranges = it61620_tx_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(it61620_tx_volatile_ranges),
+};
+
+static const struct regmap_range_cfg it61620_tx_regmap_ranges[] = {
+ {
+ .range_min = 0,
+ .range_max = 0x3ff,
+ .selector_reg = TX_REG_HDMITX_BANK,
+ .selector_mask = M_HDMITX_BANK,
+ .selector_shift = 0,
+ .window_start = 0x00,
+ .window_len = 0x100,
+ },
+};
+
+static const struct regmap_config it61620_tx_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &it61620_tx_volatile_table,
+ .ranges = it61620_tx_regmap_ranges,
+ .num_ranges = ARRAY_SIZE(it61620_tx_regmap_ranges),
+ .max_register = 0x3ff,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_range it61620_mipirx_volatile_ranges[] = {
+ { .range_min = 0, .range_max = 0x1ff },
+};
+
+static const struct regmap_access_table it61620_mipirx_volatile_table = {
+ .yes_ranges = it61620_mipirx_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(it61620_mipirx_volatile_ranges),
+};
+
+static const struct regmap_range_cfg it61620_mipirx_regmap_ranges[] = {
+ {
+ .range_min = 0,
+ .range_max = 0x1ff,
+ .selector_reg = RX_REG_BANK,
+ .selector_mask = M_MIPIRX_BANK,
+ .selector_shift = 0,
+ .window_start = 0x00,
+ .window_len = 0x100,
+ },
+};
+
+static const struct regmap_config it61620_mipi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &it61620_mipirx_volatile_table,
+ .ranges = it61620_mipirx_regmap_ranges,
+ .num_ranges = ARRAY_SIZE(it61620_mipirx_regmap_ranges),
+ .max_register = 0x1ff,
+ .cache_type = REGCACHE_NONE,
+};
+
+static void it61620_mipi_reset_video(struct it61620 *it61620)
+{
+ regmap_write(it61620->mipirx_regmap, RX_REG_DSC_RESET, 0x38);
+ usleep_range(100, 200);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D2P_RESET, 0x70, 0x70);
+ regmap_write(it61620->mipirx_regmap, RX_REG_DSC_RESET, 0x00);
+
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_RESET_CTRL, 0x57, 0x00);
+ usleep_range(1000, 2000);
+}
+
+static void it61620_mipi_m2p_reset(struct it61620 *it61620)
+{
+ if (it61620->dev_ver != DEV_VERSION_A0)
+ return;
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_MIPI_CTRL02, B_FIFO_RST,
+ B_FIFO_RST);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_MIPI_CTRL02, B_FIFO_RST,
+ 0x00);
+}
+
+static void it61620_mipi_d2p_reset_fifo(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D2P_RESET, 0x70, 0x70);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D2P_RESET, 0x70, 0x50);
+ usleep_range(100, 200);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D2P_RESET, 0x70, 0x10);
+ usleep_range(100, 200);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D2P_RESET, 0x70, 0x00);
+}
+
+static void it61620_mipi_d2p_reset(struct it61620 *it61620)
+{
+ it61620_mipi_m2p_reset(it61620);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D_RST, B_D_RST, B_D_RST);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D_RST, B_D_RST, 0x00);
+ it61620_mipi_d2p_reset_fifo(it61620);
+}
+
+static void it61620_mipi_reset(struct it61620 *it61620)
+{
+ unsigned int val;
+ u8 dev_ver = it61620->dev_ver;
+ struct it61620_mipirx *mipirx = &it61620->mipirx_config;
+
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_RESET_CTRL, B_REF_CLOCK_RESET,
+ B_REF_CLOCK_RESET);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_RESET_CTRL, B_REF_CLOCK_RESET,
+ 0x00);
+ usleep_range(1000, 2000);
+
+ it61620_mipi_d2p_reset(it61620);
+
+ regmap_write(it61620->mipirx_regmap, RX_REG_HS_CTRL, 0x93);
+ regmap_write(it61620->mipirx_regmap, RX_REG_LP_CTRL, 0x0c);
+ regmap_write(it61620->mipirx_regmap, RX_REG_AUTO_SYNC, 0x01);
+ regmap_write(it61620->mipirx_regmap, RX_REG_MV_MAX, 0x0f);
+ regmap_write(it61620->mipirx_regmap, RX_REG_FORCE_M, B_FORCE_MHT_STB);
+
+ regmap_write(it61620->mipirx_regmap, RX_REG_MIPI_CTRL01, 0x2c);
+ regmap_write(it61620->mipirx_regmap, RX_REG_AUTO_D2P_RESET, 0x13);
+ regmap_write(it61620->mipirx_regmap, RX_REG_D2P_CTRL, 0x28);
+ regmap_write(it61620->mipirx_regmap, RX_REG_TUNEOPT, 0x9c);
+
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_CLK_CTRL, 0x30, 0x20);
+
+ if (dev_ver != DEV_VERSION_A0) {
+ regmap_write(it61620->mipirx_regmap, RX_REG_TUNETHRE, 0x02);
+ regmap_write(it61620->mipirx_regmap, RX_REG_AUTO_D2P_RESET, 0x83);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_FORCE_M, B_FORCE_MVT_STB,
+ B_FORCE_MVT_STB);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_SYNC_NUM, 0xf7, 0x44);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_BSP_SEL, 0x03, 0x02);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_PWD_CTRL, 0x24, 0x24);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_ENVRR, 0x01, 0x00);
+ regmap_write(it61620->mipirx_regmap, RX_REG_ENVBLK, 0x00);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_DSCCTRL, 0x40, 0x00);
+ }
+ val = (mipirx->lane_num - 1) |
+ (mipirx->pn_swap ? B_MIPI_PN_SWAP : 0x00) |
+ (mipirx->lane_swap ? B_MIPI_LANE_SWAP : 0x00);
+
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_MIPI_CONFIG, 0x0f, val);
+
+ it61620_mipi_reset_video(it61620);
+}
+
+static void it61620_mipi_video_change_irq(struct it61620 *it61620)
+{
+ unsigned int reg22;
+ unsigned int video_stable;
+
+ regmap_read(it61620->mipirx_regmap, RX_REG_INT_STATUS_02, ®22);
+ video_stable = reg22 & B_INI_V_STB;
+
+ if (video_stable) {
+ it61620_mipi_m2p_reset(it61620);
+ it61620_mipi_d2p_reset_fifo(it61620);
+ } else {
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D_RST, 0x01, 0x01);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D_RST, 0x01, 0x00);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_D2P_RESET, 0x70, 0x70);
+ }
+}
+
+static void it61620_mipi_irq_handler(struct it61620 *it61620)
+{
+ unsigned int reg0a, reg_val;
+
+ regmap_read(it61620->mipirx_regmap, RX_REG_CLK_CTRL, ®_val);
+ reg_val &= B_MIPI_INT_STATUS;
+ if (reg_val == 0)
+ return;
+
+ regmap_read(it61620->mipirx_regmap, RX_REG_INT_STATUS_01, ®0a);
+ regmap_write(it61620->mipirx_regmap, RX_REG_INT_STATUS_01, reg0a);
+ if (reg0a & B_INI_V_CHG)
+ it61620_mipi_video_change_irq(it61620);
+}
+
+static void it61620_show_drm_video_mode(struct it61620 *it61620,
+ const struct drm_display_mode *mode)
+{
+ struct drm_device *drm = it61620->drm;
+
+ drm_dbg_kms(drm, "HActive = %u\n", mode->hdisplay);
+ drm_dbg_kms(drm, "VActive = %u\n", mode->vdisplay);
+ drm_dbg_kms(drm, "HTotal = %u\n", mode->htotal);
+ drm_dbg_kms(drm, "VTotal = %u\n", mode->vtotal);
+ drm_dbg_kms(drm, "PCLK = %u khz\n", mode->clock);
+ drm_dbg_kms(drm, "HFP = %u\n", mode->hsync_start - mode->hdisplay);
+ drm_dbg_kms(drm, "HSW = %u\n", mode->hsync_end - mode->hsync_start);
+ drm_dbg_kms(drm, "HBP = %u\n", mode->htotal - mode->hsync_end);
+ drm_dbg_kms(drm, "VFP = %u\n", mode->vsync_start - mode->vdisplay);
+ drm_dbg_kms(drm, "VSW = %u\n", mode->vsync_end - mode->vsync_start);
+ drm_dbg_kms(drm, "VBP = %u\n", mode->vtotal - mode->vsync_end);
+ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+ drm_dbg_kms(drm, "HPOL +\n");
+ else
+ drm_dbg_kms(drm, "HPOL -\n");
+
+ if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+ drm_dbg_kms(drm, "VPOL +\n");
+ else
+ drm_dbg_kms(drm, "VPOL -\n");
+
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ drm_dbg_kms(drm, "Intelaced\n");
+ else
+ drm_dbg_kms(drm, "Progressive\n");
+}
+
+static inline void it61620_write16(struct regmap *map,
+ unsigned int reg, u16 val)
+{
+ u8 data[2] = {val & 0xff, val >> 8};
+
+ regmap_bulk_write(map, reg, data, 2);
+}
+
+static void it61620_mipi_set_d2v_video_timing(struct it61620 *it61620,
+ struct drm_display_mode *mode)
+{
+ u8 d2vffrd_adr_dly;
+ u32 htotal, hfp, hsw, hbp, hdew;
+ u32 vfp, vsw, vbp, vdew;
+ u32 clock;
+ bool hpol_high = 0, vpol_high = 0;
+
+ it61620_show_drm_video_mode(it61620, mode);
+
+ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+ hpol_high = true;
+
+ if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+ vpol_high = true;
+
+ clock = mode->clock;
+ hdew = mode->hdisplay;
+
+ hfp = mode->hsync_start - mode->hdisplay;
+ hsw = mode->hsync_end - mode->hsync_start;
+ hbp = mode->htotal - mode->hsync_end;
+ htotal = mode->htotal;
+
+ vdew = mode->vdisplay;
+ vfp = mode->vsync_start - mode->vdisplay;
+ vsw = mode->vsync_end - mode->vsync_start;
+ vbp = mode->vtotal - mode->vsync_end;
+
+ if (it61620->dev_ver != DEV_VERSION_A0)
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_SELDCLK, 0x1c, 0x04);
+
+ if (hdew > 1920) {
+ if (htotal < 4272) {
+ d2vffrd_adr_dly = abs(htotal - 2880) / 24;
+ regmap_write(it61620->mipirx_regmap, RX_REG_DSC_VFRD,
+ d2vffrd_adr_dly);
+ } else {
+ regmap_write(it61620->mipirx_regmap, RX_REG_DSC_VFRD, 0x50);
+ }
+ } else {
+ regmap_write(it61620->mipirx_regmap, RX_REG_DSC_VFRD, hdew / 36);
+ }
+
+ it61620_write16(it61620->mipirx_regmap, RX_REG_HFP_L, hfp);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_HSW_L, hsw);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_HBP_L, hbp);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_HDEW_L, hdew);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_HTOTAL_L, htotal);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_VFP_L, vfp);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_VSW_L, vsw);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_VBP_L, vbp);
+ it61620_write16(it61620->mipirx_regmap, RX_REG_VDEW_L, vdew);
+
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_POL, 0x03,
+ ((!vpol_high) << 1) | (!hpol_high));
+
+ if (it61620->dev_ver == DEV_VERSION_A0 &&
+ ((hdew == 2560 && vdew == 1440 && clock == 241500) ||
+ (hdew == 720 && vdew == 400 && clock == 28320) ||
+ (hdew == 720 && vdew == 576 && clock == 27000))) {
+ dev_dbg(it61620->dev, "device A0 %dx%d %d Khz",
+ hdew, vdew, clock);
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_MPPCLKI, 0x80, 0x80);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_VH_TIME, 0x48, 0x48);
+
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_HFP_L, hfp);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_HSW_L, hsw);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_HBP_L, hbp);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_DEW_L, hdew);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_HVR2_L, 0x0fff);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_VFP_L, vfp);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_VSW_L, vsw);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_VBP_L, vbp);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_VDEW_L, vdew);
+ it61620_write16(it61620->mipirx_regmap, TX_REG_PG_VFP2_L, 0x0fff);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_PG_POL, 0x07,
+ ((vpol_high) << 1) | (hpol_high));
+
+ } else {
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_MPPCLKI, 0x80, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_VH_TIME, 0x48, 0x00);
+ }
+
+ it61620_mipi_d2p_reset(it61620);
+}
+
+static void it61620_hdmi_reset(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_1_CTRL, 0x7e, 0x7e);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x36, 0x36);
+ usleep_range(1000, 2000);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_1_CTRL, 0x1f, 0x00);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_1_CTRL, 0x40, 0x00);
+
+ regmap_write(it61620->tx_regmap, TX_REG_RDROM_TRG, 0x04);
+ usleep_range(1000, 2000);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_SYS_CONFIG, B_EN_HDMI, B_EN_HDMI);
+
+ /* Reset AFE */
+ regmap_update_bits(it61620->tx_regmap, TX_REG_XLC_7_CTRL, 0x04, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_IPLL_CTRL, 0x02, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXPLL_CTRL, 0x04, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0x01, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_XLC_7_CTRL, 0x04, 0x04);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_IPLL_CTRL, 0x02, 0x02);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXPLL_CTRL, 0x04, 0x04);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0x01, 0x01);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0x08, 0x08);
+
+ regmap_write(it61620->tx_regmap, TX_REG_V_QUEUE, 0x08);
+ regmap_write(it61620->tx_regmap, TX_REG_V_TU, 0x07);
+
+ regmap_write(it61620->tx_regmap, TX_REG_CR_1_CTRL, 0x09);
+
+ regmap_write(it61620->tx_regmap, TX_REG_CR_2_CTRL, 0x16);
+
+ regmap_write(it61620->tx_regmap, TX_REG_VD_CTRL1, 0x04);
+
+ regmap_write(it61620->tx_regmap, TX_REG_HDCP_CTRL2, 0x04);
+
+ regmap_write(it61620->tx_regmap, TX_REG_VD_CTRL3, 0x84);
+ regmap_write(it61620->tx_regmap, TX_REG_HPD_CONFIG, 0x06);
+ usleep_range(1000, 2000);
+
+ regmap_write(it61620->tx_regmap, TX_REG_VD_CTRL2, 0x2e);
+ regmap_write(it61620->tx_regmap, TX_REG_HDMI_CTRL1, 0x30);
+
+ regmap_write(it61620->tx_regmap, TX_REG_HDMI_CTRL2, 0x04);
+}
+
+static void it61620_hdmi_poweron(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_PD_CTRL, 0x70, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_XLC_7_CTRL, 0x07, 0x06);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_IPLL_CTRL, 0x12, 0x12);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXPLL_CTRL, 0xc6, 0x84);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_SSC_PD, 0x03, 0x03);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_CLOCK_PWD_CTRL, 0x0f, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_VD_CTRL2, B_VIDEO_FIFO_REST,
+ B_VIDEO_FIFO_REST);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_VD_CTRL2, B_VIDEO_FIFO_REST,
+ 0x00);
+}
+
+static void it61620_hdmi_powerdown(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_PD_CTRL, 0x70, 0x70);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_SSC_PD, 0x03, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_IPLL_CTRL, 0x12, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXPLL_CTRL, 0xc6, 0xc2);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_XLC_7_CTRL, 0x07, 0x01);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0xf9, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AUX_CTRL, 0x90, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_CLOCK_PWD_CTRL, 0x0f, 0x0a);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_CEC_CONFIG, B_EN_CEC, 0x00);
+}
+
+static bool it61620_hdmi_get_hpd_status(struct it61620 *it61620)
+{
+ unsigned int val;
+
+ regmap_read(it61620->tx_regmap, TX_REG_STATUS01, &val);
+ return !!(val & B_HPD_STATUS);
+}
+
+static void it61620_hdmi_ddc_abort(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ unsigned int val;
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_DDC_CTRL2, B_DDC_REST, B_DDC_REST);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_DDC_CTRL2, B_DDC_REST, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND, DDC_COMMAND_ABORT);
+ usleep_range(1000, 2000);
+ regmap_read(it61620->tx_regmap, TX_REG_DDC_STATUS, &val);
+ drm_dbg(drm, "tx ddc ststus %02X\n", val);
+}
+
+static unsigned int it61620_hdmi_read_ddc_status(struct it61620 *it61620)
+{
+ unsigned int val;
+
+ regmap_read(it61620->tx_regmap, TX_REG_DDC_STATUS, &val);
+ return val;
+}
+
+static int it61620_hdmi_ddc_wait(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ unsigned int ddc_status;
+ int ret = 0;
+
+ ret = readx_poll_timeout(it61620_hdmi_read_ddc_status,
+ it61620, ddc_status,
+ (ddc_status &
+ (B_DDC_NOACK | B_DDC_TX_DONE | B_DDC_FULL)),
+ 2000,
+ 1000 * SOFT_DDC_TIMEOUT_MS);
+
+ if (ret < 0) {
+ drm_dbg(drm, "DDC SOFT timeout %x\n", ddc_status);
+ } else {
+ if (ddc_status & B_DDC_NOACK) {
+ drm_dbg(drm, "DDC no ack");
+ ret = -EIO;
+ }
+
+ if (ddc_status & B_DDC_FULL)
+ drm_dbg(drm, "DDC FULL");
+ }
+ return ret;
+}
+
+static int it61620_hdmi_get_ddc_fifo(struct it61620 *it61620, u8 *buf,
+ size_t len)
+{
+ int err;
+ struct device *dev = it61620->dev;
+
+ if (!it61620->powered)
+ return -ENODEV;
+
+ err = regmap_bulk_read(it61620->tx_regmap, TX_REG_DDC_FIFO, buf, len);
+ if (err < 0) {
+ dev_err(dev, "read ddc fifo failed tx reg[0x%x] err = %d",
+ TX_REG_DDC_FIFO, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct it61620_hdmi_afe_setting hdmi_afe[4] = {
+ {375000, 0x01, 0x02,
+ {0x03, 0x53, 0x1A, 0x03, 0x00, 0x04,
+ 0x03, 0x53, 0x1A, 0x03, 0x00, 0x04,
+ 0x03, 0x53, 0x1A, 0x03, 0x00, 0x04,
+ 0x01, 0x4B, 0x0F, 0x00, 0x07, 0x04}},
+ {340000, 0x01, 0x02,
+ {0x03, 0x53, 0x1A, 0x03, 0x00, 0x04,
+ 0x03, 0x53, 0x1A, 0x03, 0x00, 0x04,
+ 0x03, 0x53, 0x1A, 0x03, 0x00, 0x04,
+ 0x01, 0x4B, 0x0F, 0x00, 0x07, 0x04}},
+ {150000, 0x00, 0x00,
+ {0x03, 0x43, 0x18, 0x03, 0x00, 0x04,
+ 0x03, 0x43, 0x18, 0x03, 0x00, 0x04,
+ 0x03, 0x43, 0x18, 0x03, 0x00, 0x04,
+ 0x03, 0x43, 0x18, 0x03, 0x00, 0x04}},
+ {0, 0x00, 0x00,
+ {0x03, 0x43, 0x18, 0x03, 0x00, 0x04,
+ 0x03, 0x43, 0x18, 0x03, 0x00, 0x04,
+ 0x03, 0x43, 0x18, 0x03, 0x00, 0x04,
+ 0x03, 0x43, 0x18, 0x03, 0x00, 0x04}}
+};
+
+static void it61620_hdmi_setup_afe(struct it61620 *it61620, int clock)
+{
+ int i;
+ unsigned int reg_ofset;
+ const struct it61620_hdmi_afe_setting *afe;
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AFE30, 0x1f, 0x07);
+ regmap_write(it61620->tx_regmap, TX_REG_AFEE9, 0x10);
+ regmap_write(it61620->tx_regmap, TX_REG_AFE33, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AFE34, 0xe4);
+
+ regmap_write(it61620->tx_regmap, TX_REG_AFE35, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AFEE9, 0x10);
+
+ for (i = 0; i < sizeof(hdmi_afe); i++) {
+ if (clock > hdmi_afe[i].clock || hdmi_afe[i].clock == 0)
+ break;
+ }
+
+ afe = &hdmi_afe[i];
+
+ regmap_write(it61620->tx_regmap, TX_REG_AFE0E, 0xf0);
+
+ if (clock > 100000)
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXPLL_CTRL, 0x19, 0x08);
+ else
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXPLL_CTRL, 0x19, 0x11);
+
+ if (afe->h2on_pll) {
+ regmap_write(it61620->tx_regmap, TX_REG_AFE_XP, 0x48);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AFE_XLC1, 0x87, 0x81);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AFE_XLC2, 0x40, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AFE_XLC3, 0x32);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_XLC_7_CTRL, 0xff, 0xb6);
+ } else {
+ regmap_write(it61620->tx_regmap, TX_REG_AFE_XP, 0x00);
+ }
+
+ regmap_write(it61620->tx_regmap, TX_REG_AFE_DRV, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0x02, afe->hs);
+
+ for (i = 0, reg_ofset = 0x280; reg_ofset <= 0x297; reg_ofset++)
+ regmap_write(it61620->tx_regmap, reg_ofset, afe->afe_val[i++]);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_INT_MASK3, B_TMDS_STB_CHG,
+ B_TMDS_STB_CHG);
+}
+
+static inline void it61620_hdmi_fire_afe(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0xf1, 0xf1);
+}
+
+static inline void it61620_hdmi_disable_afe(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_TXDRV_CTRL, 0xf1, 0x00);
+}
+
+static int it61620_hdmi_hdcprd(struct it61620 *it61620, int offset, int bytenum)
+{
+ int ret = 0;
+
+ guard(mutex)(&it61620->ddc_lock);
+
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND, DDC_COMMAND_FIFO_CLR);
+ usleep_range(1000, 2000);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_ADDR, DDC_HDCP_ADDR);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_OFFSET, offset);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_NUM_L, bytenum);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_NUM_H, (bytenum & 0x300) >> 8);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND, DDC_COMMAND_BURST_R);
+
+ if (it61620_hdmi_ddc_wait(it61620) < 0) {
+ it61620_hdmi_ddc_abort(it61620);
+ ret = -EIO;
+ dev_dbg(it61620->dev, "ddc fail");
+ }
+ return ret;
+}
+
+static int it61620_hdmi_hdcp_ksvlist_rd(struct it61620 *it61620,
+ unsigned int bytenum, u8 *out)
+{
+ int ret = 0;
+ unsigned int i;
+ unsigned int count;
+
+ guard(mutex)(&it61620->ddc_lock);
+
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND, DDC_COMMAND_FIFO_CLR);
+ usleep_range(1000, 2000);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_ADDR, DDC_HDCP_ADDR);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_OFFSET, 0x43);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_NUM_L, bytenum);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_NUM_H, (bytenum & 0x300) >> 8);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND, DDC_COMMAND_BURST_R);
+
+ for (i = 0; i < bytenum;) {
+ if (it61620_hdmi_ddc_wait(it61620) < 0) {
+ it61620_hdmi_ddc_abort(it61620);
+ ret = -EIO;
+ dev_dbg(it61620->dev, "ddc fail");
+ break;
+ }
+
+ regmap_read(it61620->tx_regmap, TX_REG_DDC_FIFO_STS, &count);
+ count &= M_DDC_STAGE_NUM;
+ it61620_hdmi_get_ddc_fifo(it61620, (out + i), count);
+ i += count;
+ }
+
+ return ret;
+}
+
+static int it61620_hdmi_setup_sha1_input(struct it61620 *it61620, u8 *input)
+{
+ struct drm_device *drm = it61620->drm;
+ u8 bstatus[2];
+ int down_stream_count, count = 0;
+
+ it61620_hdmi_hdcprd(it61620, DRM_HDCP_DDC_BSTATUS, DRM_HDCP_BSTATUS_LEN);
+ regmap_bulk_read(it61620->tx_regmap, TX_REG_HDCP_BSTS_L, bstatus, 2);
+
+ down_stream_count = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]);
+ if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
+ DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) {
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL3,
+ (B_PAUSE | B_ENC_DIS), B_PAUSE);
+ return 0;
+ }
+
+ if (!down_stream_count ||
+ down_stream_count > MAX_HDCP_DOWN_STREAM_COUNT) {
+ drm_dbg(drm, "HDCP down stream count Error %d",
+ down_stream_count);
+ return 0;
+ }
+ drm_dbg(drm, "down stream count %d\n", down_stream_count);
+
+ count = down_stream_count * DRM_HDCP_KSV_LEN;
+ it61620_hdmi_hdcp_ksvlist_rd(it61620, count, input);
+ if (drm_hdcp_check_ksvs_revoked(drm, input, down_stream_count) > 0)
+ return 0;
+
+ input[count++] = bstatus[0];
+ input[count++] = bstatus[1];
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_SHA_SEL, 0x70, 0x70);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL2, B_EN_M0_RD, B_EN_M0_RD);
+ regmap_bulk_read(it61620->tx_regmap, TX_REG_ANM0V1, &input[count], 8);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL2, B_EN_M0_RD, 0x00);
+
+ return count;
+}
+
+static bool it61620_hdmi_hdcp_part2_ksvlist_check(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ u8 av[5][4], bv[5][4];
+ int i;
+
+ i = it61620_hdmi_setup_sha1_input(it61620, it61620->sha1_input);
+ if (i <= 0)
+ return false;
+
+ sha1(it61620->sha1_input, i, (u8 *)av);
+
+ for (i = 0; i < DRM_HDCP_V_PRIME_NUM_PARTS; i++) {
+ it61620_hdmi_hdcprd(it61620, DRM_HDCP_DDC_V_PRIME(i),
+ DRM_HDCP_V_PRIME_PART_LEN);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL2,
+ B_EN_M0_RD, B_EN_M0_RD);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_SHA_SEL, 0x70, (i << 4));
+
+ regmap_bulk_read(it61620->tx_regmap, TX_REG_ANM0V1, bv[i],
+ DRM_HDCP_V_PRIME_PART_LEN);
+ }
+
+ for (i = 0; i < DRM_HDCP_V_PRIME_NUM_PARTS; i++)
+ if (bv[i][3] != av[i][0] || bv[i][2] != av[i][1] ||
+ bv[i][1] != av[i][2] || bv[i][0] != av[i][3])
+ break;
+
+ if (i == DRM_HDCP_V_PRIME_NUM_PARTS)
+ return true;
+
+ drm_dbg(drm, "V' Not match!!");
+ return false;
+}
+
+static unsigned int it61620_hdmi_hdcp_read_bcaps(struct it61620 *it61620)
+{
+ unsigned int val;
+
+ it61620_hdmi_hdcprd(it61620, DRM_HDCP_DDC_BCAPS, 1);
+ regmap_read(it61620->tx_regmap, TX_REG_HDCP_BCAPS, &val);
+ return val;
+}
+
+static void it61620_hdmi_hdcp_wait_ksv_list(struct it61620 *it61620)
+{
+ unsigned int bcaps = 0;
+
+ readx_poll_timeout(it61620_hdmi_hdcp_read_bcaps,
+ it61620, bcaps,
+ ((bcaps & B_KSV_READY) |
+ (it61620->hdcp_state != CP_GOING)),
+ 2000,
+ 1000 * HDCP_KSV_LIST_TIMEOUT_MS);
+
+ if ((bcaps & B_KSV_READY) &&
+ it61620_hdmi_hdcp_part2_ksvlist_check(it61620)) {
+ regmap_write(it61620->tx_regmap, TX_REG_HDCP_PRO, B_LIST_CHK_DONE);
+ return;
+ }
+ regmap_write(it61620->tx_regmap, TX_REG_HDCP_PRO,
+ B_LIST_CHK_DONE | B_LIST_CHK_FAIL);
+}
+
+static inline void it61620_hdmi_enable_avmute(struct it61620 *it61620,
+ bool enable)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDMI_CTRL2, B_EN_AVMUTE, enable);
+}
+
+static int it61620_hdmi_enable_hdcp(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ unsigned int sts, auth_cs;
+
+ regmap_read(it61620->tx_regmap, TX_REG_V_STS, &sts);
+ if ((sts & B_TMDS_STABLE) != B_TMDS_STABLE) {
+ drm_dbg(drm, "TMDS not stable, stop hdcp %x", sts);
+ return false;
+ }
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL3, B_ENC_DIS, B_ENC_DIS);
+ usleep_range(1000, 2000);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x10, 0x10);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x10, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_R0TM, 0xc0, 0x40);
+ regmap_write(it61620->tx_regmap, TX_REG_SHA_SEL, 0x00);
+
+ regmap_write(it61620->tx_regmap, TX_REG_AUTOMUTE, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL2, B_AN_SEL, B_AN_SEL);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL2, B_EN_AN_GEN,
+ B_EN_AN_GEN);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL2, B_EN_AN_GEN, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL1, B_CPDESIRED,
+ B_CPDESIRED);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL3, (B_PAUSE | B_ENC_DIS),
+ 0x00);
+
+ regmap_write(it61620->tx_regmap, TX_REG_HDCP_PRO, B_AUTH_FIRE);
+
+ /*
+ * HDCP start requires 100ms for the first part of the authentication
+ * protocol,20ms is used to wait for 61620 HW completion.
+ */
+ if (wait_event_timeout(it61620->wq, !it61620->hpd, msecs_to_jiffies(120)))
+ return false;
+
+ regmap_read(it61620->tx_regmap, TX_REG_HDCP_AUTH_CS, &auth_cs);
+ auth_cs &= M_AUTH_CH;
+ if (auth_cs == CS_KSVLIST_CHK) {
+ it61620_hdmi_hdcp_wait_ksv_list(it61620);
+ usleep_range(1000, 2000);
+ regmap_read(it61620->tx_regmap, TX_REG_HDCP_AUTH_CS, &auth_cs);
+ auth_cs &= M_AUTH_CH;
+ }
+
+ if (auth_cs == CS_AUTH_DONE) {
+ it61620_hdmi_enable_avmute(it61620, false);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_INT1, B_INT_AUTH_F,
+ B_INT_AUTH_F);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_INT_MASK1, B_INT_AUTH_F,
+ B_INT_AUTH_F);
+ drm_dbg(drm, "auth done");
+ it61620->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ drm_hdcp_update_content_protection(it61620->connector,
+ it61620->hdcp_cp);
+ return true;
+ }
+
+ drm_dbg(drm, "auth fail");
+ it61620_hdmi_enable_avmute(it61620, true);
+ it61620_hdmi_ddc_abort(it61620);
+ return false;
+}
+
+static void it61620_hdmi_reset_hdcp(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_INT_MASK1,
+ (B_INT_AUTH_D | B_INT_AUTH_F), 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_INT_MASK2, B_KSV_CHECK, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL3, B_ENC_DIS, B_ENC_DIS);
+ usleep_range(1000, 2000);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x18, 0x18);
+ usleep_range(1000, 2000);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x18, 0x00);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL1, B_CPDESIRED,
+ B_CPDESIRED);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDCP_CTRL3,
+ (B_PAUSE | B_ENC_DIS), B_PAUSE);
+ regmap_write(it61620->tx_regmap, TX_REG_AUTOMUTE, 0x00);
+}
+
+static bool it61620_hdmi_hdcp_is_ksv_valid(u8 *ksv)
+{
+ int i, ones = 0;
+
+ if ((ksv[4] == 0x93 && ksv[3] == 0x43 && ksv[2] == 0x5c &&
+ ksv[1] == 0xde && ksv[0] == 0x23) ||
+ (ksv[4] == 0x7d && ksv[3] == 0xb4 && ksv[2] == 0x21 &&
+ ksv[1] == 0x37 && ksv[0] == 0x0b))
+ return false;
+
+ /* KSV has 20 1's and 20 0's */
+ for (i = 0; i < 5; i++)
+ ones += hweight8(ksv[i]);
+
+ return ones == 20;
+}
+
+static void it61620_hdmi_disable_hdcp(struct it61620 *it61620)
+{
+ it61620_hdmi_reset_hdcp(it61620);
+}
+
+static int it61620_hdmi_start_hdcp(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ unsigned int rx_hdmi_mode;
+ u8 bksv[DRM_HDCP_KSV_LEN];
+ bool retcheck;
+
+ if (it61620_hdmi_hdcprd(it61620, DRM_HDCP_DDC_BSTATUS,
+ DRM_HDCP_BSTATUS_LEN) < 0) {
+ drm_dbg(drm, "read bstatus fail!\n");
+ return false;
+ }
+
+ regmap_read(it61620->tx_regmap, 0x7e, &rx_hdmi_mode);
+ rx_hdmi_mode = (rx_hdmi_mode & 0x10) >> 4;
+ if (it61620->is_hdmi != rx_hdmi_mode)
+ return false;
+
+ it61620_hdmi_hdcprd(it61620, DRM_HDCP_DDC_BKSV, DRM_HDCP_KSV_LEN);
+ regmap_bulk_read(it61620->tx_regmap, TX_REG_HDCP_BKSV1, bksv, 5);
+ retcheck = it61620_hdmi_hdcp_is_ksv_valid(bksv);
+ if (!retcheck) {
+ drm_dbg(drm, "ksv valid!\n");
+ return false;
+ }
+
+ if (drm_hdcp_check_ksvs_revoked(drm, bksv, 1) > 0)
+ return false;
+
+ return it61620_hdmi_enable_hdcp(it61620);
+}
+
+static void it61620_start_hdcp_work(struct it61620 *it61620)
+{
+ if (it61620->hdcp_cp == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+ return;
+
+ it61620->hdcp_state = CP_GOING;
+ queue_delayed_work(system_wq, &it61620->hdcp_work,
+ msecs_to_jiffies(2400));
+}
+
+static void it61620_stop_hdcp_work(struct it61620 *it61620)
+{
+ it61620->hdcp_state = CP_NONE;
+ cancel_delayed_work_sync(&it61620->hdcp_work);
+ it61620_hdmi_disable_hdcp(it61620);
+}
+
+static void it61620_hdmi_irq_hdcp_auth_fail(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+
+ if (it61620->hdcp_state == CP_GOING) {
+ it61620_hdmi_enable_avmute(it61620, true);
+ drm_dbg(drm, "auth fail after done, set avmute");
+ it61620->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ drm_hdcp_update_content_protection(it61620->connector,
+ it61620->hdcp_cp);
+ it61620_start_hdcp_work(it61620);
+ }
+}
+
+static void it61620_hdmi_irq_hpd(struct it61620 *it61620)
+{
+ it61620->hpd = it61620_hdmi_get_hpd_status(it61620);
+
+ if (!it61620->hpd) {
+ wake_up(&it61620->wq);
+ it61620_stop_hdcp_work(it61620);
+ it61620_hdmi_disable_afe(it61620);
+ } else if (it61620->video_state == it61620_VIDEO_ON) {
+ it61620_hdmi_fire_afe(it61620);
+ it61620_start_hdcp_work(it61620);
+ }
+}
+
+static void it61620_hdmi_irq_rxsen_chg(struct it61620 *it61620)
+{
+ unsigned int rxsen;
+
+ if (!it61620_hdmi_get_hpd_status(it61620))
+ return;
+
+ regmap_read(it61620->tx_regmap, TX_REG_V_STS, &rxsen);
+ rxsen &= B_RXSEN;
+ if (it61620->video_state == it61620_VIDEO_ON) {
+ if (rxsen) {
+ it61620_hdmi_fire_afe(it61620);
+ it61620_start_hdcp_work(it61620);
+ } else {
+ it61620_stop_hdcp_work(it61620);
+ it61620_hdmi_disable_afe(it61620);
+ }
+ }
+}
+
+static void it61620_hdmi_irq_tmds_stb_change(struct it61620 *it61620)
+{
+ unsigned int video_status;
+
+ regmap_read(it61620->tx_regmap, TX_REG_V_STS, &video_status);
+
+ if (video_status & B_TMDS_STABLE)
+ it61620_start_hdcp_work(it61620);
+}
+
+static void it61620_hdmi_interrupt_handler(struct it61620 *it61620)
+{
+ unsigned int int_status1, int_status2, int_status3;
+
+ regmap_read(it61620->tx_regmap, TX_REG_INT1, &int_status1);
+ regmap_read(it61620->tx_regmap, TX_REG_INT2, &int_status2);
+ regmap_read(it61620->tx_regmap, TX_REG_INT3, &int_status3);
+
+ regmap_write(it61620->tx_regmap, TX_REG_INT1, int_status1);
+ regmap_write(it61620->tx_regmap, TX_REG_INT2, int_status2);
+ regmap_write(it61620->tx_regmap, TX_REG_INT3, int_status3);
+
+ if (TX_REG_INT1 & B_HPD_CHG)
+ it61620_hdmi_irq_hpd(it61620);
+
+ if (TX_REG_INT1 & B_RXSEN_CHANGE)
+ it61620_hdmi_irq_rxsen_chg(it61620);
+
+ if (TX_REG_INT1 & B_INT_AUTH_F)
+ it61620_hdmi_irq_hdcp_auth_fail(it61620);
+
+ if (int_status3 & B_TMDS_STB_CHG)
+ it61620_hdmi_irq_tmds_stb_change(it61620);
+}
+
+static void it61620_hdmi_irq(struct it61620 *it61620)
+{
+ unsigned int reg_val;
+
+ regmap_read(it61620->tx_regmap, TX_REG_HDMITX_BANK, ®_val);
+ if (reg_val & B_INT_EVENT_HDMI)
+ it61620_hdmi_interrupt_handler(it61620);
+}
+
+static void it61620_hdmi_audio_set_ncts(struct it61620 *it61620,
+ unsigned int sample_rate)
+{
+ unsigned int n, cts;
+
+ drm_hdmi_acr_get_n_cts(it61620->tmds_char_rate, sample_rate,
+ &n, &cts);
+
+ regmap_write(it61620->tx_regmap, TX_REG_AUDPKT_N_0, n & 0xff);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDPKT_N_1, (n >> 8) & 0xff);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDPKT_N_2, (n >> 16) & 0x0f);
+
+ regmap_write(it61620->tx_regmap, TX_REG_AUDPKT_CTS_0, cts & 0xff);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDPKT_CTS_1, (cts >> 8) & 0xff);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDPKT_CTS_2, (cts >> 16) & 0x0f);
+}
+
+static void it61620_hdmi_avi_infoframe_set(struct it61620 *it61620,
+ const u8 *buffer, size_t len)
+{
+ struct drm_device *drm = it61620->drm;
+ const u8 *ptr;
+ u8 i;
+
+ drm_dbg(drm, "avi info set\n");
+
+ /* fill PB */
+ ptr = buffer + HDMI_INFOFRAME_HEADER_SIZE;
+ for (i = 0; i < len - HDMI_INFOFRAME_HEADER_SIZE; i++)
+ regmap_write(it61620->tx_regmap, TX_REG_AVIINFO_DB01 + i, ptr[i]);
+ /* checksum */
+ regmap_write(it61620->tx_regmap, TX_REG_AVIINFO_DB14, buffer[3]);
+
+ /* Enable */
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1, (B_EN_AVI | B_AVI_RP),
+ (B_EN_AVI | B_AVI_RP));
+}
+
+static void it61620_hdmi_spd_infoframe_set(struct it61620 *it61620,
+ const u8 *buffer, size_t len)
+{
+ struct drm_device *drm = it61620->drm;
+ u8 i;
+ const u8 *ptr;
+
+ drm_dbg(drm, "spd info set\n");
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT2,
+ (B_EN_NULL | B_EN_NULL_RP), 0x00);
+
+ for (i = 0; i < 3; i++)
+ regmap_write(it61620->tx_regmap, TX_REG_NULLPKT_HB00 + i, buffer[i]);
+ ptr = buffer + 3;
+ for (i = 0; i < len - 3; i++)
+ regmap_write(it61620->tx_regmap, TX_REG_NULLPKT_PB00 + i, ptr[i]);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT2,
+ (B_EN_NULL | B_EN_NULL_RP),
+ (B_EN_NULL | B_EN_NULL_RP));
+}
+
+static void it61620_hdmi_vendor_infoframe_set(struct it61620 *it61620,
+ const u8 *buffer, size_t len)
+{
+ struct drm_device *drm = it61620->drm;
+ u8 i;
+ const u8 *ptr;
+
+ drm_dbg(drm, "VSIF set\n");
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1,
+ (B_EN_VSIF | B_EN_VSIF_RP), 0x00);
+
+ regmap_write(it61620->tx_regmap, TX_REG_VSIFPKT_HB02, buffer[2]);
+ ptr = buffer + 3;
+ for (i = 3; i < len - 3; i++)
+ regmap_write(it61620->tx_regmap, TX_REG_VSIFPKT_PB00 + i, ptr[i]);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1,
+ (B_EN_VSIF | B_EN_VSIF_RP),
+ (B_EN_VSIF | B_EN_VSIF_RP));
+}
+
+static void it61620_hdmi_config_output(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+
+ it61620_hdmi_reset(it61620);
+ it61620_hdmi_poweron(it61620);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDMI_CTRL2, 0x70, 0x00);
+ if (it61620->is_hdmi) {
+ drm_dbg(drm, "HDMI\n");
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDMI_CTRL1,
+ B_EN_HDMI_MODE, B_EN_HDMI_MODE);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT2,
+ (B_EN_GEN | B_GEN_RP),
+ (B_EN_GEN | B_GEN_RP));
+ } else {
+ drm_dbg(drm, "DVI\n");
+ regmap_update_bits(it61620->tx_regmap, TX_REG_HDMI_CTRL1,
+ B_EN_HDMI_MODE, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_EN_PKT2, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_EN_PKT1, 0x00);
+ }
+
+ it61620_hdmi_enable_avmute(it61620, false);
+ it61620_hdmi_setup_afe(it61620, it61620->tmds_char_rate / 1000);
+ it61620_hdmi_fire_afe(it61620);
+ it61620->video_state = it61620_VIDEO_ON;
+}
+
+static int it61620_hdmi_audio_infoframe_set(struct it61620 *it61620,
+ const u8 *buffer, size_t len)
+{
+ u8 i;
+ const u8 *ptr;
+
+ /* fill PB */
+ ptr = buffer + HDMI_INFOFRAME_HEADER_SIZE;
+ for (i = 0; i < len - HDMI_INFOFRAME_HEADER_SIZE; i++)
+ regmap_write(it61620->tx_regmap, TX_REG_AUDINFO_DB01 + i, ptr[i]);
+
+ regmap_write(it61620->tx_regmap, TX_REG_AUDINFO_DB06, buffer[3]);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDINFO_DB07, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDINFO_DB08, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDINFO_DB09, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AUDINFO_DB10, 0x00);
+
+ /* Enable */
+ regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1, (B_EN_AUD | B_EN_AUD_RP),
+ (B_EN_AUD | B_EN_AUD_RP));
+ return 0;
+}
+
+static void it61620_hw_reset(struct it61620 *it61620)
+{
+ if (!it61620->gpiod_reset)
+ return;
+
+ gpiod_set_value_cansleep(it61620->gpiod_reset, 1);
+
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(it61620->gpiod_reset, 0);
+ usleep_range(10000, 20000);
+}
+
+static int it61620_enable_devices(struct it61620 *it61620)
+{
+ struct device *dev = &it61620->it61620_i2c->dev;
+ unsigned int device_id[5];
+ unsigned int i, vid, pid;
+
+ regmap_write(it61620->it61620_regmap, REG_CTRL_PW, 0x55);
+ regmap_write(it61620->it61620_regmap, REG_CTRL_PW, 0xaa);
+ regmap_write(it61620->it61620_regmap, REG_CTRL_PW, 0xc3);
+ regmap_write(it61620->it61620_regmap, REG_CTRL_PW, 0xa5);
+ usleep_range(1000, 2000);
+
+ for (i = 0; i < 5; i++)
+ regmap_read(it61620->mipirx_regmap, REG_VENDER_ID_L + i, &device_id[i]);
+
+ dev_dbg(dev, "IT61620 ver %02X", device_id[4]);
+
+ vid = (device_id[1] << 8) | device_id[0];
+ pid = (device_id[3] << 8) | device_id[2];
+
+ if (vid != it61620->chip_info->vid ||
+ pid != it61620->chip_info->pid) {
+ dev_err(dev, "vid %X != %X",
+ vid, it61620->chip_info->vid);
+ dev_err(dev, "pid %X != %X",
+ pid, it61620->chip_info->pid);
+
+ return -ENODEV;
+ }
+
+ it61620->dev_ver = device_id[4];
+ return 0;
+}
+
+static void it61620_int_setup(struct it61620 *it61620)
+{
+ /* SET INT# to Active Low open-drain */
+ regmap_update_bits(it61620->mipirx_regmap, RX_REG_INT_POL, 0x08, 0x08);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_SYS_CONFIG, 0x0f, B_INT_MODE);
+ regmap_update_bits(it61620->tx_regmap, REG_TX_INT_CTRL, B_DIS_INT_OUTPUT, 0x00);
+}
+
+static void it61620_int_enable(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_INT_MASK1, B_HPD_CHG, B_HPD_CHG);
+}
+
+static int it61620_reset_init(struct it61620 *it61620)
+{
+ it61620_hw_reset(it61620);
+
+ if (it61620_enable_devices(it61620) < 0)
+ return -ENODEV;
+
+ it61620_mipi_reset(it61620);
+ it61620_hdmi_reset(it61620);
+ it61620_int_setup(it61620);
+ it61620_int_enable(it61620);
+ it61620_hdmi_powerdown(it61620);
+
+ return 0;
+}
+
+static int it61620_poweron(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ struct device *dev = it61620->dev;
+ int err;
+
+ if (it61620->powered) {
+ drm_dbg(drm, "Already powered on");
+ return 0;
+ }
+
+ err = regulator_enable(it61620->ivdd);
+ if (err) {
+ dev_err(dev, "Failed to enable IVDD: %d", err);
+ goto poweron_exit;
+ }
+
+ err = regulator_enable(it61620->ovdd1833);
+ if (err) {
+ dev_err(dev, "Failed to enable OVDD1833: %d", err);
+ goto disable_ivdd;
+ }
+
+ err = regulator_enable(it61620->ovdd33);
+ if (err) {
+ dev_err(dev, "Failed to enable OVDD33: %d", err);
+ goto disable_ovdd1833;
+ }
+
+ gpiod_set_value_cansleep(it61620->gpiod_reset, 1);
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(it61620->gpiod_reset, 0);
+ usleep_range(10000, 20000);
+
+ err = it61620_reset_init(it61620);
+ if (err < 0)
+ goto disable_ovdd33;
+
+ it61620->powered = true;
+ it61620->hpd = it61620_hdmi_get_hpd_status(it61620);
+ if (it61620->it61620_i2c->irq) {
+ enable_irq(it61620->it61620_i2c->irq);
+ drm_dbg(drm, "enable irq %d\n",
+ it61620->it61620_i2c->irq);
+ }
+ drm_dbg(drm, "it61620 poweron end\n");
+ return 0;
+
+disable_ovdd33:
+ regulator_disable(it61620->ovdd33);
+disable_ovdd1833:
+ regulator_disable(it61620->ovdd1833);
+disable_ivdd:
+ regulator_disable(it61620->ivdd);
+poweron_exit:
+ return err;
+}
+
+static int it61620_poweroff(struct it61620 *it61620)
+{
+ struct drm_device *drm = it61620->drm;
+ struct device *dev = it61620->dev;
+ int err;
+
+ if (!it61620->powered) {
+ drm_dbg(drm, "Already powered off");
+ return 0;
+ }
+
+ if (it61620->it61620_i2c->irq) {
+ disable_irq(it61620->it61620_i2c->irq);
+ drm_dbg(drm, "disable irq %d\n",
+ it61620->it61620_i2c->irq);
+ }
+
+ gpiod_set_value_cansleep(it61620->gpiod_reset, 1);
+
+ err = regulator_disable(it61620->ovdd33);
+ if (err)
+ dev_err(dev, "Failed to disable ovdd33: %d", err);
+
+ err = regulator_disable(it61620->ivdd);
+ if (err)
+ dev_err(dev, "Failed to disable IVDD: %d", err);
+
+ usleep_range(2000, 3000);
+
+ err = regulator_disable(it61620->ovdd1833);
+ if (err)
+ dev_err(dev, "Failed to disable ovdd1833: %d", err);
+
+ it61620->powered = false;
+ it61620->hpd = false;
+ it61620->connector_status = connector_status_disconnected;
+ drm_dbg(drm, "it61620 poweroff\n");
+
+ return 0;
+}
+
+static void it61620_config_default(struct it61620 *it61620)
+{
+ struct it61620_mipirx *mipirx = &it61620->mipirx_config;
+
+ mipirx->lane_num = 4;
+ mipirx->pn_swap = 0;
+ mipirx->lane_swap = 0;
+ it61620->connector_status = connector_status_disconnected;
+ it61620->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ it61620->i2s_input_format = I2S_INPUT_FORMAT_STANDARD;
+}
+
+static int it61620_get_edid_block(void *data, u8 *buf, unsigned int block,
+ size_t len)
+{
+ struct it61620 *it61620 = data;
+ unsigned int edid_offset;
+ unsigned int cnt;
+ unsigned int i;
+ int ret = 0;
+
+ if (len > EDID_LENGTH)
+ return -EINVAL;
+
+ guard(mutex)(&it61620->ddc_lock);
+
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND, DDC_COMMAND_FIFO_CLR);
+
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_ADDR, DDC_EDID_ADDR);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_SEGMENT, block / 2);
+
+ cnt = 0;
+ edid_offset = block * 128;
+
+ for (i = 0; i < EDID_LENGTH; i += EDID_R_BURST_NUM,
+ edid_offset += EDID_R_BURST_NUM,
+ cnt += EDID_R_BURST_NUM) {
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_OFFSET, edid_offset);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_SEGMENT, block >> 1);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_NUM_L, EDID_R_BURST_NUM);
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_NUM_H,
+ (EDID_R_BURST_NUM >> 8));
+ regmap_write(it61620->tx_regmap, TX_REG_DDC_COMMAND,
+ DDC_COMMAND_EDID_RD);
+
+ if (it61620_hdmi_ddc_wait(it61620) < 0) {
+ it61620_hdmi_ddc_abort(it61620);
+ ret = -EIO;
+ break;
+ }
+
+ it61620_hdmi_get_ddc_fifo(it61620, &buf[cnt], EDID_R_BURST_NUM);
+ }
+
+ return ret;
+}
+
+static void it61620_enable_audio(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x01, 0x00);
+}
+
+static void it61620_disable_audio(struct it61620 *it61620)
+{
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x01, 0x01);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_LINK_CTRL0,
+ B_EN_AUDIO_MUTE, B_EN_AUDIO_MUTE);
+}
+
+static irqreturn_t it61620_int_threaded_handler(int unused, void *data)
+{
+ struct it61620 *it61620 = data;
+ struct device *dev = it61620->dev;
+
+ pm_runtime_get_sync(dev);
+
+ it61620_mipi_irq_handler(it61620);
+ it61620_hdmi_irq(it61620);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return IRQ_HANDLED;
+}
+
+static void it61620_audio_update_hw_params(struct it61620 *it61620,
+ struct hdmi_codec_daifmt *fmt,
+ struct hdmi_codec_params *hparms)
+{
+ struct drm_device *drm = it61620->drm;
+ u8 audsrc, sample_rate_val, sample_width;
+ bool is_lpcm;
+
+ switch (hparms->sample_rate) {
+ case 32000:
+ sample_rate_val = SAMPLE_RATE_32K;
+ break;
+ case 44100:
+ sample_rate_val = SAMPLE_RATE_44_1K;
+ break;
+ case 48000:
+ sample_rate_val = SAMPLE_RATE_48K;
+ break;
+ case 88200:
+ sample_rate_val = SAMPLE_RATE_88_2K;
+ break;
+ case 96000:
+ sample_rate_val = SAMPLE_RATE_96K;
+ break;
+ case 176400:
+ sample_rate_val = SAMPLE_RATE_176_4K;
+ break;
+ case 192000:
+ sample_rate_val = SAMPLE_RATE_192K;
+ break;
+ }
+
+ switch (hparms->sample_width) {
+ case 16:
+ sample_width = WORD_LENGTH_16BIT;
+ break;
+ case 20:
+ sample_width = WORD_LENGTH_20BIT;
+ break;
+ case 24:
+ sample_width = WORD_LENGTH_24BIT;
+ break;
+ }
+
+ switch (fmt->fmt) {
+ case HDMI_I2S:
+ case HDMI_SPDIF:
+ break;
+ default:
+ return;
+ }
+
+ is_lpcm = !(hparms->iec.status[0] & IEC958_AES0_NONAUDIO);
+ it61620_hdmi_audio_set_ncts(it61620, hparms->sample_rate);
+
+ drm_dbg(drm, "sample rate %d", sample_rate_val);
+ drm_dbg(drm, "sample width %d", sample_width);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AUD_FMT, 0x7f,
+ (sample_width << 5) | it61620->i2s_input_format);
+ if (fmt->fmt == HDMI_SPDIF) {
+ drm_dbg(drm, "SPDIF");
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_FIFO1, 0x00);
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_FIFO2, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AUD_SPDIF, 0x0f, 0x02);
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_CTRL, 0X01);
+ } else {
+ drm_dbg(drm, "I2S");
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_FIFO1, 0x10);
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_FIFO2, 0x32);
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_CTRL, 0X00);
+ }
+
+ if (is_lpcm)
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_STS1, 0x00);
+ else
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_STS1, B_EN_AUD_NLPCM);
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_STS2, sample_rate_val);
+ regmap_write(it61620->tx_regmap, TX_REG_AUD_STS3,
+ ((~(sample_rate_val << 4)) & 0xf0) + 0x0B);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_AUD_CTS, 0x08, 0x08);
+
+ switch (hparms->channels) {
+ case 1:
+ case 2:
+ audsrc = 0x01;
+ break;
+ case 3:
+ case 4:
+ audsrc = 0x03;
+ break;
+ case 5:
+ case 6:
+ audsrc = 0x07;
+ break;
+ case 7:
+ case 8:
+ audsrc = 0x0f;
+ break;
+ }
+
+ regmap_write(it61620->tx_regmap, TX_REG_EN_AUDIO, audsrc);
+
+ regmap_update_bits(it61620->tx_regmap, TX_REG_LINK_CTRL0, B_EN_AUDIO_MUTE, 0x00);
+ regmap_update_bits(it61620->tx_regmap, TX_REG_RESET_2_CTRL, 0x01, 0x00);
+}
+
+static void it61620_hdcp_work(struct work_struct *work)
+{
+ struct it61620 *it61620 = container_of(work, struct it61620,
+ hdcp_work.work);
+ it61620_hdmi_reset_hdcp(it61620);
+ if (!it61620_hdmi_start_hdcp(it61620) &&
+ it61620->hdcp_state == CP_GOING) {
+ it61620_hdmi_disable_hdcp(it61620);
+ it61620_start_hdcp_work(it61620);
+ }
+}
+
+static int it61620_i2c_and_regmap_init(struct i2c_client *client,
+ struct it61620 *it61620)
+{
+ struct device *dev = it61620->dev;
+
+ it61620->it61620_i2c = client;
+
+ it61620->tx_i2c = devm_i2c_new_dummy_device(dev,
+ client->adapter,
+ TX_I2C_ADDRESS);
+ if (IS_ERR(it61620->tx_i2c))
+ return dev_err_probe(dev, PTR_ERR(it61620->tx_i2c),
+ "failed to create TX dummy i2c device at 0x%02x\n",
+ TX_I2C_ADDRESS);
+
+ it61620->mipirx_i2c = devm_i2c_new_dummy_device(dev,
+ client->adapter,
+ MIPIRX_I2C_ADDRESS);
+ if (IS_ERR(it61620->mipirx_i2c))
+ return dev_err_probe(dev, PTR_ERR(it61620->mipirx_i2c),
+ "failed to create MIPI dummy i2c device at 0x%02x\n",
+ MIPIRX_I2C_ADDRESS);
+
+ it61620->it61620_regmap = devm_regmap_init_i2c(it61620->it61620_i2c,
+ &it61620_regmap_config);
+ if (IS_ERR(it61620->it61620_regmap))
+ return dev_err_probe(dev, PTR_ERR(it61620->it61620_regmap),
+ "failed to init I2C regmap for it61620\n");
+
+ it61620->tx_regmap = devm_regmap_init_i2c(it61620->tx_i2c,
+ &it61620_tx_regmap_config);
+ if (IS_ERR(it61620->tx_regmap))
+ return dev_err_probe(dev, PTR_ERR(it61620->tx_regmap),
+ "failed to init I2C regmap for TX\n");
+
+ it61620->mipirx_regmap = devm_regmap_init_i2c(it61620->mipirx_i2c,
+ &it61620_mipi_regmap_config);
+ if (IS_ERR(it61620->mipirx_regmap))
+ return dev_err_probe(dev, PTR_ERR(it61620->mipirx_regmap),
+ "failed to init I2C regmap for MIPI\n");
+ return 0;
+}
+
+static int it61620_attach_dsi(struct it61620 *it61620,
+ struct mipi_dsi_host *host)
+{
+ struct device *dev = it61620->dev;
+ struct mipi_dsi_device *dsi;
+ const struct mipi_dsi_device_info info = {"it61620",
+ 0,
+ dev->of_node};
+
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi))
+ return dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n");
+
+ it61620->dsi = dsi;
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+
+ return devm_mipi_dsi_attach(dev, dsi);
+}
+
+static void it61620_detach_dsi(struct it61620 *it61620)
+{
+ if (!it61620->dsi)
+ return;
+
+ mipi_dsi_detach(it61620->dsi);
+}
+
+static unsigned int it61620_parse_dt(struct it61620 *it61620)
+{
+ struct device *dev = it61620->dev;
+ struct device_node *np = it61620->dev->of_node;
+ int num_lanes;
+
+ if (!dev->of_node)
+ return -EINVAL;
+
+ num_lanes = drm_of_get_data_lanes_count_ep(np, 0, -1, 1, 4);
+ if (num_lanes < 0)
+ num_lanes = 4;
+ it61620->mipirx_config.lane_num = num_lanes;
+
+ it61620->next_bridge = devm_drm_of_get_bridge(dev, np, 1, -1);
+ if (IS_ERR(it61620->next_bridge))
+ return dev_err_probe(dev, PTR_ERR(it61620->next_bridge),
+ "failed to get next bridge\n");
+
+ return 0;
+}
+
+static int it61620_init_power(struct it61620 *it61620)
+{
+ struct device *dev = it61620->dev;
+
+ it61620->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(it61620->gpiod_reset))
+ return dev_err_probe(dev, PTR_ERR(it61620->gpiod_reset),
+ "gpiod_reset not found\n");
+
+ it61620->ivdd = devm_regulator_get(dev, "ivdd");
+ if (IS_ERR(it61620->ivdd))
+ return dev_err_probe(dev, PTR_ERR(it61620->ivdd),
+ "ivdd regulator not found\n");
+
+ it61620->ovdd1833 = devm_regulator_get(dev, "ovdd1833");
+ if (IS_ERR(it61620->ovdd1833))
+ return dev_err_probe(dev, PTR_ERR(it61620->ovdd1833),
+ "ovdd1833 regulator not found\n");
+
+ it61620->ovdd33 = devm_regulator_get(dev, "ovdd");
+ if (IS_ERR(it61620->ovdd33))
+ return dev_err_probe(dev, PTR_ERR(it61620->ovdd33),
+ "ovdd33 regulator not found\n");
+
+ return 0;
+}
+
+static inline int __maybe_unused it61620_pm_bridge_suspend(struct device *dev)
+{
+ struct it61620 *it61620 = dev_get_drvdata(dev);
+
+ it61620_poweroff(it61620);
+
+ return 0;
+}
+
+static inline int __maybe_unused it61620_pm_bridge_resume(struct device *dev)
+{
+ struct it61620 *it61620 = dev_get_drvdata(dev);
+
+ return it61620_poweron(it61620);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(it61620_bridge_pm_ops,
+ it61620_pm_bridge_suspend,
+ it61620_pm_bridge_resume, NULL);
+
+static int it61620_bridge_attach(struct drm_bridge *bridge,
+ struct drm_encoder *encoder,
+ enum drm_bridge_attach_flags flags)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+ struct drm_device *drm = bridge->dev;
+
+ it61620->drm = drm;
+
+ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
+ drm_dbg(drm,
+ "DRM_BRIDGE_ATTACH_NO_CONNECTOR must be supplied");
+ return -EINVAL;
+ }
+
+ return drm_bridge_attach(bridge->encoder, it61620->next_bridge,
+ bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+}
+
+static enum drm_mode_status
+it61620_bridge_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
+{
+ /* 297 MHz for 4k@30 8-bit */
+ if (tmds_rate > 297000000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static void it61620_bridge_hpd_notify(struct drm_bridge *bridge,
+ struct drm_connector *connector,
+ enum drm_connector_status status)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+ struct drm_device *drm = it61620->drm;
+ struct device *dev = it61620->dev;
+ int hpd, ret;
+
+ hpd = (status == connector_status_connected) ? 1 : 0;
+
+ if (it61620->connector_status == status) {
+ drm_dbg(drm, "GPIO hpd status NO change %d", hpd);
+ return;
+ }
+
+ drm_dbg(drm, "GPIO hpd status change %d->%d",
+ !hpd, hpd);
+
+ it61620->connector_status = status;
+ if (hpd) {
+ drm_dbg(drm, "HPD_GPIO get to wake up");
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
+ dev_err(dev,
+ "pm_runtime_get_sync error %d", ret);
+ } else {
+ drm_dbg(drm, "HPD_GPIO put to sleep");
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ }
+}
+
+static void it61620_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+ struct device *dev = it61620->dev;
+
+ pm_runtime_get_sync(dev);
+}
+
+static void it61620_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ struct drm_display_mode *adj_mode;
+ struct drm_connector *connector;
+
+ connector = drm_atomic_get_new_connector_for_encoder(state,
+ bridge->encoder);
+
+ if (!connector)
+ return;
+ it61620->connector = connector;
+
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+
+ it61620->hdcp_cp = conn_state->content_protection;
+ adj_mode = &crtc_state->adjusted_mode;
+
+ /*
+ * Keep the video pixel clock for later N/CTS calculation and
+ * HDMI AFE configuration
+ */
+ it61620->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
+ it61620->is_hdmi = connector->display_info.is_hdmi;
+ it61620->en_audio = connector->display_info.has_audio;
+ drm_dbg(it61620->drm, "%s mode, monitor %s support audio",
+ it61620->is_hdmi ? "HDMI" : "DVI",
+ it61620->en_audio ? "" : "not ");
+
+ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
+ it61620_mipi_set_d2v_video_timing(it61620, adj_mode);
+ it61620_hdmi_config_output(it61620);
+}
+
+static void it61620_bridge_atomic_disable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ if (!it61620->powered)
+ return;
+
+ it61620_hdmi_enable_avmute(it61620, true);
+ /* wait at least one frame for AVMute to take effect*/
+ msleep(45);
+ it61620_stop_hdcp_work(it61620);
+ if (it61620->hdcp_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+ drm_hdcp_update_content_protection(it61620->connector,
+ DRM_MODE_CONTENT_PROTECTION_DESIRED);
+ it61620->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ }
+ it61620_hdmi_disable_afe(it61620);
+ it61620_hdmi_powerdown(it61620);
+ it61620->video_state = it61620_VIDEO_OFF;
+}
+
+static void it61620_bridge_atomic_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+ struct device *dev = it61620->dev;
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+}
+
+static const struct drm_edid *it61620_bridge_edid_read(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+ struct device *dev = it61620->dev;
+ const struct drm_edid *edid;
+
+ edid = drm_edid_read_custom(connector, it61620_get_edid_block, it61620);
+
+ if (!edid)
+ dev_dbg(dev, "failed to get edid!");
+
+ return edid;
+}
+
+static int it61620_bridge_hdmi_clear_avi_infoframe(struct drm_bridge *bridge)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ return regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1,
+ (B_EN_AVI | B_AVI_RP), 0x00);
+}
+
+static int it61620_bridge_hdmi_clear_spd_infoframe(struct drm_bridge *bridge)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ return regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT2,
+ (B_EN_NULL | B_EN_NULL_RP), 0x00);
+}
+
+static int it61620_bridge_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ return regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1,
+ (B_EN_VSIF | B_EN_VSIF_RP), 0x00);
+}
+
+static int it61620_bridge_hdmi_clear_audio_infoframe(struct drm_bridge *bridge)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ return regmap_update_bits(it61620->tx_regmap, TX_REG_EN_PKT1,
+ (B_EN_AUD | B_EN_AUD_RP), 0x00);
+}
+
+static int it61620_bridge_hdmi_write_avi_infoframe(struct drm_bridge *bridge,
+ const u8 *buffer, size_t len)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ it61620_bridge_hdmi_clear_hdmi_infoframe(bridge);
+ it61620_hdmi_avi_infoframe_set(it61620, buffer, len);
+
+ return 0;
+}
+
+static int it61620_bridge_hdmi_write_spd_infoframe(struct drm_bridge *bridge,
+ const u8 *buffer, size_t len)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ it61620_hdmi_spd_infoframe_set(it61620, buffer, len);
+
+ return 0;
+}
+
+static int it61620_bridge_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge,
+ const u8 *buffer, size_t len)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ it61620_hdmi_vendor_infoframe_set(it61620, buffer, len);
+
+ return 0;
+}
+
+static int it61620_bridge_hdmi_write_audio_infoframe(struct drm_bridge *bridge,
+ const u8 *buffer, size_t len)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ it61620_bridge_hdmi_clear_audio_infoframe(bridge);
+ it61620_hdmi_audio_infoframe_set(it61620, buffer, len);
+
+ return 0;
+}
+
+static int it61620_bridge_hdmi_audio_startup(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ it61620_enable_audio(it61620);
+ return 0;
+}
+
+static int it61620_bridge_hdmi_audio_prepare(struct drm_bridge *bridge,
+ struct drm_connector *connector,
+ struct hdmi_codec_daifmt *fmt,
+ struct hdmi_codec_params *hparms)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ it61620_audio_update_hw_params(it61620, fmt, hparms);
+
+ return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
+ &hparms->cea);
+}
+
+static void it61620_bridge_hdmi_audio_shutdown(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct it61620 *it61620 = bridge_to_it61620(bridge);
+
+ drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector);
+
+ it61620_disable_audio(it61620);
+}
+
+static const struct drm_bridge_funcs it61620_bridge_funcs = {
+ .attach = it61620_bridge_attach,
+ .hpd_notify = it61620_bridge_hpd_notify,
+
+ .atomic_pre_enable = it61620_bridge_atomic_pre_enable,
+ .atomic_enable = it61620_bridge_atomic_enable,
+ .atomic_disable = it61620_bridge_atomic_disable,
+ .atomic_post_disable = it61620_bridge_atomic_post_disable,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+
+ .edid_read = it61620_bridge_edid_read,
+ .hdmi_tmds_char_rate_valid = it61620_bridge_hdmi_tmds_char_rate_valid,
+
+ .hdmi_clear_audio_infoframe = it61620_bridge_hdmi_clear_audio_infoframe,
+ .hdmi_write_audio_infoframe = it61620_bridge_hdmi_write_audio_infoframe,
+ .hdmi_clear_avi_infoframe = it61620_bridge_hdmi_clear_avi_infoframe,
+ .hdmi_write_avi_infoframe = it61620_bridge_hdmi_write_avi_infoframe,
+ .hdmi_clear_spd_infoframe = it61620_bridge_hdmi_clear_spd_infoframe,
+ .hdmi_write_spd_infoframe = it61620_bridge_hdmi_write_spd_infoframe,
+ .hdmi_clear_hdmi_infoframe = it61620_bridge_hdmi_clear_hdmi_infoframe,
+ .hdmi_write_hdmi_infoframe = it61620_bridge_hdmi_write_hdmi_infoframe,
+
+ .hdmi_audio_startup = it61620_bridge_hdmi_audio_startup,
+ .hdmi_audio_prepare = it61620_bridge_hdmi_audio_prepare,
+ .hdmi_audio_shutdown = it61620_bridge_hdmi_audio_shutdown,
+};
+
+static int it61620_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
+ struct mipi_dsi_host *host;
+ struct it61620 *it61620;
+ int ret = 0;
+
+ it61620 = devm_drm_bridge_alloc(dev, struct it61620, bridge,
+ &it61620_bridge_funcs);
+ if (IS_ERR(it61620))
+ return PTR_ERR(it61620);
+
+ it61620->dev = dev;
+ it61620->chip_info = of_device_get_match_data(dev);
+
+ host = drm_of_get_dsi_bus(dev);
+ if (IS_ERR(host))
+ return dev_err_probe(dev, PTR_ERR(host),
+ "failed to find dsi host\n");
+
+ ret = it61620_i2c_and_regmap_init(client, it61620);
+ if (ret < 0)
+ return ret;
+
+ i2c_set_clientdata(client, it61620);
+
+ ret = it61620_init_power(it61620);
+ if (ret < 0)
+ return ret;
+
+ it61620_config_default(it61620);
+
+ ret = it61620_parse_dt(it61620);
+ if (ret < 0)
+ return ret;
+
+ if (!client->irq)
+ return dev_err_probe(dev, -ENODEV,
+ "Failed to get INTP IRQ\n");
+
+ ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ it61620_int_threaded_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT |
+ IRQF_NO_AUTOEN,
+ "it61620-intp", it61620);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "failed to request INTP threaded IRQ\n");
+
+ INIT_DELAYED_WORK(&it61620->hdcp_work, it61620_hdcp_work);
+ init_waitqueue_head(&it61620->wq);
+
+ mutex_init(&it61620->ddc_lock);
+
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, 1000);
+ pm_runtime_use_autosuspend(dev);
+
+ it61620->bridge.of_node = np;
+ /*
+ * Although IT61620 has an HPD pin, hotplug detection is handled by the
+ * system connector. The bridge only receives HPD status notifications,
+ * and the HPD pin is used solely for short pulses during HDCP
+ * authentication.
+ *
+ * Therefore, this bridge does not implement OP_HPD or OP_DETECT, as it
+ * does not originate or determine hotplug or connection status.
+ */
+ it61620->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HDMI |
+ DRM_BRIDGE_OP_HDMI_AUDIO;
+ it61620->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+ it61620->bridge.support_hdcp = true;
+ it61620->bridge.vendor = "ITE";
+ it61620->bridge.product = "IT61620";
+ it61620->bridge.hdmi_audio_dev = dev;
+ it61620->bridge.hdmi_audio_max_i2s_playback_channels = 8;
+ it61620->bridge.hdmi_audio_spdif_playback = false;
+ it61620->bridge.hdmi_audio_dai_port = 2;
+
+ ret = devm_drm_bridge_add(dev, &it61620->bridge);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "failed to add drm bridge\n");
+
+ ret = it61620_attach_dsi(it61620, host);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "failed to attach to DSI host\n");
+
+ return 0;
+}
+
+static void it61620_remove(struct i2c_client *client)
+{
+ struct it61620 *it61620 = i2c_get_clientdata(client);
+ struct device *dev = it61620->dev;
+
+ disable_irq(client->irq);
+ pm_runtime_disable(dev);
+ it61620_detach_dsi(it61620);
+
+ mutex_destroy(&it61620->ddc_lock);
+}
+
+static const struct it6162_chip_info it61620_chip_info = {
+ .vid = 0x4954,
+ .pid = 0x6152,
+};
+
+static const struct of_device_id it61620_dt_ids[] = {
+ { .compatible = "ite,it61620", .data = &it61620_chip_info},
+ { }
+};
+MODULE_DEVICE_TABLE(of, it61620_dt_ids);
+
+static const struct i2c_device_id it61620_i2c_ids[] = {
+ { "it61620", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, it61620_i2c_ids);
+
+static struct i2c_driver it61620_driver = {
+ .driver = {
+ .name = "it61620",
+ .of_match_table = it61620_dt_ids,
+ .pm = &it61620_bridge_pm_ops,
+ },
+ .probe = it61620_probe,
+ .remove = it61620_remove,
+ .id_table = it61620_i2c_ids,
+};
+
+module_i2c_driver(it61620_driver);
+
+MODULE_AUTHOR("Pet Weng <pet.weng@ite.com.tw>");
+MODULE_AUTHOR("Hermes Wu <Hermes.Wu@ite.com.tw>");
+MODULE_DESCRIPTION("it61620 MIPI to HDMI driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v9 0/2] Add ITE IT61620 MIPI DSI to HDMI bridge driver
From: Pet Weng @ 2026-03-27 8:02 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: dri-devel, devicetree, linux-kernel, Hermes Wu, Kenneth Hung,
Pet Weng, Jau-chih Tseng, Pin-yen Lin, Krzysztof Kozlowski,
Dmitry Baryshkov
This patch series adds support for the ITE IT61620 MIPI DSI to HDMI
bridge chip.
The IT61620 is an I2C-controlled bridge that receives MIPI DSI input
and outputs HDMI signals. A single-port MIPI DSI input is converted to
an HDMI 1.4 output. This series introduces:
- A device tree binding YAML file describing the hardware
- A new DRM bridge driver implementing the basic functionality
Signed-off-by: Pet Weng <pet.weng@ite.com.tw>
---
Changes in v9:
- Fix commit message wrapping to follow kernel style
- Run checkpatch.pl and address reported issues
- Restore Reviewed-by from Krzysztof as the change is non-functional
- Link to v8: https://lore.kernel.org/r/20260320-it61620-0714-v8-0-0e70271cf5a9@ite.com.tw
Changes in v8:
- dt-binding:
1. Clarify the hardware differences between IT6162 and IT61620 in the
description (IT61620 is single-port and lacks an internal MCU). [Krzysztof]
2. Dropped Reviewed-by from Krzysztof due to description changes.
- Call drm_atomic_helper_connector_hdmi_clear_audio_infoframe() in audio
shutdown path [Dmitry]
- Link to v7: https://lore.kernel.org/r/20260313-it61620-0714-v7-0-36a16dc036d6@ite.com.tw
Changes in v7:
- The dt-bindings were previously reviewed by Krzysztof Kozlowski.
- drm/bridge: [Dmitry]
1. drop redundant register access wrappers and use regmap APIs directly
2. use drm_dbg_kms() instead of drm_dbg() when printing display timing information
3. use drm_display_mode directly for video timing
4. add helper for writing 16-bit timing registers
5. simplify HDMI interrupt handling
6. add mono audio support
7. program audio parameters directly
8. inline audio infoframe disable logic
- MAINTAINERS: squash to driver patch [Dmitry]
- Link to v6: https://lore.kernel.org/r/20260130-it61620-0714-v6-0-70afa65923b5@ite.com.tw
Changes in v6:
- In patch 1 [Luca]
1. Fix a typo in the commit message.
2. Remove redundant assignment of bridge.funcs, which is already set by
devm_drm_bridge_alloc().
- Link to v5: https://lore.kernel.org/r/20251222-it61620-0714-v5-0-afb6479ad3ca@ite.com.tw
Changes in v5:
- Fix dt_binding_check errors by adding missing unevaluatedProperties constraints
for port and endpoint nodes in the device tree binding. [Rob]
- Link to v4: https://lore.kernel.org/r/20251216-it61620-0714-v4-0-9d2fea7847ae@ite.com.tw
Changes in v4:
- In patch 1 [Krzysztof]
1. Remove redundant "description" fields from interrupts and regulators
2. Drop pinctrl-names and pinctrl-0; driver does not require them
3. Remove port/endpoint properties already covered by video interfaces schema
4. Fix example indentation to 4 spaces for readability
- In patch 2 [Jani]
1. Use connector->display_info from DRM helper instead of parsing EDID manually
- In patch 2 [Dmitry]
1. Remove redundant powered check in reg access
2. Use TMDS character rate instead of pixel clock for N/CTS
3. Use consistent lowercase naming for tmds.
4. Use test_bit() instead of custom bit-test helper
5. Use tmds_char_rate_valid instead of custom mode_valid
6. Use custom EDID read instead of DDC bus for segment handling
7. Drop redundant atomic feature check
8. Pass flags directly to drm_bridge_attach()
9. Check DRM_BRIDGE_ATTACH_NO_CONNECTOR flag before drm_bridge_attach()
10. Short-circuit HPD update if connector status unchanged
11. Remove unnecessary NULL check for connector state
12. Rename cached_edid to edid since it's no longer cached
13. Remove redundant sample rate checks; rely on hdmi-codec validation
14. Remove unsupported 18-bit audio sample size; rely on hdmi-codec
15. Remove unnecessary fmt switch; rely on hdmi-codec defaults
16. Check and propagate errors from it61620_audio_update_hw_params instead of
ignoring them
- In patch 3 [Krzysztof]
1. Remove unnecessary T: field pointing to git; subsystem already defines it
- Link to v3: https://lore.kernel.org/r/20251009-it61620-0714-v3-0-5d682d028441@ite.com.tw
Changes in v3:
- Wrapped description lines to comply with 80-character line length limit
in patch 1. [Rob]
- Renamed node from "it61620@58" to "bridge@58" in patch 1. [Rob]
- Add port@2 for I2S audio input in patch 1. [Dmitry]
- Updated the Kconfig dependency from CRYPTO and CRYPTO_HASH to
CRYPTO_LIB_SHA1 in patch 2. [Eric]
- In patch 2 [Dmitry]
1. Audio and InfoFrame
- Rename audfmt to i2s_input_format for clarity.
- Remove unused infoframe[HDMI_INFOFRAME_SIZE(AUDIO)].
2. Platform data and structure
- Drop platform data usage; migrate members into struct it61620
3. Code organization
- Reorder functions to avoid the need for forward declarations.
- Add static inline to small helper functions
(e.g. bridge_to_it61620()).
4. HDCP handling
- Make HDCP enable/disable conditional on conn_state->content_protection.
- Report authentication result using drm_hdcp_update_content_protection().
5. Error handling
- Replace manual error path with dev_err_probe().
6. Power management
- Inline suspend/resume callbacks.
- Use DEFINE_RUNTIME_DEV_PM_OPS() instead of explicit struct definition.
7. Bridge callbacks
- Drop empty bridge_detach().
- Inline it61620_bridge_mode_valid().
8. EDID handling
- Remove unnecessary cached EDID duplication.
9. Mode set and pixel clock
- Move mode handling to atomic_enable().
- Keep only pixelclock for future N/CTS audio calculations.
10. Logging
- Replace noisy drm_err() calls with drm_dbg().
11. InfoFrame support
- Add support for SPD and Vendor InfoFrames.
- Link to v2: https://lore.kernel.org/r/20250828-it61620-0714-v2-0-586f5934d5f8@ite.com.tw
Changes in v2:
- Call the sha1() library function instead of using the crypto_shash
"sha1" in patch 2.
- Rewrite it61620_hdmi_ddc_wait() with readx_poll_timeout() in patch 2. [Pin-yen]
- Rewrite it61620_hdmi_hdcp_wait_ksv_list() with readx_poll_timeout() in
patch 2.
- Replace interrupts-extended with interrupts in patch 1. [Rob]
- Replace dsi-lanes with the standard property data-lanes from the graph
binding. [Rob]
- Replace "#/$defs/port-base" with "#/properties/port" in patch 1. [Rob]
- Drop unused labels and "hdmi" for the node name. [Rob]
- Drop status in patch 1. [Rob]
- Link to v1: https://lore.kernel.org/r/20250714-it61620-0714-v1-0-3761164d0b98@ite.com.tw
---
Pet Weng (2):
dt-bindings: display: Add ITE IT61620 MIPI DSI to HDMI bridge
drm/bridge: Add ITE IT61620 MIPI DSI to HDMI bridge driver
.../bindings/display/bridge/ite,it61620.yaml | 152 ++
MAINTAINERS | 7 +
drivers/gpu/drm/bridge/Kconfig | 18 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/ite-it61620.c | 2592 ++++++++++++++++++++
5 files changed, 2770 insertions(+)
---
base-commit: a42c0d615ad29e3e11b1c91f677bcabcb5dc8e13
change-id: 20250714-it61620-0714-ab4ab4ceff29
Best regards,
--
Pet Weng <pet.weng@ite.com.tw>
^ permalink raw reply
* Re: [PATCH 04/22] dt-bindings: dma: renesas,rz-dmac: Document optional DMA ACK cell
From: Geert Uytterhoeven @ 2026-03-27 8:00 UTC (permalink / raw)
To: John Madieu
Cc: Kuninori Morimoto, Vinod Koul, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
Conor Dooley, Frank Li, Liam Girdwood, magnus.damm,
Thomas Gleixner, Jaroslav Kysela, Takashi Iwai, Philipp Zabel,
Claudiu.Beznea, Biju Das, Fabrizio Castro, Prabhakar Mahadev Lad,
John Madieu, linux-renesas-soc@vger.kernel.org,
linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
linux-sound@vger.kernel.org
In-Reply-To: <TY6PR01MB1737720136E84FAF590F637C4FF56A@TY6PR01MB17377.jpnprd01.prod.outlook.com>
Hi John,
On Thu, 26 Mar 2026 at 23:42, John Madieu <john.madieu.xa@bp.renesas.com> wrote:
> > From: Geert Uytterhoeven <geert@linux-m68k.org>
> > On Thu, 19 Mar 2026 at 16:55, John Madieu <john.madieu.xa@bp.renesas.com>
> > wrote:
> > > Some peripherals on RZ/V2H, RZ/V2N, and RZ/G3E SoCs require explicit
> > > ACK signal routing through the ICU. Document the optional second cell
> > > in the DMA specifier for specifying the ACK signal number.
> > >
> > > The first cell remains unchanged and specifies the encoded MID/RID and
> > > channel configuration. The optional second cell specifies the DMA ACK
> > > signal number for peripherals requiring level-based handshaking.
> > >
> > > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> >
> > Thanks for your patch!
> >
> > Just a quick head-up, as I haven't read the actual secion in the
> > documentation yet.
> >
> > > --- a/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> > > +++ b/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> > > @@ -63,17 +63,27 @@ properties:
> > > - const: register
> > >
> > > '#dma-cells':
> > > - const: 1
> > > - description:
> > > + description: |
> > > The cell specifies the encoded MID/RID or the REQ No values of
> > > the DMAC port connected to the DMA client and the slave channel
> > > configuration parameters.
> > > + Use 1 cell for basic DMA configuration.
> > > + Use 2 cells when DMA ACK signal routing through ICU is required
> > > + (RZ/V2H, RZ/V2N, RZ/G3E audio peripherals such as SSIU, SPDIF,
> > SRC, DVC).
> > > +
> > > + First cell:
> > > bits[0:9] - Specifies the MID/RID or the REQ No value
> > > bit[10] - Specifies DMA request high enable (HIEN)
> > > bit[11] - Specifies DMA request detection type (LVL)
> > > bits[12:14] - Specifies DMAACK output mode (AM)
> > > bit[15] - Specifies Transfer Mode (TM)
> > >
> > > + Second cell (optional, when #dma-cells = <2>):
> > > + bits[6:0] - DMA acknowledge signal number (from ICU ACK table),
> > > + where 0 is a valid signal number.
> > > + Required for peripherals using level-based DMA
> > > + handshaking (SSIU, SPDIF, RSPI, SCU, ADC, PDM).
> >
> > How do you expect this to work? #dma-cells applies to all DMA consumers of
> > this provider, and these SoCs already have DMA users relying on #dma-cells
> > being one.
>
> Indeed.
>
> > In addition, you cannot have optional cells: if #dma-cells is two, then
> > all consumers must supply two cells (of course we could switch all of them
> > to two cells at once). However, as zero is a valid signal number, we
> > cannot use that as a dummy when no DMA acknowledge signal number is needed
> > (we could use e.g. 0xffffffff instead).
> >
> > Is there any other way to provide this information?
> > E.g. could we have a table in the driver that contains this info for the
> > (presumably few) MID/RID values that need it?
>
> There are actually 89 entries, and I could identify 3 peripheral
> group with linear ACK assignments. Thus instead of static array
> we would get a simple function handling 3 req_no ranges.
>
> Something like:
>
> /*
> * Map MID/RID request number (bits[0:9] of DMA specifier) to the ICU
> * DMA ACK signal number, per RZ/G3E hardware manual Table 4.6-28.
> *
> * Three peripheral groups with linear ACK assignment:
> *
> * PFC external DMA pins (DREQ0..DREQ4):
> * req_no 0x000-0x004 -> ACK No. 84-88 (ack = req_no + 84)
> *
> * SSIU BUSIFs (ssip00..ssip93):
> * req_no 0x161-0x198 -> ACK No. 28-83 (ack = req_no - 0x145)
> *
> * SPDIF (CH0..CH2) + SCU SRC (sr0..sr9) + DVC (cmd0..cmd1):
> * req_no 0x199-0x1b4 -> ACK No. 0-27 (ack = req_no - 0x199)
> */
> static int rz_dmac_get_ack_no(const struct rz_dmac_info *info, u16 req_no)
> {
> if (!info->icu_register_dma_ack)
> return -EINVAL;
>
> /* PFC external DMA pins: ACK No. 84-88 */
> if (req_no <= 0x004)
> return req_no + 84;
>
> /* SSIU BUSIFs: ACK No. 28-83 */
> if (req_no >= 0x161 && req_no <= 0x198)
> return req_no - 0x145;
>
> /* SPDIF + SCU SRC + DVC: ACK No. 0-27 */
> if (req_no >= 0x199 && req_no <= 0x1b4)
> return req_no - 0x199;
>
> return -EINVAL;
> }
Nice!
Note that you can use ranges in case statements:
git grep "case.*\.\.\."
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH v5 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Vladimir Zapolskiy @ 2026-03-27 7:54 UTC (permalink / raw)
To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul,
Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong
Cc: linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <fedd369d-a0fc-4dbd-9862-3b6e3a403764@linaro.org>
On 3/27/26 03:03, Bryan O'Donoghue wrote:
> On 26/03/2026 14:49, Vladimir Zapolskiy wrote:
>> Here the description of hardware is done, and my point is that the new
>> PHY_QCOM_CSI2_MODE_SPLIT_DPHY phy type is simply not needed, since it's
>> possible to give a proper description of hardware without this invention.
>
> Perhaps I'm not understanding you.
You are welcome to ask questions, it may save time.
> If we use PHY_TYPE_DPHY
>
> include/dt-bindings/phy/phy.h:#define PHY_TYPE_DPHY 10
>
> We _must_ then add SPLIT_MODE to phy.h if/when we implement that
> support.
I don't think it is the must.
> Which means successfully arguing the toss of weather SPLIT_MODE
> is a Qualcommism - a vendor specific mode or not.
>
> <&phy PHY_TYPE_DPHY> committed to an upstream dts will then need to be
> supported perpetually.
>
First of all, nobody says/defines that the phy type is mandatory to be
present in the cell at all, for instance it could be provided over bus-type
property of media endpoints, and a connected sensor unavoidably postulates
the value of this property.
> So for example qrb5615 - kona/rb5 support split mode.
>
> Pretend go with <&phy PHY_TYPE_DPHY>; and retrofit individual PHY
> support to this platform.
>
> Grand so far.
>
> The pretend we want to switch from one sensor to a split-mode sensor on
> the existing mezzanine.
You may think how it should be done, it's been asked for a while to provide
a complete valid example, it may help you to get a better understanding of
the whole picture.
>
> Then we need a representation of split mode in phy.h to represent that
> in DT.
Some kind of split mode representation should be in DT, it does not
mean that it sticks to phy.h or whatever else. Lanes (and bus-type) are
described under endpoint device tree nodes, this is totally sufficient
to separate what you call "a split mode". So, it excludes phy.h.
>
> <&phy PHY_TYPE_DPHY_SPLIT_MODE>;
>
> Except split-mode is not an appropriate mode to define in phy.h since it
> is vendor specific - even if a few vendors support it, its not a generic
> PHY mode.
>
> Hence we would have an enormously difficult time justifying adding that
> mode to phy.h and rightly so.
We still discuss a hardware description, it should not be problematic to
provide descriptions of regular DPHY and what you call 'split mode' DPHY
without any new extentions of the existing dt bindings.
>>> https://review.lineageos.org/c/LineageOS/
>>> android_kernel_motorola_sm6375/+/423960/1/drivers/cam_sensor_module/
>>> cam_csiphy/cam_csiphy_core.c#b285
>>>
>>> There is disjunction all over this file depending on the mode.
>>>
>>> https://review.lineageos.org/c/LineageOS/
>>> android_kernel_motorola_sm6375/+/423960/1/drivers/cam_sensor_module/
>>> cam_csiphy/cam_csiphy_core.c#b767
>
>
> OTOH
>
> - SPLIT_MODE will certainly require _both_ separate init sequences
> and specific logical disjunction for additional configuration steps
> lane-assignment and masking, etc.
>
> - That phy.h isn't the right location for SPLIT_MODE as its vendor
> specific. Just look at the modes we have for the USB PHYs
> same logic => include/dt-bindings/phy/phy-qcom-qmp.h same
> raison d'être
>
> - And that specifying PHY_TYPE_DPHY now binds us into an ABI that we
> cannot subsequently change - it will not be possible to introduce
> include/dt-bindings/phy/phy-qcom-mipi-csi2.h later on with our mode
>
> So therefore include/dt-bindings/phy/phy-qcom-mipi-csi2.h + PHY modes is
> the logical outcome.
>
Unnecessary extention of the dt bindings ABI is not needed to complete
the task.
--
Best wishes,
Vladimir
^ permalink raw reply
* Re: [PATCH 4/7] dt-bindings: leds: irled: ir-spi-led: Add new duty-cycle value
From: Krzysztof Kozlowski @ 2026-03-27 7:51 UTC (permalink / raw)
To: Biswapriyo Nath
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
Michael Turquette, Stephen Boyd, Martin Botka, linux-arm-msm,
devicetree, linux-kernel, linux-leds, linux-clk,
~postmarketos/upstreaming, phone-devel
In-Reply-To: <20260325-ginkgo-add-usb-ir-vib-v1-4-446c6e865ad6@gmail.com>
On Wed, Mar 25, 2026 at 06:07:27PM +0000, Biswapriyo Nath wrote:
> 30 duty cycle for IR transmitter is used in Xiaomi Redmi Note 8 (ginkgo).
>
> Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
> ---
> Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml b/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
> index 72cadebf6e3..0297bfbb275 100644
> --- a/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
> +++ b/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
> @@ -25,7 +25,7 @@ properties:
>
> duty-cycle:
> $ref: /schemas/types.yaml#/definitions/uint8
> - enum: [50, 60, 70, 75, 80, 90]
> + enum: [30, 50, 60, 70, 75, 80, 90]
Hm, why is this enum, instead of 1-99, in the first place?
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH] dt-bindings: mfd: twl: Reference converted YAML schemas for subnodes
From: Krzysztof Kozlowski @ 2026-03-27 7:37 UTC (permalink / raw)
To: Jihed Chaibi
Cc: lee, andreas, robh, krzk+dt, conor+dt, devicetree, linux-kernel
In-Reply-To: <20260325095016.48752-1-jihed.chaibi.dev@gmail.com>
On Wed, Mar 25, 2026 at 10:50:16AM +0100, Jihed Chaibi wrote:
> Now that all TWL subnode bindings (audio, keypad, twl4030-usb, gpio,
> usb-comparator) have been converted to YAML and merged into mainline,
subject and here: drop YAML. There are no YAML schemas.
> update the parent ti,twl.yaml to properly reference them via $ref.
> Previously these subnodes used inline compatible definitions with
> additionalProperties: true, which meant properties defined in the
> subnode schemas were not being validated. Replace them with $ref to the
No, they were validated by their child device schemas. Everything was
correct and expected.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2] dt-bindings: sound: Convert pcm3060 to DT schema
From: Krzysztof Kozlowski @ 2026-03-27 7:32 UTC (permalink / raw)
To: Padmashree S S
Cc: k.marinushkin, lgirdwood, broonie, robh, conor+dt, krzk+dt,
devicetree, linux-sound, linux-kernel
In-Reply-To: <20260326183747.528754-1-padmashreess2006@gmail.com>
On Fri, Mar 27, 2026 at 12:07:47AM +0530, Padmashree S S wrote:
> Note:
> * This patch is part of the GSoC2026 application process for device tree bindings conversions
> * https://github.com/LinuxFoundationGSoC/ProjectIdeas/wiki/GSoC-2026-Device-Tree-Bindings
And this should go to commit log forever? Why?
No, this wasn't ever reviewed as requested by the GSoC process.
>
> Signed-off-by: Padmashree S S <padmashreess2006@gmail.com>
> ---
> .../devicetree/bindings/sound/pcm3060.txt | 23 ----------
> .../devicetree/bindings/sound/pcm3060.yaml | 45 +++++++++++++++++++
> 2 files changed, 45 insertions(+), 23 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/sound/pcm3060.txt
> create mode 100644 Documentation/devicetree/bindings/sound/pcm3060.yaml
>
> diff --git a/Documentation/devicetree/bindings/sound/pcm3060.txt b/Documentation/devicetree/bindings/sound/pcm3060.txt
> deleted file mode 100644
> index 97de66932d44..000000000000
> --- a/Documentation/devicetree/bindings/sound/pcm3060.txt
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -PCM3060 audio CODEC
> -
> -This driver supports both I2C and SPI.
> -
> -Required properties:
> -
> -- compatible: "ti,pcm3060"
> -
> -- reg : the I2C address of the device for I2C, the chip select
> - number for SPI.
> -
> -Optional properties:
> -
> -- ti,out-single-ended: "true" if output is single-ended;
> - "false" or not specified if output is differential.
> -
> -Examples:
> -
> - pcm3060: pcm3060@46 {
> - compatible = "ti,pcm3060";
> - reg = <0x46>;
> - ti,out-single-ended = "true";
> - };
> diff --git a/Documentation/devicetree/bindings/sound/pcm3060.yaml b/Documentation/devicetree/bindings/sound/pcm3060.yaml
> new file mode 100644
> index 000000000000..ceb6f044b196
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/pcm3060.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/pcm3060.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: PCM3060 audio CODEC
> +
> +maintainers:
> + - Kirill Marinushkin <k.marinushkin@gmail.com>
> +
> +properties:
> + compatible:
> + const: ti,pcm3060
> +
> + reg:
> + maxItems: 1
> + description: |
> + The I2C address of the device
> + or SPI chip select number.
Nah, wasn't reviewed.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2] dt-bindings: sound: Convert pcm3060 to DT schema
From: Kirill Marinushkin @ 2026-03-27 7:30 UTC (permalink / raw)
To: Padmashree S S, lgirdwood, broonie
Cc: robh, conor+dt, krzk+dt, devicetree, linux-sound, linux-kernel
In-Reply-To: <20260326183747.528754-1-padmashreess2006@gmail.com>
Good day Padmashree,
i received your patch, and support your interest to keep the driver
documentation
up-to-date! I would kindly ask you to give me some time to get
up to speed with the context of the documentation change.
You may expect to hear back from me next week.
At the same time, i don't want to block any progress.
If you receive enough approvals from the other members of the community,
please feel free to proceed without my feedback.
Best regards,
Kirill Marinushkin
On 3/26/26 7:37 PM, Padmashree S S wrote:
> Note:
> * This patch is part of the GSoC2026 application process for device tree bindings conversions
> * https://github.com/LinuxFoundationGSoC/ProjectIdeas/wiki/GSoC-2026-Device-Tree-Bindings
>
> Signed-off-by: Padmashree S S <padmashreess2006@gmail.com>
> ---
> .../devicetree/bindings/sound/pcm3060.txt | 23 ----------
> .../devicetree/bindings/sound/pcm3060.yaml | 45 +++++++++++++++++++
> 2 files changed, 45 insertions(+), 23 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/sound/pcm3060.txt
> create mode 100644 Documentation/devicetree/bindings/sound/pcm3060.yaml
>
> diff --git a/Documentation/devicetree/bindings/sound/pcm3060.txt b/Documentation/devicetree/bindings/sound/pcm3060.txt
> deleted file mode 100644
> index 97de66932d44..000000000000
> --- a/Documentation/devicetree/bindings/sound/pcm3060.txt
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -PCM3060 audio CODEC
> -
> -This driver supports both I2C and SPI.
> -
> -Required properties:
> -
> -- compatible: "ti,pcm3060"
> -
> -- reg : the I2C address of the device for I2C, the chip select
> - number for SPI.
> -
> -Optional properties:
> -
> -- ti,out-single-ended: "true" if output is single-ended;
> - "false" or not specified if output is differential.
> -
> -Examples:
> -
> - pcm3060: pcm3060@46 {
> - compatible = "ti,pcm3060";
> - reg = <0x46>;
> - ti,out-single-ended = "true";
> - };
> diff --git a/Documentation/devicetree/bindings/sound/pcm3060.yaml b/Documentation/devicetree/bindings/sound/pcm3060.yaml
> new file mode 100644
> index 000000000000..ceb6f044b196
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/pcm3060.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/pcm3060.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: PCM3060 audio CODEC
> +
> +maintainers:
> + - Kirill Marinushkin <k.marinushkin@gmail.com>
> +
> +properties:
> + compatible:
> + const: ti,pcm3060
> +
> + reg:
> + maxItems: 1
> + description: |
> + The I2C address of the device
> + or SPI chip select number.
> +
> + ti,out-single-ended:
> + type: boolean
> + description: |
> + If present, the output is single-ended.
> + If absent, the output is differential.
> +
> +required:
> + - compatible
> + - reg
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pcm3060: audio-codec@46 {
> + compatible = "ti,pcm3060";
> + reg = <0x46>;
> + ti,out-single-ended;
> + };
> + };
^ permalink raw reply
* Re: [PATCH v2 3/7] dt-bindings: dmaengine: Add SpacemiT K3 DMA request definitions
From: Krzysztof Kozlowski @ 2026-03-27 7:30 UTC (permalink / raw)
To: Troy Mitchell
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk,
liyeshan
In-Reply-To: <20260326-k3-pdma-v2-3-ca94ca7bb595@linux.spacemit.com>
On Thu, Mar 26, 2026 at 04:17:18PM +0800, Troy Mitchell wrote:
> From: liyeshan <yeshan.li@spacemit.com>
>
> Add device tree binding header for SpacemiT k3 DMA request numbers. This
Why?
> defines the DMA request mapping for non-secure peripherals including UART,
> I2C, SSP/SPI, CAN, and QSPI.
>
> Signed-off-by: liyeshan <yeshan.li@spacemit.com>
Name looks close to login name?
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
> include/dt-bindings/dma/k3-pdma.h | 83 +++++++++++++++++++++++++++++++++++++++
I am already confused what is happening in this patchset - so which
device are you adding? K1 or K3?
> 1 file changed, 83 insertions(+)
>
> diff --git a/include/dt-bindings/dma/k3-pdma.h b/include/dt-bindings/dma/k3-pdma.h
> new file mode 100644
> index 000000000000..05541a9a9973
> --- /dev/null
> +++ b/include/dt-bindings/dma/k3-pdma.h
> @@ -0,0 +1,83 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * This header provides DMA request number for non-secure peripherals of
> + * SpacemiT K3 PDMA.
> + *
> + * Copyright (c) 2025 SpacemiT
> + * Copyright (c) 2025 Guodong Xu <guodong@riscstar.com>
> + */
> +
> +#ifndef __DT_BINDINGS_DMA_K3_PDMA_H__
> +#define __DT_BINDINGS_DMA_K3_PDMA_H__
> +
> +/* UART DMA request numbers */
> +#define K3_PDMA_UART0_TX 3
This starts from 0 or 1.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 1/7] dt-bindings: dmaengine: Add SpacemiT K1 DMA request definitions
From: Krzysztof Kozlowski @ 2026-03-27 7:28 UTC (permalink / raw)
To: Troy Mitchell
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-k3-pdma-v2-1-ca94ca7bb595@linux.spacemit.com>
On Thu, Mar 26, 2026 at 04:17:16PM +0800, Troy Mitchell wrote:
> From: Guodong Xu <guodong@riscstar.com>
>
> Add the DMA request numbers for non-secure peripherals of the K1 SoC
> from SpacemiT.
>
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
> include/dt-bindings/dma/k1-pdma.h | 56 +++++++++++++++++++++++++++++++++++++++
Also, this is not a separate commit.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 1/7] dt-bindings: dmaengine: Add SpacemiT K1 DMA request definitions
From: Krzysztof Kozlowski @ 2026-03-27 7:27 UTC (permalink / raw)
To: Troy Mitchell
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-k3-pdma-v2-1-ca94ca7bb595@linux.spacemit.com>
On Thu, Mar 26, 2026 at 04:17:16PM +0800, Troy Mitchell wrote:
> From: Guodong Xu <guodong@riscstar.com>
>
> Add the DMA request numbers for non-secure peripherals of the K1 SoC
> from SpacemiT.
>
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
No changelog - neither here, nor in commit msg.
> include/dt-bindings/dma/k1-pdma.h | 56 +++++++++++++++++++++++++++++++++++++++
So previous review applies, no? Was there such?
> 1 file changed, 56 insertions(+)
>
> diff --git a/include/dt-bindings/dma/k1-pdma.h b/include/dt-bindings/dma/k1-pdma.h
> new file mode 100644
> index 000000000000..061748c177dc
> --- /dev/null
> +++ b/include/dt-bindings/dma/k1-pdma.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * This header provides DMA request number for non-secure peripherals of
> + * SpacemiT K1 PDMA.
> + *
> + * Copyright (c) 2025 Guodong Xu <guodong@riscstar.com>
> + */
> +
> +#ifndef __DT_BINDINGS_DMA_K1_PDMA_H__
> +#define __DT_BINDINGS_DMA_K1_PDMA_H__
> +
> +#define K1_PDMA_UART0_TX 3
abstract IDs start from 0 or 1.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: arm: tegra: Add Tegra238 CBB compatible strings
From: Krzysztof Kozlowski @ 2026-03-27 7:26 UTC (permalink / raw)
To: Sumit Gupta
Cc: treding, jonathanh, robh, krzk+dt, conor+dt, devicetree,
linux-tegra, linux-kernel, bbasu
In-Reply-To: <20260325125726.2694144-2-sumitg@nvidia.com>
On Wed, Mar 25, 2026 at 06:27:25PM +0530, Sumit Gupta wrote:
> Add compatible strings for CBB v2.0 based fabrics in Tegra238:
> - nvidia,tegra238-ape-fabric
> - nvidia,tegra238-aon-fabric
> - nvidia,tegra238-bpmp-fabric
> - nvidia,tegra238-cbb-fabric
So you just pasted diff contents here. What's the point?
Comit msg is not a copy of the diff. We can read the diff.
Drop.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 1/3] dt-bindings: clock: amlogic: Fix redundant hyphen in "amlogic,t7-gp1--pll" string.
From: Krzysztof Kozlowski @ 2026-03-27 7:23 UTC (permalink / raw)
To: Jian Hu
Cc: Jerome Brunet, Neil Armstrong, Kevin Hilman, Martin Blumenstingl,
Stephen Boyd, Michael Turquette, robh+dt, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Ronald Claveau, devicetree,
linux-clk, linux-amlogic, linux-kernel, linux-arm-kernel,
Ferass El Hafidi
In-Reply-To: <20260326092645.1053261-2-jian.hu@amlogic.com>
On Thu, Mar 26, 2026 at 05:26:43PM +0800, Jian Hu wrote:
> Fix redundant hyphen in "amlogic,t7-gp1--pll" string.
>
> Fixes: 5437753728ac ("dt-bindings: clock: add Amlogic T7 PLL clock controller")
Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v11] arm64: dts: imx8ulp: Add CSI and ISI Nodes
From: guoniu.zhou @ 2026-03-27 7:11 UTC (permalink / raw)
To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Philipp Zabel, Frank Li
Cc: linux-media, devicetree, imx, linux-arm-kernel, linux-kernel,
G . N . Zhou
From: Guoniu Zhou <guoniu.zhou@nxp.com>
The CSI-2 in the i.MX8ULP is almost identical to the version present
in the i.MX8QXP/QM and is routed to the ISI. Add both the ISI and CSI
nodes and mark them as disabled by default since capture is dependent
on an attached camera.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
---
This was previously sent as patch 5/5 in the v10 series based on media
tree [1]. Patches 1-4 have already been applied to linux-next tree, but
not yet to media tree . This v11 addresses the conflict with the removal
of include/dt-bindings/reset/imx8ulp-pcc-reset.h.
Changes in v11:
- Rebased on latest media/next
- Removed #include <dt-bindings/reset/imx8ulp-pcc-reset.h> which was
deleted by Rob's dt-bindings cleanup series [2]
- Replaced reset macros with numeric values and added comments to
document the reset indices
- Link to v10: https://lore.kernel.org/r/20251205-csi2_imx8ulp-v10-5-190cdadb20a3@nxp.com
Changes in v6:
- Update compatible string in dts for csi node.
- Link to v5: https://lore.kernel.org/r/20250901-csi2_imx8ulp-v5-4-67964d1471f3@nxp.com
Changes in v4:
- Change csr clock name to pclk which is more readability.
- Link to v3: https://lore.kernel.org/all/20250825-csi2_imx8ulp-v3-4-35885aba62bc@nxp.com
Changes in v3:
- Change pclk clock name to csr to match IP port name.
- Link to v2: https://lore.kernel.org/all/20250822-csi2_imx8ulp-v2-4-26a444394965@nxp.com
Changes in v2:
- Move dts patch as the last one.
- Add "fsl,imx8qxp-mipi-csi2" to compatible string list of csi node.
- Link to v1: https://lore.kernel.org/all/20250812081923.1019345-3-guoniu.zhou@oss.nxp.com
[1] https://lore.kernel.org/all/20251205-csi2_imx8ulp-v10-0-190cdadb20a3@nxp.com/
[2] https://lore.kernel.org/all/20251212231203.727227-1-robh@kernel.org/
Signed-off-by: Guoniu Zhou <guoniu.zhou@oss.nxp.com>
---
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 66 ++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index 9b5d98766512..84f05c83c702 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -859,6 +859,72 @@ spdif: spdif@2dab0000 {
dma-names = "rx", "tx";
status = "disabled";
};
+
+ isi: isi@2dac0000 {
+ compatible = "fsl,imx8ulp-isi";
+ reg = <0x2dac0000 0x10000>;
+ interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc5 IMX8ULP_CLK_ISI>,
+ <&cgc2 IMX8ULP_CLK_LPAV_AXI_DIV>;
+ clock-names = "axi", "apb";
+ power-domains = <&scmi_devpd IMX8ULP_PD_ISI>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ isi_in: endpoint {
+ remote-endpoint = <&mipi_csi_out>;
+ };
+ };
+ };
+ };
+
+ mipi_csi: csi@2daf0000 {
+ compatible = "fsl,imx8ulp-mipi-csi2";
+ reg = <0x2daf0000 0x10000>,
+ <0x2dad0000 0x10000>;
+ clocks = <&pcc5 IMX8ULP_CLK_CSI>,
+ <&pcc5 IMX8ULP_CLK_CSI_CLK_ESC>,
+ <&pcc5 IMX8ULP_CLK_CSI_CLK_UI>,
+ <&pcc5 IMX8ULP_CLK_CSI_REGS>;
+ clock-names = "core", "esc", "ui", "pclk";
+ assigned-clocks = <&pcc5 IMX8ULP_CLK_CSI>,
+ <&pcc5 IMX8ULP_CLK_CSI_CLK_ESC>,
+ <&pcc5 IMX8ULP_CLK_CSI_CLK_UI>,
+ <&pcc5 IMX8ULP_CLK_CSI_REGS>;
+ assigned-clock-parents = <&cgc2 IMX8ULP_CLK_PLL4_PFD1_DIV1>,
+ <&cgc2 IMX8ULP_CLK_PLL4_PFD1_DIV2>,
+ <&cgc2 IMX8ULP_CLK_PLL4_PFD0_DIV1>;
+ assigned-clock-rates = <200000000>,
+ <80000000>,
+ <100000000>,
+ <79200000>;
+ power-domains = <&scmi_devpd IMX8ULP_PD_MIPI_CSI>;
+ resets = <&pcc5 5>, /* PCC5_CSI_REGS_SWRST */
+ <&pcc5 6>; /* PCC5_CSI_SWRST> */
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mipi_csi_out: endpoint {
+ remote-endpoint = <&isi_in>;
+ };
+ };
+ };
+ };
};
gpiod: gpio@2e200000 {
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] arm64: dts: qcom: lemans-evk: Enable mdss1 display Port
From: Gopi Botlagunta @ 2026-03-27 7:08 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, devicetree, linux-kernel,
venkata.valluru, jessica.zhang
In-Reply-To: <d54f4b17-a137-494b-b103-2734987c4f14@kernel.org>
On Thu, Feb 19, 2026 at 03:24:24PM +0100, Krzysztof Kozlowski wrote:
> On 19/02/2026 14:36, Gopi Botlagunta wrote:
> > This change enables DP controllers, DPTX0 and DPTX1 alongside
>
>
> Please do not use "This commit/patch/change", but imperative mood. See
> longer explanation here:
> https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94
>
I’ll update the commit text in the next revision.
> >
> > ---
> > base-commit: 1a0829927afbfe654c632eb2e779fa32df825b06
> > change-id: 20260219-enable-edp2-3-lemans-evk-mezzanine-1bef9932ee6d
> > prerequisite-message-id: 20260203193848.123307-2-umang.chheda@oss.qualcomm.com
> > prerequisite-patch-id: baf07fce333b86c35c3d4cefbba5800a519952a3
> > prerequisite-message-id: 20260217071420.2240380-1-mkuntuma@qti.qualcomm.com
> > prerequisite-patch-id: 74a76fd6a1129cdbbd32d91d2a119d693dba78a7
> > prerequisite-patch-id: f4a858f7e707c8e330daf2ea1f4da58b4da00f05
> >
>
> Why do you have so many dependencies? Why isn't this merged there?
>
The following changes will be included in the next revision of the
dependent patch series: https://lore.kernel.org/all/20260226111322.250176-1-quic_mkuntuma@quicinc.com/
> Was this patch tested (see internal testing guideline) prior to posting?
>
yes, changes were tested together with the dependent patches before posting
> Best regards,
> Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/7] dt-bindings: dmaengine: Add SpacemiT K3 DMA compatible string
From: Troy Mitchell @ 2026-03-27 7:04 UTC (permalink / raw)
To: Conor Dooley, Troy Mitchell
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-explode-surplus-24c0e0813099@spud>
Hi Conor,
On Fri Mar 27, 2026 at 2:34 AM CST, Conor Dooley wrote:
> On Thu, Mar 26, 2026 at 04:17:17PM +0800, Troy Mitchell wrote:
>> From: Guodong Xu <guodong@riscstar.com>
>>
>> Add k3 compatible string.
>
> That's obvious. What you need to explain is why it is not compatible with
> the existing k1.
>
Thanks for the review.
The SpacemiT K3 PDMA requires a new compatible string because it is not fully
backward compatible with the K1 implementation due to two main hardware differences:
- Variable extended DRCMR base: The DRCMR (DMA Request/Command Register) base
address for extended DMA request numbers (>= 64) is different in the K3 hardware
implementation.
- Memory addressing capabilities: Unlike the K1 SoC, where some DMA masters had
memory addressing limitations (restricted to the 0-4GB space) and required a
dedicated dma-bus, the K3 DMA masters have full memory addressing capabilities.
I will update the commit message in the v3 series.
-Troy
^ permalink raw reply
* [PATCH] ARM: dts: aspeed: anacapa: Enable MCTP and FRU for NIC
From: Andy Chung via B4 Relay @ 2026-03-27 6:59 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
Andy Chung, Andy Chung
From: Andy Chung <Andy.Chung@amd.com>
Add the mctp-controller property to enable frontend NIC management
via PLDM over MCTP.
Also add EEPROM device for NIC FRU.
Signed-off-by: Andy Chung <Andy.Chung@amd.com>
---
Add the mctp-controller property to enable frontend NIC management
via PLDM over MCTP.
Also add EEPROM device for NIC FRU.
---
.../dts/aspeed/aspeed-bmc-facebook-anacapa.dts | 67 +++++++++++++++++++++-
1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
index 221af858cb6b..138b081be049 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
@@ -584,38 +584,67 @@ eeprom@56 {
// R Bridge Board
&i2c10 {
status = "okay";
+ multi-master;
+ mctp@10 {
+ compatible = "mctp-i2c-controller";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ };
i2c-mux@71 {
compatible = "nxp,pca9548";
reg = <0x71>;
#address-cells = <1>;
#size-cells = <0>;
- i2c-mux-idle-disconnect;
i2c10mux0ch0: i2c@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
};
i2c10mux0ch1: i2c@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c10mux0ch2: i2c@2 {
reg = <2>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c10mux0ch3: i2c@3 {
reg = <3>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c10mux0ch4: i2c@4 {
reg = <4>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c10mux0ch5: i2c@5 {
reg = <5>;
@@ -661,38 +690,72 @@ i2c10mux0ch7: i2c@7 {
// L Bridge Board
&i2c11 {
status = "okay";
+ multi-master;
+ mctp@10 {
+ compatible = "mctp-i2c-controller";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ };
i2c-mux@71 {
compatible = "nxp,pca9548";
reg = <0x71>;
#address-cells = <1>;
#size-cells = <0>;
- i2c-mux-idle-disconnect;
i2c11mux0ch0: i2c@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // FE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c11mux0ch1: i2c@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c11mux0ch2: i2c@2 {
reg = <2>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c11mux0ch3: i2c@3 {
reg = <3>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c11mux0ch4: i2c@4 {
reg = <4>;
#address-cells = <1>;
#size-cells = <0>;
+ mctp-controller;
+ // BE NIC FRU
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
};
i2c11mux0ch5: i2c@5 {
reg = <5>;
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260327-dts_enable_nic_mctp-e35a5765b176
Best regards,
--
Andy Chung <Andy.Chung@amd.com>
^ permalink raw reply related
* Re: [PATCH v5] MAINTAINERS: Add Axiado reviewer and Maintainers
From: Krzysztof Kozlowski @ 2026-03-27 6:54 UTC (permalink / raw)
To: Karthikeyan Mitran, Arnd Bergmann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Prasad Bolisetty, Tzu-Hao Wei,
Axiado Reviewers
Cc: devicetree, linux-arm-kernel, linux-kernel, Alexandre Belloni,
Drew Fustini, Linus Walleij, Harshit Shah
In-Reply-To: <20260326-maintainers-addition-and-axiado-ax3000_dtsi-update-v5-1-648dfe9bff29@axiado.com>
On 26/03/2026 21:50, Karthikeyan Mitran wrote:
> From: Prasad Bolisetty <pbolisetty@axiado.com>
>
> Adding 3 new maintainers Prasad,Tzu-Hao, and Karthikeyan
> and adding a group reviewer entry for review coverage,
> Removed previous maintainer as the previous maintainer moved from project
...
> ---
> MAINTAINERS | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 55af015174a5..49f47e8c2ec3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2605,7 +2605,10 @@ F: arch/arm/mach-aspeed/
> N: aspeed
>
> ARM/AXIADO ARCHITECTURE
> -M: Harshit Shah <hshah@axiado.com>
> +M: Prasad Bolisetty <pbolisetty@axiado.com>
> +M: Tzu-Hao Wei <twei@axiado.com>
> +M: Karthikeyan Mitran <kmitran@axiado.com>
> +R: Axiado Reviewers <linux-maintainer@axiado.com>
How many entries do you need? You already have three, so who is in
Axiado reviewers? And what is "review coverage" you mentioned in the
commit msg.
I skimmed through https://lore.kernel.org/all/?q=f%3Aaxiado.com and I do
not see reviews from any of these addresses, so it all looks like you
add some corporate structure, because some managers want to see what is
posted.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH] arm64: dts: qcom: lemans-evk: Enable mdss1 display Port
From: Gopi Botlagunta @ 2026-03-27 6:51 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, devicetree, linux-kernel,
venkata.valluru, jessica.zhang
In-Reply-To: <98730ff5-05b7-4275-be1d-1f9506adeac7@oss.qualcomm.com>
On Thu, Feb 19, 2026 at 02:41:27PM +0100, Konrad Dybcio wrote:
> On 2/19/26 2:36 PM, Gopi Botlagunta wrote:
> > This change enables DP controllers, DPTX0 and DPTX1 alongside
> > their corresponding PHYs of mdss1 which corresponds to edp2
> > and edp3.
> >
> > Signed-off-by: Gopi Botlagunta <venkata.botlagunta@oss.qualcomm.com>
> > ---
>
> [...]
>
> > +&mdss1_dp0 {
> > + pinctrl-0 = <&dp2_hot_plug_det>;
> > + pinctrl-names = "default";
> > + status = "okay";
> > +};
> > +
> > +&mdss1_dp1 {
> > + pinctrl-0 = <&dp3_hot_plug_det>;
> > + pinctrl-names = "default";
> > + status = "okay";
>
> Nit: a \n before 'status' is customary and it's present in all other
> nodes in this file
>
> [...]
>
I’ll fix the formatting in the next revision.
> > ---
> > base-commit: 1a0829927afbfe654c632eb2e779fa32df825b06
> > change-id: 20260219-enable-edp2-3-lemans-evk-mezzanine-1bef9932ee6d
> > prerequisite-message-id: 20260203193848.123307-2-umang.chheda@oss.qualcomm.com
> > prerequisite-patch-id: baf07fce333b86c35c3d4cefbba5800a519952a3
> > prerequisite-message-id: 20260217071420.2240380-1-mkuntuma@qti.qualcomm.com
> > prerequisite-patch-id: 74a76fd6a1129cdbbd32d91d2a119d693dba78a7
> > prerequisite-patch-id: f4a858f7e707c8e330daf2ea1f4da58b4da00f05
>
> This is really long and scattered across multiple people, effectively
> making it a chaos for tracking. Could you please coordinate with Mani
> who submitted the changes for the SoC as well as the ride board to
> send these patches together?
>
> Konrad
Sure, I’ve coordinated with Mani. This will be addressed in the next
revision of the dependent patch series: https://lore.kernel.org/all/20260226111322.250176-1-quic_mkuntuma@quicinc.com/
^ permalink raw reply
* Re: [PATCH] arm64: dts: qcom: Move board nodes to common DTSI
From: Krzysztof Kozlowski @ 2026-03-27 6:45 UTC (permalink / raw)
To: Sibi Sankar, Gopikrishna Garmidi, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, devicetree, linux-kernel, rajendra.nayak
In-Reply-To: <328a120e-e9e0-4b3d-a2c0-04eb471c0937@oss.qualcomm.com>
On 26/03/2026 17:55, Sibi Sankar wrote:
>
> On 3/26/2026 7:55 PM, Krzysztof Kozlowski wrote:
>> On 26/03/2026 15:21, Gopikrishna Garmidi wrote:
>>> The display, peripherals (touchpad/touchscreen/keypad), usb and their
>>> dependent device nodes are common to both Glymur and Mahua CRDs,
>>> so move them from glymur-crd.dts to glymur-crd.dtsi to enable code
>>> reuse.
>>>
>> Same questions as for earlier tries (why this has to be repeated?), e.g.
>> x1-crd: Please describe here what is the actual common hardware. In
>> terms of physical hardware, not what you want to share.
>
>
> There seems to be some kind of confusion here. This patch doesn't
Indeed!
> introduce the common board file rather it just moves the nodes
> mentioned in the commit message to the common board file.
>
> https://lore.kernel.org/lkml/20260318124100.212992-3-gopikrishna.garmidi@oss.qualcomm.com/
The question stays. The common DTSI represented actual shared
motherboard design between these, so I would like to still see the
answers here. I just don't trust such commits because they mimic
downstream approach (and they were actually copying downstream in the past).
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v1 1/2] dt-bindings: i2c: ls2x-i2c: Add clock- related properties
From: Krzysztof Kozlowski @ 2026-03-27 6:39 UTC (permalink / raw)
To: Hongliang Wang
Cc: Binbin Zhou, Andi Shyti, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-i2c, devicetree, loongarch
In-Reply-To: <bc22bad4-9825-829d-1df0-a801ebd933d6@loongson.cn>
On 27/03/2026 04:09, Hongliang Wang wrote:
> The initial idea was that this patch could be used for both ACPI and DTS.
>>>> The i2c-ls2x driver is compatible with both Loongson 2K and 3A+7A
>>>> platform, parse
>>>> the same parameters regardless of dts or acpi parameter passing, So
>>>> clock-input
>>>> and clock-div attributes are defined to describe input clock of i2c
>>>> controller and
>>>> divisor of input clock. It can be used on both 2K and 3A+7A platform.
>>> And you cannot use them in DTS.
> OK
>> I need to keep guessing what you want to achieve, because neither your
>> message nor commit text was explicit
> What I want to achieve is to describe the input clock and divisor of I2C
> controller
Input clocks are defined as clock inputs obviously in DT, not as
integers. Bindings need to describe the hardware, so start with that.
Best regards,
Krzysztof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox