* [PATCH v3 3/3] arm64: dts: qcom: shikra-evk: Enable Iris core
From: Vikash Garodia @ 2026-06-18 10:39 UTC (permalink / raw)
To: Bryan O'Donoghue, Dikshita Agarwal, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel,
Vikash Garodia, Dmitry Baryshkov
In-Reply-To: <20260618-shikra_vpu-v3-0-1a32e26a35a1@oss.qualcomm.com>
Enable video en/decoder on the Shikra EVK board.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi
index d0c48bad704c61d17309753ba2a97e89bbfe083f..e2a3131594f0410931122657b12c8a6e70b435f0 100644
--- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi
+++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi
@@ -3,6 +3,12 @@
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
+&iris {
+ firmware-name = "qcom/vpu/ar50lt_p1_gen2_s6.mbn";
+
+ status = "okay";
+};
+
&qupv3_0 {
firmware-name = "qcom/shikra/qupv3fw.elf";
--
2.34.1
^ permalink raw reply related
* [PATCH v3 2/3] arm64: dts: qcom: shikra: Add Iris video codec node
From: Vikash Garodia @ 2026-06-18 10:39 UTC (permalink / raw)
To: Bryan O'Donoghue, Dikshita Agarwal, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel,
Vikash Garodia, Konrad Dybcio, Dmitry Baryshkov
In-Reply-To: <20260618-shikra_vpu-v3-0-1a32e26a35a1@oss.qualcomm.com>
Add the Iris video codec device tree node for the Shikra platform.
Shikra reuses the QCM2290-class video hardware and programming model.
The video node is added to describe the Iris based video decoder
encoder block, allowing the media driver to probe and initialize
the hardware.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra.dtsi | 61 ++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi
index 1ccb0f1419aaa34d32f3c3eaabdb8727a497b501..d8edd14d1f81a49e352f6939d27ea9cf8bb0f019 100644
--- a/arch/arm64/boot/dts/qcom/shikra.dtsi
+++ b/arch/arm64/boot/dts/qcom/shikra.dtsi
@@ -655,6 +655,67 @@ gpucc: clock-controller@5990000 {
#power-domain-cells = <1>;
};
+ iris: video-codec@5a00000 {
+ compatible = "qcom,shikra-venus", "qcom,qcm2290-venus";
+ reg = <0x0 0x5a00000 0x0 0x200000>;
+ interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH 0>;
+
+ power-domains = <&gcc GCC_VENUS_GDSC>,
+ <&gcc GCC_VCODEC0_GDSC>,
+ <&rpmpd QCM2290_VDDCX>;
+ power-domain-names = "venus",
+ "vcodec0",
+ "cx";
+ operating-points-v2 = <&venus_opp_table>;
+
+ clocks = <&gcc GCC_VIDEO_VENUS_CTL_CLK>,
+ <&gcc GCC_VIDEO_AHB_CLK>,
+ <&gcc GCC_VENUS_CTL_AXI_CLK>,
+ <&gcc GCC_VIDEO_THROTTLE_CORE_CLK>,
+ <&gcc GCC_VIDEO_VCODEC0_SYS_CLK>,
+ <&gcc GCC_VCODEC0_AXI_CLK>;
+ clock-names = "core",
+ "iface",
+ "bus",
+ "throttle",
+ "vcodec0_core",
+ "vcodec0_bus";
+
+ memory-region = <&video_mem>;
+ interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ALWAYS_TAG
+ &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
+ <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG
+ &config_noc SLAVE_VENUS_CFG RPM_ACTIVE_TAG>;
+ interconnect-names = "video-mem",
+ "cpu-cfg";
+
+ iommus = <&apps_smmu 0x780 0x0020>;
+
+ venus_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-133333333 {
+ opp-hz = /bits/ 64 <133333333>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-240000000 {
+ opp-hz = /bits/ 64 <240000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+ };
+
dispcc: clock-controller@5f00000 {
compatible = "qcom,shikra-dispcc", "qcom,qcm2290-dispcc";
reg = <0x0 0x05f00000 0x0 0x20000>;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v4 0/5] arm64: dts: qcom: sm8[56]50: add PMIC5 Gen3 ADC channels
From: Konrad Dybcio @ 2026-06-18 10:40 UTC (permalink / raw)
To: Neil Armstrong, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Dmitry Baryshkov
Cc: linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260617-topic-sm8x50-adc5-gen3-v4-0-4af9251731f1@linaro.org>
On 6/17/26 2:53 PM, Neil Armstrong wrote:
> Now the bindings and driver was merged for the SPMI PMIC5 Gen3 ADC
> found on the PMK8550 which allow reading ADC data on the PMK8550
> and other PMICs on the system.
>
> Add the SPMI ADC channels on the PMK8550 SPMI5 ADC3 for the
> other PMICS on the system.
>
> Depends on:
> - https://lore.kernel.org/all/20260614-adc5_gen3_dt-v2-1-32ec576c5865@oss.qualcomm.com/
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> Changes in v4:
> - Rebase on https://lore.kernel.org/all/20260614-adc5_gen3_dt-v2-0-32ec576c5865@oss.qualcomm.com/
> - Change all defines
> - Reorder nodes
> - Link to v3: https://patch.msgid.link/20260615-topic-sm8x50-adc5-gen3-v3-0-216a2b5ccb85@linaro.org
wrt
https://lore.kernel.org/all/qgjntewdw2qesvkeabvx46zxcwrikvpkgthk7e2cqw7biuhmqt@2khmbjh2dt26/
you added a comment:
/* use the default settle time */
which the bindings tell me is 15. +Dmitry did you grab that value
from the downstream kernel or something?
Konrad
^ permalink raw reply
* [PATCH v3 1/3] dt-bindings: media: qcom,qcm2290-venus: document shikra Iris compatible
From: Vikash Garodia @ 2026-06-18 10:39 UTC (permalink / raw)
To: Bryan O'Donoghue, Dikshita Agarwal, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel,
Vikash Garodia
In-Reply-To: <20260618-shikra_vpu-v3-0-1a32e26a35a1@oss.qualcomm.com>
Document the iris video accelerator used on shikra platforms by adding
the qcom,shikra-iris compatible.
Although QCM2290 and shikra share the same video hardware and overall
integration, their SMMU programming differs. QCM2290 exposes separate
stream IDs for the video hardware and the Xtensa path, requiring two
explicit IOMMU entries, whereas shikra uses a masked SMR to collapse
equivalent stream IDs into a single mapping. Due to QCM2290’s SID layout
and Xtensa isolation requirements, such SMR masking is not applicable on
QCM2290 platforms.
Since shikra uses the same video hardware as QCM2290 and shares the same
programming model and capabilities, it is added as a fallback compatible
to qcom,qcm2290-venus, with conditional handling to allow either one or
two IOMMU entries.
Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
---
.../bindings/media/qcom,qcm2290-venus.yaml | 26 ++++++++++++++++------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
index 5977e7d0a71b4fb5681f1c2094439c251366f01f..b27899ebf164229ceff1ca5cda50ee30d875e953 100644
--- a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
+++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
@@ -13,14 +13,13 @@ description:
The Venus AR50_LITE IP is a video encode and decode accelerator present
on Qualcomm platforms.
-allOf:
- - $ref: qcom,venus-common.yaml#
-
properties:
compatible:
oneOf:
- items:
- - const: qcom,sm6115-venus
+ - enum:
+ - qcom,shikra-venus
+ - qcom,sm6115-venus
- const: qcom,qcm2290-venus
- const: qcom,qcm2290-venus
@@ -45,9 +44,6 @@ properties:
- const: vcodec0_core
- const: vcodec0_bus
- iommus:
- maxItems: 2
-
interconnects:
maxItems: 2
@@ -65,6 +61,22 @@ required:
- power-domain-names
- iommus
+allOf:
+ - $ref: qcom,venus-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: qcom,shikra-venus
+ then:
+ properties:
+ iommus:
+ maxItems: 1
+ else:
+ properties:
+ iommus:
+ maxItems: 2
+
unevaluatedProperties: false
examples:
--
2.34.1
^ permalink raw reply related
* [PATCH v3 0/3] media: qcom: Add support for the iris codec on shikra
From: Vikash Garodia @ 2026-06-18 10:39 UTC (permalink / raw)
To: Bryan O'Donoghue, Dikshita Agarwal, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel,
Vikash Garodia, Konrad Dybcio, Dmitry Baryshkov
The shikra platform uses AR50_LITE IP core as video en/decoder codec
block (the same as agatti platform). Extend iris driver to support this
platform. This has been tested on the Qualcomm shikra boards, shikra-cqm-evk,
shikra-cqs-evk and shikra-iqs-evk boards with HFI Gen2 firmware.
v4l2-compliance results:
v4l2-compliance -d /dev/video1 -s
v4l2-compliance 1.31.0-5396, 64 bits, 64-bit time_t
v4l2-compliance SHA: 3f22c6fcee75 2025-09-18 09:49:23
Compliance test for iris_driver device /dev/video1:
Driver Info:
Driver name : iris_driver
Card type : Iris Encoder
Bus info : platform:5a00000.video-codec
Driver version : 7.0.0
Capabilities : 0x84204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Detected Stateful Encoder
Required ioctls:
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video1 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 41 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test CREATE_BUFS maximum buffers: OK
test VIDIOC_REMOVE_BUFS: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
test blocking wait: OK
Test input 0:
Streaming ioctls:
test read/write: OK (Not Supported)
Video Capture Multiplanar: Captured 61 buffers
test MMAP (select, REQBUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (epoll, REQBUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (select, CREATE_BUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (epoll, CREATE_BUFS): OK
test USERPTR (select): OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0,
Warnings: 0
v4l2-compliance -d /dev/video0 -s5
--stream-from=./data/resource/simple_AVC_720p_10fps_90frames.264
v4l2-compliance 1.31.0-5396, 64 bits, 64-bit time_t
v4l2-compliance SHA: 3f22c6fcee75 2025-09-18 09:49:23
Compliance test for iris_driver device /dev/video0:
Driver Info:
Driver name : iris_driver
Card type : Iris Decoder
Bus info : platform:5a00000.video-codec
Driver version : 7.0.0
Capabilities : 0x84204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Detected Stateful Decoder
Required ioctls:
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video0 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 10 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK
test Composing: OK
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test CREATE_BUFS maximum buffers: OK
test VIDIOC_REMOVE_BUFS: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
test blocking wait: OK
Test input 0:
Streaming ioctls:
test read/write: OK (Not Supported)
the input file is smaller than 7077888 bytes
Video Capture Multiplanar: Captured 65 buffers
test MMAP (select, REQBUFS): OK
the input file is smaller than 7077888 bytes
Video Capture Multiplanar: Captured 65 buffers
test MMAP (epoll, REQBUFS): OK
the input file is smaller than 7077888 bytes
Video Capture Multiplanar: Captured 65 buffers
test MMAP (select, CREATE_BUFS): OK
the input file is smaller than 7077888 bytes
Video Capture Multiplanar: Captured 65 buffers
test MMAP (epoll, CREATE_BUFS): OK
test USERPTR (select): OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Total for iris_driver device /dev/video0: 54, Succeeded: 54, Failed: 0,
Warnings: 0
Fluster results for HFI Gen2 firmware:
./fluster.py run -ts JVT-AVC_V1 -d GStreamer-H.264-V4L2-Gst1.0 - 77/135
The failing test case:
- Unsupported profile: H.264 Extended profile is deprecated.
- BA3_SVA_C
- Interlaced content is not supported yet.
- CABREF3_Sand_D
- CAFI1_SVA_C
- CAMA1_Sony_C
- CAMA1_TOSHIBA_B
- CAMA3_Sand_E
- CAMACI3_Sony_C
- CAMANL1_TOSHIBA_B
- CAMANL2_TOSHIBA_B
- CAMANL3_Sand_E
- CAMASL3_Sony_B
- CAMP_MOT_MBAFF_L30
- CAMP_MOT_MBAFF_L31
- CANLMA2_Sony_C
- CANLMA3_Sony_C
- CAPA1_TOSHIBA_B
- CAPAMA3_Sand_F
- CVCANLMA2_Sony_C
- CVFI1_SVA_C
- CVFI1_Sony_D
- CVFI2_SVA_C
- CVFI2_Sony_H
- CVMA1_Sony_D
- CVMA1_TOSHIBA_B
- CVMANL1_TOSHIBA_B
- CVMANL2_TOSHIBA_B
- CVMAPAQP3_Sony_E
- CVMAQP2_Sony_G
- CVMAQP3_Sony_D
- CVMP_MOT_FLD_L30_B
- CVMP_MOT_FRM_L31
- CVNLFI1_Sony_C
- CVNLFI2_Sony_H
- CVPA1_TOSHIBA_B
- FI1_Sony_E
- MR6_BT_B
- MR7_BT_B
- MR8_BT_B
- MR9_BT_B
- Sharp_MP_Field_1_B
- Sharp_MP_Field_2_B
- Sharp_MP_Field_3_B
- Sharp_MP_PAFF_1r2
- Sharp_MP_PAFF_2r
- cabac_mot_fld0_full
- cabac_mot_mbaff0_full
- cabac_mot_picaff0_full
- cama1_vtc_c
- cama2_vtc_b
- cama3_vtc_b
- cavlc_mot_fld0_full_B
- cavlc_mot_mbaff0_full_B
- cavlc_mot_picaff0_full_B
- Unsupported bitstream: num_slice_group_minus1 > 0 (slice groups not
supported by hardware).
- FM1_BT_B
- FM1_FT_E
- FM2_SVA_C
- Unsupported bitstream: SP slice type is not supported by hardware.
- SP1_BT_A
- sp2_bt_b
./fluster.py run -ts JCT-VC-HEVC_V1 -d GStreamer-H.265-V4L2-Gst1.0 -
113/147
The failing test case:
- Unsupported level
- AMP_D_Hisilicon_3
- AMP_E_Hisilicon_3
- AMP_F_Hisilicon_3
- DELTAQP_A_BRCM_4
- IPRED_A_docomo_2
- IPRED_C_Mitsubishi_3
- LS_A_Orange_2
- LS_B_Orange_4
- PPS_A_qualcomm_7
- RAP_B_Bossen_2
- RPS_F_docomo_2
- SAO_G_Canon_3
- SDH_A_Orange_4
- 10bit content - not supported in this generation of video IP
- DBLK_A_MAIN10_VIXS_4
- INITQP_B_Main10_Sony_1
- TSUNEQBD_A_MAIN10_Technicolor_2
- WPP_A_ericsson_MAIN10_2
- WPP_B_ericsson_MAIN10_2
- WPP_C_ericsson_MAIN10_2
- WPP_D_ericsson_MAIN10_2
- WPP_E_ericsson_MAIN10_2
- WPP_F_ericsson_MAIN10_2
- WP_A_MAIN10_Toshiba_3
- WP_MAIN10_B_Toshiba_3
- Unsupported resolution
- AMP_A_Samsung_7
- AMP_B_Samsung_7
- PICSIZE_A_Bossen_1
- PICSIZE_B_Bossen_1
- PICSIZE_C_Bossen_1
- PICSIZE_D_Bossen_1
- TUSIZE_A_Samsung_1
- WPP_D_ericsson_MAIN_2
- CRC mismatch
- RAP_A_docomo_6
- CRC mismatch - bitstream issue - fails with ffmpeg sw decoder as well
- VPSSPSPPS_A_MainConcept_1
./fluster.py run -ts VP9-TEST-VECTORS -d GStreamer-VP9-V4L2-Gst1.0 -j1 - 206/305
The failing test case:
- Unsupported resolution
- vp90-2-02-size-08x08.webm
- vp90-2-02-size-08x10.webm
- vp90-2-02-size-08x16.webm
- vp90-2-02-size-08x18.webm
- vp90-2-02-size-08x32.webm
- vp90-2-02-size-08x34.webm
- vp90-2-02-size-08x64.webm
- vp90-2-02-size-08x66.webm
- vp90-2-02-size-10x08.webm
- vp90-2-02-size-10x10.webm
- vp90-2-02-size-10x16.webm
- vp90-2-02-size-10x18.webm
- vp90-2-02-size-10x32.webm
- vp90-2-02-size-10x34.webm
- vp90-2-02-size-10x64.webm
- vp90-2-02-size-10x66.webm
- vp90-2-02-size-16x08.webm
- vp90-2-02-size-16x10.webm
- vp90-2-02-size-16x16.webm
- vp90-2-02-size-16x18.webm
- vp90-2-02-size-16x32.webm
- vp90-2-02-size-16x34.webm
- vp90-2-02-size-16x64.webm
- vp90-2-02-size-16x66.webm
- vp90-2-02-size-18x08.webm
- vp90-2-02-size-18x10.webm
- vp90-2-02-size-18x16.webm
- vp90-2-02-size-18x18.webm
- vp90-2-02-size-18x32.webm
- vp90-2-02-size-18x34.webm
- vp90-2-02-size-18x64.webm
- vp90-2-02-size-18x66.webm
- vp90-2-02-size-32x08.webm
- vp90-2-02-size-32x10.webm
- vp90-2-02-size-32x16.webm
- vp90-2-02-size-32x18.webm
- vp90-2-02-size-32x32.webm
- vp90-2-02-size-32x34.webm
- vp90-2-02-size-32x64.webm
- vp90-2-02-size-32x66.webm
- vp90-2-02-size-34x08.webm
- vp90-2-02-size-34x10.webm
- vp90-2-02-size-34x16.webm
- vp90-2-02-size-34x18.webm
- vp90-2-02-size-34x32.webm
- vp90-2-02-size-34x34.webm
- vp90-2-02-size-34x64.webm
- vp90-2-02-size-34x66.webm
- vp90-2-02-size-64x08.webm
- vp90-2-02-size-64x10.webm
- vp90-2-02-size-64x16.webm
- vp90-2-02-size-64x18.webm
- vp90-2-02-size-64x32.webm
- vp90-2-02-size-64x34.webm
- vp90-2-02-size-64x64.webm
- vp90-2-02-size-64x66.webm
- vp90-2-02-size-66x08.webm
- vp90-2-02-size-66x10.webm
- vp90-2-02-size-66x16.webm
- vp90-2-02-size-66x18.webm
- vp90-2-02-size-66x32.webm
- vp90-2-02-size-66x34.webm
- vp90-2-02-size-66x64.webm
- vp90-2-02-size-66x66.webm
- vp90-2-08-tile_1x8.webm
- vp90-2-08-tile_1x8_frame_parallel.webm
- vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm
- vp90-2-14-resize-10frames-fp-tiles-1-8.webm
- vp90-2-14-resize-10frames-fp-tiles-2-8.webm
- vp90-2-14-resize-10frames-fp-tiles-4-8.webm
- vp90-2-14-resize-10frames-fp-tiles-8-1.webm
- vp90-2-14-resize-10frames-fp-tiles-8-2.webm
- vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm
- vp90-2-14-resize-10frames-fp-tiles-8-4.webm
- vp90-2-14-resize-fp-tiles-1-16.webm
- vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm
- vp90-2-14-resize-fp-tiles-1-8.webm
- vp90-2-14-resize-fp-tiles-16-1.webm
- vp90-2-14-resize-fp-tiles-16-2.webm
- vp90-2-14-resize-fp-tiles-16-4.webm
- vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm
- vp90-2-14-resize-fp-tiles-16-8.webm
- vp90-2-14-resize-fp-tiles-2-16.webm
- vp90-2-14-resize-fp-tiles-2-8.webm
- vp90-2-14-resize-fp-tiles-4-16.webm
- vp90-2-14-resize-fp-tiles-4-8.webm
- vp90-2-14-resize-fp-tiles-8-1.webm
- vp90-2-14-resize-fp-tiles-8-16.webm
- vp90-2-14-resize-fp-tiles-8-2.webm
- vp90-2-14-resize-fp-tiles-8-4.webm
- Unsupported format
- vp91-2-04-yuv422.webm
- vp91-2-04-yuv444.webm
- CRC mismatch
- vp90-2-22-svc_1280x720_3.ivf
- Unsupported resolution after sequence change
- vp90-2-18-resize.ivf
- vp90-2-21-resize_inter_320x180_5_1-2.webm
- vp90-2-21-resize_inter_320x180_7_1-2.webm
- vp90-2-21-resize_inter_320x240_5_1-2.webm
- p90-2-21-resize_inter_320x240_7_1-2.webm
- Unsupported stream
- vp90-2-16-intra-only.webm
Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
---
Changes in v3:
- Fix the compat name (Bryan, Dmitry)
- Link to v2: https://lore.kernel.org/r/20260612-shikra_vpu-v2-0-bf8727370a1e@oss.qualcomm.com
Changes in v2:
- Move the if/then schema at the end (Krzysztof)
- Fixed the order of compat (Krzysztof)
- Link to v1: https://lore.kernel.org/r/20260609-shikra_vpu-v1-0-3a32bb38b080@oss.qualcomm.com
---
Vikash Garodia (3):
dt-bindings: media: qcom,qcm2290-venus: document shikra Iris compatible
arm64: dts: qcom: shikra: Add Iris video codec node
arm64: dts: qcom: shikra-evk: Enable Iris core
.../bindings/media/qcom,qcm2290-venus.yaml | 26 ++++++---
arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 6 +++
arch/arm64/boot/dts/qcom/shikra.dtsi | 61 ++++++++++++++++++++++
3 files changed, 86 insertions(+), 7 deletions(-)
---
base-commit: a87737435cfa134f9cdcc696ba3080759d04cf72
change-id: 20260609-shikra_vpu-b5421c03270c
prerequisite-message-id: <20260604-shikra-dispcc-gpucc-v4-0-8204f1029311@oss.qualcomm.com>
prerequisite-patch-id: 67fa5f31ee5109470da23db3b513721580f4c86f
prerequisite-patch-id: 0e79e46bc5a88849a2f0a410b39c08f3244dfed3
prerequisite-patch-id: 0396ac157aba73a5afd7ba4a8a744847f5a7b433
prerequisite-patch-id: 2b1aecd97b9c073a1b323138cd7a98cb34e3715f
prerequisite-patch-id: 823bc7bc713f6fce1b9de47a266307f1829636b9
prerequisite-patch-id: 8a8a9df61f7c7c51d7ea9cdacc52b7bdd917f12c
prerequisite-patch-id: 5b89b41d7c729c23b3b1fff9b5f572f4baa915ca
prerequisite-patch-id: acd08e91e5e2c6f4799879e48481b07167c0a400
prerequisite-patch-id: c9f2942207341ad4f450b20f049199f35188c02a
prerequisite-patch-id: dd62ebff6be6a2e2d32743812d35ec54daf91d00
prerequisite-patch-id: 3a6e9752793f2d7b084008b47daed10ea572064a
prerequisite-patch-id: 3338cdc5915c1e6b991067d3a7afb734c182663e
prerequisite-patch-id: a3026c858ffdfd3bfafc837e72c67fffe46021eb
Best regards,
--
Vikash Garodia <vikash.garodia@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 07/12] rtc: rzn1: fix alarm range check truncation on 32-bit systems
From: Lad, Prabhakar @ 2026-06-18 10:38 UTC (permalink / raw)
To: Wolfram Sang
Cc: Miquel Raynal, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
Magnus Damm, linux-rtc, linux-renesas-soc, devicetree,
linux-kernel, Biju Das, Fabrizio Castro, Lad Prabhakar
In-Reply-To: <ajJ9kNJtrY6DyQ-S@shikoro>
Hi Wolfram,
Thank you for testing.
On Wed, Jun 17, 2026 at 11:57 AM Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
>
> Hi,
>
> Sashiko found issues, not introduced by your patch, but still.. I
> curated the list and left only those which I think are valid. Do you
> have time to look at these issues?
>
Can you please share the commands you tried, I'll try and replicate it
on my side.
Cheers,
Prabhakar
> Thank you and happy hacking,
>
> Wolfram
>
> > Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> >
> > Pre-existing issues:
> > - [High] Incorrect hardware alarm weekday assignment due to unsigned underflow when the alarm crosses a month boundary.
> > - [High] Unconfigured alarms in `rzn1_rtc_read_alarm` can return an invalid `tm_wday` value of `-1`, risking out-of-bounds array access in userspace.
> > - [High] Potential spurious interrupt when sequentially updating active hardware alarm registers.
> > --
> >
> > commit d278abd6309a65fff235820bea9a8e8631da47be
> > Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Subject: rtc: rzn1: fix alarm range check truncation on 32-bit systems
> >
> > This commit fixes a silent truncation issue on 32-bit systems by changing
> > the alarm and farest variables from unsigned long to time64_t. It also
> > replaces the time_after() macro with a direct signed comparison.
> >
> > > diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
> > > index fe21fa6242881..06339adae71f6 100644
> > > --- a/drivers/rtc/rtc-rzn1.c
> > > +++ b/drivers/rtc/rtc-rzn1.c
> > [ ... ]
> > > @@ -265,8 +266,8 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > > {
> > > struct rzn1_rtc *rtc = dev_get_drvdata(dev);
> > > struct rtc_time *tm = &alrm->time, tm_now;
> > > - unsigned long alarm, farest;
> > > unsigned int days_ahead, wday;
> > > + time64_t alarm, farest;
> > > int ret;
> > >
> > > ret = rzn1_rtc_read_time(dev, &tm_now);
> > > @@ -276,7 +277,7 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > > /* We cannot set alarms more than one week ahead */
> > > farest = rtc_tm_to_time64(&tm_now) + rtc->rtcdev->alarm_offset_max;
> > > alarm = rtc_tm_to_time64(tm);
> > > - if (time_after(alarm, farest))
> > > + if (alarm > farest)
> > > return -ERANGE;
> > >
> > > /* Convert alarm day into week day */
> >
> > [Severity: High]
> > This isn't a bug introduced by this patch, but does the calculation for
> > days_ahead underflow if the alarm crosses a month boundary?
> >
> > In rzn1_rtc_set_alarm(), days_ahead is typed as an unsigned int and is
> > calculated like this:
> >
> > days_ahead = tm->tm_mday - tm_now.tm_mday;
> > wday = (tm_now.tm_wday + days_ahead) % 7;
> >
> > If the alarm is set for the 1st of the next month, and today is the 31st,
> > the subtraction results in -30. When assigned to an unsigned int, this
> > underflows. Because 2^32 % 7 evaluates to 4, the resulting wday calculation
> > shifts the weekday by exactly 4 days, causing the hardware alarm register
> > to be programmed for the wrong day.
> >
> > [Severity: High]
> > This is a pre-existing issue, but is there a risk of a spurious interrupt
> > when updating the active hardware alarm registers?
> >
> > Just below this hunk in rzn1_rtc_set_alarm(), the match registers are
> > updated sequentially:
> >
> > writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
> > writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
> > writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
> >
> > The RTC core can invoke this function without first disabling the hardware
> > alarm if replacing an existing timer. If the hardware alarm interrupt is
> > active, modifying these registers sequentially could cause the intermediate
> > hardware state to momentarily match the current time, triggering a spurious
> > interrupt and prematurely expiring the next timer in the queue.
> >
> > [Severity: High]
> > This is a pre-existing issue, but what happens in rzn1_rtc_read_alarm() if
> > the hardware alarm is unconfigured?
> >
> > If the hardware alarm register reads 0, fls(0) - 1 evaluates to -1:
> >
> > drivers/rtc/rtc-rzn1.c:rzn1_rtc_read_alarm() {
> > ...
> > wday = readl(rtc->base + RZN1_RTC_ALW);
> > ...
> > delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7;
> > tm->tm_wday = fls(wday) - 1;
> > ...
> > }
> >
> > If the current weekday is Saturday (6), delta_days evaluates to 0:
> > ((-1 - 6 + 7) % 7) == 0.
> >
> > Because delta_days is 0, the rtc_time64_to_tm() block is skipped, and the
> > function returns with tm->tm_wday = -1. Since rtc_valid_tm() does not
> > bound-check tm_wday, this -1 is passed to userspace where tools commonly
> > use it as an array index, which could cause an out-of-bounds memory read.
> >
> > --
> > Sashiko AI review · https://sashiko.dev/#/patchset/20260615154805.1619693-1-prabhakar.mahadev-lad.rj@bp.renesas.com?part=7
^ permalink raw reply
* [PATCH 2/2] media: i2c: og0va1b: Add OmniVision OG0VA1B camera sensor
From: Wenmeng Liu @ 2026-06-18 10:37 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus
Cc: linux-media, devicetree, linux-kernel, Wenmeng Liu
In-Reply-To: <20260618-og0va1b-v1-0-dda71bb83009@oss.qualcomm.com>
Add V4L2 sub device driver for OmniVision OG0VA1B image sensor.
OmniVision OG0VA1B is an image sensor, which produces frames in 10-bit
raw output format (Y10) over a 1-lane MIPI CSI-2 interface and supports
the 640x480 (VGA) resolution.
Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
---
MAINTAINERS | 1 +
drivers/media/i2c/Kconfig | 10 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/og0va1b.c | 867 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 879 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aa846c8479b20651291d5bd2e316308310f826c..85a06eb9eacc410a565b80d56979eaa565515d0e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19891,6 +19891,7 @@ M: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/ovti,og0va1b.yaml
+F: drivers/media/i2c/og0va1b.c
OMNIVISION OG0VE1B SENSOR DRIVER
M: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 5d173e0ecf424f2f204f8d426be818e44357f8e4..56680772f5f47b4629c4e17f5a5feba08b1d94fc 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -363,6 +363,16 @@ config VIDEO_OG01A1B
To compile this driver as a module, choose M here: the
module will be called og01a1b.
+config VIDEO_OG0VA1B
+ tristate "OmniVision OG0VA1B sensor support"
+ select V4L2_CCI_I2C
+ help
+ This is a Video4Linux2 sensor driver for the OmniVision
+ OG0VA1B camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called og0va1b.
+
config VIDEO_OG0VE1B
tristate "OmniVision OG0VE1B sensor support"
select V4L2_CCI_I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index e45359efe0e41e13e3c0869e5ead7d6cf4aca3a7..c60851c7fe07e3bdc511c5f482525ba7a044f48e 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o
obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o
+obj-$(CONFIG_VIDEO_OG0VA1B) += og0va1b.o
obj-$(CONFIG_VIDEO_OG0VE1B) += og0ve1b.o
obj-$(CONFIG_VIDEO_OS05B10) += os05b10.o
obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o
diff --git a/drivers/media/i2c/og0va1b.c b/drivers/media/i2c/og0va1b.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0505b7ba7f329ad57ffafa8f90a24204f002d3c
--- /dev/null
+++ b/drivers/media/i2c/og0va1b.c
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * OmniVision OG0VA1B Camera Sensor Driver
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define OG0VA1B_REG_CHIP_ID CCI_REG16(0x300a)
+#define OG0VA1B_CHIP_ID 0xC756
+
+#define OG0VA1B_REG_SW_RESET CCI_REG8(0x103)
+#define OG0VA1B_SW_RESET BIT(0)
+
+#define OG0VA1B_REG_STREAMING CCI_REG8(0x100)
+#define OG0VA1B_STREAMING_ON BIT(0)
+
+/* Exposure: 16-bit coarse integration time at 0x3501/0x3502 */
+#define OG0VA1B_REG_EXPOSURE CCI_REG16(0x3501)
+#define OG0VA1B_EXPOSURE_MIN 1
+#define OG0VA1B_EXPOSURE_STEP 1
+#define OG0VA1B_EXPOSURE_DEFAULT 0x100
+
+#define OG0VA1B_REG_GAIN_H CCI_REG8(0x3508)
+#define OG0VA1B_REG_GAIN_L CCI_REG8(0x3509)
+#define OG0VA1B_GAIN_MIN 0x10
+#define OG0VA1B_GAIN_MAX 0x1ff
+#define OG0VA1B_GAIN_STEP 1
+#define OG0VA1B_GAIN_DEFAULT 0x10
+
+#define OG0VA1B_REG_VTS CCI_REG16(0x380e)
+
+/* Test pattern: register 0x5100, BIT(7) = enable, BIT[3:2] = bar style */
+#define OG0VA1B_REG_TEST_PATTERN CCI_REG8(0x5100)
+#define OG0VA1B_TEST_PATTERN_EN BIT(7)
+#define OG0VA1B_TEST_PATTERN_BAR_SHIFT 2
+
+#define OG0VA1B_EXPOSURE_MARGIN 14
+#define OG0VA1B_VBLANK_MIN OG0VA1B_EXPOSURE_MARGIN
+
+#define OG0VA1B_XVCLK_RATE 19200000UL
+
+#define OG0VA1B_AUTOSUSPEND_DELAY_MS 1000
+
+static const s64 og0va1b_link_freqs[] = {
+ 480000000,
+};
+
+#define OG0VA1B_PIXEL_RATE 48000000UL
+#define OG0VA1B_LINK_FREQ_INDEX 0
+
+#define OG0VA1B_DATA_LANES 1
+
+static const char * const og0va1b_supply_names[] = {
+ "avdd", /* VANA */
+ "dovdd", /* VIO */
+ "dvdd", /* VDIG */
+};
+
+#define OG0VA1B_NUM_SUPPLIES ARRAY_SIZE(og0va1b_supply_names)
+
+struct og0va1b_mode {
+ u32 width;
+ u32 height;
+ u32 hts;
+ u32 vts;
+ u32 num_regs;
+ const struct cci_reg_sequence *regs;
+};
+
+/* VGA 640x480 @ 60 fps */
+static const struct cci_reg_sequence og0va1b_vga_60fps_regs[] = {
+ { CCI_REG8(0x0302), 0x31 },
+ { CCI_REG8(0x0303), 0x02 },
+ { CCI_REG8(0x0304), 0x01 },
+ { CCI_REG8(0x0305), 0x90 },
+ { CCI_REG8(0x0306), 0x00 },
+ { CCI_REG8(0x0323), 0x02 },
+ { CCI_REG8(0x0325), 0x68 },
+ { CCI_REG8(0x0326), 0xd8 },
+ { CCI_REG8(0x3006), 0x0e },
+ { CCI_REG8(0x300d), 0x08 },
+ { CCI_REG8(0x3018), 0xf0 },
+ { CCI_REG8(0x301c), 0xf0 },
+ { CCI_REG8(0x3020), 0x20 },
+ { CCI_REG8(0x3022), 0x01 },
+ { CCI_REG8(0x3040), 0x0f },
+ { CCI_REG8(0x3107), 0x40 },
+ { CCI_REG8(0x3216), 0x01 },
+ { CCI_REG8(0x3217), 0x00 },
+ { CCI_REG8(0x3218), 0xc0 },
+ { CCI_REG8(0x3219), 0x55 },
+ { CCI_REG8(0x3500), 0x00 },
+ { CCI_REG8(0x3501), 0x00 },
+ { CCI_REG8(0x3502), 0x01 },
+ { CCI_REG8(0x3506), 0x01 },
+ { CCI_REG8(0x3507), 0x50 },
+ { CCI_REG8(0x3508), 0x01 },
+ { CCI_REG8(0x3509), 0x00 },
+ { CCI_REG8(0x350a), 0x01 },
+ { CCI_REG8(0x350b), 0x00 },
+ { CCI_REG8(0x350c), 0x00 },
+ { CCI_REG8(0x3541), 0x00 },
+ { CCI_REG8(0x3542), 0x40 },
+ { CCI_REG8(0x3605), 0x90 },
+ { CCI_REG8(0x3606), 0x41 },
+ { CCI_REG8(0x3612), 0x00 },
+ { CCI_REG8(0x3620), 0x08 },
+ { CCI_REG8(0x3630), 0x17 },
+ { CCI_REG8(0x3631), 0x99 },
+ { CCI_REG8(0x3639), 0x88 },
+ { CCI_REG8(0x3668), 0x00 },
+ { CCI_REG8(0x3674), 0x00 },
+ { CCI_REG8(0x3677), 0x3f },
+ { CCI_REG8(0x368f), 0x06 },
+ { CCI_REG8(0x36a2), 0x19 },
+ { CCI_REG8(0x36a4), 0xf1 },
+ { CCI_REG8(0x36a5), 0x2d },
+ { CCI_REG8(0x3706), 0x30 },
+ { CCI_REG8(0x370d), 0x72 },
+ { CCI_REG8(0x3713), 0x86 },
+ { CCI_REG8(0x3715), 0x03 },
+ { CCI_REG8(0x3716), 0x00 },
+ { CCI_REG8(0x376d), 0x24 },
+ { CCI_REG8(0x3770), 0x3a },
+ { CCI_REG8(0x3778), 0x00 },
+ { CCI_REG8(0x37a8), 0x03 },
+ { CCI_REG8(0x37a9), 0x00 },
+ { CCI_REG8(0x37df), 0x7d },
+ { CCI_REG8(0x3800), 0x00 },
+ { CCI_REG8(0x3801), 0x00 },
+ { CCI_REG8(0x3802), 0x00 },
+ { CCI_REG8(0x3803), 0x00 },
+ { CCI_REG8(0x3804), 0x02 },
+ { CCI_REG8(0x3805), 0x8f },
+ { CCI_REG8(0x3806), 0x01 },
+ { CCI_REG8(0x3807), 0xef },
+ { CCI_REG8(0x3808), 0x02 },
+ { CCI_REG8(0x3809), 0x80 },
+ { CCI_REG8(0x380a), 0x01 },
+ { CCI_REG8(0x380b), 0xe0 },
+ { CCI_REG8(0x380c), 0x01 },
+ { CCI_REG8(0x380d), 0x78 },
+ { CCI_REG8(0x380e), 0x08 },
+ { CCI_REG8(0x380f), 0x30 },
+ { CCI_REG8(0x3810), 0x00 },
+ { CCI_REG8(0x3811), 0x08 },
+ { CCI_REG8(0x3812), 0x00 },
+ { CCI_REG8(0x3813), 0x08 },
+ { CCI_REG8(0x3814), 0x11 },
+ { CCI_REG8(0x3815), 0x11 },
+ { CCI_REG8(0x3816), 0x00 },
+ { CCI_REG8(0x3817), 0x01 },
+ { CCI_REG8(0x3818), 0x00 },
+ { CCI_REG8(0x3819), 0x05 },
+ { CCI_REG8(0x3820), 0x40 },
+ { CCI_REG8(0x3821), 0x04 },
+ { CCI_REG8(0x3823), 0x00 },
+ { CCI_REG8(0x3826), 0x00 },
+ { CCI_REG8(0x3827), 0x00 },
+ { CCI_REG8(0x382b), 0x52 },
+ { CCI_REG8(0x384a), 0xa2 },
+ { CCI_REG8(0x3858), 0x00 },
+ { CCI_REG8(0x3859), 0x00 },
+ { CCI_REG8(0x3860), 0x00 },
+ { CCI_REG8(0x3861), 0x00 },
+ { CCI_REG8(0x3866), 0x0c },
+ { CCI_REG8(0x3867), 0x07 },
+ { CCI_REG8(0x3884), 0x00 },
+ { CCI_REG8(0x3885), 0x08 },
+ { CCI_REG8(0x3888), 0x50 },
+ { CCI_REG8(0x3893), 0x6c },
+ { CCI_REG8(0x3898), 0x00 },
+ { CCI_REG8(0x389a), 0x04 },
+ { CCI_REG8(0x389b), 0x01 },
+ { CCI_REG8(0x389c), 0x0b },
+ { CCI_REG8(0x389d), 0xdc },
+ { CCI_REG8(0x389f), 0x08 },
+ { CCI_REG8(0x38a0), 0x00 },
+ { CCI_REG8(0x38a1), 0x00 },
+ { CCI_REG8(0x38b1), 0x04 },
+ { CCI_REG8(0x38b2), 0x00 },
+ { CCI_REG8(0x38b3), 0x08 },
+ { CCI_REG8(0x38c1), 0x46 },
+ { CCI_REG8(0x38c9), 0x02 },
+ { CCI_REG8(0x38d4), 0x06 },
+ { CCI_REG8(0x38d5), 0x5a },
+ { CCI_REG8(0x38d6), 0x08 },
+ { CCI_REG8(0x38d7), 0x3a },
+ { CCI_REG8(0x391e), 0x01 },
+ { CCI_REG8(0x391f), 0x00 },
+ { CCI_REG8(0x3920), 0xaa },
+ { CCI_REG8(0x3921), 0x00 },
+ { CCI_REG8(0x3922), 0x00 },
+ { CCI_REG8(0x3923), 0x00 },
+ { CCI_REG8(0x3924), 0x00 },
+ { CCI_REG8(0x3925), 0x00 },
+ { CCI_REG8(0x3926), 0x00 },
+ { CCI_REG8(0x3927), 0x00 },
+ { CCI_REG8(0x3928), 0x10 },
+ { CCI_REG8(0x3929), 0x01 },
+ { CCI_REG8(0x392a), 0xb4 },
+ { CCI_REG8(0x392b), 0x00 },
+ { CCI_REG8(0x392c), 0x10 },
+ { CCI_REG8(0x392d), 0x01 },
+ { CCI_REG8(0x392e), 0x78 },
+ { CCI_REG8(0x392f), 0x4a },
+ { CCI_REG8(0x3a06), 0x06 },
+ { CCI_REG8(0x3a07), 0x78 },
+ { CCI_REG8(0x3a08), 0x08 },
+ { CCI_REG8(0x3a09), 0x80 },
+ { CCI_REG8(0x3a52), 0x00 },
+ { CCI_REG8(0x3a53), 0x01 },
+ { CCI_REG8(0x3a54), 0x0c },
+ { CCI_REG8(0x3a55), 0x04 },
+ { CCI_REG8(0x3a58), 0x0c },
+ { CCI_REG8(0x3a59), 0x04 },
+ { CCI_REG8(0x4000), 0xcf },
+ { CCI_REG8(0x4003), 0x40 },
+ { CCI_REG8(0x4008), 0x04 },
+ { CCI_REG8(0x4009), 0x13 },
+ { CCI_REG8(0x400a), 0x02 },
+ { CCI_REG8(0x400b), 0x34 },
+ { CCI_REG8(0x4010), 0x71 },
+ { CCI_REG8(0x4042), 0xc3 },
+ { CCI_REG8(0x4306), 0x04 },
+ { CCI_REG8(0x4307), 0x12 },
+ { CCI_REG8(0x4500), 0x70 },
+ { CCI_REG8(0x4509), 0x00 },
+ { CCI_REG8(0x450b), 0x83 },
+ { CCI_REG8(0x4604), 0x68 },
+ { CCI_REG8(0x4f00), 0x04 },
+ { CCI_REG8(0x4f10), 0x04 },
+ { CCI_REG8(0x4f21), 0x01 },
+ { CCI_REG8(0x4f22), 0x00 },
+ { CCI_REG8(0x4f23), 0x54 },
+ { CCI_REG8(0x4f24), 0x51 },
+ { CCI_REG8(0x4f25), 0x41 },
+ { CCI_REG8(0x5000), 0x3f },
+ { CCI_REG8(0x5001), 0x80 },
+ { CCI_REG8(0x500a), 0x00 },
+ { CCI_REG8(0x5100), 0x00 },
+ { CCI_REG8(0x5111), 0x20 },
+ { CCI_REG8(0x481b), 0x44 },
+ { CCI_REG8(0x481f), 0x30 },
+ { CCI_REG8(0x4823), 0x44 },
+ { CCI_REG8(0x4825), 0x35 },
+ { CCI_REG8(0x4837), 0x11 },
+};
+
+static const struct og0va1b_mode og0va1b_modes[] = {
+ {
+ .width = 640,
+ .height = 480,
+ .hts = 376,
+ .vts = 2096,
+ .num_regs = ARRAY_SIZE(og0va1b_vga_60fps_regs),
+ .regs = og0va1b_vga_60fps_regs,
+ },
+};
+
+struct og0va1b {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct regmap *regmap;
+ struct clk *inclk;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[OG0VA1B_NUM_SUPPLIES];
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *exposure;
+ struct v4l2_ctrl *gain;
+ struct v4l2_ctrl *test_pattern;
+};
+
+static inline struct og0va1b *sd_to_og0va1b(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct og0va1b, sd);
+}
+
+static int og0va1b_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct og0va1b *og0va1b = sd_to_og0va1b(sd);
+ int ret;
+
+ ret = regulator_bulk_enable(OG0VA1B_NUM_SUPPLIES, og0va1b->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(og0va1b->inclk);
+ if (ret) {
+ dev_err(dev, "failed to enable clock: %d\n", ret);
+ goto err_regulators;
+ }
+
+ gpiod_set_value_cansleep(og0va1b->reset_gpio, 0);
+
+ usleep_range(18000, 20000);
+
+ return 0;
+
+err_regulators:
+ regulator_bulk_disable(OG0VA1B_NUM_SUPPLIES, og0va1b->supplies);
+ return ret;
+}
+
+static int og0va1b_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct og0va1b *og0va1b = sd_to_og0va1b(sd);
+
+ clk_disable_unprepare(og0va1b->inclk);
+ gpiod_set_value_cansleep(og0va1b->reset_gpio, 1);
+ regulator_bulk_disable(OG0VA1B_NUM_SUPPLIES, og0va1b->supplies);
+
+ return 0;
+}
+
+static int og0va1b_check_id(struct og0va1b *og0va1b)
+{
+ struct device *dev = og0va1b->sd.dev;
+ u64 chip_id;
+ int ret;
+
+ ret = cci_read(og0va1b->regmap, OG0VA1B_REG_CHIP_ID, &chip_id, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to read chip ID\n");
+
+ if (chip_id != OG0VA1B_CHIP_ID)
+ return dev_err_probe(dev, -ENODEV,
+ "unexpected chip ID 0x%04llx (expected 0x%04x)\n",
+ chip_id, OG0VA1B_CHIP_ID);
+
+ return 0;
+}
+
+static int og0va1b_check_hwcfg(struct device *dev)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+ struct fwnode_handle *ep;
+ unsigned int i;
+ int ret;
+
+ if (!fwnode)
+ return -ENXIO;
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return dev_err_probe(dev, -ENXIO, "no endpoint found\n");
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to parse endpoint\n");
+
+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != OG0VA1B_DATA_LANES) {
+ ret = dev_err_probe(dev, -EINVAL,
+ "unsupported number of CSI2 data lanes %u\n",
+ bus_cfg.bus.mipi_csi2.num_data_lanes);
+ goto err_free;
+ }
+
+ if (!bus_cfg.nr_of_link_frequencies) {
+ ret = dev_err_probe(dev, -EINVAL,
+ "no link frequencies defined\n");
+ goto err_free;
+ }
+
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
+ if (bus_cfg.link_frequencies[i] ==
+ og0va1b_link_freqs[OG0VA1B_LINK_FREQ_INDEX])
+ break;
+
+ if (i == bus_cfg.nr_of_link_frequencies)
+ ret = dev_err_probe(dev, -EINVAL,
+ "no supported link frequency %lld found\n",
+ og0va1b_link_freqs[OG0VA1B_LINK_FREQ_INDEX]);
+
+err_free:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+
+ return ret;
+}
+
+static int og0va1b_init(struct og0va1b *og0va1b,
+ const struct og0va1b_mode *mode)
+{
+ int ret;
+
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_SW_RESET,
+ OG0VA1B_SW_RESET, NULL);
+ if (ret)
+ return ret;
+
+ usleep_range(5000, 6000);
+
+ return cci_multi_reg_write(og0va1b->regmap, mode->regs, mode->num_regs,
+ NULL);
+}
+
+static int og0va1b_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct og0va1b *og0va1b =
+ container_of(ctrl->handler, struct og0va1b, ctrl_handler);
+ const struct og0va1b_mode *mode = &og0va1b_modes[0];
+ int ret = 0;
+
+ if (ctrl->id == V4L2_CID_VBLANK) {
+ int exp_max = mode->height + ctrl->val - OG0VA1B_EXPOSURE_MARGIN;
+
+ ret = __v4l2_ctrl_modify_range(og0va1b->exposure,
+ og0va1b->exposure->minimum,
+ exp_max,
+ og0va1b->exposure->step,
+ min(og0va1b->exposure->val, exp_max));
+ if (ret)
+ return ret;
+ }
+
+ if (!pm_runtime_get_if_active(og0va1b->sd.dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_EXPOSURE,
+ ctrl->val, NULL);
+ break;
+
+ case V4L2_CID_ANALOGUE_GAIN:
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_GAIN_H,
+ (ctrl->val >> 4) & 0x1f, NULL);
+ if (!ret)
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_GAIN_L,
+ (ctrl->val & 0xf) << 4, NULL);
+ break;
+
+ case V4L2_CID_VBLANK:
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_VTS,
+ mode->height + ctrl->val, NULL);
+ break;
+
+ case V4L2_CID_TEST_PATTERN:
+ if (ctrl->val)
+ ret = cci_write(og0va1b->regmap,
+ OG0VA1B_REG_TEST_PATTERN,
+ (ctrl->val - 1) << OG0VA1B_TEST_PATTERN_BAR_SHIFT |
+ OG0VA1B_TEST_PATTERN_EN, NULL);
+ else
+ ret = cci_write(og0va1b->regmap,
+ OG0VA1B_REG_TEST_PATTERN, 0, NULL);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put_autosuspend(og0va1b->sd.dev);
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops og0va1b_ctrl_ops = {
+ .s_ctrl = og0va1b_s_ctrl,
+};
+
+static const char * const og0va1b_test_pattern_menu[] = {
+ "Disabled",
+ "Standard Color Bar",
+ "Top-Bottom Darker Color Bar",
+ "Right-Left Darker Color Bar",
+ "Bottom-Top Darker Color Bar",
+};
+
+static void og0va1b_fill_format(const struct og0va1b_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->code = MEDIA_BUS_FMT_Y10_1X10;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_RAW;
+ fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->xfer_func = V4L2_XFER_FUNC_NONE;
+}
+
+static int og0va1b_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index != 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_Y10_1X10;
+ return 0;
+}
+
+static int og0va1b_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->code != MEDIA_BUS_FMT_Y10_1X10 ||
+ fse->index >= ARRAY_SIZE(og0va1b_modes))
+ return -EINVAL;
+
+ fse->min_width = og0va1b_modes[fse->index].width;
+ fse->max_width = og0va1b_modes[fse->index].width;
+ fse->min_height = og0va1b_modes[fse->index].height;
+ fse->max_height = og0va1b_modes[fse->index].height;
+ return 0;
+}
+
+static int og0va1b_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *fmt)
+{
+ const struct og0va1b_mode *mode;
+ struct v4l2_mbus_framefmt *format;
+
+ mode = v4l2_find_nearest_size(og0va1b_modes,
+ ARRAY_SIZE(og0va1b_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+
+ og0va1b_fill_format(mode, &fmt->format);
+
+ format = v4l2_subdev_state_get_format(state, 0);
+ *format = fmt->format;
+
+ return 0;
+}
+
+static int og0va1b_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct v4l2_mbus_framefmt *fmt =
+ v4l2_subdev_state_get_format(state, 0);
+
+ og0va1b_fill_format(&og0va1b_modes[0], fmt);
+ return 0;
+}
+
+static int og0va1b_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ struct og0va1b *og0va1b = sd_to_og0va1b(sd);
+ const struct og0va1b_mode *mode = &og0va1b_modes[0];
+ int ret;
+
+ ret = pm_runtime_resume_and_get(og0va1b->sd.dev);
+ if (ret < 0)
+ return ret;
+
+ ret = og0va1b_init(og0va1b, mode);
+ if (ret)
+ goto err_pm;
+
+ ret = __v4l2_ctrl_handler_setup(&og0va1b->ctrl_handler);
+ if (ret)
+ goto err_pm;
+
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_STREAMING,
+ OG0VA1B_STREAMING_ON, NULL);
+ if (ret)
+ goto err_pm;
+
+ return 0;
+
+err_pm:
+ pm_runtime_put_autosuspend(og0va1b->sd.dev);
+ return ret;
+}
+
+static int og0va1b_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ struct og0va1b *og0va1b = sd_to_og0va1b(sd);
+ int ret;
+
+ ret = cci_write(og0va1b->regmap, OG0VA1B_REG_STREAMING, 0, NULL);
+ if (ret)
+ dev_warn(og0va1b->sd.dev,
+ "failed to stop streaming: %d\n", ret);
+
+ usleep_range(5000, 6000);
+ pm_runtime_put_autosuspend(og0va1b->sd.dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops og0va1b_pm_ops = {
+ SET_RUNTIME_PM_OPS(og0va1b_power_off, og0va1b_power_on, NULL)
+};
+
+static const struct v4l2_subdev_video_ops og0va1b_video_ops = {
+ .s_stream = v4l2_subdev_s_stream_helper,
+};
+
+static const struct v4l2_subdev_pad_ops og0va1b_pad_ops = {
+ .enum_mbus_code = og0va1b_enum_mbus_code,
+ .enum_frame_size = og0va1b_enum_frame_size,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = og0va1b_set_fmt,
+ .enable_streams = og0va1b_enable_streams,
+ .disable_streams = og0va1b_disable_streams,
+};
+
+static const struct v4l2_subdev_ops og0va1b_subdev_ops = {
+ .video = &og0va1b_video_ops,
+ .pad = &og0va1b_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops og0va1b_internal_ops = {
+ .init_state = og0va1b_init_state,
+};
+
+static const struct media_entity_operations og0va1b_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static int og0va1b_init_controls(struct og0va1b *og0va1b)
+{
+ struct v4l2_ctrl_handler *hdl = &og0va1b->ctrl_handler;
+ const struct og0va1b_mode *mode = &og0va1b_modes[0];
+ struct v4l2_fwnode_device_properties props;
+ int vblank_def = mode->vts - mode->height;
+ int vblank_max = 0xffff - mode->height;
+ int hblank_val = mode->hts - mode->width;
+ int ret;
+
+ v4l2_ctrl_handler_init(hdl, 9);
+
+ og0va1b->link_freq =
+ v4l2_ctrl_new_int_menu(hdl, NULL, V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(og0va1b_link_freqs) - 1, 0,
+ og0va1b_link_freqs);
+ if (og0va1b->link_freq)
+ og0va1b->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ og0va1b->pixel_rate =
+ v4l2_ctrl_new_std(hdl, NULL, V4L2_CID_PIXEL_RATE,
+ OG0VA1B_PIXEL_RATE, OG0VA1B_PIXEL_RATE, 1,
+ OG0VA1B_PIXEL_RATE);
+
+ og0va1b->vblank =
+ v4l2_ctrl_new_std(hdl, &og0va1b_ctrl_ops, V4L2_CID_VBLANK,
+ OG0VA1B_VBLANK_MIN, vblank_max, 1, vblank_def);
+
+ og0va1b->hblank =
+ v4l2_ctrl_new_std(hdl, NULL, V4L2_CID_HBLANK,
+ hblank_val, hblank_val, 1, hblank_val);
+ if (og0va1b->hblank)
+ og0va1b->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ og0va1b->exposure =
+ v4l2_ctrl_new_std(hdl, &og0va1b_ctrl_ops, V4L2_CID_EXPOSURE,
+ OG0VA1B_EXPOSURE_MIN,
+ mode->vts - OG0VA1B_EXPOSURE_MARGIN,
+ OG0VA1B_EXPOSURE_STEP,
+ OG0VA1B_EXPOSURE_DEFAULT);
+
+ og0va1b->gain =
+ v4l2_ctrl_new_std(hdl, &og0va1b_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ OG0VA1B_GAIN_MIN, OG0VA1B_GAIN_MAX,
+ OG0VA1B_GAIN_STEP, OG0VA1B_GAIN_DEFAULT);
+
+ og0va1b->test_pattern =
+ v4l2_ctrl_new_std_menu_items(hdl, &og0va1b_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(og0va1b_test_pattern_menu) - 1,
+ 0, 0, og0va1b_test_pattern_menu);
+
+ ret = v4l2_fwnode_device_parse(og0va1b->sd.dev, &props);
+ if (ret)
+ goto err_free;
+
+ ret = v4l2_ctrl_new_fwnode_properties(hdl, &og0va1b_ctrl_ops, &props);
+ if (ret)
+ goto err_free;
+
+ if (hdl->error) {
+ ret = hdl->error;
+ goto err_free;
+ }
+
+ og0va1b->sd.ctrl_handler = hdl;
+ return 0;
+
+err_free:
+ v4l2_ctrl_handler_free(hdl);
+ return ret;
+}
+
+static int og0va1b_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct og0va1b *og0va1b;
+ unsigned long clk_rate;
+ unsigned int i;
+ int ret;
+
+ og0va1b = devm_kzalloc(dev, sizeof(*og0va1b), GFP_KERNEL);
+ if (!og0va1b)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&og0va1b->sd, client, &og0va1b_subdev_ops);
+ og0va1b->sd.internal_ops = &og0va1b_internal_ops;
+ og0va1b->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ og0va1b->inclk = devm_v4l2_sensor_clk_get(dev, NULL);
+ if (IS_ERR(og0va1b->inclk))
+ return dev_err_probe(dev, PTR_ERR(og0va1b->inclk),
+ "failed to get clock\n");
+
+ clk_rate = clk_get_rate(og0va1b->inclk);
+ if (clk_rate != OG0VA1B_XVCLK_RATE)
+ return dev_err_probe(dev, -EINVAL,
+ "clock rate %lu Hz != required %lu Hz\n",
+ clk_rate, OG0VA1B_XVCLK_RATE);
+
+ ret = og0va1b_check_hwcfg(dev);
+ if (ret)
+ return ret;
+
+ og0va1b->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(og0va1b->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(og0va1b->reset_gpio),
+ "failed to get reset GPIO\n");
+
+ for (i = 0; i < OG0VA1B_NUM_SUPPLIES; i++)
+ og0va1b->supplies[i].supply = og0va1b_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev, OG0VA1B_NUM_SUPPLIES,
+ og0va1b->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get regulators\n");
+
+ og0va1b->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(og0va1b->regmap))
+ return dev_err_probe(dev, PTR_ERR(og0va1b->regmap),
+ "failed to init CCI regmap\n");
+
+ ret = og0va1b_power_on(dev);
+ if (ret)
+ return ret;
+
+ ret = og0va1b_check_id(og0va1b);
+ if (ret)
+ goto err_power_off;
+
+ ret = og0va1b_init_controls(og0va1b);
+ if (ret)
+ goto err_power_off;
+
+ og0va1b->sd.entity.ops = &og0va1b_entity_ops;
+ og0va1b->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ og0va1b->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&og0va1b->sd.entity, 1, &og0va1b->pad);
+ if (ret)
+ goto err_controls;
+
+ og0va1b->sd.state_lock = og0va1b->ctrl_handler.lock;
+ ret = v4l2_subdev_init_finalize(&og0va1b->sd);
+ if (ret)
+ goto err_entity;
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ ret = v4l2_async_register_subdev_sensor(&og0va1b->sd);
+ if (ret)
+ goto err_pm;
+
+ pm_runtime_set_autosuspend_delay(dev, OG0VA1B_AUTOSUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_idle(dev);
+
+ return 0;
+
+err_pm:
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+err_entity:
+ v4l2_subdev_cleanup(&og0va1b->sd);
+ media_entity_cleanup(&og0va1b->sd.entity);
+err_controls:
+ v4l2_ctrl_handler_free(&og0va1b->ctrl_handler);
+err_power_off:
+ og0va1b_power_off(dev);
+
+ return ret;
+}
+
+static void og0va1b_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct device *dev = &client->dev;
+
+ v4l2_async_unregister_subdev(sd);
+ v4l2_subdev_cleanup(sd);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+ media_entity_cleanup(&sd->entity);
+
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+
+ if (!pm_runtime_status_suspended(dev))
+ og0va1b_power_off(dev);
+
+ pm_runtime_set_suspended(dev);
+}
+
+static const struct i2c_device_id og0va1b_id[] = {
+ { "og0va1b" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, og0va1b_id);
+
+static const struct of_device_id og0va1b_of_match[] = {
+ { .compatible = "ovti,og0va1b" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, og0va1b_of_match);
+
+static struct i2c_driver og0va1b_i2c_driver = {
+ .driver = {
+ .name = "og0va1b",
+ .of_match_table = og0va1b_of_match,
+ .pm = pm_ptr(&og0va1b_pm_ops),
+ },
+ .probe = og0va1b_probe,
+ .remove = og0va1b_remove,
+ .id_table = og0va1b_id,
+};
+module_i2c_driver(og0va1b_i2c_driver);
+
+MODULE_AUTHOR("Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>");
+MODULE_DESCRIPTION("OmniVision OG0VA1B sensor driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: media: i2c: Add OmniVision OG0VA1B
From: Wenmeng Liu @ 2026-06-18 10:37 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus
Cc: linux-media, devicetree, linux-kernel, Wenmeng Liu
In-Reply-To: <20260618-og0va1b-v1-0-dda71bb83009@oss.qualcomm.com>
Add devicetree binding for OmniVision OG0VA1B image sensor.
OmniVision OG0VA1B is an image sensor, which produces frames in 10-bit
raw output format (Y10) over a 1-lane MIPI CSI-2 interface and supports
the 640x480 (VGA) resolution.
Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
---
.../bindings/media/i2c/ovti,og0va1b.yaml | 104 +++++++++++++++++++++
MAINTAINERS | 6 ++
2 files changed, 110 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,og0va1b.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,og0va1b.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..302afc41bb776f75c08b26ac2f04014f8cbea4fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,og0va1b.yaml
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,og0va1b.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OmniVision OG0VA1B Image Sensor
+
+maintainers:
+ - Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
+
+description:
+ The OmniVision OG0VA1B is a 1/10-inch black and white CMOS VGA (640x480)
+ image sensor. It is controlled over an I2C-compatible SCCB bus and transmits
+ images on a 1-lane MIPI CSI-2 output interface.
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: ovti,og0va1b
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ reset-gpios:
+ description: Active low GPIO connected to XSHUTDN pad of the sensor.
+ maxItems: 1
+
+ avdd-supply:
+ description: Analogue circuit voltage supply.
+
+ dovdd-supply:
+ description: I/O circuit voltage supply.
+
+ dvdd-supply:
+ description: Digital circuit voltage supply.
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+ description:
+ Output port node, single endpoint describing the CSI-2 transmitter.
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description: OG0VA1B supports a single MIPI CSI-2 data lane only.
+ items:
+ - const: 1
+
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ required:
+ - endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sensor@36 {
+ compatible = "ovti,og0va1b";
+ reg = <0x36>;
+ clocks = <&clk 0>;
+ reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
+ avdd-supply = <&vreg_2v8>;
+ dovdd-supply = <&vreg_1v8>;
+ dvdd-supply = <&vreg_1v2>;
+
+ port {
+ og0va1b_ep: endpoint {
+ remote-endpoint = <&csiphy_ep>;
+ data-lanes = <1>;
+ link-frequencies = /bits/ 64 <480000000>;
+ };
+ };
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 069b4aa6b523c72b661418d8f37cd214a061f9af..5aa846c8479b20651291d5bd2e316308310f826c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19886,6 +19886,12 @@ S: Maintained
F: Documentation/devicetree/bindings/media/i2c/ovti,og01a1b.yaml
F: drivers/media/i2c/og01a1b.c
+OMNIVISION OG0VA1B SENSOR DRIVER
+M: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/i2c/ovti,og0va1b.yaml
+
OMNIVISION OG0VE1B SENSOR DRIVER
M: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
L: linux-media@vger.kernel.org
--
2.34.1
^ permalink raw reply related
* [PATCH 0/2] media: i2c: Add OmniVision OG0VA1B camera sensor driver
From: Wenmeng Liu @ 2026-06-18 10:37 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sakari Ailus
Cc: linux-media, devicetree, linux-kernel, Wenmeng Liu
Add OmniVision OG0VA1B driver support. The OmniVision OG0VA1B is a
1/10-inch monochrome CMOS VGA image sensor. It outputs 10-bit raw (Y10)
frames at up to 640x480 resolution over a single-lane MIPI CSI-2
interface and is controlled via an I2C-compatible SCCB bus.
This driver has been verified on the Purwa EVK.
Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
---
Wenmeng Liu (2):
dt-bindings: media: i2c: Add OmniVision OG0VA1B
media: i2c: og0va1b: Add OmniVision OG0VA1B camera sensor
.../bindings/media/i2c/ovti,og0va1b.yaml | 104 +++
MAINTAINERS | 7 +
drivers/media/i2c/Kconfig | 10 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/og0va1b.c | 867 +++++++++++++++++++++
5 files changed, 989 insertions(+)
---
base-commit: 4fa3f5fabb30bf00d7475d5a33459ea83d639bf9
change-id: 20260618-og0va1b-55bbf3cabb0e
Best regards,
--
Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 05/12] rtc: rzn1: Add system suspend/resume support and wakeup capability
From: Lad, Prabhakar @ 2026-06-18 10:37 UTC (permalink / raw)
To: Wolfram Sang
Cc: Miquel Raynal, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
Magnus Damm, linux-rtc, linux-renesas-soc, devicetree,
linux-kernel, Biju Das, Fabrizio Castro, Lad Prabhakar
In-Reply-To: <ajPJHKut92mAoo-B@shikoro>
Hi Wolfram,
On Thu, Jun 18, 2026 at 11:31 AM Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
>
>
> > For running s2idle cases with rtcwake > 60sec this feature would be
> > helpful. What do you think?
>
> I think maintaining such a fragile feature is cumbersome. People might
> have different expectations and the maintainers have to handle the delta
> then. So, if we cannot to support to a large degree some feature, I
> think we should just skip it. Until some user really wants (and tests
> and accepts) a half-baked solution.
>
Ok, I will drop this patch from the series in v2.
Cheers,
Prabhakar
^ permalink raw reply
* Re: [RFC PATCH v3 3/5] iio: buffer: Extend DMAengine buffer interfaces to take extra sysfs attributes
From: Nuno Sá @ 2026-06-18 10:38 UTC (permalink / raw)
To: David Lechner
Cc: Marcelo Schmitt, linux-iio, devicetree, linux-kernel, jic23,
nuno.sa, Michael.Hennerich, andy, robh, krzk+dt, conor+dt,
pop.ioan-daniel, marcelo.schmitt1
In-Reply-To: <3b96ec10-b022-4135-9ade-6fd9eb6e78a6@baylibre.com>
On Wed, Jun 17, 2026 at 04:43:18PM -0500, David Lechner wrote:
> On 6/16/26 9:03 PM, Marcelo Schmitt wrote:
> > Some devices using DMAengine buffers are connected to extra hardware that
> > allows setting how fast data is transferred to/from the buffer. However,
> > those extra pieces of harwdware are external to the sensor chip such that
> > supporting the transfer speed as a sensor property is a bit of an
> > inaccuracy. Expand IIO DMAengine buffer interfaces to take arguments for
> > extra sysfs attributes, enabling the transfer speed to be configured
> > through the buffer interface.
>
> This message is a bit confusing. It sounds like it is attempting to
> control something about the DMA controller itself. But based on the
> later patches, it looks like this is just so we can add arbitrary
> sysfs attributes to the bufferX directory. And in this specific case,
> a sampling_frequency attribute.
Agreed. Seems like rate control comes from the buffer.
>
> >
> > Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> > ---
> > New patch.
> >
> > Now that I've come to this buffer "solution", I have pretty much convinced
> > myself it would be better to instead have some sort of IIO trigger to control
> > the signal source connected to SPI offloading trigger module.
> >
> In the other chips with SPI offload we've done already, we just used
> IIO_CHAN_INFO_SAMP_FREQ to control the SPI offload trigger rate.
> Any reason why we can't do that here? In the original SPI offload
> discussions, IIRC the general consensus was that adding a trigger
> just to control that was overkill when I suggested the same.
>
I tend to agree with David. Even if we come to a conclusion that we
can't use IIO_CHAN_INFO_SAMP_FREQ to control the trigger rate, I'm not
really convinced sysfs interfaces on the buffer itself are the place for
this.
- Nuno Sá
^ permalink raw reply
* Re: [PATCH 0/6] arm64: dts: qcom: sc8280xp: set GPI DMA channels according to DSDT
From: Icenowy Zheng @ 2026-06-18 10:34 UTC (permalink / raw)
To: Konrad Dybcio, Pengyu Luo
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <ab5c5f53-4119-4bbe-88ac-e2933bf6f8d8@oss.qualcomm.com>
在 2026-06-18四的 11:05 +0200,Konrad Dybcio写道:
> On 6/18/26 11:04 AM, Konrad Dybcio wrote:
> > On 6/9/26 5:54 PM, Icenowy Zheng wrote:
> > > 在 2026-06-09二的 14:23 +0200,Konrad Dybcio写道:
> > > > On 6/7/26 10:49 AM, Icenowy Zheng wrote:
> > > > > 在 2026-06-06六的 21:51 +0800,Pengyu Luo写道:
> > > > > > On Sat, Jun 6, 2026 at 9:21 PM Icenowy Zheng
> > > > > > <zhengxingda@iscas.ac.cn> wrote:
> > > > > > >
> > > > > > > 在 2026-06-06六的 17:46 +0800,Pengyu Luo写道:
> > > > > > > > On 2026-06-06 17:28:35+08:00, Icenowy Zheng wrote:
> > > > > > > > > 在 2026-06-06六的 17:22 +0800,Pengyu Luo写道:
> > > > > > > > >
> > > > > > > > > > On 2026-06-02 21:21:27+08:00, Icenowy Zheng wrote:
> > > > > > > > > >
> > > > > > > > > > The magnetic keyboard (USB HID) can't be connected
> > > > > > > > > > somehow,
> > > > > > > > > > others
> > > > > > > > > > are
> > > > > > > > > > fine, such as the spi touchscreen (not upstream
> > > > > > > > > > yet),
> > > > > > > > > > which
> > > > > > > > > > utilizes
> > > > > > > > > > DMA definitely. My config is here
> > > > > > > > > > https://pastebin.com/SdjuyJYk
> > > > > > > > >
> > > > > > > > > Is this a defconfig?
> > > > > > > > >
> > > > > > > >
> > > > > > > > Yes.
> > > > > > > >
> > > > > > > > > BTW it seems that CONFIG_ASYNC_TX_DMA needs to be
> > > > > > > > > selected
> > > > > > > > > too
> > > > > > > > > for
> > > > > > > > > exhibiting the problem (because there should be
> > > > > > > > > "public"
> > > > > > > > > GPI
> > > > > > > > > DMA
> > > > > > > > > consumers to trigger the stuck/reset).
> > > > > > > > >
> > > > > > > >
> > > > > > > > Is this still necessary? I checked the fedora
> > > > > > > > discussion and
> > > > > > > > your
> > > > > > > > GPI
> > > > > > > > DMA fix. And GPI DMA is only for the QUP-supported
> > > > > > > > peripherals as
> > > > > > > > the
> > > > > > > > binding mentioned,
> > > > > > > > devicetree/bindings/dma/qcom,gpi.yaml
> > > > > > >
> > > > > > > The devicetree without this fix seems to be still
> > > > > > > incorrect,
> > > > > > > because
> > > > > > > with the device tree fix even if the GPI DMA driver
> > > > > > > misbehaves
> > > > > > > the
> > > > > > > system won't be stuck (although it will iterate all GPI
> > > > > > > channels
> > > > > > > and
> > > > > > > then fail to function at all).
> > > > > > >
> > > > > >
> > > > > > Back to the start. You said some GPI interfaces aren't
> > > > > > available
> > > > > > to
> > > > > > HLOS, your mask is 0xb(0b1011), so I use 0x4(0b100) did a
> > > > > > quick
> > > > > > test,
> > > > > > and spi6 consumed it, no stuck or reset. Could you give me
> > > > > > a
> > > > > > unavailable channel?
> > > > >
> > > > > I think channel 0b10000 of gpi_dma2 could be an example?
> > > > >
> > > > > It seems that 4 channels are tried on gpi_dma2 before hang on
> > > > > my
> > > > > gaokun3, but as gaokun3 has no known serial access, it's
> > > > > possible
> > > > > that
> > > > > 0b100000 or 0b1000 is problematic.
> > > > >
> > > > > (The reason gpi_dma2 is checked first is because it's the GPI
> > > > > DMA
> > > > > controller with the smallest address)
> > > > >
> > > > > BTW I just took the values from Windows DSDT, which is quite
> > > > > conservative.
> > > >
> > > > So, with DMA_PRIVATE set, is this series made redundant?
> > >
> > > I assume technically the trustzone is still protecting some
> > > channels,
> > > although the system stuck issue is fixed.
> > >
> > > This series should still be relevant, although not so emergent.
> >
> > So now we're down to the case of the TZ reserving some of the GPI
> > channels (presumably for locked down/TZ-driven QUPs) crashing the
> > device on access, is that right?
>
> i.e. now, is requesting these channels through (wrongfully) enabling
> the devices in DT the only remaining concern?
Yes, I think so; although I think few devices will use GPI on these
devices (usually only one or two SPI controllers according to the
DSDTs).
Thanks,
Icenowy
>
> Konrad
^ permalink raw reply
* Re: [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support
From: Icenowy Zheng @ 2026-06-18 10:33 UTC (permalink / raw)
To: Joey Lu, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
robh, krzk+dt, conor+dt, Michael Turquette, Stephen Boyd,
Brian Masney
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, linux-clk
In-Reply-To: <df7363be-0e3f-4459-be4a-43ffb0a5366c@gmail.com>
(CC'ed clk maintainers for weird clock gate bit)
在 2026-06-17三的 18:35 +0800,Joey Lu写道:
>
> On 6/15/2026 4:51 PM, Icenowy Zheng wrote:
> > 在 2026-06-15一的 14:50 +0800,Joey Lu写道:
> > > The Nuvoton MA35D1 SoC integrates a Verisilicon DCUltraLite
> > > display
> > > controller whose register layout differs from the DC8200 in
> > > several
> > > important ways:
> > >
> > > 1. No CONFIG_EX commit path: framebuffer updates use the enable
> > > (bit
> > > 0)
> > > and reset (bit 4) bits in FB_CONFIG instead of the DC8200
> > > staging
> > > registers (FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT,
> > > FB_BLEND_CONFIG, PANEL_CONFIG_EX).
> > >
> > > 2. No PANEL_START register: panel output starts when
> > > PANEL_CONFIG.RUNNING is set; there is no multi-display sync
> > > start
> > > register.
> > >
> > > 3. Different IRQ registers: DCUltraLite uses DISP_IRQ_STA
> > > (0x147C) /
> > > DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
> > > TOP_IRQ_EN (0x0014).
> > >
> > > 4. Per-frame commit cycle: DCUltraLite requires the VALID bit in
> > > FB_CONFIG to be set at the start of each atomic commit
> > > (crtc_begin)
> > > and cleared after (crtc_flush).
> > >
> > > 5. Simpler clock topology: only 'core' (bus gate) and 'pix0'
> > > (pixel
> > > divider) clocks; no axi or ahb clocks required. Make axi_clk
> > > and
> > > ahb_clk optional (devm_clk_get_optional_enabled) so DC8000
> > > nodes
> > > without those clocks are handled gracefully.
> > >
> > > Add vs_dc8000.c implementing the vs_dc_funcs vtable for the above
> > > differences. The probe now selects vs_dc8000_funcs when the
> > > identified
> > > generation is VSDC_GEN_DC8000 (DCUltraLite reads model 0x0,
> > > revision 0x5560, customer_id 0x305).
> > >
> > > Signed-off-by: Joey Lu <a0987203069@gmail.com>
> > > ---
> > > drivers/gpu/drm/verisilicon/Makefile | 2 +-
> > > drivers/gpu/drm/verisilicon/vs_dc.c | 9 ++-
> > > drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
> > > drivers/gpu/drm/verisilicon/vs_dc8000.c | 78
> > > +++++++++++++++++++++++++
> > > 4 files changed, 86 insertions(+), 4 deletions(-)
> > > create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
> > >
> > > diff --git a/drivers/gpu/drm/verisilicon/Makefile
> > > b/drivers/gpu/drm/verisilicon/Makefile
> > > index 9d4cd16452fa..d2fd8e4dff24 100644
> > > --- a/drivers/gpu/drm/verisilicon/Makefile
> > > +++ b/drivers/gpu/drm/verisilicon/Makefile
> > > @@ -1,6 +1,6 @@
> > > # SPDX-License-Identifier: GPL-2.0-only
> > >
> > > -verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o
> > > vs_drm.o vs_hwdb.o \
> > > +verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o
> > > vs_dc8000.o vs_drm.o vs_hwdb.o \
> > > vs_plane.o vs_primary_plane.o vs_cursor_plane.o
> > >
> > > obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
> > > diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c
> > > b/drivers/gpu/drm/verisilicon/vs_dc.c
> > > index 9729b693d360..9499fffbca58 100644
> > > --- a/drivers/gpu/drm/verisilicon/vs_dc.c
> > > +++ b/drivers/gpu/drm/verisilicon/vs_dc.c
> > > @@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device
> > > *pdev)
> > > return PTR_ERR(dc->core_clk);
> > > }
> > >
> > > - dc->axi_clk = devm_clk_get_enabled(dev, "axi");
> > > + dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
> > > if (IS_ERR(dc->axi_clk)) {
> > > dev_err(dev, "can't get axi clock\n");
> > > return PTR_ERR(dc->axi_clk);
> > > }
> > >
> > > - dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
> > > + dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
> > Please make the clock change a separated patch for atomicity.
> >
> > BTW the MA35D1 manual's clock tree shows that DCUltra appears on
> > AXI2
> > ACLK, AHB_HCLK2, behind a mux of SYS-PLL/EPLL-DIV2 (which seems to
> > be
> > the core clock), and behind a divider (which seems to be the pixel
> > clock).
> >
> > However it's weird that only one DCUltra Clock Enable Bit exists
> > despite both bus clocks have "ICG" (I think it means "Integrated
> > Clock
> > Gating"). In addition the linux clk-ma35d1 driver assigns
> > "dcu_gate" as
> > a downstream of "dcu_mux", although the Figure 6.5-2 in the TRM
> > shows
> > no ICG after the "Display core CLK" mux.
> >
> > Is the two bus clocks controlled by a single gate bit, and is the
> > bit
> > also gating DC core clock?
> >
> > Thanks,
> > Icenowy
> I will split the axi/ahb optional-clock change into its own patch in
> v5
> for atomicity.
> Regarding the MA35D1 clock tree: from the TRM, the single "dcu_gate"
> bit
> gates both bus clocks (AXI ACLK and AHB HCLK) together with the
> display
> core clock through the same ICG cell. The clk-ma35d1 driver exposes
> only
> "dcu_gate" (downstream of "dcu_mux") and does not provide separate
Then it's one of the case that the clock tree doesn't properly
represent the hardware, which is bad. However, as three gates share the
same bit, I am not sure how to represent such kind of thing in the
common clk framework.
> axi/ahb clock entries. Therefore the MA35D1 DT binding will use only
> two
> clocks ("core" and "pix0"); making axi and ahb optional in the driver
> is the correct approach, and this will be stated clearly in the
> split-out patch.
I agree to make them optional, although these two clocks do exist in
the hardware of MA35D1.
Thanks,
Icenowy
> > > if (IS_ERR(dc->ahb_clk)) {
> > > dev_err(dev, "can't get ahb clock\n");
> > > return PTR_ERR(dc->ahb_clk);
^ permalink raw reply
* Re: [PATCH v2 2/2] drm/panel: add Ilitek ILI7807S panel driver
From: sashiko-bot @ 2026-06-18 10:32 UTC (permalink / raw)
To: Arpit Saini; +Cc: robh, devicetree, dri-devel, conor+dt
In-Reply-To: <20260618-ili7807s-v2-2-b3f0c109b102@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Inverted manipulation of MIPI_DSI_MODE_LPM in backlight update_status callback permanently corrupts DSI mode flags.
- [High] Concurrent read-modify-write operations on dsi->mode_flags can cause state corruption.
- [Medium] Backlight update_status callback sends DCS commands without checking if the panel is powered on.
- [Medium] Incorrect devm registration order causes the DSI device to be detached while the DRM panel and backlight sysfs are still active.
- [Medium] Missing NULL check for the return value of of_device_get_match_data() leads to a potential NULL pointer dereference.
--
commit 97a4deef0ca55e71f3420d40260130de4242cae3
Author: Arpit Saini <arpit.saini@oss.qualcomm.com>
drm/panel: add Ilitek ILI7807S panel driver
This commit adds a DRM panel driver for the DLC DLC0697 1080x1920@60Hz
MIPI DSI panel based on the Ilitek ILI7807S display controller.
> diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c b/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c
[ ... ]
> +static int ili7807s_bl_update_status(struct backlight_device *bl)
> +{
> + struct mipi_dsi_device *dsi = bl_get_data(bl);
> + u16 brightness = backlight_get_brightness(bl);
> + int ret;
> +
[Severity: Medium]
Is it safe to send DCS commands here without checking if the panel is
currently powered on? If userspace writes to the sysfs brightness control
while the regulators are disabled and the panel is off, will this attempt
to send commands and cause DSI bus timeouts?
> + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
> +
> + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
> +
> + dsi->mode_flags |= MIPI_DSI_MODE_LPM;
[Severity: High]
Does this sequence invert the intended mode flags? The default panel mode
flags do not include MIPI_DSI_MODE_LPM. Clearing it beforehand and setting it
afterward will permanently force the DSI host into Low Power Mode after the
first backlight update, which might break subsequent video transmissions.
[Severity: High]
Can concurrent calls to ili7807s_on(), ili7807s_off(), and this backlight
update callback cause a data race? These functions all modify dsi->mode_flags
using non-atomic bitwise operations, which might clobber each other's changes
if a backlight update is triggered from userspace simultaneously with a DRM
DPMS event.
[ ... ]
> +static int ili7807s_probe(struct mipi_dsi_device *dsi)
> +{
> + struct device *dev = &dsi->dev;
> + const struct panel_desc *desc;
> + struct ili7807s *ctx;
> + int ret;
> +
> + ctx = devm_drm_panel_alloc(dev, struct ili7807s, panel,
> + &ili7807s_panel_funcs,
> + DRM_MODE_CONNECTOR_DSI);
> + if (IS_ERR(ctx))
> + return PTR_ERR(ctx);
> +
> + desc = of_device_get_match_data(dev);
> + ctx->desc = desc;
[Severity: Medium]
Can of_device_get_match_data() return NULL if the driver is bound manually
via sysfs without an associated device tree node? If so, will dereferencing
desc->lanes later in this function cause a NULL pointer dereference?
[ ... ]
> + ret = devm_drm_panel_add(dev, &ctx->panel);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "failed to add panel\n");
> +
> + ret = devm_mipi_dsi_attach(dev, dsi);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "failed to attach dsi\n");
> +
> + return 0;
> +}
[Severity: Medium]
Does this devres registration order cause a teardown issue? Since devres
cleans up in reverse order of allocation, devm_mipi_dsi_detach() will run
before the DRM panel and backlight interfaces are removed. Could this leave
the sysfs interfaces exposed to userspace while the underlying DSI device is
already detached?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618-ili7807s-v2-0-b3f0c109b102@oss.qualcomm.com?part=2
^ permalink raw reply
* Re: [PATCH 05/12] rtc: rzn1: Add system suspend/resume support and wakeup capability
From: Wolfram Sang @ 2026-06-18 10:31 UTC (permalink / raw)
To: Lad, Prabhakar
Cc: Miquel Raynal, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
Magnus Damm, linux-rtc, linux-renesas-soc, devicetree,
linux-kernel, Biju Das, Fabrizio Castro, Lad Prabhakar
In-Reply-To: <CA+V-a8uo9sr3m9F_MQYbHVD5wa3LT3n6MWrVpiNiPDumnVHMYQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 421 bytes --]
> For running s2idle cases with rtcwake > 60sec this feature would be
> helpful. What do you think?
I think maintaining such a fragile feature is cumbersome. People might
have different expectations and the maintainers have to handle the delta
then. So, if we cannot to support to a large degree some feature, I
think we should just skip it. Until some user really wants (and tests
and accepts) a half-baked solution.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: (subset) [PATCH] dt-bindings: mfd: qcom,spmi-pmic: Document PMG1110
From: Lee Jones @ 2026-06-18 10:31 UTC (permalink / raw)
To: linux-arm-msm, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Fenglin Wu
Cc: David Collins, Subbaraman Narayanamurthy, Kamal Wadhwa, kernel,
devicetree, linux-kernel
In-Reply-To: <20260609-pmg1110-v1-1-6604d0adc907@oss.qualcomm.com>
On Tue, 09 Jun 2026 23:49:59 -0700, Fenglin Wu wrote:
> Add compatible string for PMG1110 which is used on Maili platform.
Applied, thanks!
[1/1] dt-bindings: mfd: qcom,spmi-pmic: Document PMG1110
commit: 1becda6be273b5c5082590a2ebc38532a2a0086f
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH v10 4/5] iio: adc: versal-sysmon: add threshold event support
From: sashiko-bot @ 2026-06-18 10:28 UTC (permalink / raw)
To: Salih Erim; +Cc: conor+dt, robh, devicetree
In-Reply-To: <20260618101414.3462934-5-salih.erim@amd.com>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [High] The delayed worker `sysmon_unmask_worker` silently clears all pending hardware interrupts, causing concurrent voltage alarm events to be permanently dropped.
- [High] Missing bounds checking in threshold value conversion leads to integer overflow and hardware register corruption.
- [High] Race condition between interrupt configuration/teardown and the unmask worker leads to unhandled interrupt storms.
- [High] Voltage alarm handler incorrectly disables the alarm configuration and early returns leak ISR status, causing interrupt storms.
- [High] The hardirq handler `sysmon_iio_irq` takes a spinlock and sleeps when using an I2C regmap.
- [High] Writing a supply voltage threshold silently clears the format (FMT) and mode (MODE) bits in the threshold register.
- [Medium] Unconditional execution of the delayed worker resets hardware tracking status on voltage alarms.
--
commit 4ebb615e40cc90088cf5fe0430223005d0197c79
Author: Salih Erim <salih.erim@amd.com>
Subject: iio: adc: versal-sysmon: add threshold event support
This commit adds threshold event support for temperature and supply voltage
channels on the Versal Sysmon. It configures hysteresis mode for temperature
alarms and window mode for supply voltage channels, along with an interrupt
handler and delayed worker to handle the level-sensitive hardware interrupts.
> diff --git a/drivers/iio/adc/versal-sysmon-core.c b/drivers/iio/adc/versal-sysmon-core.c
> index 03a745d3fb4f3..50b5228aa222f 100644
> --- a/drivers/iio/adc/versal-sysmon-core.c
> +++ b/drivers/iio/adc/versal-sysmon-core.c
[ ... ]
> @@ -52,6 +102,16 @@ static const struct iio_chan_spec temp_channels[] = {
> SYSMON_CHAN_TEMP(3, SYSMON_TEMP_MIN_MIN, "min_min"),
> };
>
> +static void sysmon_q8p7_to_millicelsius(s16 raw_data, int *val)
> +{
> + *val = (raw_data * MILLIDEGREE_PER_DEGREE) >> SYSMON_FRACTIONAL_SHIFT;
> +}
> +
> +static void sysmon_millicelsius_to_q8p7(u32 *raw_data, int val)
> +{
> + *raw_data = (val << SYSMON_FRACTIONAL_SHIFT) / MILLIDEGREE_PER_DEGREE;
> +}
[Severity: High]
Can this overflow if a large or negative value is passed from userspace?
If val << SYSMON_FRACTIONAL_SHIFT overflows, or if val is negative, the
resulting negative integer gets implicitly cast to a u32 without masking. This
sign-extends the value, which then gets written directly to the
SYSMON_TEMP_TH_UP register, potentially corrupting reserved upper bits.
> +
> static void sysmon_supply_rawtoprocessed(int raw_data, int *val)
> {
> int mantissa, format, exponent;
> @@ -69,6 +129,33 @@ static void sysmon_supply_rawtoprocessed(int raw_data, int *val)
> *val = (mantissa * (int)MILLI) >> exponent;
> }
>
> +static void sysmon_supply_processedtoraw(int val, u32 reg_val, u32 *raw_data)
> +{
> + int exponent = FIELD_GET(SYSMON_MODE_MASK, reg_val);
> + int format = FIELD_GET(SYSMON_FMT_MASK, reg_val);
> + int scale, tmp;
> +
> + scale = BIT(SYSMON_SUPPLY_MANTISSA_BITS - exponent);
> + tmp = (val * scale) / (int)MILLI;
[Severity: High]
Does val * scale overflow the 32-bit signed integer before it reaches the
clamp() below?
A large positive voltage could map to a negative integer, clamping to 0 and
inadvertently programming a 0V threshold.
> +
> + if (format)
> + tmp = clamp(tmp, S16_MIN, S16_MAX);
> + else
> + tmp = clamp(tmp, 0, U16_MAX);
> +
> + *raw_data = (u16)tmp;
> +}
[ ... ]
> +static int sysmon_write_event_value(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + enum iio_event_info info,
> + int val, int val2)
> +{
[ ... ]
> + case IIO_VOLTAGE:
> + offset = sysmon_supply_thresh_offset(chan->address, dir);
> + if (offset < 0)
> + return offset;
> +
> + ret = regmap_read(sysmon->regmap, offset, ®_val);
> + if (ret)
> + return ret;
> +
> + sysmon_supply_processedtoraw(val, reg_val, &raw_val);
> +
> + return regmap_write(sysmon->regmap, offset, raw_val);
[Severity: High]
Does casting tmp to u16 in sysmon_supply_processedtoraw() discard the extracted
exponent and format bits?
When raw_val is later written via regmap_write() here, won't this zero out the
SYSMON_FMT_MASK and SYSMON_MODE_MASK fields in the threshold register,
corrupting the hardware configuration? Should this use regmap_update_bits()
instead?
[ ... ]
> +static int sysmon_handle_event(struct iio_dev *indio_dev, u32 event)
> +{
> + u32 alarm_flag_offset = SYSMON_ALARM_FLAG + event * SYSMON_REG_STRIDE;
> + u32 alarm_reg_offset = SYSMON_ALARM_REG + event * SYSMON_REG_STRIDE;
> + struct sysmon *sysmon = iio_priv(indio_dev);
> + unsigned long alarm_flag_reg;
> + unsigned int reg_val;
> + u32 address, bit;
> + int ret;
> +
> + switch (event) {
[ ... ]
> + case SYSMON_BIT_ALARM0:
> + case SYSMON_BIT_ALARM1:
> + case SYSMON_BIT_ALARM2:
> + case SYSMON_BIT_ALARM3:
> + case SYSMON_BIT_ALARM4:
> + ret = regmap_read(sysmon->regmap, alarm_flag_offset, ®_val);
> + if (ret)
> + return ret;
> +
> + alarm_flag_reg = reg_val;
> +
> + for_each_set_bit(bit, &alarm_flag_reg, SYSMON_ALARM_BITS_PER_REG) {
> + address = bit + SYSMON_ALARM_BITS_PER_REG * event;
> + sysmon_push_event(indio_dev, address);
> + ret = regmap_clear_bits(sysmon->regmap, alarm_reg_offset, BIT(bit));
> + if (ret)
> + return ret;
> + }
[Severity: High]
Does this clear the hardware alarm configuration rather than just masking the
interrupt?
alarm_reg_offset resolves to SYSMON_ALARM_REG, which completely disables the
alarm and forces the sysfs state out of sync.
Also, if regmap_clear_bits() fails and returns early, doesn't this skip writing
to alarm_flag_offset to clear the level-sensitive hardware flag? This would
leave the interrupt unmasked and unhandled, resulting in an immediate interrupt
storm.
[ ... ]
> +static void sysmon_unmask_worker(struct work_struct *work)
> +{
> + struct sysmon *sysmon =
> + container_of(work, struct sysmon, sysmon_unmask_work.work);
> + unsigned int isr;
> +
> + /*
> + * If the ISR read fails, skip processing to avoid acting
> + * on undefined data.
> + */
> + scoped_guard(spinlock_irq, &sysmon->irq_lock) {
> + if (regmap_read(sysmon->regmap, SYSMON_ISR, &isr))
> + break;
> + regmap_write(sysmon->regmap, SYSMON_ISR, isr);
> + sysmon_unmask_temp(sysmon, isr);
> + }
[Severity: High]
Does this silently drop concurrent voltage alarm events?
SYSMON_ISR is a Write-1-to-Clear register. The code reads the entire register
and writes it back verbatim, clearing all pending interrupts. However,
sysmon_unmask_temp() only processes temperature interrupts.
If a supply voltage alarm fires just before this read, it is cleared from the
hardware but never dispatched since the worker doesn't call
sysmon_handle_events().
> +
> + if (sysmon->masked_temp)
> + schedule_delayed_work(&sysmon->sysmon_unmask_work,
> + msecs_to_jiffies(SYSMON_UNMASK_WORK_DELAY_MS));
> + else
> + regmap_write(sysmon->regmap, SYSMON_STATUS_RESET, 1);
> +}
[Severity: Medium]
Does this unintentionally flush the hardware's internal min/max tracking
registers for unrelated events?
In sysmon_iio_irq(), schedule_delayed_work() is called unconditionally. If a
voltage alarm triggers the interrupt, sysmon->masked_temp remains 0. When this
worker runs 500ms later, it sees masked_temp is 0 and executes the else branch,
resetting the hardware status on every voltage threshold crossing.
> +
> +static irqreturn_t sysmon_iio_irq(int irq, void *data)
> +{
> + struct iio_dev *indio_dev = data;
> + struct sysmon *sysmon = iio_priv(indio_dev);
> + unsigned int isr, imr;
> +
> + guard(spinlock)(&sysmon->irq_lock);
> +
> + if (regmap_read(sysmon->regmap, SYSMON_ISR, &isr) ||
> + regmap_read(sysmon->regmap, SYSMON_IMR, &imr))
> + return IRQ_NONE;
[Severity: High]
Can this sleep in a hardirq context if the device is attached via I2C?
The driver requests sysmon_iio_irq as a primary hardirq handler via
devm_request_irq(). Although the commit message mentions I2C won't have an
interrupt, if an I2C device node provides an "interrupts" property, it will
be requested.
When the IRQ fires, the I2C regmap will attempt to acquire a mutex while
holding a spinlock in hardirq context, leading to a panic. Should this use
a threaded IRQ?
[ ... ]
> +static void sysmon_disable_interrupts(void *data)
> +{
> + struct sysmon *sysmon = data;
> +
> + regmap_write(sysmon->regmap, SYSMON_IDR, SYSMON_INTR_ALL_MASK);
> +
> + scoped_guard(spinlock_irq, &sysmon->irq_lock)
> + sysmon->masked_temp = 0;
> +
> + cancel_delayed_work_sync(&sysmon->sysmon_unmask_work);
> +}
[Severity: High]
Is there a race condition here with sysmon_unmask_worker()?
The driver writes to SYSMON_IDR outside of sysmon->irq_lock. Concurrently,
sysmon_unmask_worker() calculates the unmask bit under the lock based on the
software state.
If the worker calculates the unmask state before this teardown path acquires
the lock to clear sysmon->masked_temp, the worker will write to SYSMON_IER,
overriding the teardown path's IDR write. This leaves the hardware interrupt
enabled after driver unbind and IRQ handler removal, resulting in an interrupt
storm.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618101414.3462934-1-salih.erim@amd.com?part=4
^ permalink raw reply
* Re: [PATCH v10 3/5] iio: adc: versal-sysmon: add I2C driver
From: sashiko-bot @ 2026-06-18 10:28 UTC (permalink / raw)
To: Salih Erim; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260618101414.3462934-4-salih.erim@amd.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] I2C transfer buffers are allocated on the stack, which can cause a kernel panic if the underlying I2C adapter driver uses DMA.
- [High] I2C regmap backend is executed in hardirq and spinlock context if an IRQ is erroneously specified in the device tree, causing a 'scheduling while atomic' panic.
--
commit f508dce27e50e63598a76da221a58f66b1a7c5f1
Author: Salih Erim <salih.erim@amd.com>
iio: adc: versal-sysmon: add I2C driver
Add an I2C transport driver for the Versal SysMon block. The SysMon
provides an I2C slave interface that allows an external master to
read voltage and temperature measurements through the same register
map used by the MMIO path.
[ ... ]
> diff --git a/drivers/iio/adc/versal-sysmon-i2c.c b/drivers/iio/adc/versal-sysmon-i2c.c
> new file mode 100644
> index 0000000000000..e9a7629159ab1
> --- /dev/null
> +++ b/drivers/iio/adc/versal-sysmon-i2c.c
> @@ -0,0 +1,134 @@
[ ... ]
> +static int sysmon_i2c_reg_read(void *context, unsigned int reg,
> + unsigned int *val)
> +{
> + struct i2c_client *client = context;
> + u8 write_buf[8] = { };
> + u8 read_buf[4];
[Severity: High]
Is it safe to pass these stack-allocated buffers to i2c_master_send() and
i2c_master_recv()?
If the underlying I2C adapter driver uses DMA for the transfer, it will
attempt to map these addresses using the DMA API. With CONFIG_VMAP_STACK
enabled, kernel stacks are placed in vmalloc space which cannot be mapped
for DMA, leading to a kernel panic.
Should these buffers be dynamically allocated, or perhaps embedded in a
device-managed structure? This same pattern appears to be present in
sysmon_i2c_reg_write() as well.
> + int ret;
> +
> + put_unaligned_le16(reg >> 2, &write_buf[SYSMON_I2C_REG_OFS]);
> + write_buf[SYSMON_I2C_INSTR_OFS] = SYSMON_I2C_INSTR_READ;
[ ... ]
> +static int sysmon_i2c_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct regmap *regmap;
> +
> + regmap = devm_regmap_init(dev, NULL, client, &sysmon_i2c_regmap_config);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + /* I2C has no IRQ connection; events are not supported */
> + return devm_versal_sysmon_core_probe(dev, regmap);
[Severity: High]
Does this code adequately prevent the core driver from registering an IRQ?
The commit message notes that events are not supported because the I2C regmap
backend cannot be called from atomic context. However,
devm_versal_sysmon_core_probe() unconditionally fetches the IRQ from the
device tree:
devm_versal_sysmon_core_probe()
irq = fwnode_irq_get(dev_fwnode(dev), 0);
if (irq > 0) {
...
sysmon_init_interrupt(sysmon, dev, indio_dev, irq);
}
If a misconfigured device tree provides an interrupts property for the I2C
node, the core driver will successfully register the hardirq handler
sysmon_iio_irq(). When the interrupt fires, the handler takes sysmon->irq_lock
(which is a spinlock) and calls regmap_read(). This routes back to
sysmon_i2c_reg_read(). Because the I2C transfer functions can sleep, this
would result in a 'scheduling while atomic' panic.
Could the I2C probe explicitly inform the core to bypass IRQ initialization,
instead of relying solely on the device tree being configured correctly?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618101414.3462934-1-salih.erim@amd.com?part=3
^ permalink raw reply
* Re: [PATCH 2/2] usb: typec: ucsi: Add ITE IT885x Type-C PD controller driver
From: Heikki Krogerus @ 2026-06-18 10:25 UTC (permalink / raw)
To: Amber Kao
Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jeson Yang, Yaode Fang, Bling Chiang, Eric Su,
Doreen Lin, linux-usb, devicetree, linux-kernel
In-Reply-To: <20260615-ucsi-itepd-feature-v1-2-a826cfd0df6a@ite.com.tw>
Hi,
On Mon, Jun 15, 2026 at 09:47:40PM +0800, Amber Kao wrote:
> Add core, UCSI, and Alternate Mode support for the ITE IT885x
> Type-C Power Delivery controller over I2C. The driver uses the
> auxiliary bus to spawn UCSI and Alternate Mode child devices from
> the main I2C core driver.
>
> Cc: Yaode Fang <Yaode.Fang@ite.com.tw>
> Cc: Jeson Yang <jeson.yang@ite.com.tw>
> Cc: Bling Chiang <Bling.Chiang@ite.com.tw>
> Cc: Eric Su <Eric.Su@ite.com.tw>
> Cc: Doreen Lin <doreen.lin@ite.com.tw>
>
> Signed-off-by: Amber Kao <amber.kao@ite.com.tw>
> ---
> MAINTAINERS | 4 +
> drivers/usb/typec/ucsi/Kconfig | 15 +
> drivers/usb/typec/ucsi/Makefile | 1 +
> drivers/usb/typec/ucsi/itepd.c | 481 ++++++++++++++++++++++++++++
> drivers/usb/typec/ucsi/itepd.h | 64 ++++
> drivers/usb/typec/ucsi/itepd_altmode.c | 438 ++++++++++++++++++++++++++
> drivers/usb/typec/ucsi/ucsi_itepd.c | 558 +++++++++++++++++++++++++++++++++
> 7 files changed, 1561 insertions(+)
I could not figure out what is the purpose of the separated altmode
handling. Why would you need separate handling for the retimers and
muxes? If the typec core is not doing something properly, then we need
to fix that. I also did not quite understand why are you creating
child device for the ucsi and altmode.
You need to split this into smaller patches and provide a bit of
explanation for each feature. Start with the bare minimum. So UCSI
without support for altmodes, just register the ports and partners.
Then add things one by one, each feature in its own patch.
<snip>
> +static void ucsi_itepd_command_hook(struct ucsi_itepd *ucsi_itepd, u64 *cmd)
> +{
> + /* Translate UCSI 1.2 commands/fields to ITE PD controller (v2.1) */
> + switch (UCSI_COMMAND(*cmd)) {
> + case UCSI_SET_NOTIFICATION_ENABLE:
> + if (*cmd & UCSI_ENABLE_NTFY_CMD_COMPLETE)
> + /* Enable Attention Notification for alt. mode */
> + *cmd |= FIELD_PREP(GENMASK_ULL(32, 16), BIT(3));
> + break;
> + case UCSI_GET_PDOS:
> + *cmd &= ~GENMASK_ULL(38, 37);
> + break;
> + case UCSI_GET_ERROR_STATUS:
> + *cmd &= ~GENMASK_ULL(22, 16);
> + *cmd |= UCSI_CONNECTOR_NUMBER(ucsi_itepd->cmd_port + 1);
> + break;
> + default:
> + break;
> + }
> +
> + /* Track the connector number associated with this command */
> + switch (UCSI_COMMAND(*cmd)) {
> + case UCSI_PPM_RESET:
> + case UCSI_CANCEL:
> + case UCSI_SET_NOTIFICATION_ENABLE:
> + case UCSI_GET_CAPABILITY:
> + ucsi_itepd->cmd_port = 0;
> + break;
> + case UCSI_CONNECTOR_RESET:
> + case UCSI_GET_CONNECTOR_CAPABILITY:
> + case UCSI_SET_CCOM: /* 0x08 - SET_UOM in older specs */
> + case UCSI_SET_UOR:
> + case UCSI_SET_PDR:
> + case UCSI_GET_CAM_SUPPORTED:
> + case UCSI_GET_CURRENT_CAM:
> + case UCSI_SET_NEW_CAM:
> + case UCSI_GET_PDOS:
> + case UCSI_GET_CABLE_PROPERTY:
> + case UCSI_GET_CONNECTOR_STATUS:
> + case UCSI_SET_POWER_LEVEL: /* 0x14 */
> + case UCSI_GET_PD_MESSAGE: /* 0x15 */
> + case UCSI_GET_ATTENTION_VDO: /* 0x16 */
> + case UCSI_GET_CAM_CS: /* 0x18 */
> + case 0x19:
> + case 0x1A:
> + case 0x1B:
Add definitions for these.
> + case UCSI_SET_SINK_PATH: /* 0x1C */
> + case 0x1D:
> + case UCSI_READ_POWER_LEVEL: /* 0x1E */
> + case 0x1F:
> + ucsi_itepd->cmd_port =
> + FIELD_GET(GENMASK(22, 16), *cmd) - 1;
Use the existing definitions with these.
ucsi_itepd->cmd_port = UCSI_DEFAULT_GET_CONNECTOR_NUMBER(cmd) - 1;
> + break;
> + case UCSI_GET_ALTERNATE_MODES:
> + ucsi_itepd->cmd_port =
> + FIELD_GET(GENMASK(30, 24), *cmd) - 1;
> + break;
> + }
> +
> + ucsi_itepd->cmd = *cmd;
> +}
I won't do complete review yet, but I'm just pointing out that since
you are going over all the commands here, it should not be a problem
to first disable some of them, and then add them in separate patches.
Thanks,
--
heikki
^ permalink raw reply
* Re: [PATCH v10 5/5] iio: adc: versal-sysmon: add oversampling support
From: sashiko-bot @ 2026-06-18 10:25 UTC (permalink / raw)
To: Salih Erim; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260618101414.3462934-6-salih.erim@amd.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Hardware and software state desynchronization at initialization for oversampling ratios.
- [Medium] Temperature oversampling sysfs attribute is hidden if no satellite channels are defined.
--
commit d8019119cd29dc9ea31ce2a445e3e2be9d478438
Author: Salih Erim <salih.erim@amd.com>
Subject: iio: adc: versal-sysmon: add oversampling support
Add support for reading and writing the oversampling ratio through
the IIO oversampling_ratio attribute. The hardware supports averaging
2, 4, 8, or 16 samples, plus a ratio of 1 (no averaging).
> diff --git a/drivers/iio/adc/versal-sysmon-core.c b/drivers/iio/adc/versal-sysmon-core.c
> index 50b5228aa222f..bae229f27c6b3 100644
> --- a/drivers/iio/adc/versal-sysmon-core.c
> +++ b/drivers/iio/adc/versal-sysmon-core.c
[ ... ]
> @@ -786,7 +931,11 @@ static int sysmon_parse_fw(struct iio_dev *indio_dev, struct device *dev, int ir
> .address = SYSMON_TEMP_SAT_BASE +
> (reg - 1) * SYSMON_REG_STRIDE,
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
> + .info_mask_shared_by_type =
> + BIT(IIO_CHAN_INFO_SCALE) |
> + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
> + .info_mask_shared_by_type_available =
> + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
> .datasheet_name = label,
> };
> }
[Severity: Medium]
This successfully exposes the oversampling attribute for dynamic satellite
temperature channels, but does it miss updating the static temperature channels
defined via SYSMON_CHAN_TEMP earlier in the file?
If a device has no dynamic temperature satellite channels specified in the
Device Tree, will the static IIO_TEMP channels lack the
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) flag, thereby preventing the IIO core
from creating the in_temp_oversampling_ratio sysfs attribute entirely?
[ ... ]
> @@ -833,6 +982,8 @@ int devm_versal_sysmon_core_probe(struct device *dev, struct regmap *regmap)
>
> sysmon = iio_priv(indio_dev);
> sysmon->regmap = regmap;
> + sysmon->temp_oversampling = 1;
> + sysmon->supply_oversampling = 1;
[Severity: Medium]
Does initializing the software cache to 1 here without writing to the
hardware register or reading its initial state risk a desynchronization?
If the bootloader or a previous kernel configured a different oversampling
ratio (e.g., 16x), will the hardware perform averaging while userspace
reads a ratio of 1 until explicitly updated?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618101414.3462934-1-salih.erim@amd.com?part=5
^ permalink raw reply
* Re: [PATCH 05/12] rtc: rzn1: Add system suspend/resume support and wakeup capability
From: Lad, Prabhakar @ 2026-06-18 10:24 UTC (permalink / raw)
To: Wolfram Sang
Cc: Miquel Raynal, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
Magnus Damm, linux-rtc, linux-renesas-soc, devicetree,
linux-kernel, Biju Das, Fabrizio Castro, Lad Prabhakar
In-Reply-To: <ajJwqDt2jUfhSD1x@shikoro>
Hi Wolfram,
On Wed, Jun 17, 2026 at 11:02 AM Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
>
>
> > Add system-wide power management support along with wakeup capability to
> > the rtc-rzn1 driver.
>
> Do you have an actual use case for the wakeup functionality? If it is so
> limited, then we should maybe not support the weak abilities until
> someone has a real use case? For which then, a proper solution has been
> developed and tested?
>
For running s2idle cases with rtcwake > 60sec this feature would be
helpful. What do you think?
Cheers,
Prabhakar
^ permalink raw reply
* Re: [PATCH v4 1/6] dt-bindings: display: verisilicon, dc: generalize for single-output variants
From: Icenowy Zheng @ 2026-06-18 10:24 UTC (permalink / raw)
To: Joey Lu, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel
In-Reply-To: <6d3e3121-22f2-4c59-9678-df2f57ff4d31@gmail.com>
在 2026-06-17三的 18:25 +0800,Joey Lu写道:
>
> On 6/15/2026 4:19 PM, Icenowy Zheng wrote:
> > 在 2026-06-15一的 14:49 +0800,Joey Lu写道:
> > > The existing schema hard-codes the five-clock/three-reset/dual-
> > > port
> > > topology of the DC8200 IP block, preventing reuse for single-
> > > output
> > > variants such as the Verisilicon DCUltraLite used in the Nuvoton
> > > MA35D1
> > > SoC.
> > >
> > > Rework the schema so that variant-specific constraints are
> > > expressed
> > > via
> > > allOf/if blocks:
> > >
> > > - Add nuvoton,ma35d1-dcu to the SoC-specific compatible enum.
> > > The
> > > generic verisilicon,dc fallback remains the driver-binding
> > > string.
> > > - Move clock and reset items descriptions into the per-variant
> > > allOf/if
> > > blocks; keep only minItems/maxItems at the top level so the
> > > base
> > > schema
> > > accepts all variants.
> > > - Restore full items lists for clock-names and reset-names at the
> > > top
> > > level with minItems so the names are validated against the
> > > descriptions.
> > > - Keep ports in the global required list and keep
> > > additionalProperties: false.
> > > - Add an allOf/if block for thead,th1520-dc8200: five-clock
> > > (core,
> > > axi,
> > > ahb, pix0, pix1), three-reset (core, axi, ahb), required
> > > resets.
> > > - Add an allOf/if block for nuvoton,ma35d1-dcu: two-clock (core,
> > > pix0),
> > > one-reset (core), required resets.
> > >
> > > Signed-off-by: Joey Lu <a0987203069@gmail.com>
> > > ---
> > > .../bindings/display/verisilicon,dc.yaml | 80
> > > +++++++++++++++++--
> > > 1 file changed, 73 insertions(+), 7 deletions(-)
> > >
> > > diff --git
> > > a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> > > b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> > > index 9dc35ab973f2..0c41286b8223 100644
> > > ---
> > > a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> > > +++
> > > b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> > > @@ -17,6 +17,7 @@ properties:
> > > items:
> > > - enum:
> > > - thead,th1520-dc8200
> > > + - nuvoton,ma35d1-dcu
> > > - const: verisilicon,dc # DC IPs have discoverable
> > > ID/revision
> > > registers
> > >
> > > reg:
> > > @@ -26,14 +27,12 @@ properties:
> > > maxItems: 1
> > >
> > > clocks:
> > > - items:
> > > - - description: DC Core clock
> > > - - description: DMA AXI bus clock
> > > - - description: Configuration AHB bus clock
> > > - - description: Pixel clock of output 0
> > > - - description: Pixel clock of output 1
> > Clock descriptions should still be in the global part instead of
> > the
> > per-compatible part.
> >
> > In the per-compatible part, clock-names should be constraint for
> > SoCs.
> I will move the `items:` clock descriptions back into the global
> `clocks:` property, covering all five possible clocks. In the
> per-compatible sections I will remove the description items and only
> constrain `clocks: minItems/maxItems` and `clock-names:
> minItems/maxItems`; for nuvoton,ma35d1-dcu I will additionally
> override
> `clock-names: items:` to the two names actually used (core, pix0).
Yes, this should be the correct practice, although I wonder whether the
minItems and maxItems properties are needed globally (because these two
seem to have default implicit value).
BTW the MA35D1 manual in fact shows 4 clocks for "DCUltra" in the clock
tree, maybe the DT binding needs to be reconsidered?
Thanks,
Icenowy
> > > + minItems: 2
> > > + maxItems: 5
> > >
> > > clock-names:
> > > + minItems: 2
> > > + maxItems: 5
> > > items:
> > > - const: core
> > > - const: axi
^ permalink raw reply
* [PATCH v2 2/2] drm/panel: add Ilitek ILI7807S panel driver
From: Arpit Saini @ 2026-06-18 10:24 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: arpit.saini, linux-arm-msm, dri-devel, devicetree, linux-kernel,
ayushi.makhija, rajeevny
In-Reply-To: <20260618-ili7807s-v2-0-b3f0c109b102@oss.qualcomm.com>
Add a DRM panel driver for the DLC DLC0697 1080x1920@60Hz MIPI DSI
panel based on the Ilitek ILI7807S display controller.
The panel operates in video burst mode with four data lanes using
RGB888 pixel format.
Signed-off-by: Arpit Saini <arpit.saini@oss.qualcomm.com>
---
drivers/gpu/drm/panel/Kconfig | 12 ++
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-ilitek-ili7807s.c | 297 ++++++++++++++++++++++++++
3 files changed, 310 insertions(+)
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 7450b27622a2..1cbaac1bf545 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -264,6 +264,18 @@ config DRM_PANEL_HYDIS_HV101HD1
If M is selected the module will be called panel-hydis-hv101hd1
+config DRM_PANEL_ILITEK_ILI7807S
+ tristate "Ilitek ILI7807S-based panels"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y if you want to enable support for panels based on the
+ Ilitek ILI7807S display controller, such as the DLC DLC0697
+ 1080x1920 MIPI DSI panel.
+
+ If M is selected the module will be called panel-ilitek-ili7807s.
+
config DRM_PANEL_ILITEK_IL9322
tristate "Ilitek ILI9322 320x240 QVGA panels"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index c2c5cf817116..c3002b351cb8 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112B) += panel-himax-hx83112b.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX83121A) += panel-himax-hx83121a.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
obj-$(CONFIG_DRM_PANEL_HYDIS_HV101HD1) += panel-hydis-hv101hd1.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI7807S) += panel-ilitek-ili7807s.o
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9805) += panel-ilitek-ili9805.o
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c b/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c
new file mode 100644
index 000000000000..bfbb8e29a4aa
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+struct panel_desc {
+ const struct drm_display_mode *mode;
+ unsigned int lanes;
+ enum mipi_dsi_pixel_format format;
+ unsigned long mode_flags;
+ void (*init)(struct mipi_dsi_multi_context *dsi_ctx);
+};
+
+struct ili7807s {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ const struct panel_desc *desc;
+
+ struct regulator_bulk_data *supplies;
+ struct gpio_desc *reset_gpio;
+};
+
+static const struct regulator_bulk_data ili7807s_supplies[] = {
+ { .supply = "vddi" },
+ { .supply = "avdd" },
+ { .supply = "avee" },
+};
+
+static inline struct ili7807s *to_ili7807s(struct drm_panel *panel)
+{
+ return container_of(panel, struct ili7807s, panel);
+}
+
+static void ili7807s_reset(struct ili7807s *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(10000, 11000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+static void dlc0697_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
+{
+ mipi_dsi_dcs_soft_reset_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 120);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xff, 0x78, 0x07, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x5e, 0x09, 0x99);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x53, 0x24);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x55, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x51, 0x3f, 0xff);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 120);
+
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 20);
+}
+
+static int ili7807s_on(struct ili7807s *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ ctx->desc->init(&dsi_ctx);
+
+ ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ return dsi_ctx.accum_err;
+}
+
+static int ili7807s_off(struct ili7807s *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 20);
+
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 120);
+
+ ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ return dsi_ctx.accum_err;
+}
+
+static int ili7807s_prepare(struct drm_panel *panel)
+{
+ struct ili7807s *ctx = to_ili7807s(panel);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ili7807s_supplies), ctx->supplies);
+ if (ret < 0) {
+ dev_err(ctx->panel.dev, "failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ msleep(20);
+
+ ili7807s_reset(ctx);
+
+ ret = ili7807s_on(ctx);
+ if (ret < 0) {
+ dev_err(ctx->panel.dev, "failed to initialise panel: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+ regulator_bulk_disable(ARRAY_SIZE(ili7807s_supplies), ctx->supplies);
+ return ret;
+}
+
+static int ili7807s_unprepare(struct drm_panel *panel)
+{
+ struct ili7807s *ctx = to_ili7807s(panel);
+ int ret;
+
+ ret = ili7807s_off(ctx);
+ if (ret < 0)
+ dev_err(ctx->panel.dev, "failed to disable panel: %d\n", ret);
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+ regulator_bulk_disable(ARRAY_SIZE(ili7807s_supplies), ctx->supplies);
+
+ return 0;
+}
+
+static int ili7807s_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ili7807s *ctx = to_ili7807s(panel);
+
+ return drm_connector_helper_get_modes_fixed(connector, ctx->desc->mode);
+}
+
+static const struct drm_panel_funcs ili7807s_panel_funcs = {
+ .prepare = ili7807s_prepare,
+ .unprepare = ili7807s_unprepare,
+ .get_modes = ili7807s_get_modes,
+};
+
+static int ili7807s_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return ret;
+}
+
+static const struct backlight_ops ili7807s_bl_ops = {
+ .update_status = ili7807s_bl_update_status,
+};
+
+static struct backlight_device *ili7807s_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 0x3fff,
+ .max_brightness = 0x3fff,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &ili7807s_bl_ops, &props);
+}
+
+static const struct drm_display_mode dlc0697_mode = {
+ .clock = 131911,
+
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 18,
+ .hsync_end = 1080 + 18 + 2,
+ .htotal = 1080 + 18 + 2 + 16,
+
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 26,
+ .vsync_end = 1920 + 26 + 4,
+ .vtotal = 1920 + 26 + 4 + 20,
+
+ .width_mm = 0,
+ .height_mm = 0,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct panel_desc dlc0697_desc = {
+ .mode = &dlc0697_mode,
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
+ .init = dlc0697_init_sequence,
+};
+
+static int ili7807s_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct panel_desc *desc;
+ struct ili7807s *ctx;
+ int ret;
+
+ ctx = devm_drm_panel_alloc(dev, struct ili7807s, panel,
+ &ili7807s_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ desc = of_device_get_match_data(dev);
+ ctx->desc = desc;
+
+ ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(ili7807s_supplies),
+ ili7807s_supplies, &ctx->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "failed to get reset gpio\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = desc->lanes;
+ dsi->format = desc->format;
+ dsi->mode_flags = desc->mode_flags;
+
+ ctx->panel.prepare_prev_first = true;
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return ret;
+
+ if (!ctx->panel.backlight) {
+ ctx->panel.backlight = ili7807s_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "failed to create backlight\n");
+ }
+
+ ret = devm_drm_panel_add(dev, &ctx->panel);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to add panel\n");
+
+ ret = devm_mipi_dsi_attach(dev, dsi);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to attach dsi\n");
+
+ return 0;
+}
+
+static const struct of_device_id ili7807s_of_match[] = {
+ { .compatible = "dlc,dlc0697", .data = &dlc0697_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ili7807s_of_match);
+
+static struct mipi_dsi_driver ili7807s_dsi_driver = {
+ .probe = ili7807s_probe,
+ .driver = {
+ .name = "panel-ilitek-ili7807s",
+ .of_match_table = ili7807s_of_match,
+ },
+};
+module_mipi_dsi_driver(ili7807s_dsi_driver);
+
+MODULE_AUTHOR("Arpit Saini <arpit.saini@oss.qualcomm.com>");
+MODULE_DESCRIPTION("Panel driver for Ilitek ILI7807S LCD DSI panel");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: display: panel: add Ilitek ILI7807S panel controller
From: Arpit Saini @ 2026-06-18 10:24 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: arpit.saini, linux-arm-msm, dri-devel, devicetree, linux-kernel,
ayushi.makhija, rajeevny
In-Reply-To: <20260618-ili7807s-v2-0-b3f0c109b102@oss.qualcomm.com>
ILI7807S is a DSI display controller used to drive MIPI-DSI panels.
The DLC DLC0697 1080x1920 LCD panel is based on this controller.
The panel requires a reset GPIO, I/O voltage supply (vddi), positive
LCD bias supply (avdd) and negative LCD bias supply (avee). The panel
operates in video burst mode with four data lanes using RGB888 pixel
format.
Signed-off-by: Arpit Saini <arpit.saini@oss.qualcomm.com>
---
.../bindings/display/panel/ilitek,ili7807s.yaml | 71 ++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml
new file mode 100644
index 000000000000..ba8c5bbf8ffc
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/ilitek,ili7807s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Ilitek ILI7807S-based DSI panels
+
+maintainers:
+ - Arpit Saini <arpit.saini@oss.qualcomm.com>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - dlc,dlc0697
+ - const: ilitek,ili7807s
+
+ reg:
+ maxItems: 1
+ description: DSI virtual channel
+
+ vddi-supply:
+ description: I/O voltage supply (1.8V)
+
+ avdd-supply:
+ description: Positive LCD bias supply (AVDD), typically +5.5V
+ (range 4.5V to 6.3V)
+
+ avee-supply:
+ description: Negative LCD bias supply (AVEE), typically -5.5V
+ (range -6.3V to -4.5V)
+
+required:
+ - compatible
+ - reg
+ - reset-gpios
+ - vddi-supply
+ - avdd-supply
+ - avee-supply
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "dlc,dlc0697", "ilitek,ili7807s";
+ reg = <0>;
+
+ reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>;
+ vddi-supply = <&pm4125_l15>;
+ avdd-supply = <&avdd>;
+ avee-supply = <&avee>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi0_out>;
+ };
+ };
+ };
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH v2 0/2] drm/panel: add support for Ilitek ILI7807S DSI panels
From: Arpit Saini @ 2026-06-18 10:24 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: arpit.saini, linux-arm-msm, dri-devel, devicetree, linux-kernel,
ayushi.makhija, rajeevny
Add DT bindings and a DRM panel driver for panels based on the Ilitek
ILI7807S display controller. The first supported panel is the DLC
DLC0697 1080x1920@60Hz MIPI DSI panel.
Changes in v2:
- Drop MAINTAINERS entry (Dmitry Baryshkov)
- Use devm_drm_panel_add() instead of drm_panel_add() to avoid
manual drm_panel_remove() in the error path (Dmitry Baryshkov)
- Rework backlight: call drm_panel_of_backlight() first and fall back
to creating a DCS backlight device if panel->backlight is still NULL
(Dmitry Baryshkov)
- Remove backlight-en-gpios from the binding (Dmitry Baryshkov)
- Fix mode_flags LPM not restored on backlight update error path
- Link to v1 : https://lore.kernel.org/all/20260518-ili7807s-panel-v1-0-d7b048163b1c@oss.qualcomm.com/
---
Arpit Saini (2):
dt-bindings: display: panel: add Ilitek ILI7807S panel controller
drm/panel: add Ilitek ILI7807S panel driver
.../bindings/display/panel/ilitek,ili7807s.yaml | 71 +++++
drivers/gpu/drm/panel/Kconfig | 12 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-ilitek-ili7807s.c | 297 +++++++++++++++++++++
4 files changed, 381 insertions(+)
---
base-commit: abe651837cb394f76d738a7a747322fca3bf17ba
change-id: 20260615-ili7807s-panel
Best regards,
--
Arpit Saini <arpit.saini@oss.qualcomm.com>
^ 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