[PATCH v7 0/8] Add Qualcomm JPEG V4L2 encoder for SM8250 and SC7280
From: Atanas Filipov
Date: Fri Nov 06 2026 - 03:26:46 EST
The goal is to upstream a standards-based JPEG encode path using the
V4L2 M2M framework, with DT-described hardware resources and SoC DTS
integration.
The JPEG encoder is a standalone hardware IP within the camera
subsystem. It is modelled as a peer node of CAMSS directly under the
SoC bus, with all resources self-described in its own device tree node
(power-domains, clocks, interconnects, iommus). This follows the
consensus reached in the v4 review thread (Bryan O'Donoghue, Konrad
Dybcio, Gjorgji Rosikopulos).
Supported compatibles:
- qcom,sm8250-jpeg-enc
- qcom,sc7280-jpeg-enc
Driver scope and design choices:
- uses the standard V4L2 mem2mem and vb2 framework
- the JPEG header is written by a common v4l2-jpeg helper
- all resources come from DT (clocks, interconnects, iommu,
power-domains)
- power is managed with power-domains (SM8250: TITAN_TOP_GDSC, MX,
MMCX; SC7280: TITAN_TOP_GDSC, CX) and the OPP framework
- the driver selects the core clock for each job from the image size;
the OPP table votes the SoC rails and the DDR bandwidth
Note on the camera NoC AXI clock (camnoc_axi): several camera blocks
share this clock. For now there is no upstream driver that aggregates
their votes, so the driver does this: while the encoder is powered, it
sets a minimum rate on the camera NoC AXI clock source with
clk_set_rate_range(). The minimum is 300 MHz on SM8250 and 150 MHz on
SC7280, the lowest levels. Another user of the clock cannot set a lower
rate. The series does not depend on the camcc icc-clk series.
Functional validation:
- tested with v4l2-ctl and GStreamer (v4l2jpegenc) on RB5 (SM8250)
and RB3 Gen2 (QCS6490)
- v4l2-compliance passes
- throughput and DDR traffic measured for each OPP on both boards; the
OPP bandwidth values and the reference throughput come from these
measurements
Known limitations:
- no scaling
- width and height must be multiples of 16
- the camera NoC AXI clock has a fixed minimum rate; its bandwidth is
not aggregated with the other camera blocks (see the note above)
Changes since v6:
Series:
- Added SC7280 (Kodiak) support and RB3 Gen2.
- Split the driver patch into media/jpeg.h constants, a common
v4l2-jpeg header writer and the driver. (Dmitry)
- The SoC nodes are disabled by default and enabled per board (new
qrb5165-rb5 and qcs6490-rb3gen2 patches).
- No dependency on the camcc icc-clk series any more.
Binding (dt-bindings: media: qcom: Add JPEG encoder binding):
- Added qcom,sc7280-jpeg-enc (titan_top and cx power domains).
- New clock names: core, bus, config, camnoc_axi. (Dmitry)
- Added the camnoc_axi_src clock.
- SM8250 power domains: titan_top, mx, mmcx. (Dmitry)
media/jpeg.h (media: jpeg: Add JPEG baseline and JFIF APP0 constants):
- New patch with the standard JPEG/JFIF values. (Dmitry)
v4l2-jpeg (media: v4l2-jpeg: Add a baseline JPEG header writer):
- New patch with a common header writer; the qcom JFIF header code is
removed from the driver. (Dmitry)
Driver (media: qcom: jpeg: Add Qualcomm JPEG V4L2 encoder):
- Added SC7280 support.
- Power domains are attached with devm_pm_domain_attach_list(); the
OPP table votes the SoC rails with required-opps. (Dmitry)
- Fixed the clock/OPP order in runtime PM. (Dmitry)
- Minimum camera NoC AXI rate with clk_set_rate_range().
- The core clock is selected from a measured reference throughput.
- GENMASK()/BIT() with FIELD_GET()/FIELD_PREP(). (Dmitry)
- JFIF tables from the common V4L2 JPEG helpers. (Dmitry)
- qcom_jenc_v420_* names; removed the qcom_jpeg_hw_ops table.
(Dmitry)
- Removed the custom performance controls. G/S_PARM is not used
either; the driver selects the clock and bandwidth itself.
(Dmitry, Gjorgji)
DTS (arm64: dts: qcom: sm8250, kodiak):
- required-opps on every OPP for the power domains. (Dmitry)
- Interconnect on the mmss_noc camnoc SF path to EBI; added the
camnoc_axi_src clock.
- OPP bandwidth values from measured DDR traffic.
- New kodiak node for SC7280.
Changes since v5:
Binding (dt-bindings: media: qcom,sm8250-jpeg-enc):
- Removed GCC_CAMERA_HF_AXI_CLK (hf_axi) clock and hf-mnoc interconnect
path. The JPEG encoder uses only the SF CAMNOC port; the HF port is for
real-time capture pipelines. (Loic Poulain)
- Added RPMHPD_MMCX and RPMHPD_MX to power-domains. (bod)
- Added power-domain-names property with entries "titan_top", "mmcx", "mx".
- Added power-domain-names to the required list.
DTS (arm64: dts: qcom: sm8250):
- Removed GCC_CAMERA_HF_AXI_CLK (hf_axi) clock and hf-mnoc interconnect
path from jpeg-encoder node. (Loic Poulain)
- Added RPMHPD_MMCX and RPMHPD_MX to power-domains. (bod)
- Added power-domain-names = "titan_top", "mmcx", "mx".
Changes since v4:
Architecture:
- Dropped patch 1/5 (devm_of_platform_populate in camss.c) entirely.
JPEG is now a peer node of CAMSS, not a child node. (bod)
- Dropped patch 2/5 (camss binding unevaluatedProperties). (krzk, bod)
- Moved jpeg-encoder DTS node from camss@ to soc@ level. (bod)
Binding (dt-bindings: media: qcom,sm8250-jpeg-enc):
- Renamed binding file from qcom,jpeg-encoder.yaml to
qcom,sm8250-jpeg-enc.yaml to match compatible string convention.
- Renamed compatible from qcom,sm8250-jenc to qcom,sm8250-jpeg-enc
for readability. (Bjorn Andersson)
- Added power-domains property and required entry. (bod)
- Added iommus description with SID value 0x2040 for SM8250. (bod)
- Dropped soc{} wrapper from example; node is directly under soc. (Dmitry)
- Added Gjorgji Rosikopulos as co-maintainer.
- Patch order corrected: binding before driver before DTS. (krzk)
Driver (media: qcom: jpeg):
- Removed <linux/mod_devicetable.h> include. (Uwe Kleine-Koenig)
- Removed dev_dbg calls from OPP clock selection path. (Dmitry)
- Removed camss_dev field and pm_runtime_resume_and_get(camss_dev);
PM is now managed independently via power-domains. (Dmitry)
- Removed incorrect device_link_add() to parent; not needed in peer
node model.
- Moved file-local defines out of qcom_jenc_defs.h to their respective
.c files. (Dmitry)
- Fixed dev_pm_opp_put() placement: called before rc check. (Dmitry)
- Replaced _DEFINE_DEV_PM_OPS() with SYSTEM_SLEEP_PM_OPS() +
RUNTIME_PM_OPS() macros, consistent with other media drivers. (Frank Li)
- Fixed Kconfig source order to alphabetical. (krzk)
- Updated compatible string in driver match table to qcom,sm8250-jpeg-enc.
DTS (arm64: dts: qcom: sm8250):
- Added status = "disabled" to jpeg-encoder node.
- Used 0x0 instead of bare 0 for zero cells in reg property. (Dmitry)
- Dropped opp-peak-kBps and opp-avg-kBps from OPP table; no upstream
aggregation mechanism available yet.
Changes since v3:
CAMSS binding (dt-bindings: media: qcom,sm8250-camss):
- Added as new patch 2/5; allows #address-cells, #size-cells, ranges,
and child nodes using unevaluatedProperties: false.
Binding (dt-bindings: media: qcom,jpeg-encoder):
- Dropped soc and camss wrapper nodes from example. (Dmitry)
- Removed opp-level from all OPP table entries. (Dmitry)
CAMSS (media: qcom: camss):
- Replaced patch 1/4 with Bryan O'Donoghue's original upstream commit.
Driver (media: qcom: jpeg):
- Cleaned up driver patch commit. (bod)
DTS (arm64: dts: qcom: sm8250):
- Restored camss interconnect-names to original values.
Changes since v2:
Binding (dt-bindings: media: qcom,jpeg-encoder):
- IOMMU stream IDs documented in binding description. (bod)
- Dropped "Properties documented:" section from commit message. (krzk)
- Dropped clocks minItems constraint. (krzk)
- Renamed clock-names to match hardware signal names. (krzk)
- Renamed interconnect-names to reflect path topology. (krzk, Dmitry)
DTS (arm64: dts: qcom: sm8250):
- Removed cell-index; use lowercase hex. (Dmitry)
- Moved jpeg-encoder node into the camss block as a child node. (bod)
Driver (media: qcom: jpeg):
- Sort obj-y entries alphabetically in qcom/Makefile. (krzk)
- Use devm_mutex_init() instead of mutex_init(). (Frank Li)
Changes since v1:
Binding (dt-bindings: media: qcom,jpeg-encoder):
- Removed qcm6490 and sm8550 compatible strings; SM8250 only.
- Fixed clock-names block in the binding example.
- Dropped reg-names: with a single reg entry it is unnecessary.
- Removed description literal block scalar (|).
- Dropped _clk suffix from clock-names.
- Added iommus description in the properties section.
Driver (media: qcom: jpeg):
- Migrated to devm_clk_bulk_get_all().
- Migrated to the OPP framework for clock rate management.
- Switched to RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros.
- platform_set_drvdata() moved to immediately after allocation.
- .pm uses pm_ptr().
Atanas Filipov (8):
dt-bindings: media: qcom: Add JPEG encoder binding
media: jpeg: Add JPEG baseline and JFIF APP0 constants
media: v4l2-jpeg: Add a baseline JPEG header writer
media: qcom: jpeg: Add Qualcomm JPEG V4L2 encoder
arm64: dts: qcom: sm8250: Add JPEG encoder node
arm64: dts: qcom: qrb5165-rb5: Enable JPEG encoder
arm64: dts: qcom: kodiak: Add JPEG encoder node
arm64: dts: qcom: qcs6490-rb3gen2: Enable JPEG encoder
.../bindings/media/qcom,sm8250-jpeg-enc.yaml | 193 +++
arch/arm64/boot/dts/qcom/kodiak.dtsi | 69 +
arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 4 +
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 4 +
arch/arm64/boot/dts/qcom/sm8250.dtsi | 74 +
drivers/media/platform/qcom/Kconfig | 1 +
drivers/media/platform/qcom/Makefile | 1 +
drivers/media/platform/qcom/jpeg/Kconfig | 15 +
drivers/media/platform/qcom/jpeg/Makefile | 7 +
.../media/platform/qcom/jpeg/qcom_jenc_dev.c | 375 ++++
.../media/platform/qcom/jpeg/qcom_jenc_dev.h | 122 ++
.../media/platform/qcom/jpeg/qcom_jenc_v420.c | 1527 +++++++++++++++++
.../media/platform/qcom/jpeg/qcom_jenc_v420.h | 43 +
.../qcom/jpeg/qcom_jenc_v420_hw_info.h | 215 +++
.../media/platform/qcom/jpeg/qcom_jenc_v4l2.c | 1176 +++++++++++++
.../media/platform/qcom/jpeg/qcom_jenc_v4l2.h | 13 +
drivers/media/v4l2-core/v4l2-jpeg.c | 165 ++
include/media/jpeg.h | 79 +
include/media/v4l2-jpeg.h | 31 +
19 files changed, 4114 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/qcom,sm8250-jpeg-enc.yaml
create mode 100644 drivers/media/platform/qcom/jpeg/Kconfig
create mode 100644 drivers/media/platform/qcom/jpeg/Makefile
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_dev.c
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_dev.h
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_v420.c
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_v420.h
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_v420_hw_info.h
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_v4l2.c
create mode 100644 drivers/media/platform/qcom/jpeg/qcom_jenc_v4l2.h
base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b
--
2.34.1