* Re: [PATCH 05/11] media: iris: Enable Secure PAS support with IOMMU managed by Linux
From: Konrad Dybcio @ 2026-04-14 14:09 UTC (permalink / raw)
To: Vishnu Reddy, Bryan O'Donoghue, Vikash Garodia,
Dikshita Agarwal, Abhinav Kumar, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joerg Roedel,
Will Deacon, Robin Murphy, Bjorn Andersson, Konrad Dybcio,
Stefan Schmidt, Hans Verkuil
Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, iommu,
Mukesh Ojha
In-Reply-To: <20260414-glymur-v1-5-7d3d1cf57b16@oss.qualcomm.com>
On 4/14/26 7:00 AM, Vishnu Reddy wrote:
> From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
>
> Most Qualcomm platforms feature a proprietary hypervisor (such as Gunyah
> or QHEE), which typically handles IOMMU configuration. This includes
> mapping memory regions and device memory resources for remote processors
> by intercepting qcom_scm_pas_auth_and_reset() calls. These mappings are
> later removed during teardown. Additionally, SHM bridge setup is required
> to enable memory protection for both remoteproc metadata and its memory
> regions.
>
> When the hypervisor is absent, the operating system must perform these
> configurations instead.
>
> Support for handling IOMMU and SHM setup in the absence of a hypervisor
> is now in place. Extend the Iris driver to enable this functionality on
> platforms where IOMMU is managed by Linux (i.e., non-Gunyah, non-QHEE).
>
> Additionally, the Iris driver must map the firmware and its required
> resources to the firmware SID, which is now specified via iommu-map in
> the device tree.
>
> Co-developed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
> ---
[...]
> static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> {
> + struct device *dev = core->dev_fw ? core->dev_fw : core->dev;
Maybe:
struct device *fw_dev = core->dev_fw ?: core->dev;
and preserve *dev to be the main Iris device?
Konrad
^ permalink raw reply
* Re: [PATCH v6 3/3] arm64: dts: rockchip: Add Orange Pi 5 Pro board support
From: Dennis Gilmore @ 2026-04-14 14:07 UTC (permalink / raw)
To: Alexey Charkov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
FUKAUMI Naoki, Hsun Lai, Jonas Karlman, Chaoyi Chen, John Clark,
Michael Opdenacker, Quentin Schulz, Andrew Lunn, Chukun Pan,
Peter Robinson, Michael Riesch, Mykola Kvach, Jimmy Hon,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <CABjd4YwZJe8fO+kJiXRTq5gZirVvKvCqWzNdYqN3-6eMAZUFxQ@mail.gmail.com>
On Sat, Apr 11, 2026 at 1:00 PM Alexey Charkov <alchark@gmail.com> wrote:
>
> On Sat, Apr 11, 2026 at 6:47 AM <dennis@ausil.us> wrote:
> >
> > From: Dennis Gilmore <dennis@ausil.us>
> >
> > Add device tree for the Xunlong Orange Pi 5 Pro (RK3588S).
> >
> > - eMMC module, you can optionally solder a SPI NOR in place and turn
> > off the eMMC
> > - PCIe-attached NIC (pcie2x1l1)
> > - PCIe NVMe slot (pcie2x1l2)
> > - AP6256 WiFi (BCM43456) via SDIO with mmc-pwrseq
> > - BCM4345C5 Bluetooth
> > - es8388 audio
> > - USB 2.0 and USB 3.0
> > - Two HDMI ports, the second is connected to the SoC's DP controller
> > driven by a transparent LT8711UXD bridge that has firmware onboard and
> > needs no node defined.
> >
> > Vendors description and links to schematics available:
> > http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5-Pro.html
>
> Hi Dennis,
>
> The most useful of these is the schematic, so it's best to include a
> direct link to that in a dedicated Link: tag
>
> Link: https://drive.google.com/file/d/1qs1DratHuh7C6J6MEtQIwUsiSrg8qgTi/view
Will change to that, I did not do it because a random Google Drive
link doesn't really indicate it as a source of truth
> [schematic]
>
> > Signed-off-by: Dennis Gilmore <dennis@ausil.us>
> > ---
> > .../display/rockchip/rockchip,dw-dp.yaml | 7 +
> > arch/arm64/boot/dts/rockchip/Makefile | 1 +
> > .../dts/rockchip/rk3588s-orangepi-5-pro.dts | 352 ++++++++++++++++++
> > drivers/gpu/drm/bridge/synopsys/dw-dp.c | 12 +
>
> These should be three separate patches, never lumped together. First
> the binding change, next the driver change. They go together via the
> subsystem tree (likely DRM in this case). Then the DTS addition (or
> change) separately (it goes via the SoC tree).
They were something I was doing as I worked on getting the second HDMI
port working, they ended up not being needed, and I should have
removed it there really should have only been the dts and Makefile. I
should have waited until the morning to review again and send.
> > 4 files changed, 372 insertions(+)
> > create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> >
> > diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > index 6345f0132d43..079a912d97f1 100644
> > --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > @@ -57,6 +57,13 @@ properties:
> > - const: i2s
> > - const: spdif
> >
> > + hpd-gpios:
> > + maxItems: 1
> > + description:
> > + GPIO used for hot plug detection when the controller's native HPD
> > + input is not connected. If not specified, the controller uses its
> > + internal HPD detection mechanism.
>
> Do you actually need this change? According to the schematic, the
> DP_HPDIN line from the DP-HDMI bridge is routed to the native
> DP0_HPDIN_M0 pin of the DP controller, so it shouldn't require this
> GPIO trick if the pinctrl is configured properly.
No I do not, It was an approach I had experimented with but did not
use and did not mean to include here.
> > phys:
> > maxItems: 1
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
> > index 4d384f153c13..c99dca2ae9e7 100644
> > --- a/arch/arm64/boot/dts/rockchip/Makefile
> > +++ b/arch/arm64/boot/dts/rockchip/Makefile
> > @@ -214,6 +214,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5b.dtb
> > +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5-pro.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-cm5-base.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-radxa-cm5-io.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-roc-pc.dtb
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> > new file mode 100644
> > index 000000000000..84c83aa69f63
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> > @@ -0,0 +1,352 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > +
> > +/dts-v1/;
> > +
> > +#include "rk3588s-orangepi-5.dtsi"
> > +
> > +/ {
> > + model = "Xunlong Orange Pi 5 Pro";
> > + compatible = "xunlong,orangepi-5-pro", "rockchip,rk3588s";
> > +
> > + aliases {
> > + mmc0 = &sdhci;
> > + mmc1 = &sdmmc;
> > + mmc2 = &sdio;
> > + };
> > +
> > + dp-con {
> > + compatible = "dp-connector";
>
> You don't have a physical DP connector on the board, so this node
> doesn't describe actual hardware, and is thus a no-go. What you have
> instead is an HDMI type A connector routed via an onboard DP to HDMI
> bridge, so you should describe exactly that in the device tree (a node
> for the HDMI connector, a node for the bridge, a node for the DP
> controller, and endpoints connected from the controller to the bridge,
> from the bridge to the connector). Please refer to the device tree for
> Radxa Rock 5 ITX, which has a similar setup (but a different bridge
> IC).
>
> I don't think your LT8711UXD has existing binding or driver entry, so
> a one-line patch will likely be needed to
> Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml,
> and a separate one to drivers/gpu/drm/bridge/simple-bridge.c. Separate
> ones :)
Will add in v7
> > + port {
> > + dp_con_in: endpoint {
> > + remote-endpoint = <&dp0_out_con>;
> > + };
> > + };
> > + };
> > +
> > + analog-sound {
> > + compatible = "simple-audio-card";
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&hp_detect>;
> > + simple-audio-card,bitclock-master = <&masterdai>;
> > + simple-audio-card,format = "i2s";
> > + simple-audio-card,frame-master = <&masterdai>;
> > + simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
> > + simple-audio-card,mclk-fs = <256>;
> > + simple-audio-card,name = "rockchip,es8388";
> > + simple-audio-card,routing =
> > + "Headphones", "LOUT1",
> > + "Headphones", "ROUT1",
> > + "LINPUT1", "Microphone Jack",
> > + "RINPUT1", "Microphone Jack",
> > + "LINPUT2", "Onboard Microphone",
> > + "RINPUT2", "Onboard Microphone";
> > + simple-audio-card,widgets =
> > + "Microphone", "Microphone Jack",
> > + "Microphone", "Onboard Microphone",
> > + "Headphone", "Headphones";
> > +
> > + simple-audio-card,cpu {
> > + sound-dai = <&i2s2_2ch>;
> > + };
> > +
> > + masterdai: simple-audio-card,codec {
> > + sound-dai = <&es8388>;
> > + system-clock-frequency = <12288000>;
> > + };
> > + };
> > +
> > + pwm-leds {
> > + compatible = "pwm-leds";
> > +
> > + led-0 {
> > + color = <LED_COLOR_ID_BLUE>;
> > + function = LED_FUNCTION_STATUS;
> > + linux,default-trigger = "heartbeat";
> > + max-brightness = <255>;
> > + pwms = <&pwm15 0 1000000 0>;
> > + };
> > +
> > + led-1 {
> > + color = <LED_COLOR_ID_GREEN>;
> > + function = LED_FUNCTION_ACTIVITY;
> > + linux,default-trigger = "heartbeat";
> > + max-brightness = <255>;
> > + pwms = <&pwm3 0 1000000 0>;
> > + };
> > + };
> > +
> > + fan: pwm-fan {
> > + compatible = "pwm-fan";
> > + #cooling-cells = <2>;
> > + cooling-levels = <0 50 100 150 200 255>;
> > + fan-supply = <&vcc5v0_sys>;
> > + pwms = <&pwm2 0 20000000 0>;
> > + };
> > +
> > + vcc3v3_dp: regulator-vcc3v3-dp {
> > + compatible = "regulator-fixed";
> > + enable-active-high;
> > + gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
>
> Please don't forget to add explicit pinctrl nodes for each GPIO pin
> you use (here and in other places like this). These GPIOs happen to
> work on Linux without configuring their pin control first, but that is
> pure luck and coincidence due to how the respective Linux subsystems
> are wired together, and if you ever need to use this device tree in
> e.g. U-boot (which also derives its DTS from the Linux kernel tree) it
> will break there.
Will do
> > + regulator-always-on;
> > + regulator-boot-on;
>
> Does it have to be always-on, boot-on? This looks like a hack to work
> around the fact that you didn't define the bridge node, which uses
> this as its supply. Please model the dependencies explicitly - most
> likely that will let you drop these attributes.
without these the the dp to HDMI bridge does not power up, and HPD
does not work,
> > + regulator-max-microvolt = <3300000>;
> > + regulator-min-microvolt = <3300000>;
>
> It's two separate regulators on your schematic, one DCDC at 1.25V and
> the other a load switch at 3.3V, driving six separate voltage inputs
> of the DP bridge. They are both controlled by the same GPIO pin
> though, so _maybe_ it's okay to have just one "virtual" node like this
> to model them together. Would be great for the DT maintainers to weigh
> in on this.
>
> > + regulator-name = "vcc3v3_dp";
> > + vin-supply = <&vcc_3v3_s3>;
> > + };
> > +
> > + vcc3v3_phy1: regulator-vcc3v3-phy1 {
> > + compatible = "regulator-fixed";
> > + enable-active-high;
> > + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
> > + regulator-boot-on;
>
> See above
>
> > + regulator-max-microvolt = <3300000>;
> > + regulator-min-microvolt = <3300000>;
> > + regulator-name = "vcc3v3_phy1";
> > + startup-delay-us = <50000>;
> > + vin-supply = <&vcc_3v3_s3>;
> > + };
> > +
> > + vcc5v0_otg: regulator-vcc5v0-otg {
> > + compatible = "regulator-fixed";
> > + enable-active-high;
> > + gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&vcc5v0_otg_en>;
> > + regulator-max-microvolt = <5000000>;
> > + regulator-min-microvolt = <5000000>;
> > + regulator-name = "vcc5v0_otg";
> > + vin-supply = <&vcc5v0_sys>;
> > + };
> > +
> > + sdio_pwrseq: sdio-pwrseq {
> > + compatible = "mmc-pwrseq-simple";
> > + clocks = <&hym8563>;
> > + clock-names = "ext_clock";
> > + post-power-on-delay-ms = <200>;
> > + reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_LOW>;
>
> This GPIO also needs a pinctrl
>
> > + };
> > +
> > + typea_con: usb-a-connector {
> > + compatible = "usb-a-connector";
> > + data-role = "host";
> > + label = "USB3 Type-A";
> > + power-role = "source";
> > + vbus-supply = <&vcc5v0_otg>;
> > + };
> > +};
> > +
> > +&dp0 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&dp0m0_pins>;
>
> This switches your HPD pin to the native DP controller handling
> (DP0_HPDIN_M0), so the GPIO bits you've patched into the controller
> driver aren't even used, and it doesn't look like you tested that code
> path.
Right, I had not meant to include. It was something I had worked on in
refactoring it and went a different route.
>
> > + status = "okay";
> > +};
> > +
> > +&dp0_in {
> > + dp0_in_vp1: endpoint {
> > + remote-endpoint = <&vp1_out_dp0>;
> > + };
> > +};
> > +
> > +&dp0_out {
> > + dp0_out_con: endpoint {
> > + remote-endpoint = <&dp_con_in>;
>
> This will need to be rewritten once you add the proper bridge chain
> leading up to the HDMI type A connector.
Yep
> > + };
> > +};
> > +
> > +&i2c1 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2c1m4_xfer>;
> > + status = "okay";
> > +};
> > +
> > +&i2c3 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2c3m0_xfer>;
> > + status = "okay";
> > +
> > + es8388: audio-codec@11 {
> > + compatible = "everest,es8388", "everest,es8328";
> > + reg = <0x11>;
> > + #sound-dai-cells = <0>;
> > + AVDD-supply = <&vcc_3v3_s0>;
>
> Are you sure? Schematic says VCCA_3V3_S0, which is a different
> regulator (PLDO4 output of the PMIC)
>
> > + DVDD-supply = <&vcc_1v8_s0>;
>
> Schematic says VCCA_1V8_S0, which is a different regulator (PLDO1
> output of the PMIC)
>
> > + HPVDD-supply = <&vcc_3v3_s0>;
>
> Schematic says VCCA_3V3_S0
>
> > + PVDD-supply = <&vcc_3v3_s0>;
>
> Schematic says VCCA_1V8_S0
I will rename these. It was what was used in the original orange pi 5
boards and was carried over, but looking at their schematics, they are
labeled the same so changing makes sense. after digging in the Pi 5
Pro names two of the regulators differently to the 5 and 5b. and the
naming of the current ones does not match the schematic
>
> > + assigned-clock-rates = <12288000>;
> > + assigned-clocks = <&cru I2S2_2CH_MCLKOUT>;
> > + clocks = <&cru I2S2_2CH_MCLKOUT>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2s2m1_mclk>;
> > + };
> > +};
> > +
> > +&i2c4 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2c4m3_xfer>;
> > + status = "okay";
> > +};
> > +
> > +&i2s2_2ch {
> > + pinctrl-0 = <&i2s2m1_lrck &i2s2m1_sclk
> > + &i2s2m1_sdi &i2s2m1_sdo>;
> > + status = "okay";
> > +};
> > +
> > +&package_thermal {
> > + polling-delay = <1000>;
> > +
> > + cooling-maps {
> > + map0 {
> > + trip = <&package_fan0>;
> > + cooling-device = <&fan THERMAL_NO_LIMIT 1>;
> > + };
> > +
> > + map1 {
> > + trip = <&package_fan1>;
> > + cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
> > + };
> > + };
> > +
> > + trips {
> > + package_fan0: package-fan0 {
> > + hysteresis = <2000>;
> > + temperature = <55000>;
> > + type = "active";
> > + };
> > +
> > + package_fan1: package-fan1 {
> > + hysteresis = <2000>;
> > + temperature = <65000>;
> > + type = "active";
> > + };
> > + };
> > +};
> > +
> > +/* NVMe */
> > +&pcie2x1l1 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pcie30x1m1_1_clkreqn &pcie30x1m1_1_waken>;
> > + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
>
> The GPIO also needs a pinctrl
Will fix
> > + supports-clkreq;
> > + vpcie3v3-supply = <&vcc_3v3_s3>;
> > + status = "okay";
> > +};
> > +
> > +/* NIC */
> > +&pcie2x1l2 {
> > + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
>
> The GPIO also needs a pinctrl
Will fix
> > + vpcie3v3-supply = <&vcc3v3_phy1>;
> > + status = "okay";
> > +};
> > +
> > +&pinctrl {
> > + bluetooth {
> > + bt_wake_gpio: bt-wake-pin {
> > + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
> > + };
> > +
> > + bt_wake_host_irq: bt-wake-host-irq {
> > + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>;
> > + };
> > + };
> > +
> > + usb {
> > + vcc5v0_otg_en: vcc5v0-otg-en {
> > + rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
> > + };
> > + };
> > +
> > + wlan {
> > + wifi_host_wake_irq: wifi-host-wake-irq {
> > + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
> > + };
> > + };
> > +};
> > +
> > +&pwm15 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pwm15m2_pins>;
> > + status = "okay";
> > +};
> > +
> > +&pwm2 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pwm2m1_pins>;
> > + status = "okay";
> > +};
> > +
> > +&pwm3 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pwm3m2_pins>;
> > + status = "okay";
> > +};
> > +
> > +&sdhci {
> > + status = "okay";
> > +};
> > +
> > +&sdio {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + bus-width = <4>;
> > + cap-sd-highspeed;
> > + cap-sdio-irq;
> > + keep-power-in-suspend;
> > + max-frequency = <150000000>;
> > + mmc-pwrseq = <&sdio_pwrseq>;
> > + no-mmc;
> > + no-sd;
> > + non-removable;
> > + sd-uhs-sdr104;
> > + status = "okay";
> > +
> > + ap6256: wifi@1 {
> > + compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
> > + reg = <1>;
> > + interrupt-names = "host-wake";
> > + interrupt-parent = <&gpio0>;
> > + interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&wifi_host_wake_irq>;
> > + };
> > +};
> > +
> > +&uart9 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn &uart9m2_rtsn>;
> > + uart-has-rtscts;
> > + status = "okay";
> > +
> > + bluetooth {
> > + compatible = "brcm,bcm4345c5";
> > + clocks = <&hym8563>;
> > + clock-names = "lpo";
> > + device-wakeup-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
> > + interrupt-names = "host-wakeup";
> > + interrupt-parent = <&gpio0>;
> > + interrupts = <RK_PC5 IRQ_TYPE_LEVEL_HIGH>;
> > + max-speed = <1500000>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&bt_wake_host_irq &bt_wake_gpio>;
> > + shutdown-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
> > + vbat-supply = <&vcc_3v3_s3>;
> > + vddio-supply = <&vcc_1v8_s3>;
> > + };
> > +};
> > +
> > +&usb_host0_xhci {
> > + dr_mode = "host";
> > +};
> > +
> > +&usbdp_phy0 {
> > + rockchip,dp-lane-mux = <0 1>;
>
> I'm wondering if the DP controller's "out" endpoint should go to the
> PHY instead of directly to the connector/bridge. That would describe
> the hardware better.
This was initially added to make sure that the type A port worked
because it uses lanes 2/3, and I needed to make sure 0/1, which route
to the dp were allocated. The DP PHY is already tied to the controller
via the phys property on &dp0 (inherited from rk3588s.dtsi), and the
lane mux is set via rockchip,dp-lane-mux on &usbdp_phy0. This matches
the convention used by rk3588-evb2-v10, rk3588s-coolpi-4b, and
rk3588s-indiedroid-nova — routing the dp0_out endpoint through the PHY
would diverge from the existing binding and all in-tree users.
> > +};
> > +
> > +&vp1 {
> > + vp1_out_dp0: endpoint@a {
> > + reg = <ROCKCHIP_VOP2_EP_DP0>;
> > + remote-endpoint = <&dp0_in_vp1>;
> > + };
> > +};
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > index fd23ca2834b0..b58f57b69b22 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > @@ -8,6 +8,7 @@
> > */
> > #include <linux/bitfield.h>
> > #include <linux/clk.h>
> > +#include <linux/gpio/consumer.h>
> > #include <linux/iopoll.h>
> > #include <linux/irq.h>
> > #include <linux/media-bus-format.h>
> > @@ -330,6 +331,8 @@ struct dw_dp {
> > u8 pixel_mode;
> >
> > DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
> > +
> > + struct gpio_desc *hpd_gpiod;
> > };
> >
> > enum {
> > @@ -481,6 +484,9 @@ static bool dw_dp_hpd_detect(struct dw_dp *dp)
> > {
> > u32 value;
> >
> > + if (dp->hpd_gpiod)
> > + return gpiod_get_value_cansleep(dp->hpd_gpiod);
> > +
> > regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> >
> > return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
> > @@ -2002,6 +2008,12 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> > return ERR_CAST(dp->regmap);
> > }
> >
> > + dp->hpd_gpiod = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
>
> Not tested, not needed, why bother?..
this is not needed
> Best regards,
> Alexey
Thanks for the feedback
Dennis
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: gpio: add Axiado SGPIO controller
From: Krzysztof Kozlowski @ 2026-04-14 14:06 UTC (permalink / raw)
To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-1-b5c7e4c2e69b@axiado.com>
On 14/04/2026 15:48, Petar Stepanovic wrote:
> +properties:
> + compatible:
> + enum:
> + - axiado,sgpio
That's a SoC no? Where is SoC compatible?
> +
> + reg:
> + maxItems: 1
> +
> + gpio-controller: true
> +
> + '#gpio-cells':
> + const: 2
> +
> + interrupts:
> + maxItems: 1
> +
> + interrupt-controller: true
> +
> + '#interrupt-cells':
> + const: 2
> +
> + design-variant:
Sorry, but no, none of this and further properties apply to DT. Drop all
of them.
Please also read writing bindings so you won't make trivial mistakes.
...
> + sgpio@a000 {
> + compatible = "axiado,sgpio";
Don't come with own style, please. Look at other files.
> + reg = <0xa000 0x800>;
> + gpio-controller;
> + #gpio-cells = <2>;
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/3] gpio: axiado: add SGPIO controller support
From: Krzysztof Kozlowski @ 2026-04-14 14:04 UTC (permalink / raw)
To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.com>
On 14/04/2026 15:48, Petar Stepanovic wrote:
> +
> + for (i = 0; i < sgpio->max_offset_regs; i++) {
> + sgpio->slices[2].reg_ss[i] = 0;
> + dout_value = be32_to_cpu(prop[i]);
> +
> + for (dout_reverse = 0; dout_reverse < 32; ++dout_reverse) {
> + sgpio->slices[2].reg_ss[i] <<= 1;
> + sgpio->slices[2].reg_ss[i] |= (dout_value & 1);
> + dout_value >>= 1;
> + }
> + }
> +
> + sgpio_hw_init(sgpio);
> +
> + irq = platform_get_irq(pdev, 0);
> +
Odd style
> + if (irq < 0) {
> + dev_err(&pdev->dev, "Failed to get parent IRQ: %d\n", irq);
> + return irq;
> + }
> + /* Store parent IRQ for cleanup */
> + sgpio->parent_irq = irq;
> +
> + rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, sgpio_irq_handler,
> + IRQF_ONESHOT, "axiado-sgpio", sgpio);
> +
> + if (rc < 0) {
> + dev_err(&pdev->dev, "Failed to request threaded IRQ %d: %d\n",
> + irq, rc);
Nope
> + return rc;
> + }
> +
> + sgpio->chip.parent = &pdev->dev;
> + sgpio->chip.ngpio = sgpio->ngpios * 2;
> + sgpio->chip.owner = THIS_MODULE;
> + sgpio->chip.direction_input = ax3000_sgpio_dir_in;
> + sgpio->chip.direction_output = ax3000_sgpio_dir_out;
> + sgpio->chip.get = ax3000_sgpio_get;
> + sgpio->chip.set = ax3000_sgpio_set;
> + sgpio->chip.label = dev_name(&pdev->dev);
> + sgpio->chip.base = -1;
> +
> + girq = &sgpio->chip.irq;
> +
> + girq->chip = &axiado_sgpio_irqchip;
> + girq->handler = handle_edge_irq;
> + girq->default_type = IRQ_TYPE_NONE;
> + girq->num_parents = 1;
> + girq->parents =
> + devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL);
> + if (!girq->parents) {
> + dev_err(&pdev->dev, "Failed to allocate parents array\n");
> + return -ENOMEM;
Ykes...
> + }
> +
> +static struct platform_driver sgpio_driver = {
> + .driver = {
> + .name = "sgpio",
> + .owner = THIS_MODULE,
Uh, that's 13 year old code. Please drop everything and write from
scratch using latest reviewed drivers as your base. No point to repeat
same review and fix the same issues we already fixed during last 13 years...
> + .of_match_table = ax_sgpio_match,
> + },
> + .probe = sgpio_probe,
> + .remove = sgpio_remove,
> +};
> +
> +static int __init ax_sgpio_init(void)
> +{
> + int ret;
> +
> + ret = platform_driver_register(&sgpio_driver);
> + if (ret < 0) {
> + pr_err("Failed to register SGPIO driver\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void __exit ax_sgpio_exit(void)
> +{
> + platform_driver_unregister(&sgpio_driver);
> +}
> +
> +module_init(ax_sgpio_init);
> +module_exit(ax_sgpio_exit);
And that's one more.
module_platform_driver, no?
> +
> +MODULE_DESCRIPTION("Axiado Serial GPIO Driver");
> +MODULE_AUTHOR("Axiado Corporation");
> +MODULE_LICENSE("GPL");
>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/3] pmdomain: core: add support for power-domains-child-ids
From: Ulf Hansson @ 2026-04-14 14:03 UTC (permalink / raw)
To: Kevin Hilman (TI)
Cc: Rob Herring, Geert Uytterhoeven, linux-pm, devicetree,
linux-kernel, arm-scmi, linux-arm-kernel
In-Reply-To: <20260410-topic-lpm-pmdomain-child-ids-v2-2-83396e4b5f8b@baylibre.com>
On Sat, 11 Apr 2026 at 01:44, Kevin Hilman (TI) <khilman@baylibre.com> wrote:
>
> Currently, PM domains can only support hierarchy for simple
> providers (e.g. ones with #power-domain-cells = 0).
>
> Add support for oncell providers as well by adding a new property
> `power-domains-child-ids` to describe the parent/child relationship.
>
> For example, an SCMI PM domain provider has multiple domains, each of
> which might be a child of diffeent parent domains. In this example,
> the parent domains are MAIN_PD and WKUP_PD:
>
> scmi_pds: protocol@11 {
> reg = <0x11>;
> #power-domain-cells = <1>;
> power-domains = <&MAIN_PD>, <&WKUP_PD>;
> power-domains-child-ids = <15>, <19>;
> };
>
> With this example using the new property, SCMI PM domain 15 becomes a
> child domain of MAIN_PD, and SCMI domain 19 becomes a child domain of
> WKUP_PD.
>
> To support this feature, add two new core functions
>
> - of_genpd_add_child_ids()
> - of_genpd_remove_child_ids()
>
> which can be called by pmdomain providers to add/remove child domains
> if they support the new property power-domains-child-ids.
>
> The add function is "all or nothing". If it cannot add all of the
> child domains in the list, it will unwind any additions already made
> and report a failure.
>
> Signed-off-by: Kevin Hilman (TI) <khilman@baylibre.com>
> ---
> drivers/pmdomain/core.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pm_domain.h | 16 ++++++++++++++++
> 2 files changed, 182 insertions(+)
>
> diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
> index 61c2277c9ce3..f978477dd546 100644
> --- a/drivers/pmdomain/core.c
> +++ b/drivers/pmdomain/core.c
> @@ -2909,6 +2909,172 @@ static struct generic_pm_domain *genpd_get_from_provider(
> return genpd;
> }
>
> +/**
> + * of_genpd_add_child_ids() - Parse power-domains-child-ids property
> + * @np: Device node pointer associated with the PM domain provider.
> + * @data: Pointer to the onecell data associated with the PM domain provider.
> + *
> + * Parse the power-domains and power-domains-child-ids properties to establish
> + * parent-child relationships for PM domains. The power-domains property lists
> + * parent domains, and power-domains-child-ids lists which child domain IDs
> + * should be associated with each parent.
> + *
> + * Uses "all or nothing" semantics: either all relationships are established
> + * successfully, or none are (any partially-added relationships are unwound
> + * on error).
> + *
> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error code.
> + */
As I mentioned in my earlier reply for the previous version, returning
a specific error code when the property doesn't exist will complicate
handling for the caller. Moreover, we also need to make sure we don't
returning the same error code (-ENOENT) for a different error further
down the execution path in of_genpd_add_child_ids(). Otherwise it
would the caller treat the error code in the wrong way.
To me, there are two better ways to address this. For both options,
of_genpd_add_child_ids() should return 0 when
"power-domains-child-ids" is missing.
1) Add another helper function that checks if
"power-domains-child-ids" exists. The caller can then use this to
pre-parse the property and decide whether to treat it as an error.
2) As I suggested earlier, let of_genpd_add_child_ids() return the
number of assigned parents/children, while still using the all or
nothing approach, of course.
Kind regards
Uffe
> +int of_genpd_add_child_ids(struct device_node *np,
> + struct genpd_onecell_data *data)
> +{
> + struct of_phandle_args parent_args;
> + struct generic_pm_domain *parent_genpd, *child_genpd;
> + struct generic_pm_domain **pairs; /* pairs[2*i]=parent, pairs[2*i+1]=child */
> + u32 child_id;
> + int i, ret, count, child_count, added = 0;
> +
> + /* Check if both properties exist */
> + count = of_count_phandle_with_args(np, "power-domains", "#power-domain-cells");
> + if (count <= 0)
> + return -ENOENT;
> +
> + child_count = of_property_count_u32_elems(np, "power-domains-child-ids");
> + if (child_count < 0)
> + return -ENOENT;
> + if (child_count != count)
> + return -EINVAL;
> +
> + /* Allocate tracking array for error unwind (parent/child pairs) */
> + pairs = kmalloc_array(count * 2, sizeof(*pairs), GFP_KERNEL);
> + if (!pairs)
> + return -ENOMEM;
> +
> + for (i = 0; i < count; i++) {
> + ret = of_property_read_u32_index(np, "power-domains-child-ids",
> + i, &child_id);
> + if (ret)
> + goto err_unwind;
> +
> + /* Validate child ID is within bounds */
> + if (child_id >= data->num_domains) {
> + pr_err("Child ID %u out of bounds (max %u) for %pOF\n",
> + child_id, data->num_domains - 1, np);
> + ret = -EINVAL;
> + goto err_unwind;
> + }
> +
> + /* Get the child domain */
> + child_genpd = data->domains[child_id];
> + if (!child_genpd) {
> + pr_err("Child domain %u is NULL for %pOF\n", child_id, np);
> + ret = -EINVAL;
> + goto err_unwind;
> + }
> +
> + ret = of_parse_phandle_with_args(np, "power-domains",
> + "#power-domain-cells", i,
> + &parent_args);
> + if (ret)
> + goto err_unwind;
> +
> + /* Get the parent domain */
> + parent_genpd = genpd_get_from_provider(&parent_args);
> + of_node_put(parent_args.np);
> + if (IS_ERR(parent_genpd)) {
> + pr_err("Failed to get parent domain for %pOF: %ld\n",
> + np, PTR_ERR(parent_genpd));
> + ret = PTR_ERR(parent_genpd);
> + goto err_unwind;
> + }
> +
> + /* Establish parent-child relationship */
> + ret = pm_genpd_add_subdomain(parent_genpd, child_genpd);
> + if (ret) {
> + pr_err("Failed to add child domain %u to parent in %pOF: %d\n",
> + child_id, np, ret);
> + goto err_unwind;
> + }
> +
> + /* Track for potential unwind */
> + pairs[2 * added] = parent_genpd;
> + pairs[2 * added + 1] = child_genpd;
> + added++;
> +
> + pr_debug("Added child domain %u (%s) to parent %s for %pOF\n",
> + child_id, child_genpd->name, parent_genpd->name, np);
> + }
> +
> + kfree(pairs);
> + return 0;
> +
> +err_unwind:
> + /* Reverse all previously established relationships */
> + while (added-- > 0)
> + pm_genpd_remove_subdomain(pairs[2 * added], pairs[2 * added + 1]);
> + kfree(pairs);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(of_genpd_add_child_ids);
> +
> +/**
> + * of_genpd_remove_child_ids() - Remove parent-child PM domain relationships
> + * @np: Device node pointer associated with the PM domain provider.
> + * @data: Pointer to the onecell data associated with the PM domain provider.
> + *
> + * Reverses the effect of of_genpd_add_child_ids() by parsing the same
> + * power-domains and power-domains-child-ids properties and calling
> + * pm_genpd_remove_subdomain() for each established relationship.
> + *
> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error
> + * code on failure.
> + */
> +int of_genpd_remove_child_ids(struct device_node *np,
> + struct genpd_onecell_data *data)
> +{
> + struct of_phandle_args parent_args;
> + struct generic_pm_domain *parent_genpd, *child_genpd;
> + u32 child_id;
> + int i, ret, count, child_count;
> +
> + /* Check if both properties exist */
> + count = of_count_phandle_with_args(np, "power-domains", "#power-domain-cells");
> + if (count <= 0)
> + return -ENOENT;
> +
> + child_count = of_property_count_u32_elems(np, "power-domains-child-ids");
> + if (child_count < 0)
> + return -ENOENT;
> + if (child_count != count)
> + return -EINVAL;
> +
> + for (i = 0; i < count; i++) {
> + if (of_property_read_u32_index(np, "power-domains-child-ids",
> + i, &child_id))
> + continue;
> +
> + if (child_id >= data->num_domains || !data->domains[child_id])
> + continue;
> +
> + ret = of_parse_phandle_with_args(np, "power-domains",
> + "#power-domain-cells", i,
> + &parent_args);
> + if (ret)
> + continue;
> +
> + parent_genpd = genpd_get_from_provider(&parent_args);
> + of_node_put(parent_args.np);
> + if (IS_ERR(parent_genpd))
> + continue;
> +
> + child_genpd = data->domains[child_id];
> + pm_genpd_remove_subdomain(parent_genpd, child_genpd);
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(of_genpd_remove_child_ids);
> +
> /**
> * of_genpd_add_device() - Add a device to an I/O PM domain
> * @genpdspec: OF phandle args to use for look-up PM domain
> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
> index f67a2cb7d781..b44615d79af6 100644
> --- a/include/linux/pm_domain.h
> +++ b/include/linux/pm_domain.h
> @@ -465,6 +465,10 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
> int of_genpd_parse_idle_states(struct device_node *dn,
> struct genpd_power_state **states, int *n);
> void of_genpd_sync_state(struct device_node *np);
> +int of_genpd_add_child_ids(struct device_node *np,
> + struct genpd_onecell_data *data);
> +int of_genpd_remove_child_ids(struct device_node *np,
> + struct genpd_onecell_data *data);
>
> int genpd_dev_pm_attach(struct device *dev);
> struct device *genpd_dev_pm_attach_by_id(struct device *dev,
> @@ -534,6 +538,18 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
> {
> return ERR_PTR(-EOPNOTSUPP);
> }
> +
> +static inline int of_genpd_add_child_ids(struct device_node *np,
> + struct genpd_onecell_data *data)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +static inline int of_genpd_remove_child_ids(struct device_node *np,
> + struct genpd_onecell_data *data)
> +{
> + return -EOPNOTSUPP;
> +}
> #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
>
> #ifdef CONFIG_PM
>
> --
> 2.51.0
>
^ permalink raw reply
* [PATCH 0/3] Subject: [PATCH 0/3] gpio: add support for Axiado SGPIO controller
From: Petar Stepanovic @ 2026-04-14 13:48 UTC (permalink / raw)
To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
The SGPIO controller provides a serialized interface for
controlling multiple GPIO signals over a limited number of
physical lines. It supports configurable data direction and
interrupt handling.
This series adds support for the Axiado SGPIO controller.
The series includes:
- Device tree binding documentation
- GPIO driver implementation
- MAINTAINERS entry
The driver integrates with the Linux GPIO subsystem and
registers the controller as a gpio_chip.
Tested on Axiado platforms.
---
Patch 1: dt-bindings: gpio: add Axiado SGPIO controller
Patch 2: gpio: axiado: add SGPIO controller support
Patch 3: MAINTAINERS: add Axiado SGPIO controller
Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>
---
Petar Stepanovic (3):
dt-bindings: gpio: add Axiado SGPIO controller
gpio: axiado: add SGPIO controller support
MAINTAINERS: add Axiado SGPIO controller
.../devicetree/bindings/gpio/axiado,sgpio.yaml | 98 +++
MAINTAINERS | 9 +
drivers/gpio/Kconfig | 18 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-axiado-sgpio.c | 780 +++++++++++++++++++++
5 files changed, 906 insertions(+)
---
base-commit: 63804fed149a6750ffd28610c5c1c98cce6bd377
change-id: 20260320-axiado-ax3000-sgpio-controller-00f6e1db6ce9
Best regards,
--
Petar Stepanovic <pstepanovic@axiado.com>
^ permalink raw reply
* [PATCH 1/3] dt-bindings: gpio: add Axiado SGPIO controller
From: Petar Stepanovic @ 2026-04-14 13:48 UTC (permalink / raw)
To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-0-b5c7e4c2e69b@axiado.com>
Add device tree binding for the Axiado SGPIO controller.
The SGPIO controller provides a serialized interface for
controlling multiple GPIO signals over a limited number of
physical lines. It supports configurable data direction and
interrupt handling.
The binding describes the properties required to instantiate
the controller and register it as a GPIO provider.
Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>
---
.../devicetree/bindings/gpio/axiado,sgpio.yaml | 98 ++++++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/Documentation/devicetree/bindings/gpio/axiado,sgpio.yaml b/Documentation/devicetree/bindings/gpio/axiado,sgpio.yaml
new file mode 100644
index 000000000000..1533446d69f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/axiado,sgpio.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/axiado,sgpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Axiado SGPIO Controller
+
+maintainers:
+ - Petar Stepanovic <pstepanovic@axiado.com>
+ - SriNavmani A <srinavmani@axiado.com>
+ - Prasad Bolisetty <pbolisetty@axiado.com>
+
+description: |
+ The SGPIO controller provides a serialized interface for controlling
+ multiple GPIO signals over a limited number of physical lines.
+ It supports configurable data direction and interrupt handling.
+
+properties:
+ compatible:
+ enum:
+ - axiado,sgpio
+
+ reg:
+ maxItems: 1
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+ design-variant:
+ description: SGPIO design variant size in bits (e.g. 128 or 512).
+ enum: [128, 512]
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ ngpios:
+ description: The number of gpios this controller has.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ bus-frequency:
+ description: The SGPIO shift clock frequency in Hz.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ apb-frequency:
+ description: The APB bus frequency in Hz.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ dout-init:
+ description: Initial values for the dout registers.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 4
+ maxItems: 4
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - '#gpio-cells'
+ - interrupts
+ - interrupt-controller
+ - '#interrupt-cells'
+ - design-variant
+ - ngpios
+ - bus-frequency
+ - apb-frequency
+ - dout-init
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ sgpio@a000 {
+ compatible = "axiado,sgpio";
+ reg = <0xa000 0x800>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
+ design-variant = <128>;
+ ngpios = <128>;
+ bus-frequency = <1000000>;
+ apb-frequency = <100000000>;
+ dout-init = <0x00300000 0x00006371 0x00003800 0x00000000>;
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH 3/3] MAINTAINERS: add Axiado SGPIO controller
From: Petar Stepanovic @ 2026-04-14 13:48 UTC (permalink / raw)
To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-0-b5c7e4c2e69b@axiado.com>
Add MAINTAINERS entry for the Axiado SGPIO controller driver
and corresponding device tree binding.
Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>
---
MAINTAINERS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 67db88b04537..56835c0a1863 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4234,6 +4234,15 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/axentia,*
F: sound/soc/atmel/tse850-pcm5142.c
+AXIADO SGPIO DRIVER
+M: Petar Stepanovic <pstepanovic@axiado.com>
+M: SriNavmani A <srinavmani@axiado.com>
+M: Prasad Bolisetty <pbolisetty@axiado.com>
+L: linux-gpio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/gpio/axiado,sgpio.yaml
+F: drivers/gpio/gpio-axiado-sgpio.c
+
AXIS ARTPEC ARM64 SoC SUPPORT
M: Jesper Nilsson <jesper.nilsson@axis.com>
M: Lars Persson <lars.persson@axis.com>
--
2.34.1
^ permalink raw reply related
* [PATCH 2/3] gpio: axiado: add SGPIO controller support
From: Petar Stepanovic @ 2026-04-14 13:48 UTC (permalink / raw)
To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-0-b5c7e4c2e69b@axiado.com>
Add support for the Axiado SGPIO controller.
The controller provides a serialized interface for GPIOs with
configurable direction and interrupt support.
The driver registers the controller as a gpio_chip and uses
regmap for register access.
Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>
---
drivers/gpio/Kconfig | 18 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-axiado-sgpio.c | 780 +++++++++++++++++++++++++++++++++++++++
3 files changed, 799 insertions(+)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index bd185482a7fd..42c56d157092 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -198,6 +198,24 @@ config GPIO_ATH79
Select this option to enable GPIO driver for
Atheros AR71XX/AR724X/AR913X SoC devices.
+config GPIO_AXIADO_SGPIO
+ bool "Axiado SGPIO support"
+ depends on OF_GPIO
+ depends on ARCH_AXIADO || COMPILE_TEST
+ select GPIO_GENERIC
+ select GPIOLIB_IRQCHIP
+ select REGMAP
+ help
+ Enable support for the Axiado Serial GPIO (SGPIO) controller.
+
+ The SGPIO controller provides a serialized interface for
+ controlling multiple GPIO signals over a limited number of
+ physical lines. It supports configurable data direction and
+ interrupt handling.
+
+ This driver integrates with the Linux GPIO subsystem and
+ exposes the controller as a standard GPIO provider.
+
config GPIO_RASPBERRYPI_EXP
tristate "Raspberry Pi 3 GPIO Expander"
default RASPBERRYPI_FIRMWARE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 2421a8fd3733..909a97551807 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio-aspeed-sgpio.o
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
+obj-$(CONFIG_GPIO_AXIADO_SGPIO) += gpio-axiado-sgpio.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o
obj-$(CONFIG_GPIO_BD71815) += gpio-bd71815.o
diff --git a/drivers/gpio/gpio-axiado-sgpio.c b/drivers/gpio/gpio-axiado-sgpio.c
new file mode 100644
index 000000000000..8cd349ec6f53
--- /dev/null
+++ b/drivers/gpio/gpio-axiado-sgpio.c
@@ -0,0 +1,780 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022-2026 Axiado Corporation
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+
+#include <linux/gpio/driver.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+#include <linux/regmap.h>
+
+struct sgpio_reg_offsets {
+ u32 mux_0;
+ u32 preset_0;
+ u32 count_0;
+ u32 pos_0;
+
+ u32 mux_1;
+ u32 ld;
+ u32 ld_ss;
+
+ u32 preset_1;
+ u32 count_1;
+ u32 pos_1;
+
+ u32 mux_2;
+ u32 dout;
+ u32 dout_ss;
+
+ u32 preset_2;
+ u32 count_2;
+ u32 pos_2;
+
+ u32 mux_3;
+ u32 preset_3;
+ u32 count_3;
+ u32 pos_3;
+
+ u32 mux_4;
+ u32 oe;
+ u32 oe_ss;
+
+ u32 preset_4;
+ u32 count_4;
+ u32 pos_4;
+
+ u32 mask;
+ u32 ctrl_en;
+ u32 ctrl_en_pos;
+
+ u32 din_ss;
+ u32 status;
+};
+
+static const struct sgpio_reg_offsets sgpio_offsets_512 = {
+ .mux_0 = 0x000,
+ .preset_0 = 0x1dc,
+ .count_0 = 0x1f0,
+ .pos_0 = 0x204,
+
+ .mux_1 = 0x004,
+ .ld = 0x014,
+ .ld_ss = 0x0d8,
+
+ .preset_1 = 0x1e0,
+ .count_1 = 0x1f4,
+ .pos_1 = 0x208,
+
+ .mux_2 = 0x008,
+ .dout = 0x054,
+ .dout_ss = 0x158,
+
+ .preset_2 = 0x1e4,
+ .count_2 = 0x1f8,
+ .pos_2 = 0x20c,
+
+ .mux_3 = 0x00c,
+ .preset_3 = 0x1e8,
+ .count_3 = 0x1fc,
+ .pos_3 = 0x210,
+
+ .mux_4 = 0x010,
+ .oe = 0x0d4,
+ .oe_ss = 0x1d8,
+
+ .preset_4 = 0x1ec,
+ .count_4 = 0x200,
+ .pos_4 = 0x214,
+
+ .mask = 0x224,
+ .ctrl_en = 0x218,
+ .ctrl_en_pos = 0x21c,
+
+ .din_ss = 0x198,
+ .status = 0x228,
+};
+
+static const struct sgpio_reg_offsets sgpio_offsets_128 = {
+ .mux_0 = 0x000,
+ .preset_0 = 0x08c,
+ .count_0 = 0x0a0,
+ .pos_0 = 0x0b4,
+
+ .mux_1 = 0x004,
+ .ld = 0x014,
+ .ld_ss = 0x048,
+
+ .preset_1 = 0x090,
+ .count_1 = 0x0a4,
+ .pos_1 = 0x0b8,
+
+ .mux_2 = 0x008,
+ .dout = 0x024,
+ .dout_ss = 0x068,
+
+ .preset_2 = 0x094,
+ .count_2 = 0x0a8,
+ .pos_2 = 0x0bc,
+
+ .mux_3 = 0x00c,
+ .preset_3 = 0x098,
+ .count_3 = 0x0ac,
+ .pos_3 = 0x0c0,
+
+ .mux_4 = 0x010,
+ .oe = 0x044,
+ .oe_ss = 0x088,
+
+ .preset_4 = 0x09c,
+ .count_4 = 0x0b0,
+ .pos_4 = 0x0c4,
+
+ .mask = 0x0d4,
+ .ctrl_en = 0x0c8,
+ .ctrl_en_pos = 0x0cc,
+
+ .din_ss = 0x078,
+ .status = 0x0d8,
+};
+
+#define MAX_SGPIO_PINS 512
+#define MAX_OFFSET_REG 16
+#define MAX_SLICE_COUNT 5
+
+struct ax3000_slice_info {
+ u32 out_mux;
+ u32 sgpio_mux;
+ u32 slice_mux;
+ u32 reg[MAX_OFFSET_REG];
+ u32 reg_ss[MAX_OFFSET_REG];
+ u32 preset;
+ u32 count;
+ u32 pos;
+};
+
+struct ax3000_sgpio {
+ u32 preset_value;
+ u32 count_value;
+ u32 pos_reg;
+ struct ax3000_slice_info
+ slices[MAX_SLICE_COUNT]; /* 0=clk,1=load,2=out,3=in,4=oe */
+ spinlock_t lock;
+ int ngpios;
+ int max_sgpio_pins;
+ int max_offset_regs;
+ struct gpio_chip chip;
+ u32 irq_unmasked[MAX_SGPIO_PINS];
+ int parent_irq;
+ struct regmap *regmap;
+ u32 regmap_base_offset;
+ struct sgpio_reg_offsets *regs;
+};
+
+static int sgpio_set_irq_type(struct irq_data *d, unsigned int type);
+static void sgpio_mask_irq(struct irq_data *d);
+static void sgpio_unmask_irq(struct irq_data *d);
+static void sgpio_irq_shutdown(struct irq_data *d);
+
+static const struct irq_chip axiado_sgpio_irqchip = {
+ .name = "axiado-sgpio",
+ .irq_mask = sgpio_mask_irq,
+ .irq_unmask = sgpio_unmask_irq,
+ .irq_set_type = sgpio_set_irq_type,
+ .irq_shutdown = sgpio_irq_shutdown,
+ .flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static void ax3000_sgpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct ax3000_sgpio *sgpio = gpiochip_get_data(chip);
+ unsigned long flags;
+ u32 bank = (offset / 2) / 32;
+ u32 position = (offset / 2) % 32;
+
+ spin_lock_irqsave(&sgpio->lock, flags);
+ if (value)
+ sgpio->slices[2].reg_ss[bank] |= BIT(position);
+ else
+ sgpio->slices[2].reg_ss[bank] &= ~BIT(position);
+
+ spin_unlock_irqrestore(&sgpio->lock, flags);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->dout_ss +
+ (bank * 4),
+ sgpio->slices[2].reg_ss[bank]);
+}
+
+static int ax3000_sgpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct ax3000_sgpio *sgpio = gpiochip_get_data(chip);
+ u32 bank = (offset / 2) / 32;
+ u32 position = (offset / 2) % 32;
+
+ if (offset % 2 == 0)
+ return !!(sgpio->slices[3].reg_ss[bank] & BIT(position));
+ else
+ return !!(sgpio->slices[2].reg_ss[bank] & BIT(position));
+}
+
+static int ax3000_sgpio_dir_in(struct gpio_chip *chip, unsigned int offset)
+{
+ if (!(offset % 2))
+ return 0;
+ else
+ return -EINVAL;
+}
+
+static int ax3000_sgpio_dir_out(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ if (offset % 2) {
+ if (chip->set)
+ chip->set(chip, offset, value);
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t sgpio_irq_handler(int irq, void *arg)
+{
+ struct ax3000_sgpio *sgpio = (struct ax3000_sgpio *)arg;
+ unsigned long flags;
+ u32 status, new_value;
+ u32 changed_value;
+ int i, bit, reg_ptr;
+
+ /* Read-on-clear (ACK) parent cause */
+ regmap_read(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->status, &status);
+ status >>= 16;
+
+ bool has_shifted_layout = (sgpio->max_offset_regs == MAX_OFFSET_REG);
+
+ reg_ptr = has_shifted_layout ? 16 - DIV_ROUND_UP(sgpio->ngpios, 32) : 0;
+
+ for (i = 0; i < DIV_ROUND_UP(sgpio->ngpios, 32); i++, reg_ptr++) {
+ if (status & BIT(reg_ptr)) {
+ regmap_read(sgpio->regmap,
+ sgpio->regmap_base_offset +
+ sgpio->regs->din_ss + (reg_ptr * 4),
+ &new_value);
+ spin_lock_irqsave(&sgpio->lock, flags);
+ changed_value = sgpio->slices[3].reg_ss[i] ^ new_value;
+ sgpio->slices[3].reg_ss[i] = new_value;
+ spin_unlock_irqrestore(&sgpio->lock, flags);
+
+ while (changed_value) {
+ bit = __ffs(changed_value);
+ changed_value &= ~BIT(bit);
+
+ irq_hw_number_t hwirq = i * 32 + bit;
+
+ if (sgpio->irq_unmasked[hwirq]) {
+ unsigned int child_irq;
+
+ child_irq = irq_find_mapping(sgpio->chip.irq.domain,
+ hwirq);
+
+ if (child_irq)
+ handle_nested_irq(child_irq);
+ }
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void sgpio_hw_init(struct ax3000_sgpio *sgpio)
+{
+ u32 bank;
+ u32 position;
+ int i = 0;
+ bool has_shifted_layout = (sgpio->max_offset_regs == MAX_OFFSET_REG);
+
+ /* slice A0, Clock Pin - 0 */
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mux_0, 0x306);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->preset_0,
+ sgpio->preset_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->count_0,
+ sgpio->count_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->pos_0, 0x1f001f);
+
+ /* Slice B1, Data Load Pin - 1 */
+ bank = (sgpio->ngpios - 1) / 32;
+ position = (sgpio->ngpios - 1) % 32;
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mux_1,
+ has_shifted_layout ? 0x30c : 0x304);
+
+ for (i = 0; i < bank; i++) {
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ld +
+ (i * 4),
+ 0xffffffff);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ld_ss +
+ (i * 4),
+ 0xffffffff);
+ }
+
+ if (position) {
+ u32 val;
+
+ val = sgpio->slices[1].reg_ss[i];
+ val |= GENMASK(position - 1, 0);
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ld +
+ (i * 4),
+ val);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ld_ss +
+ (i * 4),
+ val);
+ }
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->preset_1,
+ sgpio->preset_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->count_1,
+ sgpio->count_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->pos_1,
+ sgpio->pos_reg);
+
+ /* Slice C2, Data Out Pin - 2 */
+ bank = sgpio->ngpios / 32;
+ position = sgpio->ngpios % 32;
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mux_2,
+ has_shifted_layout ? 0x30c : 0x304);
+
+ for (i = 0; i < bank; i++) {
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->dout +
+ (i * 4),
+ sgpio->slices[2].reg_ss[i]);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->dout_ss +
+ (i * 4),
+ sgpio->slices[2].reg_ss[i]);
+ }
+
+ if (position) {
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->dout +
+ (i * 4),
+ sgpio->slices[2].reg_ss[i]);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->dout_ss +
+ (i * 4),
+ sgpio->slices[2].reg_ss[i]);
+ }
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->preset_2,
+ sgpio->preset_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->count_2,
+ sgpio->count_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->pos_2,
+ sgpio->pos_reg);
+
+ /* Slice D3, Data In Pin - 3 */
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mux_3, 0x14C);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->preset_3,
+ sgpio->preset_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->count_3,
+ sgpio->count_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->pos_3,
+ sgpio->pos_reg);
+
+ /* Slice E4, Output Enable for respective pins */
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mux_4,
+ has_shifted_layout ? 0x10c : 0x104);
+ regmap_write(sgpio->regmap, sgpio->regmap_base_offset + sgpio->regs->oe,
+ 0xffffffff);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->oe_ss,
+ 0xffffffff);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->preset_4,
+ sgpio->preset_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->count_4,
+ sgpio->count_value);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->pos_4, 0x1f001f);
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mask, 0xdfff);
+
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ctrl_en, 0xffff);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ctrl_en_pos,
+ 0xffff);
+}
+
+static int sgpio_set_irq_type(struct irq_data *d, unsigned int type)
+{
+ switch (type) {
+ case IRQ_TYPE_EDGE_BOTH:
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_EDGE_FALLING:
+ irq_set_handler_locked(d, handle_edge_irq);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void sgpio_mask_irq(struct irq_data *d)
+{
+ struct gpio_chip *chip;
+ struct ax3000_sgpio *sgpio;
+ u32 irq_num;
+
+ chip = irq_data_get_irq_chip_data(d);
+ if (!chip) {
+ pr_err("Unable to get gpio_chip for IRQ\n");
+ return;
+ }
+
+ sgpio = gpiochip_get_data(chip);
+ if (!sgpio) {
+ pr_err("Unable to get chip data\n");
+ return;
+ }
+
+ irq_num = irqd_to_hwirq(d);
+ sgpio->irq_unmasked[irq_num / 2] = 0;
+}
+
+static void sgpio_unmask_irq(struct irq_data *d)
+{
+ struct gpio_chip *chip;
+ struct ax3000_sgpio *sgpio;
+ u32 irq_num;
+
+ chip = irq_data_get_irq_chip_data(d);
+ if (!chip) {
+ pr_err("Unable to get gpio_chip for IRQ\n");
+ return;
+ }
+
+ sgpio = gpiochip_get_data(chip);
+ if (!sgpio) {
+ pr_err("Unable to get chip data\n");
+ return;
+ }
+
+ irq_num = irqd_to_hwirq(d);
+ sgpio->irq_unmasked[irq_num / 2] = 1;
+}
+
+static void sgpio_irq_shutdown(struct irq_data *d)
+{
+ sgpio_mask_irq(d);
+}
+
+static int sgpio_probe(struct platform_device *pdev)
+{
+ int rc;
+ int irq;
+ int i;
+ const __be32 *prop;
+ struct gpio_irq_chip *girq;
+ struct ax3000_sgpio *sgpio;
+ u32 variant;
+ u32 dout_value;
+ u32 bus_frequency;
+ u32 apb_frequency;
+ int dout_reverse;
+
+ void __iomem *base;
+
+ const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ };
+
+ sgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL);
+ if (!sgpio)
+ return -ENOMEM;
+
+ spin_lock_init(&sgpio->lock);
+
+ sgpio->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+
+ if (sgpio->regmap) {
+ rc = of_property_read_u32(pdev->dev.of_node, "reg",
+ &sgpio->regmap_base_offset);
+ if (rc) {
+ dev_err(&pdev->dev, "Failed to read reg property: %d\n",
+ rc);
+ return rc;
+ }
+ dev_info(&pdev->dev, "Using regmap with base offset: 0x%x\n",
+ sgpio->regmap_base_offset);
+ } else {
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ sgpio->regmap =
+ devm_regmap_init_mmio(&pdev->dev, base, ®map_config);
+
+ if (IS_ERR(sgpio->regmap))
+ return PTR_ERR(sgpio->regmap);
+
+ sgpio->regmap_base_offset = 0;
+
+ dev_info(&pdev->dev, "Using MMIO regmap\n");
+ }
+
+ rc = device_property_read_u32(&pdev->dev, "ngpios", &sgpio->ngpios);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Could not read ngpios property\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "design-variant", &variant)) {
+ dev_err(&pdev->dev, "design-variant not specified in DT\n");
+ return -EINVAL;
+ }
+
+ if (variant == 128) {
+ sgpio->regs = &sgpio_offsets_128;
+ sgpio->max_sgpio_pins = 128;
+ sgpio->max_offset_regs = 4;
+ } else if (variant == 512) {
+ sgpio->regs = &sgpio_offsets_512;
+ sgpio->max_sgpio_pins = 512;
+ sgpio->max_offset_regs = 16;
+ } else {
+ return -EINVAL;
+ }
+
+ if (sgpio->ngpios > sgpio->max_sgpio_pins) {
+ dev_err(&pdev->dev, "ngpio is greater than 512 pins\n");
+ return -EINVAL;
+ }
+
+ rc = device_property_read_u32(&pdev->dev, "bus-frequency",
+ &bus_frequency);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Could not read bus-frequency property\n");
+ return -EINVAL;
+ }
+
+ rc = device_property_read_u32(&pdev->dev, "apb-frequency",
+ &apb_frequency);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Could not read apb-frequency property\n");
+ return -EINVAL;
+ }
+
+ sgpio->preset_value = (apb_frequency / bus_frequency) - 1;
+ sgpio->count_value = sgpio->preset_value;
+
+ u32 pos;
+
+ pos = sgpio->ngpios - 1;
+ sgpio->pos_reg = (pos << 16) | pos;
+
+ prop = of_get_property(pdev->dev.of_node, "dout-init", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "Failed to get dout-init\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < sgpio->max_offset_regs; i++) {
+ sgpio->slices[2].reg_ss[i] = 0;
+ dout_value = be32_to_cpu(prop[i]);
+
+ for (dout_reverse = 0; dout_reverse < 32; ++dout_reverse) {
+ sgpio->slices[2].reg_ss[i] <<= 1;
+ sgpio->slices[2].reg_ss[i] |= (dout_value & 1);
+ dout_value >>= 1;
+ }
+ }
+
+ sgpio_hw_init(sgpio);
+
+ irq = platform_get_irq(pdev, 0);
+
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get parent IRQ: %d\n", irq);
+ return irq;
+ }
+ /* Store parent IRQ for cleanup */
+ sgpio->parent_irq = irq;
+
+ rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, sgpio_irq_handler,
+ IRQF_ONESHOT, "axiado-sgpio", sgpio);
+
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Failed to request threaded IRQ %d: %d\n",
+ irq, rc);
+ return rc;
+ }
+
+ sgpio->chip.parent = &pdev->dev;
+ sgpio->chip.ngpio = sgpio->ngpios * 2;
+ sgpio->chip.owner = THIS_MODULE;
+ sgpio->chip.direction_input = ax3000_sgpio_dir_in;
+ sgpio->chip.direction_output = ax3000_sgpio_dir_out;
+ sgpio->chip.get = ax3000_sgpio_get;
+ sgpio->chip.set = ax3000_sgpio_set;
+ sgpio->chip.label = dev_name(&pdev->dev);
+ sgpio->chip.base = -1;
+
+ girq = &sgpio->chip.irq;
+
+ girq->chip = &axiado_sgpio_irqchip;
+ girq->handler = handle_edge_irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->num_parents = 1;
+ girq->parents =
+ devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL);
+ if (!girq->parents) {
+ dev_err(&pdev->dev, "Failed to allocate parents array\n");
+ return -ENOMEM;
+ }
+ girq->parents[0] = irq;
+
+ rc = devm_gpiochip_add_data(&pdev->dev, &sgpio->chip, sgpio);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", rc);
+ return rc;
+ }
+
+ /* Store driver data for remove() */
+ platform_set_drvdata(pdev, sgpio);
+ dev_info(&pdev->dev, "SGPIO registered with %d GPIOs\n",
+ sgpio->chip.ngpio);
+
+ return 0;
+}
+
+static int sgpio_remove(struct platform_device *pdev)
+{
+ struct ax3000_sgpio *sgpio = platform_get_drvdata(pdev);
+ int i;
+
+ if (!sgpio)
+ return 0;
+
+ /* Disable interrupts in hardware */
+ if (sgpio->regs) {
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->mask,
+ 0x0);
+ regmap_write(sgpio->regmap,
+ sgpio->regmap_base_offset + sgpio->regs->ctrl_en,
+ 0x0);
+ }
+
+ /* Disable and synchronize parent IRQ to avoid races with handlers */
+ if (sgpio->parent_irq >= 0) {
+ disable_irq(sgpio->parent_irq);
+ synchronize_irq(sgpio->parent_irq);
+ }
+
+ /* Ensure all GPIO IRQ handlers complete before removal */
+ if (sgpio->chip.irq.domain) {
+ struct irq_domain *domain = sgpio->chip.irq.domain;
+ unsigned int irq;
+ int hwirq;
+
+ for (hwirq = 0; hwirq < sgpio->chip.ngpio; hwirq++) {
+ irq = irq_find_mapping(domain, hwirq);
+ if (irq) {
+ disable_irq(irq);
+ synchronize_irq(irq);
+ }
+ }
+ }
+
+ /* Clear internal IRQ state */
+ for (i = 0; i < sgpio->max_sgpio_pins; i++)
+ sgpio->irq_unmasked[i] = 0;
+
+ return 0;
+}
+
+static const struct of_device_id ax_sgpio_match[] = {
+ { .compatible = "axiado,sgpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, ax_sgpio_match);
+
+static struct platform_driver sgpio_driver = {
+ .driver = {
+ .name = "sgpio",
+ .owner = THIS_MODULE,
+ .of_match_table = ax_sgpio_match,
+ },
+ .probe = sgpio_probe,
+ .remove = sgpio_remove,
+};
+
+static int __init ax_sgpio_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&sgpio_driver);
+ if (ret < 0) {
+ pr_err("Failed to register SGPIO driver\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit ax_sgpio_exit(void)
+{
+ platform_driver_unregister(&sgpio_driver);
+}
+
+module_init(ax_sgpio_init);
+module_exit(ax_sgpio_exit);
+
+MODULE_DESCRIPTION("Axiado Serial GPIO Driver");
+MODULE_AUTHOR("Axiado Corporation");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 2/3] pmdomain: core: add support for power-domains-child-ids
From: Ulf Hansson @ 2026-04-14 13:42 UTC (permalink / raw)
To: Kevin Hilman
Cc: Rob Herring, Geert Uytterhoeven, linux-pm, devicetree,
linux-kernel, arm-scmi, linux-arm-kernel
In-Reply-To: <7hqzomqwpv.fsf@baylibre.com>
On Sat, 11 Apr 2026 at 00:25, Kevin Hilman <khilman@baylibre.com> wrote:
>
> Ulf Hansson <ulf.hansson@linaro.org> writes:
>
> > On Fri, 10 Apr 2026 at 02:45, Kevin Hilman <khilman@baylibre.com> wrote:
> >>
> >> Ulf Hansson <ulf.hansson@linaro.org> writes:
> >>
> >> > On Wed, 11 Mar 2026 at 01:19, Kevin Hilman (TI) <khilman@baylibre.com> wrote:
> >> >>
> >> >> Currently, PM domains can only support hierarchy for simple
> >> >> providers (e.g. ones with #power-domain-cells = 0).
> >> >>
> >> >> Add support for oncell providers as well by adding a new property
> >> >> `power-domains-child-ids` to describe the parent/child relationship.
> >> >>
> >> >> For example, an SCMI PM domain provider has multiple domains, each of
> >> >> which might be a child of diffeent parent domains. In this example,
> >> >> the parent domains are MAIN_PD and WKUP_PD:
> >> >>
> >> >> scmi_pds: protocol@11 {
> >> >> reg = <0x11>;
> >> >> #power-domain-cells = <1>;
> >> >> power-domains = <&MAIN_PD>, <&WKUP_PD>;
> >> >> power-domains-child-ids = <15>, <19>;
> >> >> };
> >> >>
> >> >> With this example using the new property, SCMI PM domain 15 becomes a
> >> >> child domain of MAIN_PD, and SCMI domain 19 becomes a child domain of
> >> >> WKUP_PD.
> >> >>
> >> >> To support this feature, add two new core functions
> >> >>
> >> >> - of_genpd_add_child_ids()
> >> >> - of_genpd_remove_child_ids()
> >> >>
> >> >> which can be called by pmdomain providers to add/remove child domains
> >> >> if they support the new property power-domains-child-ids.
> >> >>
> >> >> Signed-off-by: Kevin Hilman (TI) <khilman@baylibre.com>
> >> >
> >> > Thanks for working on this! It certainly is a missing feature!
> >>
> >> You're welcome, thanks for the detailed review.
> >>
> >> >> ---
> >> >> drivers/pmdomain/core.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >> >> include/linux/pm_domain.h | 16 ++++++++++++++++
> >> >> 2 files changed, 185 insertions(+)
> >> >>
> >> >> diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
> >> >> index 61c2277c9ce3..acb45dd540b7 100644
> >> >> --- a/drivers/pmdomain/core.c
> >> >> +++ b/drivers/pmdomain/core.c
> >> >> @@ -2909,6 +2909,175 @@ static struct generic_pm_domain *genpd_get_from_provider(
> >> >> return genpd;
> >> >> }
> >> >>
> >> >> +/**
> >> >> + * of_genpd_add_child_ids() - Parse power-domains-child-ids property
> >> >> + * @np: Device node pointer associated with the PM domain provider.
> >> >> + * @data: Pointer to the onecell data associated with the PM domain provider.
> >> >> + *
> >> >> + * Parse the power-domains and power-domains-child-ids properties to establish
> >> >> + * parent-child relationships for PM domains. The power-domains property lists
> >> >> + * parent domains, and power-domains-child-ids lists which child domain IDs
> >> >> + * should be associated with each parent.
> >> >> + *
> >> >> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error code.
> >> >
> >> > I think we should avoid returning specific error codes for specific
> >> > errors, simply because it usually becomes messy.
> >> >
> >> > If I understand correctly the intent here is to allow the caller to
> >> > check for -ENOENT and potentially avoid bailing out as it may not
> >> > really be an error, right?
> >>
> >> Right, -ENOENT is not an error of parsing, it's to indicate that there
> >> are no child-ids to be parsed.
> >>
> >> > Perhaps a better option is to return the number of children for whom
> >> > we successfully assigned parents. Hence 0 or a positive value allows
> >> > the caller to understand what happened. More importantly, a negative
> >> > error code then really becomes an error for the caller to consider.
> >>
> >> I explored this a bit, but it gets messy quick. It means we have to
> >> track cases where only some of the children were added as well as when
> >> all children were added. Personally, I think this should be an "all or
> >> nothing" thing. If all the children cannot be parsed/added, then none
> >> of them should be added.
> >>
> >> This also allows the remove to not have to care about how many were
> >> added, and just remove them all, with the additional benefit of not
> >> having to track the state of how many children were successfully added.
> >>
> >
> > I fully agree, it should be all or nothing. Failing with one
> > child/parent should end up with an error code being returned.
> >
> > That said, it still seems to make perfect sense to return the number
> > of children for whom we assigned parents for, no?
>
> No, because what will the caller use that number for? If we are
> assuming "all or nothing", what would we use it for (other than a debug print?)
>
> It also makes it a bit confusing what a zero return value means. Does
> that mean success? Or that zero children were added (which would be
> fail.)
>
> I prefer to keep it as is.
In that case, how should we treat the scenario where the device node
lacks a "power-domains-child-ids" property? In some cases it is
probably fine, while in others it may not be.
I guess the caller of of_genpd_add_child_ids(), would then need to
pre-parse for the "power-domains-child-ids" property before deciding
to call of_genpd_add_child_ids().
At least, we don't of_genpd_add_child_ids() to return an error code if
there is no "power-domains-child-ids" in the device node, as that
would just confuse the caller.
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: iio: dac: add support for Microchip MCP48FEB02 to MCP47FEB02
From: Ariana.Lazar @ 2026-04-14 13:39 UTC (permalink / raw)
To: conor
Cc: dlechner, nuno.sa, Conor.Dooley, Jonathan.Cameron, robh, jic23,
andy, krzk+dt, linux-iio, conor+dt, linux-kernel, devicetree
In-Reply-To: <20260403-speed-childless-1360de358229@spud>
Hi Conor,
> >
> > patternProperties:
> > @@ -161,8 +222,7 @@ patternProperties:
> > properties:
> > reg:
> > description: The channel number.
> > - minItems: 1
> > - maxItems: 8
> > + maxItems: 1
>
> Why is this changing? Was it originally a mistake and what you wanted
> was a max of 8 but only one entry?
>
> >
Thank you for the review.
It was a mistake I missed in the devicetree
binding for the mcp47feb02 driver. The property contains a single
integer representing the channel number (0-7), as you said.
Should I send a fix for the mcp47feb02 binding first or can I continue
to rewrite/split mcp47feb02 driver into the core module with I2C
protocol file and include this binding fix there too?
Best regards,
Ariana
^ permalink raw reply
* Re: [PATCH v2 2/2] riscv: dts: spacemit: Add cpu scaling for K1 SoC
From: Anand Moon @ 2026-04-14 13:25 UTC (permalink / raw)
To: Shuwei Wu
Cc: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, linux-pm, linux-kernel, linux-riscv,
spacemit, devicetree
In-Reply-To: <20260410-shadow-deps-v2-2-4e16b8c0f60e@mailbox.org>
Hi Shuwei,
On Fri, 10 Apr 2026 at 13:30, Shuwei Wu <shuwei.wu@mailbox.org> wrote:
>
> Add Operating Performance Points (OPP) tables and CPU clock properties
> for the two clusters in the SpacemiT K1 SoC.
>
> Also assign the CPU power supply (cpu-supply) for the Banana Pi BPI-F3
> board to fully enable CPU DVFS.
>
> Signed-off-by: Shuwei Wu <shuwei.wu@mailbox.org>
>
> ---
> Changes in v2:
> - Add k1-opp.dtsi with OPP tables for both CPU clusters
> - Assign CPU supplies and include OPP table for Banana Pi BPI-F3
> ---
> arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 35 +++++++-
> arch/riscv/boot/dts/spacemit/k1-opp.dtsi | 105 ++++++++++++++++++++++++
> arch/riscv/boot/dts/spacemit/k1.dtsi | 8 ++
> 3 files changed, 147 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
> index 444c3b1e6f44..3780593f610d 100644
> --- a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
> +++ b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
> @@ -5,6 +5,7 @@
>
> #include "k1.dtsi"
> #include "k1-pinctrl.dtsi"
> +#include "k1-opp.dtsi"
>
> / {
> model = "Banana Pi BPI-F3";
> @@ -86,6 +87,38 @@ &combo_phy {
> status = "okay";
> };
>
> +&cpu_0 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_1 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_2 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_3 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_4 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_5 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_6 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> +&cpu_7 {
> + cpu-supply = <&buck1_3v45>;
> +};
> +
> &emmc {
> bus-width = <8>;
> mmc-hs400-1_8v;
> @@ -201,7 +234,7 @@ pmic@41 {
> dldoin2-supply = <&buck5>;
>
> regulators {
> - buck1 {
> + buck1_3v45: buck1 {
> regulator-min-microvolt = <500000>;
> regulator-max-microvolt = <3450000>;
> regulator-ramp-delay = <5000>;
> diff --git a/arch/riscv/boot/dts/spacemit/k1-opp.dtsi b/arch/riscv/boot/dts/spacemit/k1-opp.dtsi
> new file mode 100644
> index 000000000000..768ae390686d
> --- /dev/null
> +++ b/arch/riscv/boot/dts/spacemit/k1-opp.dtsi
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +
> +/ {
> + cluster0_opp_table: opp-table-cluster0 {
> + compatible = "operating-points-v2";
> + opp-shared;
> +
> + opp-614400000 {
> + opp-hz = /bits/ 64 <614400000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-819000000 {
> + opp-hz = /bits/ 64 <819000000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-1000000000 {
> + opp-hz = /bits/ 64 <1000000000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-1228800000 {
> + opp-hz = /bits/ 64 <1228800000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-1600000000 {
> + opp-hz = /bits/ 64 <1600000000>;
> + opp-microvolt = <1050000>;
> + clock-latency-ns = <200000>;
> + };
> + };
> +
> + cluster1_opp_table: opp-table-cluster1 {
> + compatible = "operating-points-v2";
> + opp-shared;
> +
> + opp-614400000 {
> + opp-hz = /bits/ 64 <614400000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-819000000 {
> + opp-hz = /bits/ 64 <819000000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-1000000000 {
> + opp-hz = /bits/ 64 <1000000000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-1228800000 {
> + opp-hz = /bits/ 64 <1228800000>;
> + opp-microvolt = <950000>;
> + clock-latency-ns = <200000>;
> + };
> +
> + opp-1600000000 {
> + opp-hz = /bits/ 64 <1600000000>;
> + opp-microvolt = <1050000>;
> + clock-latency-ns = <200000>;
> + };
> + };
> +};
> +
> +&cpu_0 {
> + operating-points-v2 = <&cluster0_opp_table>;
> +};
> +
> +&cpu_1 {
> + operating-points-v2 = <&cluster0_opp_table>;
> +};
> +
> +&cpu_2 {
> + operating-points-v2 = <&cluster0_opp_table>;
> +};
> +
> +&cpu_3 {
> + operating-points-v2 = <&cluster0_opp_table>;
> +};
> +
> +&cpu_4 {
> + operating-points-v2 = <&cluster1_opp_table>;
> +};
> +
> +&cpu_5 {
> + operating-points-v2 = <&cluster1_opp_table>;
> +};
> +
> +&cpu_6 {
> + operating-points-v2 = <&cluster1_opp_table>;
> +};
> +
> +&cpu_7 {
> + operating-points-v2 = <&cluster1_opp_table>;
> +};
> diff --git a/arch/riscv/boot/dts/spacemit/k1.dtsi b/arch/riscv/boot/dts/spacemit/k1.dtsi
> index 529ec68e9c23..bdd109b81730 100644
> --- a/arch/riscv/boot/dts/spacemit/k1.dtsi
> +++ b/arch/riscv/boot/dts/spacemit/k1.dtsi
> @@ -54,6 +54,7 @@ cpu_0: cpu@0 {
> compatible = "spacemit,x60", "riscv";
> device_type = "cpu";
> reg = <0>;
> + clocks = <&syscon_apmu CLK_CPU_C0_CORE>;
> riscv,isa = "rv64imafdcbv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
> riscv,isa-base = "rv64i";
> riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "v", "zicbom",
> @@ -84,6 +85,7 @@ cpu_1: cpu@1 {
> compatible = "spacemit,x60", "riscv";
> device_type = "cpu";
> reg = <1>;
> + clocks = <&syscon_apmu CLK_CPU_C0_CORE>;
Based on the Spacemit kernel source, the k1-x_opp_table.dtsi file
defines several additional clocks for the Operating Performance Points
(OPP) table:
clocks = <&ccu CLK_CPU_C0_ACE>, <&ccu CLK_CPU_C1_ACE>, <&ccu CLK_CPU_C0_TCM>,
<&ccu CLK_CCI550>, <&ccu CLK_PLL3>, <&ccu
CLK_CPU_C0_HI>, <&ccu CLK_CPU_C1_HI>;
clock-names = "ace0","ace1","tcm","cci","pll3", "c0hi", "c1hi";
These hardware clocks are also explicitly registered in the APMU clock driver
via the k1_ccu_apmu_hws array, confirming their availability for frequency
and voltage scaling on the K1-X SoC.
static struct clk_hw *k1_ccu_apmu_hws[] = {
[CLK_CCI550] = &cci550_clk.common.hw,
[CLK_CPU_C0_HI] = &cpu_c0_hi_clk.common.hw,
[CLK_CPU_C0_CORE] = &cpu_c0_core_clk.common.hw,
[CLK_CPU_C0_ACE] = &cpu_c0_ace_clk.common.hw,
[CLK_CPU_C0_TCM] = &cpu_c0_tcm_clk.common.hw,
[CLK_CPU_C1_HI] = &cpu_c1_hi_clk.common.hw,
[CLK_CPU_C1_CORE] = &cpu_c1_core_clk.common.hw,
[CLK_CPU_C1_ACE] = &cpu_c1_ace_clk.common.hw,
Yes, it is possible to add these clocks for DVFS to work correctly,
provided they are managed by the appropriate driver and declared in
the Device Tree (DT).
Thanks
-Anand
^ permalink raw reply
* Re: [PATCH v4] ASoC: dt-bindings: ti,pcm3060: add descriptions and rename binding
From: Padmashree S S @ 2026-04-14 13:22 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: k.marinushkin, lgirdwood, broonie, robh, krzk+dt, conor+dt,
linux-sound, devicetree, linux-kernel
In-Reply-To: <20260414-tentacled-mantis-of-control-cb08f3@quoll>
On Tue, Apr 14, 2026 at 12:09 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Tue, Apr 14, 2026 at 09:18:54AM +0530, Padmashree S S wrote:
> > Add description to reg property and overall binding mentioning that this
> > driver supports both I2C and SPI. Rename binding to match compatible
> > naming convention.
> >
> > Signed-off-by: Padmashree S S <padmashreess2006@gmail.com>
> > ---
> > Changes in v4:
> > - Rename binding from pcm3060 to ti,pcm3060
> > - Add binding description
> > - Add description to 'reg' property
> > - Remove unused label in example
> >
> > Changes in v3:
> > - Remove description from 'reg' property
> > ---
> > .../bindings/sound/{pcm3060.yaml => ti,pcm3060.yaml} | 10 +++++-----
>
> What v4 is that of? There is no such file.
>
> Do not attach (thread) your patchsets to some other threads (unrelated
> or older versions). This buries them deep in the mailbox and might
> interfere with applying entire sets. See also:
> https://elixir.bootlin.com/linux/v6.16-rc2/source/Documentation/process/submitting-patches.rst#L830
>
> Best regards,
> Krzysztof
>
Thanks for pointing this out.
Since this is a DT binding patch for the same pcm3060 device, I linked
it to the previous version. However, I realize the subject changed
significantly, which made the threading confusing.
I’m planning to resend it as a new patch in a separate thread. Please
let me know if that works.
^ permalink raw reply
* Re: [PATCH v4 00/11] Add support for the TI BQ25792 battery charger
From: Mark Brown @ 2026-04-14 13:07 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chris Morgan, Liam Girdwood, Sebastian Reichel, Alexey Charkov
Cc: devicetree, linux-kernel, Sebastian Reichel, linux-pm,
Krzysztof Kozlowski, stable
In-Reply-To: <20260311-bq25792-v4-0-7213415d9eec@flipper.net>
On Wed, 11 Mar 2026 15:56:13 +0400, Alexey Charkov wrote:
> This adds support for the TI BQ25792 battery charger, which is similar in
> overall logic to the BQ25703A, but has a different register layout and
> slightly different lower-level programming logic.
>
> The series is organized as follows:
> - Patch 1 adds the new variant to the existing DT binding, including the
> changes in electrical characteristics
> - Patches 2-4 are minor cleanups to the existing BQ25703A OTG regulator
> driver, slimming down the code and making it more reusable for the new
> BQ25792 variant
> - Patch 5 is a logical fix to the BQ25703A clamping logic for VSYSMIN
> (this is a standalone fix which can be applied independently and may be
> backported to stable)
> - Patches 6-8 are slight refactoring of the existing BQ25703A charger
> driver to make it more reusable for the new BQ25792 variant
> - Patch 9 adds platform data to distinguish between the two variants in
> the parent MFD driver, and binds it to the new compatible string
> - Patches 10-11 add variant-specific code to support the new BQ25792
> variant in the regulator part and the charger part respectively,
> selected by the platform data added in patch 9
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
Thanks!
[01/11] dt-bindings: mfd: ti,bq25703a: Expand to include BQ25792
(no commit info)
[02/11] regulator: bq257xx: Remove reference to the parent MFD's dev
https://git.kernel.org/broonie/misc/c/aef4d87f2c1f
[03/11] regulator: bq257xx: Drop the regulator_dev from the driver data
(no commit info)
[04/11] regulator: bq257xx: Make OTG enable GPIO really optional
https://git.kernel.org/broonie/misc/c/de76a763805d
[05/11] power: supply: bq257xx: Fix VSYSMIN clamping logic
(no commit info)
[06/11] power: supply: bq257xx: Make the default current limit a per-chip attribute
(no commit info)
[07/11] power: supply: bq257xx: Consistently use indirect get/set helpers
(no commit info)
[08/11] power: supply: bq257xx: Add fields for 'charging' and 'overvoltage' states
(no commit info)
[09/11] mfd: bq257xx: Add BQ25792 support
(no commit info)
[10/11] regulator: bq257xx: Add support for BQ25792
(no commit info)
[11/11] power: supply: bq257xx: Add support for BQ25792
(no commit info)
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply
* Re: [PATCH v4 00/11] drm/mxsfb/lcdif: use DRM_BRIDGE_ATTACH_NO_CONNECTOR and the bridge-connector
From: Luca Ceresoli @ 2026-04-14 13:04 UTC (permalink / raw)
To: Marek Vasut, Stefan Agner, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Liu Ying, Rob Herring,
Saravana Kannan, Luca Ceresoli
Cc: Damon Ding, Kory Maincent (TI.com), Hervé Codina, Hui Pu,
Ian Ray, Thomas Petazzoni, dri-devel, imx, linux-arm-kernel,
linux-kernel, devicetree, Adam Ford, Alexander Stein,
Christopher Obbard, Daniel Scally, Emanuele Ghidoli,
Fabio Estevam, Francesco Dolcini, Frieder Schrempf, Gilles Talis,
Goran Rađenović, Heiko Schocher, Josua Mayer,
Kieran Bingham, Marco Felsch, Martyn Welch, Oleksij Rempel,
Peng Fan, Richard Hu, Shengjiu Wang, Stefan Eichenberger,
Vitor Soares
In-Reply-To: <20260407-drm-lcdif-dbanc-v4-0-247a16e61ef9@bootlin.com>
On Tue, 07 Apr 2026 14:24:14 +0200, Luca Ceresoli wrote:
> This series modernizes the i.mx8mp LCDIF driver to use the
> bridge-connector, which is the current best practice in DRM.
>
> == Call for testing on i.MX8MP boards (especially those using HDMI)!
>
> For who tested previous versions (thanks!): some patches have changed
> ingnificantly in v2 and v3 so I had to drop your Tested-by on them. A new
> round of test would still be useful.
>
> [...]
Applied, thanks!
[01/11] drm/mxsfb/lcdif: simplify remote pointer management using __free
commit: 1bff813f8864f72528da4e1b389b62360e9c26ad
[02/11] drm/mxsfb/lcdif: simplify ep pointer management using __free
commit: 23bc92902eddd51e51613790c9c0f9e759fde174
[03/11] drm/mxsfb/lcdif: use dev_err_probe() consistently in lcdif_attach_bridge
commit: b08bfcbc138a450434e9fa38dfd487f687ae7ba3
[04/11] drm/mxsfb/lcdif: move iteration-specific variables declaration inside loop in lcdif_attach_bridge
commit: a6bdf27448b49af6a9daa1d081e2f019fb002a4a
[05/11] drm/bridge: dw-hdmi: document the output_port field
commit: ec9dfa70c2915c2dd3676d674287ee56e52a7ef5
[06/11] drm/bridge: dw-hdmi: warn on unsupported attach combination
commit: 5316b7464c998357c468fcfe3717be6258330708
[07/11] drm/bridge: dw-hdmi: move next_bridge lookup to attach time
commit: 91938b4fdc267931943d3e9f1b14d46d2b615330
[08/11] drm/bridge: imx8mp-hdmi-tx-connector-fixup: add an hdmi-connector when missing using a DT overlay at boot time
commit: 73cb588a6d90849301ef48ac89f3439a8942a890
[09/11] drm/bridge: imx8mp-hdmi-tx-connector-fixup: show a warning when adding the overlay
commit: 1148ef0c600f641f4ea95b3d8275cc911fd2f232
[10/11] drm/bridge: imx8mp-hdmi-tx: switch to DRM_BRIDGE_ATTACH_NO_CONNECTOR
commit: 06a2950fef18c0a8a26bee01b9550bf3006545c6
[11/11] drm/mxsfb/lcdif: use DRM_BRIDGE_ATTACH_NO_CONNECTOR and the bridge-connector
commit: f604819d9cc9532f88bb4cbd76e7227532ce5abb
Best regards,
--
Luca Ceresoli <luca.ceresoli@bootlin.com>
^ permalink raw reply
* Re: [PATCH v3 16/21] drm/panel: jadard-jd9365da-h3: support Waveshare 720p DSI panels
From: Neil Armstrong @ 2026-04-14 12:59 UTC (permalink / raw)
To: Dmitry Baryshkov, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Jie Gan
Cc: dri-devel, devicetree, linux-kernel, linux-gpio, Riccardo Mereu
In-Reply-To: <20260413-waveshare-dsi-touch-v3-16-3aeb53022c32@oss.qualcomm.com>
On 4/13/26 16:05, Dmitry Baryshkov wrote:
> Add configuration for Waveshare 9.0" and 10.1" 720p DSI panels using
> JD9365 controller.
>
> Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 312 +++++++++++++++++++++++
> 1 file changed, 312 insertions(+)
>
> diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> index 7744c66514c9..6fff3299f4ad 100644
> --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> @@ -21,6 +21,8 @@
> #include <linux/of.h>
> #include <linux/regulator/consumer.h>
>
> +#include <video/mipi_display.h>
> +
> struct jadard;
>
> struct jadard_panel_desc {
> @@ -2283,6 +2285,49 @@ static const struct jadard_panel_desc waveshare_8_0_inch_a_desc = {
> MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> };
>
> +static int waveshare_10_1_b_init(struct jadard *jadard);
> +
> +static const struct jadard_panel_desc waveshare_9_0_inch_b_desc = {
> + .mode_4ln = &(const struct drm_display_mode) {
> + .clock = (720 + 60 + 60 + 4) * (1280 + 16 + 12 + 4) * 60 / 1000,
> +
> + .hdisplay = 720,
> + .hsync_start = 720 + 60,
> + .hsync_end = 720 + 60 + 60,
> + .htotal = 720 + 60 + 60 + 4,
> +
> + .vdisplay = 1280,
> + .vsync_start = 1280 + 16,
> + .vsync_end = 1280 + 16 + 12,
> + .vtotal = 1280 + 16 + 12 + 4,
> +
> + .width_mm = 114,
> + .height_mm = 196,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> + },
> + .mode_2ln = &(const struct drm_display_mode) {
> + .clock = (720 + 50 + 50 + 50) * (1280 + 26 + 12 + 4) * 60 / 1000,
> +
> + .hdisplay = 720,
> + .hsync_start = 720 + 50,
> + .hsync_end = 720 + 50 + 50,
> + .htotal = 720 + 50 + 50 + 50,
> +
> + .vdisplay = 1280,
> + .vsync_start = 1280 + 26,
> + .vsync_end = 1280 + 26 + 12,
> + .vtotal = 1280 + 26 + 12 + 4,
> +
> + .width_mm = 114,
> + .height_mm = 196,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> + },
> + .format = MIPI_DSI_FMT_RGB888,
> + .init = waveshare_10_1_b_init,
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> +};
> +
> static const struct drm_display_mode waveshare_10_1_a_mode = {
> .clock = (800 + 40 + 20 + 20) * (1280 + 20 + 20 + 4) * 60 / 1000,
>
> @@ -2627,6 +2672,265 @@ static const struct jadard_panel_desc waveshare_10_1_inch_a_desc = {
> MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> };
>
> +static int waveshare_10_1_b_init(struct jadard *jadard)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + jadard_enable_standard_cmds(&dsi_ctx);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x3f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xbf);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xbf);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x74);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x7e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x24);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0xa9);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x38);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x65);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x52);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x2d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x14);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x28);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x25);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x23);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x3f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x2d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x34);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x27);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x24);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x18);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x65);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x52);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x2d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x14);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x28);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x25);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x23);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x3f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x2d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x34);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x27);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x24);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x18);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x00);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x51);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x55);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x51);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x51);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x55);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x51);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x11);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x15);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x11);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x11);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x15);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x11);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x66);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x55);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x13);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x66);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xe3);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xd5);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x21);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x66);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x60);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1d);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> + msleep(120);
> + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> + msleep(5);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_TEAR_ON);
> +
> + return 0;
> +}
> +
> +static const struct jadard_panel_desc waveshare_10_1_inch_b_desc = {
> + .mode_4ln = &(const struct drm_display_mode) {
> + .clock = (720 + 60 + 60 + 4) * (1280 + 16 + 12 + 4) * 60 / 1000,
> +
> + .hdisplay = 720,
> + .hsync_start = 720 + 60,
> + .hsync_end = 720 + 60 + 60,
> + .htotal = 720 + 60 + 60 + 4,
> +
> + .vdisplay = 1280,
> + .vsync_start = 1280 + 16,
> + .vsync_end = 1280 + 16 + 12,
> + .vtotal = 1280 + 16 + 12 + 4,
> +
> + .width_mm = 125,
> + .height_mm = 222,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> + },
> + .mode_2ln = &(const struct drm_display_mode) {
> + .clock = (720 + 50 + 50 + 50) * (1280 + 26 + 12 + 4) * 60 / 1000,
> +
> + .hdisplay = 720,
> + .hsync_start = 720 + 50,
> + .hsync_end = 720 + 50 + 50,
> + .htotal = 720 + 50 + 50 + 50,
> +
> + .vdisplay = 1280,
> + .vsync_start = 1280 + 26,
> + .vsync_end = 1280 + 26 + 12,
> + .vtotal = 1280 + 26 + 12 + 4,
> +
> + .width_mm = 125,
> + .height_mm = 222,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> + },
> + .format = MIPI_DSI_FMT_RGB888,
> + .init = waveshare_10_1_b_init,
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> +};
> +
> static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
> {
> struct device *dev = &dsi->dev;
> @@ -2762,10 +3066,18 @@ static const struct of_device_id jadard_of_match[] = {
> .compatible = "waveshare,8.0-dsi-touch-a",
> .data = &waveshare_8_0_inch_a_desc
> },
> + {
> + .compatible = "waveshare,9.0-dsi-touch-b",
> + .data = &waveshare_9_0_inch_b_desc
> + },
> {
> .compatible = "waveshare,10.1-dsi-touch-a",
> .data = &waveshare_10_1_inch_a_desc
> },
> + {
> + .compatible = "waveshare,10.1-dsi-touch-b",
> + .data = &waveshare_10_1_inch_b_desc
> + },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, jadard_of_match);
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH v3 15/21] drm/panel: jadard-jd9365da-h3: support Waveshare WXGA DSI panels
From: Neil Armstrong @ 2026-04-14 12:58 UTC (permalink / raw)
To: Dmitry Baryshkov, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Jie Gan
Cc: dri-devel, devicetree, linux-kernel, linux-gpio, Riccardo Mereu
In-Reply-To: <20260413-waveshare-dsi-touch-v3-15-3aeb53022c32@oss.qualcomm.com>
On 4/13/26 16:05, Dmitry Baryshkov wrote:
> Add configuration for several Waveshare 8.0" and 10.1" WXGA DSI panels
> using JD9365 controller
>
> Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 568 +++++++++++++++++++++++
> 1 file changed, 568 insertions(+)
>
> diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> index 61d67efed379..7744c66514c9 100644
> --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> @@ -2067,6 +2067,566 @@ static const struct jadard_panel_desc waveshare_4_0_inch_c_desc = {
> MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> };
>
> +static int waveshare_8_0_a_init(struct jadard *jadard)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + jadard_enable_standard_cmds(&dsi_ctx);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
> + if (jadard->dsi->lanes == 4)
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x7e);
> + else
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x4e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x65);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xb7);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xb7);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x70);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x28);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0xa9);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x19);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x78);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x63);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x54);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x38);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x28);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x62);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x23);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x78);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x63);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x54);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x38);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x28);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x62);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x23);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x10);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x35);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x35);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x0c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x56);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x7b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xf8);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xd5);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x12);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x7b);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x60);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x59);
> + if (jadard->dsi->lanes != 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f);
> + }
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> + msleep(120);
> + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> + msleep(60);
> +
> + return 0;
> +}
> +
> +static const struct drm_display_mode waveshare_8_0_a_mode = {
> + .clock = (800 + 40 + 20 + 20) * (1280 + 30 + 12 + 4) * 60 / 1000,
> +
> + .hdisplay = 800,
> + .hsync_start = 800 + 40,
> + .hsync_end = 800 + 40 + 20,
> + .htotal = 800 + 40 + 20 + 20,
> +
> + .vdisplay = 1280,
> + .vsync_start = 1280 + 30,
> + .vsync_end = 1280 + 30 + 12,
> + .vtotal = 1280 + 30 + 12 + 4,
> +
> + .width_mm = 107,
> + .height_mm = 172,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +};
> +
> +static const struct jadard_panel_desc waveshare_8_0_inch_a_desc = {
> + .mode_4ln = &waveshare_8_0_a_mode,
> + .mode_2ln = &waveshare_8_0_a_mode,
> + .format = MIPI_DSI_FMT_RGB888,
> + .init = waveshare_8_0_a_init,
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> +};
> +
> +static const struct drm_display_mode waveshare_10_1_a_mode = {
> + .clock = (800 + 40 + 20 + 20) * (1280 + 20 + 20 + 4) * 60 / 1000,
> +
> + .hdisplay = 800,
> + .hsync_start = 800 + 40,
> + .hsync_end = 800 + 40 + 20,
> + .htotal = 800 + 40 + 20 + 20,
> +
> + .vdisplay = 1280,
> + .vsync_start = 1280 + 20,
> + .vsync_end = 1280 + 20 + 20,
> + .vtotal = 1280 + 20 + 20 + 4,
> +
> + .width_mm = 135,
> + .height_mm = 216,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +};
> +
> +static int waveshare_10_1_a_init(struct jadard *jadard)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + jadard_enable_standard_cmds(&dsi_ctx);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
> + if (jadard->dsi->lanes == 4)
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x3b);
> + else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x38);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x38);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xaf);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xaf);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x81);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x14);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x23);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0d);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x28);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x69);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x6b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x5c);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x6a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x5b);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x4f);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x3f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x42);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x2b);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x2a);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x43);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x63);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x62);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x52);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x5a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x4f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x4e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x20);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x0f);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x59);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x4c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x3a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x26);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x6b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x5c);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x6a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x5b);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x4f);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x3f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x42);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x2b);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x2a);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x43);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x63);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x62);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x52);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x5a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x4f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x4e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x20);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x0f);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x59);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x4c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x3a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x26);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x00);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x37);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x42);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x42);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x77);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x49);
> + if (jadard->dsi->lanes == 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x37);
> + } else {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x77);
> + }
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x48);
> + if (jadard->dsi->lanes == 4)
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x1f);
> + else
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x30);
> + if (jadard->dsi->lanes == 4)
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x16);
> + else
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x34);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
> + if (jadard->dsi->lanes == 4)
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x1d);
> + else
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xdd);
> + if (jadard->dsi->lanes == 4)
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x3f);
> + else
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x15);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x14);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x82);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48);
> + if (jadard->dsi->lanes != 4) {
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f);
> + }
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe7, 0x0c);
> + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> + msleep(120);
> + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> + msleep(60);
> +
> + return dsi_ctx.accum_err;
> +}
> +
> +static const struct jadard_panel_desc waveshare_10_1_inch_a_desc = {
> + .mode_4ln = &waveshare_10_1_a_mode,
> + .mode_2ln = &waveshare_10_1_a_mode,
> + .format = MIPI_DSI_FMT_RGB888,
> + .init = waveshare_10_1_a_init,
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> +};
> +
> static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
> {
> struct device *dev = &dsi->dev;
> @@ -2198,6 +2758,14 @@ static const struct of_device_id jadard_of_match[] = {
> .compatible = "waveshare,4.0-dsi-touch-c",
> .data = &waveshare_4_0_inch_c_desc
> },
> + {
> + .compatible = "waveshare,8.0-dsi-touch-a",
> + .data = &waveshare_8_0_inch_a_desc
> + },
> + {
> + .compatible = "waveshare,10.1-dsi-touch-a",
> + .data = &waveshare_10_1_inch_a_desc
> + },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, jadard_of_match);
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH v3 14/21] drm/panel: jadard-jd9365da-h3: support Waveshare round DSI panels
From: Neil Armstrong @ 2026-04-14 12:58 UTC (permalink / raw)
To: Dmitry Baryshkov, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Jie Gan
Cc: dri-devel, devicetree, linux-kernel, linux-gpio, Riccardo Mereu
In-Reply-To: <20260413-waveshare-dsi-touch-v3-14-3aeb53022c32@oss.qualcomm.com>
On 4/13/26 16:05, Dmitry Baryshkov wrote:
> Add configuration for Waveshare 3.4" and 4.0" round DSI panels using
> JD9365 controller.
>
> Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 476 +++++++++++++++++++++++
> 1 file changed, 476 insertions(+)
>
> diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> index bc079b97cfb3..61d67efed379 100644
> --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
> @@ -1599,6 +1599,474 @@ static const struct jadard_panel_desc taiguan_xti05101_01a_desc = {
> .enter_sleep_to_reset_down_delay_ms = 100,
> };
>
> +static int waveshare_3_4_c_init(struct jadard *jadard)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + jadard_enable_standard_cmds(&dsi_ctx);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x64);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0xc7);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x18);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x14);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x1b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x19);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x56);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x25);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x32);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x53);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x4c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x31);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x20);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x0f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x56);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x25);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x32);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x53);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x4c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x31);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x20);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x0f);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x42);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0xa6);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xd9);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> +
> + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> + msleep(120);
> + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> + msleep(5);
> + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
> +
> + return dsi_ctx.accum_err;
> +}
> +
> +static const struct jadard_panel_desc waveshare_3_4_inch_c_desc = {
> + .mode_2ln = &(const struct drm_display_mode) {
> + .clock = (800 + 40 + 20 + 20) * (800 + 24 + 4 + 12) * 60 / 1000,
> +
> + .hdisplay = 800,
> + .hsync_start = 800 + 40,
> + .hsync_end = 800 + 40 + 20,
> + .htotal = 800 + 40 + 20 + 20,
> +
> + .vdisplay = 800,
> + .vsync_start = 800 + 24,
> + .vsync_end = 800 + 24 + 4,
> + .vtotal = 800 + 24 + 4 + 12,
> +
> + .width_mm = 88,
> + .height_mm = 88,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> + },
> + .lanes = 2,
> + .format = MIPI_DSI_FMT_RGB888,
> + .init = waveshare_3_4_c_init,
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> +};
> +
> +static int waveshare_4_0_c_init(struct jadard *jadard)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> + jadard_enable_standard_cmds(&dsi_ctx);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd0);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x64);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0xc7);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x18);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x14);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x1b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x19);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x56);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x25);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x32);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x53);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x4c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x31);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x20);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x0f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x56);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x37);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x25);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x32);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x53);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x4c);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x3d);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x31);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x20);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x0f);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x48);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x44);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x46);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x42);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x5e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x50);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x49);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x45);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x47);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x57);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x41);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x07);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x0b);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x09);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x06);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x0a);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x1f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x17);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0xa6);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x7f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xd9);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43);
> +
> + jd9365da_switch_page(&dsi_ctx, 0x00);
> +
> + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> + msleep(120);
> + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
> + msleep(5);
> + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
> +
> + return dsi_ctx.accum_err;
> +}
> +
> +static const struct jadard_panel_desc waveshare_4_0_inch_c_desc = {
> + .mode_2ln = &(const struct drm_display_mode) {
> + .clock = (720 + 40 + 20 + 20) * (720 + 24 + 4 + 12) * 60 / 1000,
> +
> + .hdisplay = 720,
> + .hsync_start = 720 + 40,
> + .hsync_end = 720 + 40 + 20,
> + .htotal = 720 + 40 + 20 + 20,
> +
> + .vdisplay = 720,
> + .vsync_start = 720 + 24,
> + .vsync_end = 720 + 24 + 4,
> + .vtotal = 720 + 24 + 4 + 12,
> +
> + .width_mm = 88,
> + .height_mm = 88,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> + },
> + .lanes = 2,
> + .format = MIPI_DSI_FMT_RGB888,
> + .init = waveshare_4_0_c_init,
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> +};
> +
> static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
> {
> struct device *dev = &dsi->dev;
> @@ -1722,6 +2190,14 @@ static const struct of_device_id jadard_of_match[] = {
> .compatible = "taiguanck,xti05101-01a",
> .data = &taiguan_xti05101_01a_desc
> },
> + {
> + .compatible = "waveshare,3.4-dsi-touch-c",
> + .data = &waveshare_3_4_inch_c_desc
> + },
> + {
> + .compatible = "waveshare,4.0-dsi-touch-c",
> + .data = &waveshare_4_0_inch_c_desc
> + },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, jadard_of_match);
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH v3 07/21] drm/panel: himax-hx83102: support Waveshare 12.3" DSI panel
From: Neil Armstrong @ 2026-04-14 12:57 UTC (permalink / raw)
To: Dmitry Baryshkov, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Jie Gan
Cc: dri-devel, devicetree, linux-kernel, linux-gpio
In-Reply-To: <20260413-waveshare-dsi-touch-v3-7-3aeb53022c32@oss.qualcomm.com>
On 4/13/26 16:05, Dmitry Baryshkov wrote:
> Add support for the Waveshare 12.3" DSI TOUCH-A panel. According to the
> vendor driver, it uses different mode_flags, so let the panel
> descriptions override driver-wide defaults.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
> drivers/gpu/drm/panel/panel-himax-hx83102.c | 144 +++++++++++++++++++++++++++-
> 1 file changed, 142 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c
> index 8b2a68ee851e..eab67893da86 100644
> --- a/drivers/gpu/drm/panel/panel-himax-hx83102.c
> +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
> @@ -29,11 +29,14 @@
> #define HX83102_UNKNOWN_B8 0xb8
> #define HX83102_SETEXTC 0xb9
> #define HX83102_SETMIPI 0xba
> +#define HX83102_UNKNOWN_BB 0xbb
> #define HX83102_SETVDC 0xbc
> #define HX83102_SETBANK 0xbd
> #define HX83102_UNKNOWN_BE 0xbe
> #define HX83102_SETPTBA 0xbf
> #define HX83102_SETSTBA 0xc0
> +#define HX83102_UNKNOWN_C2 0xc2
> +#define HX83102_UNKNOWN_C6 0xc6
> #define HX83102_SETTCON 0xc7
> #define HX83102_SETRAMDMY 0xc8
> #define HX83102_SETPWM 0xc9
> @@ -78,6 +81,7 @@ struct hx83102_panel_desc {
> } size;
>
> bool has_backlight;
> + unsigned long mode_flags;
>
> int (*init)(struct hx83102 *ctx);
> };
> @@ -765,6 +769,111 @@ static int holitech_htf065h045_init(struct hx83102 *ctx)
> return dsi_ctx.accum_err;
> }
>
> +/* This is HX83102-E, assuming commands are the same as the normal HX83102 */
> +static int waveshare_12_3_a_init(struct hx83102 *ctx)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETEXTC, 0x83, 0x10, 0x2e);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BB, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x67, 0x2c, 0xff, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x11, 0x96, 0x89);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0x04, 0x03, 0x04);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER,
> + 0x10, 0xfa, 0xaf, 0xaf, 0x33, 0x33, 0xb1, 0x4d, 0x2f, 0x36,
> + 0x36, 0x36, 0x36, 0x22, 0x21, 0x15, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP,
> + 0x00, 0xd0, 0x27, 0x80, 0x00, 0x14, 0x40, 0x2c, 0x32, 0x02,
> + 0x00, 0x00, 0x15, 0x20, 0xd7, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC,
> + 0x98, 0xa0, 0x01, 0x01, 0x98, 0xa0, 0x68, 0x50, 0x01, 0xc7,
> + 0x01, 0x58, 0x00, 0xff, 0x00, 0xff);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_B6, 0x4d, 0x4d, 0xe3);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x85, 0x80);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x33, 0x33);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0,
> + 0x00, 0x00, 0x00, 0x00, 0x64, 0x04, 0x00, 0x08, 0x08, 0x27,
> + 0x27, 0x22, 0x2f, 0x15, 0x15, 0x04, 0x04, 0x32, 0x10, 0x13,
> + 0x00, 0x13, 0x32, 0x10, 0x1f, 0x00,
> + 0x02, 0x32, 0x17, 0xfd, 0x00, 0x10, 0x00, 0x00, 0x20,
> + 0x30, 0x01, 0x55, 0x21, 0x38, 0x01, 0x55, 0x0f);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA,
> + 0x00, 0x0c, 0x1a, 0x23, 0x2b, 0x4f, 0x64, 0x69, 0x6c, 0x64,
> + 0x77, 0x77, 0x76, 0x80, 0x79, 0x7e, 0x85, 0x9a, 0x97, 0x4d,
> + 0x56, 0x64, 0x70, 0x00, 0x0c, 0x1a, 0x23, 0x2b, 0x4f, 0x64,
> + 0x69, 0x6c, 0x64, 0x77, 0x77, 0x76, 0x80, 0x79, 0x7e, 0x85,
> + 0x9a, 0x97, 0x4d, 0x56, 0x64, 0x76);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x9b, 0x01, 0x31);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK,
> + 0x80, 0x36, 0x12, 0x16, 0xc0, 0x28, 0x40, 0x84, 0x22);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0,
> + 0x01, 0x00, 0xfc, 0x00, 0x00, 0x11, 0x10, 0x00, 0x0e, 0x00,
> + 0x01);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x4e, 0x00, 0x33, 0x11, 0x33, 0x88);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2, 0x00, 0x02);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA,
> + 0x23, 0x23, 0x22, 0x11, 0xa2, 0x17, 0x00, 0x80, 0x00, 0x00,
> + 0x08, 0x00, 0x63, 0x63);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_C6, 0xf9);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x30);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY,
> + 0x00, 0x04, 0x04, 0x00, 0x00, 0x82, 0x13, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x07, 0x04, 0x05);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1,
> + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x21, 0x20,
> + 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x1a, 0x1a,
> + 0x1a, 0x1a, 0x9a, 0x9a, 0x9a, 0x9a, 0x18, 0x18, 0x18, 0x18,
> + 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
> + 0x18, 0x18, 0x18, 0x18);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2,
> + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x21, 0x20, 0x21,
> + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x1a, 0x1a,
> + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x18, 0x18, 0x18, 0x18,
> + 0x20, 0x21, 0x20, 0x21, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
> + 0x98, 0x98, 0x98, 0x98);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1,
> + 0x00, 0x34, 0x01, 0x88, 0x0e, 0xbe, 0x0f);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_C2, 0x43, 0xff, 0x10);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x80);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3,
> + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
> + 0xaa, 0xaa, 0xaa, 0x80, 0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0x80,
> + 0x2a, 0xaa, 0xaa, 0xaa);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3,
> + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
> + 0xaa, 0xaa);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3,
> + 0xff, 0xff, 0xff, 0xff,
> + 0xff, 0xf0, 0xff, 0xff,
> + 0xff, 0xff, 0xff, 0xf0);
> +
> + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
> +
> + return dsi_ctx.accum_err;
> +};
> +
> static const struct drm_display_mode starry_mode = {
> .clock = 162680,
> .hdisplay = 1200,
> @@ -920,6 +1029,30 @@ static const struct hx83102_panel_desc holitech_htf065h045_desc = {
> .init = holitech_htf065h045_init,
> };
>
> +static const struct drm_display_mode waveshare_12_3_a_mode = {
> + .clock = 95000,
> + .hdisplay = 720,
> + .hsync_start = 720 + 10,
> + .hsync_end = 720 + 10 + 10,
> + .htotal = 720 + 10 + 10 + 12,
> + .vdisplay = 1920,
> + .vsync_start = 1920 + 64,
> + .vsync_end = 1920 + 64 + 18,
> + .vtotal = 1920 + 64 + 18 + 4,
> + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +};
> +
> +static const struct hx83102_panel_desc waveshare_12_3_inch_a_desc = {
> + .modes = &waveshare_12_3_a_mode,
> + .size = {
> + .width_mm = 109,
> + .height_mm = 292,
> + },
> + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
> + .init = waveshare_12_3_a_init,
> +};
> +
> static int hx83102_enable(struct drm_panel *panel)
> {
> msleep(130);
> @@ -1168,8 +1301,12 @@ static int hx83102_probe(struct mipi_dsi_device *dsi)
> desc = of_device_get_match_data(&dsi->dev);
> dsi->lanes = 4;
> dsi->format = MIPI_DSI_FMT_RGB888;
> - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
> - MIPI_DSI_MODE_LPM;
> + if (desc->mode_flags)
> + dsi->mode_flags = desc->mode_flags;
> + else
> + dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
> + MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
> + MIPI_DSI_MODE_LPM;
> ctx->desc = desc;
> ctx->dsi = dsi;
> ret = hx83102_panel_add(ctx);
> @@ -1220,6 +1357,9 @@ static const struct of_device_id hx83102_of_match[] = {
> { .compatible = "holitech,htf065h045",
> .data = &holitech_htf065h045_desc
> },
> + { .compatible = "waveshare,12.3-dsi-touch-a",
> + .data = &waveshare_12_3_inch_a_desc
> + },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, hx83102_of_match);
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: socfpga: Add the Agilex7 series SoC's
From: Krzysztof Kozlowski @ 2026-04-14 12:55 UTC (permalink / raw)
To: Dinh Nguyen; +Cc: robh, krzk+dt, conor+dt, devicetree
In-Reply-To: <a2945037-d8c9-45b5-b161-ac55ac9b0835@kernel.org>
On 14/04/2026 14:53, Dinh Nguyen wrote:
>
>
> On 4/14/26 02:17, Krzysztof Kozlowski wrote:
>> On Mon, Apr 13, 2026 at 09:45:52AM -0500, Dinh Nguyen wrote:
>>> The Agilex7 is a series of devices from Altera that are derived from
>>> the Agilex family.
>>>
>>> The Agilex7F device supports PCIE 4.0 and DDR4. The Agilex7I device supports
>>> PCIE 5.0 and DDR4, while the Agilex7M device supports DDR4, DDR5, LPDDR5
>>> and PCIE 5.0.
>>>
>>> All other peripherals from these devices are the same as the Agilex
>>> device.
>>>
>>> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
>>> ---
>>> Documentation/devicetree/bindings/arm/altera.yaml | 10 ++++++++++
>>> 1 file changed, 10 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/altera.yaml b/Documentation/devicetree/bindings/arm/altera.yaml
>>> index 206686f3eebc..5ee09f8d4698 100644
>>> --- a/Documentation/devicetree/bindings/arm/altera.yaml
>>> +++ b/Documentation/devicetree/bindings/arm/altera.yaml
>>> @@ -115,6 +115,16 @@ properties:
>>> - intel,socfpga-agilex5-socdk-nand
>>> - const: intel,socfpga-agilex5
>>>
>>> + - description: Agilex7 series F, I and M boards
>>> + items:
>>> + - enum:
>>> + - intel,socfpga-agilex7m-socdk
>>> + - enum:
>>> + - intel,socfpga-agilex7f
>>> + - intel,socfpga-agilex7i
>>> + - intel,socfpga-agilex7m
>>> + - const: intel,socfpga-agilex
>>
>> And separate question - why previous soc "agilex" is used as fallback?
>> Even more confusing.
>>
>
> You're right. Sorry for the confusion. The Agilex7M, I, F devices are
> basically "agilex" devices with some few additions (PCIE, DDR5). Maybe I
> should place the Agilex7M/I/F devices into the "agilex" boards area?
Compatibles should be specific and not based on families, thus what is
"intel,socfpga-agilex"? SoC, right?
Then "intel,socfpga-agilex7f" is a new SoC, no?
Best regards,
Krzysztof
^ permalink raw reply
* RE: [PATCH v7 6/6] docs: iio: adc: ad4691: add driver documentation
From: Sabau, Radu bogdan @ 2026-04-14 12:54 UTC (permalink / raw)
To: David Lechner, Lars-Peter Clausen, Hennerich, Michael,
Jonathan Cameron, Sa, Nuno, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Uwe Kleine-König,
Liam Girdwood, Mark Brown, Linus Walleij, Bartosz Golaszewski,
Philipp Zabel, Jonathan Corbet, Shuah Khan
Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org
In-Reply-To: <9c36ee85-12da-41e8-b9ab-e32b7ec29e75@baylibre.com>
> -----Original Message-----
> From: David Lechner <dlechner@baylibre.com>
> Sent: Saturday, April 11, 2026 12:39 AM
...
> > +Buffer data format
> > +==================
> > +
> > +The IIO buffer data format (``in_voltageN_type``) is the same across all
> > +paths: 16-bit unsigned big-endian samples with no shift.
> > +
> > ++-------------------------+-------------+----------+-------+
> > +| Path | storagebits | realbits | shift |
> > ++=========================+=============+==========+=======+
> > +| Triggered buffer | 16 | 16 | 0 |
> > ++-------------------------+-------------+----------+-------+
> > +| CNV Burst offload (DMA) | 16 | 16 | 0 |
> > ++-------------------------+-------------+----------+-------+
> > +| Manual offload (DMA) | 16 | 16 | 0 |
> > ++-------------------------+-------------+----------+-------+
>
> Not sure this table is helpful since all values are the same everywhere.
>
> Also, doesn't SPI offload have storagebits == 32?
I tried using 16 storage bits for offload too, and so use the same channels
macro. For Manual its received in the next transfer and for CNV only the
receive transfers are rx streamed, and so 16 storage bits suffice for both.
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: socfpga: Add the Agilex7 series SoC's
From: Dinh Nguyen @ 2026-04-14 12:53 UTC (permalink / raw)
To: Krzysztof Kozlowski; +Cc: robh, krzk+dt, conor+dt, devicetree
In-Reply-To: <20260414-certain-puffin-from-avalon-29ceeb@quoll>
On 4/14/26 02:17, Krzysztof Kozlowski wrote:
> On Mon, Apr 13, 2026 at 09:45:52AM -0500, Dinh Nguyen wrote:
>> The Agilex7 is a series of devices from Altera that are derived from
>> the Agilex family.
>>
>> The Agilex7F device supports PCIE 4.0 and DDR4. The Agilex7I device supports
>> PCIE 5.0 and DDR4, while the Agilex7M device supports DDR4, DDR5, LPDDR5
>> and PCIE 5.0.
>>
>> All other peripherals from these devices are the same as the Agilex
>> device.
>>
>> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
>> ---
>> Documentation/devicetree/bindings/arm/altera.yaml | 10 ++++++++++
>> 1 file changed, 10 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/altera.yaml b/Documentation/devicetree/bindings/arm/altera.yaml
>> index 206686f3eebc..5ee09f8d4698 100644
>> --- a/Documentation/devicetree/bindings/arm/altera.yaml
>> +++ b/Documentation/devicetree/bindings/arm/altera.yaml
>> @@ -115,6 +115,16 @@ properties:
>> - intel,socfpga-agilex5-socdk-nand
>> - const: intel,socfpga-agilex5
>>
>> + - description: Agilex7 series F, I and M boards
>> + items:
>> + - enum:
>> + - intel,socfpga-agilex7m-socdk
>> + - enum:
>> + - intel,socfpga-agilex7f
>> + - intel,socfpga-agilex7i
>> + - intel,socfpga-agilex7m
>> + - const: intel,socfpga-agilex
>
> And separate question - why previous soc "agilex" is used as fallback?
> Even more confusing.
>
You're right. Sorry for the confusion. The Agilex7M, I, F devices are
basically "agilex" devices with some few additions (PCIE, DDR5). Maybe I
should place the Agilex7M/I/F devices into the "agilex" boards area?
Thanks,
Dinh
^ permalink raw reply
* Re: [PATCH v2 1/8] dt-bindings: thermal: amlogic: Add support for T7
From: Ronald Claveau @ 2026-04-14 12:33 UTC (permalink / raw)
To: Conor Dooley
Cc: Guillaume La Roque, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
linux-pm, linux-amlogic, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <20260413-impose-cartel-bd7d18f91a24@spud>
On 4/13/26 5:42 PM, Conor Dooley wrote:
> On Mon, Apr 13, 2026 at 12:52:42PM +0200, Ronald Claveau wrote:
>> Add the amlogic,t7-thermal compatible for the Amlogic T7 thermal sensor.
>>
>> Unlike existing variants which use a phandle to the ao-secure syscon,
>> the T7 relies on a secure monitor interface described by a phandle and
>> a sensor index argument.
>>
>> The T7 integrates multiple thermal sensors, all accessed through the
>> same SMC call. The sensor index argument is required to identify which
>> sensor's calibration data the secure monitor should return, as a single
>> SM_THERMAL_CALIB_READ command serves all of them.
>>
>> Introduce the amlogic,secure-monitor property as a phandle-array and
>> make amlogic,ao-secure or amlogic,secure-monitor conditionally required
>> depending on the compatible.
>>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
>> ---
>> .../bindings/thermal/amlogic,thermal.yaml | 42 ++++++++++++++++++++--
>> 1 file changed, 40 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml b/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
>> index 70b273271754b..1c096116b2dda 100644
>> --- a/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
>> +++ b/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
>> @@ -21,7 +21,9 @@ properties:
>> - amlogic,g12a-cpu-thermal
>> - amlogic,g12a-ddr-thermal
>> - const: amlogic,g12a-thermal
>> - - const: amlogic,a1-cpu-thermal
>> + - enum:
>> + - amlogic,a1-cpu-thermal
>> + - amlogic,t7-thermal
>>
>> reg:
>> maxItems: 1
>> @@ -42,12 +44,39 @@ properties:
>> '#thermal-sensor-cells':
>> const: 0
>>
>> + amlogic,secure-monitor:
>> + description: phandle to the secure monitor
>> + $ref: /schemas/types.yaml#/definitions/phandle-array
>> + items:
>> + - items:
>> + - description: phandle to the secure monitor
>> + - description: sensor index to get specific calibration data
>> +
>> required:
>> - compatible
>> - reg
>> - interrupts
>> - clocks
>> - - amlogic,ao-secure
>> +
>> +allOf:
>> + - if:
>> + properties:
>> + compatible:
>> + contains:
>> + enum:
>> + - amlogic,a1-cpu-thermal
>> + - amlogic,g12a-thermal
>> + then:
>> + required:
>> + - amlogic,ao-secure
>> + - if:
>> + properties:
>> + compatible:
>> + contains:
>> + const: amlogic,t7-thermal
>
> This can just be replaced by a else I think.
>
Thank you for your feedback, I will replace this `if` condition by an
`else`.
>> + then:
>> + required:
>> + - amlogic,secure-monitor
>>
>> unevaluatedProperties: false
>>
>> @@ -62,4 +91,13 @@ examples:
>> #thermal-sensor-cells = <0>;
>> amlogic,ao-secure = <&sec_AO>;
>> };
>> + - |
>> + a73_tsensor: temperature-sensor@20000 {
>
> Can drop the label here, it has no users.
>
Ok, I will remove this label.
> Otherwise, seems fine.
>
> Cheers,
> Conor.
>
> pw-bot: changes-requested
>
>> + compatible = "amlogic,t7-thermal";
>> + reg = <0x0 0x20000 0x0 0x50>;
>> + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&clkc_periphs CLKID_TS>;
>> + #thermal-sensor-cells = <0>;
>> + amlogic,secure-monitor = <&sm 1>;
>> + };
>> ...
>>
>> --
>> 2.49.0
>>
--
Best regards,
Ronald
^ permalink raw reply
* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Andy Shevchenko @ 2026-04-14 12:03 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Manivannan Sadhasivam, Manivannan Sadhasivam, Rob Herring,
Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor, Nicolas Schier,
Hans de Goede, Ilpo Järvinen, Mark Pearson, Derek J. Clark,
Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
Luiz Augusto von Dentz, Bartosz Golaszewski, Bartosz Golaszewski,
linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
Bartosz Golaszewski
In-Reply-To: <CAGXv+5EGe59nJctLweEdZjb3MNmMvjuCHngGSfptzN985OiLdg@mail.gmail.com>
On Tue, Apr 14, 2026 at 06:29:02PM +0800, Chen-Yu Tsai wrote:
> On Tue, Apr 14, 2026 at 4:28 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> > On Tue, Apr 14, 2026 at 01:03:19PM +0800, Chen-Yu Tsai wrote:
> > > On Tue, Apr 14, 2026 at 12:08 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > > On Mon, Apr 13, 2026 at 07:33:12PM +0530, Manivannan Sadhasivam wrote:
> > > > > On Mon, Apr 13, 2026 at 03:54:59PM +0800, Chen-Yu Tsai wrote:
> > > > > > On Thu, Mar 26, 2026 at 01:36:28PM +0530, Manivannan Sadhasivam wrote:
...
> > > > > > - Given that this connector actually represents two devices, how do I
> > > > > > say I want the BT part to be a wakeup source, but not the WiFi part?
> > > > > > Does wakeup-source even work at this point?
> > > > >
> > > > > You can't use the DT property since the devices are not described in DT
> > > > > statically. But you can still use the per-device 'wakeup' sysfs knob to enable
> > > > > wakeup.
> > >
> > > I see. I think not being able to specify generic properties for the devices
> > > on the connector is going to be a bit problematic.
> >
> > This is nature of the open-connectors, especially on the busses that are
> > hotpluggable, like PCIe. We never know what is connected there _ahead_.
>
> I believe what you mean by "hotpluggable" is "user replaceable".
From the OS perspective it's the same. From platform perspective
there is a difference, granted.
> > In other words you can't describe in DT something that may not exist.
>
> But this is actually doable with the PCIe slot representation. The
> properties are put in the device node for the slot. If no card is
> actually inserted in the slot, then no device is created, and the
> device node is left as not associated with anything.
But you need to list all devices in the world if you want to support this
somehow. Yes, probably many of them (or majority) will be enumerated as is,
but some may need an assistance via (dynamic) properties or similar mechanisms.
> It's just that for this new M.2 E-key connector, there aren't separate
> nodes for each interface. And the system doesn't associate the device
> node with the device, because it's no longer a child node of the
> controller or hierarchy, but connected over the OF graph.
>
> Moving over to the E-key connector representation seems like one step
> forward and one step backward in descriptive ability. We gain proper
> power sequencing, but lose generic properties.
The "key" is property of the connector. Hence if you have an idea what can be
common for ALL "key":s, that's probably can be abstracted. Note, I'm not
familiar with the connector framework in the Linux kernel, perhaps it's already
that kind of abstraction.
> The latter part is solvable, but we likely need child nodes under the
> connector for the different interfaces. Properties that make sense for
> one type might not make sense for another.
>
> P.S. We could also just add child device nodes under the controller to
> put the generic properties, but that's splitting the description into
> multiple parts. Let's not go there if at all possible.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v1 1/4] arm64: dts: qcom: Enable secondary mi2s
From: Konrad Dybcio @ 2026-04-14 11:58 UTC (permalink / raw)
To: Kumar Anurag, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Srinivas Kandagatla,
Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
Cc: linux-arm-msm, devicetree, linux-kernel, linux-sound
In-Reply-To: <20260413091937.134469-2-kumar.singh@oss.qualcomm.com>
On 4/13/26 11:19 AM, Kumar Anurag wrote:
> Enable secondary mi2s to support HDMI audio.
>
> Signed-off-by: Kumar Anurag <kumar.singh@oss.qualcomm.com>
> ---
[...]
> +&mi2s1_data0 {
> + drive-strength = <8>;
> + bias-disable;
> +};
> +
> +&mi2s1_mclk {
> + drive-strength = <8>;
> + bias-disable;
> + output-high;
> +};
> +
> +&mi2s1_sclk {
> + drive-strength = <8>;
> + bias-disable;
> + output-high;
> +};
> +
> +&mi2s1_ws {
> + drive-strength = <8>;
> + bias-disable;
> + output-high;
For these pins in their "mission mode" function, do we expect these
pincfg settings to ever change (i.e. across boards, will the drive-strength/
bias/output properties differ?)
Konrad
^ 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