* [PATCH 0/8] Add support for Wave6 video codec driver
@ 2025-02-10 9:07 Nas Chung
2025-02-10 9:07 ` [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter Nas Chung
` (7 more replies)
0 siblings, 8 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
This patch series introduces support for the Chips&Media Wave6 video
codec IP, a completely different hardware architecture compared to Wave5.
The wave6 driver is a M2M stateful encoder/decoder driver.
It supports various video formats, including H.264 and H.265,
for both encoding and decoding.
On NXP i.MX SoCs, the Wave6 IP functionality is split between two devices:
VPU Control Device, Manages shared resources such as firmware access and
power domains.
VPU Device, Provides encoding and decoding capabilities.
The VPU device cannot operate independently without the VPU control device.
This driver has been tested with GStreamer on:
- NXP i.MX95 board
- pre-silicon FPGA environment
Test results for decoder fluster:
- JVT-AVC_V1, Ran 77/135 tests successfully in 35.929 secs
- JVT-FR-EXT, Ran 25/69 tests successfully in 17.717 secs
- JCT-VC-HEVC_V1, Ran 132/147 tests successfully in 81.568 secs
- All failures are due to unsupported hardware features:
-- 10bit, Resolutions higher than 4K, FMO, MBAFF
-- Extended profile, Field encoding and High422 sreams.
Test results for v4l2-compliance:
v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t
v4l2-compliance SHA: 77f5df419204 2025-02-07 08:59:59
Compliance test for wave6-dec device /dev/video0:
Driver Info:
Driver name : wave6-dec
Card type : wave6-dec
Bus info : platform:wave6-dec
Driver version : 6.9.2
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
fail: ../utils/v4l2-compliance/v4l2-test-controls.cpp(1180): !have_source_change || !have_eos
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 7 Private Controls: 1
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
Total for wave6-dec device /dev/video0: 48, Succeeded: 47, Failed: 1, Warnings: 0
v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t
v4l2-compliance SHA: 77f5df419204 2025-02-07 08:59:59
Compliance test for wave6-enc device /dev/video1:
Driver Info:
Driver name : wave6-enc
Card type : wave6-enc
Bus info : platform:wave6-enc
Driver version : 6.9.2
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
fail: ../utils/v4l2-compliance/v4l2-test-controls.cpp(1169): node->codec_mask & STATEFUL_ENCODER
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 53 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
Total for wave6-enc device /dev/video1: 48, Succeeded: 47, Failed: 1, Warnings: 0
Nas Chung (8):
media: platform: chips-media: wave5: Rename Kconfig parameter
media: v4l2-common: Add YUV24 format info
dt-bindings: media: nxp: Add Wave6 video codec device
media: chips-media: wave6: Add Wave6 codec driver
media: chips-media: wave6: Add v4l2 m2m driver
media: chips-media: wave6: Add Wave6 vpu interface
media: chips-media: wave6: Add Wave6 control driver
media: chips-media: wave6: Improve debugging capabilities
.../bindings/media/nxp,wave633c.yaml | 202 ++
MAINTAINERS | 8 +
arch/arm64/configs/defconfig | 2 +-
drivers/media/platform/chips-media/Kconfig | 1 +
drivers/media/platform/chips-media/Makefile | 1 +
.../media/platform/chips-media/wave5/Kconfig | 6 +-
.../media/platform/chips-media/wave5/Makefile | 2 +-
.../media/platform/chips-media/wave6/Kconfig | 26 +
.../media/platform/chips-media/wave6/Makefile | 17 +
.../platform/chips-media/wave6/wave6-hw.c | 3113 +++++++++++++++++
.../platform/chips-media/wave6/wave6-hw.h | 69 +
.../chips-media/wave6/wave6-regdefine.h | 675 ++++
.../platform/chips-media/wave6/wave6-trace.h | 336 ++
.../platform/chips-media/wave6/wave6-vdi.c | 52 +
.../platform/chips-media/wave6/wave6-vdi.h | 59 +
.../chips-media/wave6/wave6-vpu-ctrl.c | 1020 ++++++
.../chips-media/wave6/wave6-vpu-ctrl.h | 38 +
.../chips-media/wave6/wave6-vpu-dbg.c | 230 ++
.../chips-media/wave6/wave6-vpu-dbg.h | 22 +
.../chips-media/wave6/wave6-vpu-dec.c | 1883 ++++++++++
.../chips-media/wave6/wave6-vpu-enc.c | 2698 ++++++++++++++
.../chips-media/wave6/wave6-vpu-v4l2.c | 381 ++
.../platform/chips-media/wave6/wave6-vpu.c | 487 +++
.../platform/chips-media/wave6/wave6-vpu.h | 106 +
.../platform/chips-media/wave6/wave6-vpuapi.c | 1001 ++++++
.../platform/chips-media/wave6/wave6-vpuapi.h | 993 ++++++
.../chips-media/wave6/wave6-vpuconfig.h | 80 +
.../chips-media/wave6/wave6-vpuerror.h | 262 ++
drivers/media/v4l2-core/v4l2-common.c | 1 +
29 files changed, 13766 insertions(+), 5 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/nxp,wave633c.yaml
create mode 100644 drivers/media/platform/chips-media/wave6/Kconfig
create mode 100644 drivers/media/platform/chips-media/wave6/Makefile
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-regdefine.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-trace.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-enc.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-v4l2.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuapi.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuapi.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuconfig.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuerror.h
--
2.31.1
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
@ 2025-02-10 9:07 ` Nas Chung
2025-02-10 17:24 ` Krzysztof Kozlowski
2025-02-10 9:07 ` [PATCH 2/8] media: v4l2-common: Add YUV24 format info Nas Chung
` (6 subsequent siblings)
7 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
The existing Kconfig parameter VIDEO_WAVE_VPU is ambiguous,
as it does not clearly indicate that it is specific to the Wave5 IP.
Rename VIDEO_WAVE_VPU to VIDEO_WAVE5_VPU to make it explicit
that the parameter is specific to the Wave5 IP.
No functional changes, only the parameter name is updated.
Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
arch/arm64/configs/defconfig | 2 +-
drivers/media/platform/chips-media/wave5/Kconfig | 6 +++---
drivers/media/platform/chips-media/wave5/Makefile | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..d904d4dc4f0d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -837,7 +837,7 @@ CONFIG_VIDEO_AMPHION_VPU=m
CONFIG_VIDEO_CADENCE_CSI2RX=m
CONFIG_VIDEO_MEDIATEK_JPEG=m
CONFIG_VIDEO_MEDIATEK_VCODEC=m
-CONFIG_VIDEO_WAVE_VPU=m
+CONFIG_VIDEO_WAVE5_VPU=m
CONFIG_VIDEO_E5010_JPEG_ENC=m
CONFIG_VIDEO_IMX7_CSI=m
CONFIG_VIDEO_IMX_MIPI_CSIS=m
diff --git a/drivers/media/platform/chips-media/wave5/Kconfig b/drivers/media/platform/chips-media/wave5/Kconfig
index f1bcef5177bd..914720a35de8 100644
--- a/drivers/media/platform/chips-media/wave5/Kconfig
+++ b/drivers/media/platform/chips-media/wave5/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-config VIDEO_WAVE_VPU
- tristate "Chips&Media Wave Codec Driver"
+config VIDEO_WAVE5_VPU
+ tristate "Chips&Media Wave5 Codec Driver"
depends on V4L_MEM2MEM_DRIVERS
depends on VIDEO_DEV && OF
depends on ARCH_K3 || COMPILE_TEST
@@ -9,7 +9,7 @@ config VIDEO_WAVE_VPU
select V4L2_MEM2MEM_DEV
select GENERIC_ALLOCATOR
help
- Chips&Media stateful encoder and decoder driver.
+ Chips&Media Wave5 stateful encoder and decoder driver.
The driver supports HEVC and H264 formats.
To compile this driver as modules, choose M here: the
modules will be called wave5.
diff --git a/drivers/media/platform/chips-media/wave5/Makefile b/drivers/media/platform/chips-media/wave5/Makefile
index 3d738a03bd8e..81be0e1dcebd 100644
--- a/drivers/media/platform/chips-media/wave5/Makefile
+++ b/drivers/media/platform/chips-media/wave5/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_VIDEO_WAVE_VPU) += wave5.o
+obj-$(CONFIG_VIDEO_WAVE5_VPU) += wave5.o
wave5-objs += wave5-hw.o \
wave5-vpuapi.o \
wave5-vdi.o \
--
2.31.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 2/8] media: v4l2-common: Add YUV24 format info
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
2025-02-10 9:07 ` [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter Nas Chung
@ 2025-02-10 9:07 ` Nas Chung
2025-02-10 14:00 ` Sebastian Fricke
2025-02-10 9:07 ` [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device Nas Chung
` (5 subsequent siblings)
7 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
The YUV24 format is missing an entry in the v4l2_format_info().
The YUV24 format is the packed YUV 4:4:4 formats with 8 bits
per component.
Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
drivers/media/v4l2-core/v4l2-common.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 0a2f4f0d0a07..de3636f1cdf1 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -269,6 +269,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
{ .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
{ .format = V4L2_PIX_FMT_Y216, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
{ .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YUV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
{ .format = V4L2_PIX_FMT_MT2110T, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
.block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
{ .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
--
2.31.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
2025-02-10 9:07 ` [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter Nas Chung
2025-02-10 9:07 ` [PATCH 2/8] media: v4l2-common: Add YUV24 format info Nas Chung
@ 2025-02-10 9:07 ` Nas Chung
2025-02-10 17:30 ` Krzysztof Kozlowski
2025-02-10 9:07 ` [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver Nas Chung
` (4 subsequent siblings)
7 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Add documents for the Wave6 video codec on NXP i.MX SoCs.
Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
.../bindings/media/nxp,wave633c.yaml | 202 ++++++++++++++++++
MAINTAINERS | 8 +
2 files changed, 210 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/nxp,wave633c.yaml
diff --git a/Documentation/devicetree/bindings/media/nxp,wave633c.yaml b/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
new file mode 100644
index 000000000000..99c3008314c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
@@ -0,0 +1,202 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nxp,wave633c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Chips&Media Wave6 Series multi-standard codec IP on NXP i.MX SoCs.
+
+maintainers:
+ - Nas Chung <nas.chung@chipsnmedia.com>
+ - Jackson Lee <jackson.lee@chipsnmedia.com>
+
+description:
+ The Chips&Media Wave6 codec IP is a multi-standard video encoder/decoder.
+ On NXP i.MX SoCs, Wave6 codec IP functionality is split between the VPU control device
+ (vpu-ctrl) and the VPU device (vpu). The VPU control device manages shared resources
+ such as firmware access and power domains, while the VPU device provides encoding
+ and decoding capabilities. The VPU devie cannot operate independently
+ without the VPU control device.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - nxp,imx95-wave633c-ctrl
+ - nxp,imx95-wave633c
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: VPU clock
+ - description: VPU associated block clock
+
+ clock-names:
+ items:
+ - const: vpu
+ - const: vpublk_wave
+
+ power-domains:
+ minItems: 1
+ items:
+ - description: Main VPU power domain
+ - description: Performance power domain
+
+ power-domain-names:
+ items:
+ - const: vpumix
+ - const: vpuperf
+
+ cnm,ctrl:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle of the VPU control device node. Required for VPU operation.
+
+ boot:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle of the boot memory region node for the VPU control device.
+
+ sram:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle of the SRAM memory region node for the VPU control device.
+
+ '#cooling-cells':
+ const: 2
+
+ support-follower:
+ type: boolean
+ description: Indicates whether the VPU domain power always on.
+
+patternProperties:
+ "^vpu-ctrl@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ items:
+ - enum:
+ - nxp,imx95-wave633c-ctrl
+ reg: true
+ clocks: true
+ clock-names: true
+ power-domains:
+ items:
+ - description: Main VPU power domain
+ - description: Performance power domain
+ power-domain-names:
+ items:
+ - const: vpumix
+ - const: vpuperf
+ sram: true
+ boot: true
+ '#cooling-cells': true
+ support-follower: true
+ required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - power-domains
+ - power-domain-names
+ - sram
+ - boot
+
+ additionalProperties: false
+
+ "^vpu@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ items:
+ - enum:
+ - nxp,imx95-wave633c
+ reg: true
+ interrupts: true
+ clocks: true
+ clock-names: true
+ power-domains:
+ maxItems: 1
+ description: Main VPU power domain
+ cnm,ctrl: true
+ required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - power-domains
+ - cnm,ctrl
+
+ additionalProperties: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/nxp,imx95-clock.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ vpuctrl: vpu-ctrl@4c4c0000 {
+ compatible = "nxp,imx95-wave633c-ctrl";
+ reg = <0x0 0x4c4c0000 0x0 0x10000>;
+ clocks = <&scmi_clk 115>,
+ <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
+ clock-names = "vpu", "vpublk_wave";
+ power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
+ power-domain-names = "vpumix", "vpuperf";
+ #cooling-cells = <2>;
+ boot = <&vpu_boot>;
+ sram = <&sram1>;
+ };
+
+ vpu0: vpu@4c480000 {
+ compatible = "nxp,imx95-wave633c";
+ reg = <0x0 0x4c480000 0x0 0x10000>;
+ interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk 115>,
+ <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
+ clock-names = "vpu", "vpublk_wave";
+ power-domains = <&scmi_devpd 21>;
+ cnm,ctrl = <&vpuctrl>;
+ };
+
+ vpu1: vpu@4c490000 {
+ compatible = "nxp,imx95-wave633c";
+ reg = <0x0 0x4c490000 0x0 0x10000>;
+ interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk 115>,
+ <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
+ clock-names = "vpu", "vpublk_wave";
+ power-domains = <&scmi_devpd 21>;
+ cnm,ctrl = <&vpuctrl>;
+ };
+
+ vpu2: vpu@4c4a0000 {
+ compatible = "nxp,imx95-wave633c";
+ reg = <0x0 0x4c4a0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk 115>,
+ <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
+ clock-names = "vpu", "vpublk_wave";
+ power-domains = <&scmi_devpd 21>;
+ cnm,ctrl = <&vpuctrl>;
+ };
+
+ vpu3: vpu@4c4b0000 {
+ compatible = "nxp,imx95-wave633c";
+ reg = <0x0 0x4c4b0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk 115>,
+ <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
+ clock-names = "vpu", "vpublk_wave";
+ power-domains = <&scmi_devpd 21>;
+ cnm,ctrl = <&vpuctrl>;
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 896a307fa065..5ff5b1f1ced2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25462,6 +25462,14 @@ S: Maintained
F: Documentation/devicetree/bindings/media/cnm,wave521c.yaml
F: drivers/media/platform/chips-media/wave5/
+WAVE6 VPU CODEC DRIVER
+M: Nas Chung <nas.chung@chipsnmedia.com>
+M: Jackson Lee <jackson.lee@chipsnmedia.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/nxp,wave633c.yaml
+F: drivers/media/platform/chips-media/wave6/
+
WHISKEYCOVE PMIC GPIO DRIVER
M: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
L: linux-gpio@vger.kernel.org
--
2.31.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
` (2 preceding siblings ...)
2025-02-10 9:07 ` [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device Nas Chung
@ 2025-02-10 9:07 ` Nas Chung
2025-02-10 17:40 ` Krzysztof Kozlowski
2025-02-10 9:07 ` [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver Nas Chung
` (3 subsequent siblings)
7 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Chips&Media Wave6 stateful codec driver.
The codec driver provides encoding and decoding capabilities
for H.264, HEVC, and other video formats.
Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
drivers/media/platform/chips-media/Kconfig | 1 +
drivers/media/platform/chips-media/Makefile | 1 +
.../media/platform/chips-media/wave6/Kconfig | 26 +
.../media/platform/chips-media/wave6/Makefile | 17 +
.../platform/chips-media/wave6/wave6-vpu.c | 487 ++++++++++++++++++
.../platform/chips-media/wave6/wave6-vpu.h | 106 ++++
6 files changed, 638 insertions(+)
create mode 100644 drivers/media/platform/chips-media/wave6/Kconfig
create mode 100644 drivers/media/platform/chips-media/wave6/Makefile
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.h
diff --git a/drivers/media/platform/chips-media/Kconfig b/drivers/media/platform/chips-media/Kconfig
index ad350eb6b1fc..8ef7fc8029a4 100644
--- a/drivers/media/platform/chips-media/Kconfig
+++ b/drivers/media/platform/chips-media/Kconfig
@@ -4,3 +4,4 @@ comment "Chips&Media media platform drivers"
source "drivers/media/platform/chips-media/coda/Kconfig"
source "drivers/media/platform/chips-media/wave5/Kconfig"
+source "drivers/media/platform/chips-media/wave6/Kconfig"
diff --git a/drivers/media/platform/chips-media/Makefile b/drivers/media/platform/chips-media/Makefile
index 6b5d99de8b54..b9a07a91c9d6 100644
--- a/drivers/media/platform/chips-media/Makefile
+++ b/drivers/media/platform/chips-media/Makefile
@@ -2,3 +2,4 @@
obj-y += coda/
obj-y += wave5/
+obj-y += wave6/
diff --git a/drivers/media/platform/chips-media/wave6/Kconfig b/drivers/media/platform/chips-media/wave6/Kconfig
new file mode 100644
index 000000000000..0f45581ff273
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/Kconfig
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_WAVE6_VPU
+ tristate "Chips&Media Wave6 Codec Driver"
+ depends on V4L_MEM2MEM_DRIVERS
+ depends on VIDEO_DEV && OF
+ depends on ARCH_MXC || COMPILE_TEST
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_MEM2MEM_DEV
+ select GENERIC_ALLOCATOR
+ help
+ Chips&Media Wave6 stateful codec driver.
+ The codec driver provides encoding and decoding capabilities
+ for H.264, HEVC, and other video formats.
+ To compile this driver as modules, choose M here: the
+ modules will be called wave6.
+
+config VIDEO_WAVE6_VPU_CTRL
+ tristate "Chips&Media Wave6 Codec Control Driver"
+ depends on VIDEO_WAVE6_VPU
+ default VIDEO_WAVE6_VPU if ARCH_MXC || COMPILE_TEST
+ help
+ Chips&Media Wave6 control driver.
+ The control driver manages shared resources such as firmware
+ access and power domains and clock.
+ To compile this driver as modules, choose M here: the
+ modules will be called wave6-ctrl.
diff --git a/drivers/media/platform/chips-media/wave6/Makefile b/drivers/media/platform/chips-media/wave6/Makefile
new file mode 100644
index 000000000000..c2180406c193
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# tell define_trace.h where to find the trace header
+CFLAGS_wave6-vpu.o := -I$(src)
+
+wave6-ctrl-objs += wave6-vpu-ctrl.o
+obj-$(CONFIG_VIDEO_WAVE6_VPU_CTRL) += wave6-ctrl.o
+
+wave6-objs += wave6-vpu.o \
+ wave6-vpu-v4l2.o \
+ wave6-vpu-dbg.o \
+ wave6-vdi.o \
+ wave6-vpuapi.o \
+ wave6-vpu-dec.o \
+ wave6-vpu-enc.o \
+ wave6-hw.o
+obj-$(CONFIG_VIDEO_WAVE6_VPU) += wave6.o
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu.c b/drivers/media/platform/chips-media/wave6/wave6-vpu.c
new file mode 100644
index 000000000000..470d22489ecc
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu.c
@@ -0,0 +1,487 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave6 series multi-standard codec IP - wave6 codec driver
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_platform.h>
+#include <linux/debugfs.h>
+#include "wave6-vpu.h"
+#include "wave6-regdefine.h"
+#include "wave6-vpuconfig.h"
+#include "wave6-hw.h"
+#include "wave6-vpu-ctrl.h"
+#include "wave6-vpu-dbg.h"
+
+#define CREATE_TRACE_POINTS
+#include "wave6-trace.h"
+
+#define VPU_PLATFORM_DEVICE_NAME "wave6-vpu"
+#define VPU_CLK_NAME "vcodec"
+#define WAVE6_VPU_DEBUGFS_DIR "wave6"
+
+#define WAVE6_IS_ENC BIT(0)
+#define WAVE6_IS_DEC BIT(1)
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+
+struct wave6_match_data {
+ int codec_types;
+ u32 compatible_fw_version;
+};
+
+static const struct wave6_match_data wave633c_data = {
+ .codec_types = WAVE6_IS_ENC | WAVE6_IS_DEC,
+ .compatible_fw_version = 0x3000000,
+};
+
+unsigned int wave6_vpu_debug(void)
+{
+ return debug;
+}
+
+static void wave6_vpu_get_clk(struct vpu_device *vpu_dev)
+{
+ int i;
+
+ if (!vpu_dev || !vpu_dev->num_clks || vpu_dev->clk_vpu)
+ return;
+
+ for (i = 0; i < vpu_dev->num_clks; i++) {
+ if (vpu_dev->clks[i].id && !strcmp(vpu_dev->clks[i].id, "vpu")) {
+ vpu_dev->clk_vpu = vpu_dev->clks[i].clk;
+ return;
+ }
+ }
+
+ vpu_dev->clk_vpu = vpu_dev->clks[0].clk;
+}
+
+static irqreturn_t wave6_vpu_irq(int irq, void *dev_id)
+{
+ struct vpu_device *dev = dev_id;
+ u32 irq_status;
+
+ if (wave6_vdi_readl(dev, W6_VPU_VPU_INT_STS)) {
+ irq_status = wave6_vdi_readl(dev, W6_VPU_VINT_REASON);
+
+ wave6_vdi_writel(dev, W6_VPU_VINT_REASON_CLR, irq_status);
+ wave6_vdi_writel(dev, W6_VPU_VINT_CLEAR, 0x1);
+
+ trace_irq(dev, irq_status);
+
+ kfifo_in(&dev->irq_status, &irq_status, sizeof(int));
+
+ return IRQ_WAKE_THREAD;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wave6_vpu_irq_thread(int irq, void *dev_id)
+{
+ struct vpu_device *dev = dev_id;
+ struct vpu_instance *inst;
+ int irq_status, ret;
+
+ while (kfifo_len(&dev->irq_status)) {
+ bool error = false;
+
+ ret = kfifo_out(&dev->irq_status, &irq_status, sizeof(int));
+ if (!ret)
+ break;
+
+ if (irq_status & BIT(W6_INT_BIT_REQ_WORK_BUF)) {
+ if (!dev->ctrl)
+ continue;
+
+ wave6_vpu_ctrl_require_buffer(dev->ctrl, &dev->entity);
+ continue;
+ }
+
+ if ((irq_status & BIT(W6_INT_BIT_INIT_SEQ)) ||
+ (irq_status & BIT(W6_INT_BIT_ENC_SET_PARAM))) {
+ complete(&dev->irq_done);
+ continue;
+ }
+
+ if (irq_status & BIT(W6_INT_BIT_BSBUF_ERROR))
+ error = true;
+
+ inst = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+ if (inst)
+ inst->ops->finish_process(inst, error);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static u32 wave6_vpu_read_reg(struct device *dev, u32 addr)
+{
+ struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+ return wave6_vdi_readl(vpu_dev, addr);
+}
+
+static void wave6_vpu_write_reg(struct device *dev, u32 addr, u32 data)
+{
+ struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+ wave6_vdi_writel(vpu_dev, addr, data);
+}
+
+static void wave6_vpu_on_boot(struct device *dev)
+{
+ struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+ u32 product_code;
+ u32 version;
+ u32 revision;
+ u32 hw_version;
+ int ret;
+
+ product_code = wave6_vdi_readl(vpu_dev, W6_VPU_RET_PRODUCT_VERSION);
+
+ wave6_vpu_enable_interrupt(vpu_dev);
+ ret = wave6_vpu_get_version(vpu_dev, &version, &revision);
+ if (ret) {
+ dev_err(dev, "wave6_vpu_get_version fail\n");
+ return;
+ }
+
+ hw_version = wave6_vdi_readl(vpu_dev, W6_RET_CONF_REVISION);
+
+ if (vpu_dev->product_code != product_code ||
+ vpu_dev->fw_version != version ||
+ vpu_dev->fw_revision != revision ||
+ vpu_dev->hw_version != hw_version) {
+ vpu_dev->product_code = product_code;
+ vpu_dev->fw_version = version;
+ vpu_dev->fw_revision = revision;
+ vpu_dev->hw_version = hw_version;
+ dev_info(dev, "product: %08x, fw_version : %d.%d.%d(r%d), hw_version : 0x%x\n",
+ vpu_dev->product_code,
+ (version >> 24) & 0xFF,
+ (version >> 16) & 0xFF,
+ (version >> 0) & 0xFFFF,
+ revision,
+ vpu_dev->hw_version);
+ }
+
+ if (vpu_dev->res->compatible_fw_version > version)
+ dev_err(dev, "compatible firmware version is v%d.%d.%d or higher, but only v%d.%d.%d\n",
+ (vpu_dev->res->compatible_fw_version >> 24) & 0xFF,
+ (vpu_dev->res->compatible_fw_version >> 16) & 0xFF,
+ vpu_dev->res->compatible_fw_version & 0xFFFF,
+ (version >> 24) & 0xFF,
+ (version >> 16) & 0xFF,
+ version & 0xFFFF);
+
+ wave6_vpu_get_clk(vpu_dev);
+}
+
+void wave6_vpu_pause(struct device *dev, int resume)
+{
+ struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+ mutex_lock(&vpu_dev->pause_lock);
+ if (resume) {
+ vpu_dev->pause_request--;
+ if (!vpu_dev->pause_request)
+ v4l2_m2m_resume(vpu_dev->m2m_dev);
+ } else {
+ if (!vpu_dev->pause_request)
+ v4l2_m2m_suspend(vpu_dev->m2m_dev);
+ vpu_dev->pause_request++;
+ }
+ mutex_unlock(&vpu_dev->pause_lock);
+}
+
+void wave6_vpu_activate(struct vpu_device *dev)
+{
+ dev->active = true;
+}
+
+void wave6_vpu_wait_activated(struct vpu_device *dev)
+{
+ wave6_vpu_check_state(dev);
+}
+
+static int wave6_vpu_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct vpu_device *dev;
+ const struct wave6_match_data *match_data;
+ struct device_node *np;
+ struct platform_device *pctrl;
+
+ match_data = device_get_match_data(&pdev->dev);
+ if (!match_data) {
+ dev_err(&pdev->dev, "missing match_data\n");
+ return -EINVAL;
+ }
+
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret < 0) {
+ dev_err(&pdev->dev, "dma_set_mask_and_coherent failed: %d\n", ret);
+ return ret;
+ }
+
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ mutex_init(&dev->dev_lock);
+ mutex_init(&dev->hw_lock);
+ mutex_init(&dev->pause_lock);
+ init_completion(&dev->irq_done);
+ dev_set_drvdata(&pdev->dev, dev);
+ dev->dev = &pdev->dev;
+ dev->res = match_data;
+
+ dev->entity.dev = dev->dev;
+ dev->entity.read_reg = wave6_vpu_read_reg;
+ dev->entity.write_reg = wave6_vpu_write_reg;
+ dev->entity.on_boot = wave6_vpu_on_boot;
+ dev->entity.pause = wave6_vpu_pause;
+
+ dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dev->reg_base))
+ return PTR_ERR(dev->reg_base);
+
+ np = of_parse_phandle(pdev->dev.of_node, "cnm,ctrl", 0);
+ if (np) {
+ pctrl = of_find_device_by_node(np);
+ of_node_put(np);
+ if (pctrl) {
+ dev->ctrl = &pctrl->dev;
+ if (wave6_vpu_ctrl_get_state(dev->ctrl) < 0) {
+ dev_info(&pdev->dev, "vpu ctrl is not ready, defer probe\n");
+ return -EPROBE_DEFER;
+ }
+ } else {
+ dev_info(&pdev->dev, "vpu ctrl is not found\n");
+ return -EINVAL;
+ }
+ }
+
+ ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "unable to get clocks: %d\n", ret);
+ ret = 0;
+ }
+ dev->num_clks = ret;
+
+ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "v4l2_device_register fail: %d\n", ret);
+ return ret;
+ }
+
+ ret = wave6_vpu_init_m2m_dev(dev);
+ if (ret)
+ goto err_v4l2_unregister;
+
+ dev->irq = platform_get_irq(pdev, 0);
+ if (dev->irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq resource\n");
+ ret = -ENXIO;
+ goto err_m2m_dev_release;
+ }
+
+ if (kfifo_alloc(&dev->irq_status, 16 * sizeof(int), GFP_KERNEL)) {
+ dev_err(&pdev->dev, "failed to allocate fifo\n");
+ goto err_m2m_dev_release;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, dev->irq, wave6_vpu_irq,
+ wave6_vpu_irq_thread, 0, "vpu_irq", dev);
+ if (ret) {
+ dev_err(&pdev->dev, "fail to register interrupt handler: %d\n", ret);
+ goto err_kfifo_free;
+ }
+
+ dev->temp_vbuf.size = ALIGN(WAVE6_TEMPBUF_SIZE, 4096);
+ ret = wave6_alloc_dma(dev->dev, &dev->temp_vbuf);
+ if (ret) {
+ dev_err(&pdev->dev, "alloc temp of size %zu failed\n",
+ dev->temp_vbuf.size);
+ goto err_kfifo_free;
+ }
+
+ dev->debugfs = debugfs_lookup(WAVE6_VPU_DEBUGFS_DIR, NULL);
+ if (IS_ERR_OR_NULL(dev->debugfs))
+ dev->debugfs = debugfs_create_dir(WAVE6_VPU_DEBUGFS_DIR, NULL);
+
+ pm_runtime_enable(&pdev->dev);
+
+ if (dev->res->codec_types & WAVE6_IS_DEC) {
+ ret = wave6_vpu_dec_register_device(dev);
+ if (ret) {
+ dev_err(&pdev->dev, "wave6_vpu_dec_register_device fail: %d\n", ret);
+ goto err_temp_vbuf_free;
+ }
+ }
+ if (dev->res->codec_types & WAVE6_IS_ENC) {
+ ret = wave6_vpu_enc_register_device(dev);
+ if (ret) {
+ dev_err(&pdev->dev, "wave6_vpu_enc_register_device fail: %d\n", ret);
+ goto err_dec_unreg;
+ }
+ }
+
+ if (dev->ctrl && wave6_vpu_ctrl_support_follower(dev->ctrl)) {
+ wave6_vpu_activate(dev);
+ ret = pm_runtime_resume_and_get(dev->dev);
+ if (ret)
+ goto err_enc_unreg;
+ }
+
+ dev_dbg(&pdev->dev, "Added wave6 driver with caps %s %s\n",
+ dev->res->codec_types & WAVE6_IS_ENC ? "'ENCODE'" : "",
+ dev->res->codec_types & WAVE6_IS_DEC ? "'DECODE'" : "");
+
+ return 0;
+
+err_enc_unreg:
+ if (dev->res->codec_types & WAVE6_IS_ENC)
+ wave6_vpu_enc_unregister_device(dev);
+err_dec_unreg:
+ if (dev->res->codec_types & WAVE6_IS_DEC)
+ wave6_vpu_dec_unregister_device(dev);
+err_temp_vbuf_free:
+ wave6_free_dma(&dev->temp_vbuf);
+err_kfifo_free:
+ kfifo_free(&dev->irq_status);
+err_m2m_dev_release:
+ wave6_vpu_release_m2m_dev(dev);
+err_v4l2_unregister:
+ v4l2_device_unregister(&dev->v4l2_dev);
+
+ return ret;
+}
+
+static void wave6_vpu_remove(struct platform_device *pdev)
+{
+ struct vpu_device *dev = dev_get_drvdata(&pdev->dev);
+
+ if (dev->ctrl && wave6_vpu_ctrl_support_follower(dev->ctrl)) {
+ if (!pm_runtime_suspended(&pdev->dev))
+ pm_runtime_put_sync(&pdev->dev);
+ }
+ pm_runtime_disable(&pdev->dev);
+
+ wave6_vpu_enc_unregister_device(dev);
+ wave6_vpu_dec_unregister_device(dev);
+ wave6_free_dma(&dev->temp_vbuf);
+ kfifo_free(&dev->irq_status);
+ wave6_vpu_release_m2m_dev(dev);
+ v4l2_device_unregister(&dev->v4l2_dev);
+}
+
+#ifdef CONFIG_PM
+static int wave6_vpu_runtime_suspend(struct device *dev)
+{
+ struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+ if (!vpu_dev)
+ return -ENODEV;
+
+ dprintk(dev, "runtime suspend\n");
+ if (vpu_dev->ctrl && vpu_dev->active)
+ wave6_vpu_ctrl_put_sync(vpu_dev->ctrl, &vpu_dev->entity);
+ if (vpu_dev->num_clks)
+ clk_bulk_disable_unprepare(vpu_dev->num_clks, vpu_dev->clks);
+
+ return 0;
+}
+
+static int wave6_vpu_runtime_resume(struct device *dev)
+{
+ struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (!vpu_dev)
+ return -ENODEV;
+
+ dprintk(dev, "runtime resume\n");
+ if (vpu_dev->num_clks) {
+ ret = clk_bulk_prepare_enable(vpu_dev->num_clks, vpu_dev->clks);
+ if (ret) {
+ dev_err(dev, "failed to enable clocks: %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (vpu_dev->ctrl && vpu_dev->active) {
+ ret = wave6_vpu_ctrl_resume_and_get(vpu_dev->ctrl, &vpu_dev->entity);
+ if (ret && vpu_dev->num_clks)
+ clk_bulk_disable_unprepare(vpu_dev->num_clks, vpu_dev->clks);
+ } else {
+ wave6_vpu_check_state(vpu_dev);
+ }
+
+ return ret;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int wave6_vpu_suspend(struct device *dev)
+{
+ int ret;
+
+ dprintk(dev, "suspend\n");
+ wave6_vpu_pause(dev, 0);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ wave6_vpu_pause(dev, 1);
+
+ return ret;
+}
+
+static int wave6_vpu_resume(struct device *dev)
+{
+ int ret;
+
+ dprintk(dev, "resume\n");
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ wave6_vpu_pause(dev, 1);
+ return 0;
+}
+#endif
+static const struct dev_pm_ops wave6_vpu_pm_ops = {
+ SET_RUNTIME_PM_OPS(wave6_vpu_runtime_suspend, wave6_vpu_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(wave6_vpu_suspend, wave6_vpu_resume)
+};
+
+static const struct of_device_id wave6_dt_ids[] = {
+ { .compatible = "nxp,imx95-wave633c", .data = &wave633c_data },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, wave6_dt_ids);
+
+static struct platform_driver wave6_vpu_driver = {
+ .driver = {
+ .name = VPU_PLATFORM_DEVICE_NAME,
+ .of_match_table = of_match_ptr(wave6_dt_ids),
+ .pm = &wave6_vpu_pm_ops,
+ },
+ .probe = wave6_vpu_probe,
+ .remove = wave6_vpu_remove,
+};
+
+module_platform_driver(wave6_vpu_driver);
+MODULE_DESCRIPTION("chips&media VPU V4L2 driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu.h b/drivers/media/platform/chips-media/wave6/wave6-vpu.h
new file mode 100644
index 000000000000..51cda07863a4
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - wave6 codec driver
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE6_VPU_H__
+#define __WAVE6_VPU_H__
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+#include "wave6-vpuconfig.h"
+#include "wave6-vpuapi.h"
+
+struct vpu_buffer {
+ struct v4l2_m2m_buffer v4l2_m2m_buf;
+ bool consumed;
+ bool used;
+ bool error;
+ bool force_key_frame;
+ bool force_frame_qp;
+ u32 force_i_frame_qp;
+ u32 force_p_frame_qp;
+ u32 force_b_frame_qp;
+ ktime_t ts_input;
+ ktime_t ts_start;
+ ktime_t ts_finish;
+ ktime_t ts_output;
+ u64 hw_time;
+ u32 average_qp;
+};
+
+enum vpu_fmt_type {
+ VPU_FMT_TYPE_CODEC = 0,
+ VPU_FMT_TYPE_RAW = 1
+};
+
+struct vpu_format {
+ unsigned int v4l2_pix_fmt;
+ unsigned int max_width;
+ unsigned int min_width;
+ unsigned int max_height;
+ unsigned int min_height;
+ unsigned int num_planes;
+};
+
+static inline struct vpu_instance *wave6_to_vpu_inst(struct v4l2_fh *vfh)
+{
+ return container_of(vfh, struct vpu_instance, v4l2_fh);
+}
+
+static inline struct vpu_instance *wave6_ctrl_to_vpu_inst(struct v4l2_ctrl *vctrl)
+{
+ return container_of(vctrl->handler, struct vpu_instance, v4l2_ctrl_hdl);
+}
+
+static inline struct vpu_buffer *wave6_to_vpu_buf(struct vb2_v4l2_buffer *vbuf)
+{
+ return container_of(vbuf, struct vpu_buffer, v4l2_m2m_buf.vb);
+}
+
+static inline bool wave6_vpu_both_queues_are_streaming(struct vpu_instance *inst)
+{
+ struct vb2_queue *vq_cap = v4l2_m2m_get_dst_vq(inst->v4l2_fh.m2m_ctx);
+ struct vb2_queue *vq_out = v4l2_m2m_get_src_vq(inst->v4l2_fh.m2m_ctx);
+
+ return vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out);
+}
+
+u32 wave6_vpu_get_consumed_fb_num(struct vpu_instance *inst);
+u32 wave6_vpu_get_used_fb_num(struct vpu_instance *inst);
+void wave6_vpu_pause(struct device *dev, int resume);
+void wave6_vpu_activate(struct vpu_device *dev);
+void wave6_vpu_wait_activated(struct vpu_device *dev);
+void wave6_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp,
+ unsigned int width,
+ unsigned int height);
+struct vb2_v4l2_buffer *wave6_get_dst_buf_by_addr(struct vpu_instance *inst,
+ dma_addr_t addr);
+dma_addr_t wave6_get_dma_addr(struct vb2_v4l2_buffer *buf,
+ unsigned int plane_no);
+enum codec_std wave6_to_codec_std(enum vpu_instance_type type, unsigned int v4l2_pix_fmt);
+const char *wave6_vpu_instance_state_name(u32 state);
+void wave6_vpu_set_instance_state(struct vpu_instance *inst, u32 state);
+u64 wave6_vpu_cycle_to_ns(struct vpu_device *vpu_dev, u64 cycle);
+int wave6_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout);
+int wave6_vpu_dec_register_device(struct vpu_device *dev);
+void wave6_vpu_dec_unregister_device(struct vpu_device *dev);
+int wave6_vpu_enc_register_device(struct vpu_device *dev);
+void wave6_vpu_enc_unregister_device(struct vpu_device *dev);
+void wave6_vpu_finish_job(struct vpu_instance *inst);
+void wave6_vpu_handle_performance(struct vpu_instance *inst, struct vpu_buffer *vpu_buf);
+void wave6_vpu_reset_performance(struct vpu_instance *inst);
+int wave6_vpu_init_m2m_dev(struct vpu_device *dev);
+void wave6_vpu_release_m2m_dev(struct vpu_device *dev);
+int wave6_vpu_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub);
+void wave6_vpu_return_buffers(struct vpu_instance *inst,
+ unsigned int type, enum vb2_buffer_state state);
+
+#endif /* __WAVE6_VPU_H__ */
--
2.31.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
` (3 preceding siblings ...)
2025-02-10 9:07 ` [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver Nas Chung
@ 2025-02-10 9:07 ` Nas Chung
2025-02-10 17:37 ` Krzysztof Kozlowski
` (2 more replies)
2025-02-10 9:07 ` [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities Nas Chung
` (2 subsequent siblings)
7 siblings, 3 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Chips&Media Wave6 control driver.
The control driver manages shared resources such as firmware
access and power domains and clock.
Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
.../chips-media/wave6/wave6-vpu-ctrl.c | 1020 +++++++++++++++++
.../chips-media/wave6/wave6-vpu-ctrl.h | 38 +
2 files changed, 1058 insertions(+)
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.h
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c b/drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
new file mode 100644
index 000000000000..fa7bf5ccc0d0
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
@@ -0,0 +1,1020 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave6 series multi-standard codec IP - wave6 control driver
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
+#include <linux/genalloc.h>
+#include <linux/thermal.h>
+#include <linux/units.h>
+#include <linux/pm_opp.h>
+#include <linux/freezer.h>
+
+#include "wave6-vpuconfig.h"
+#include "wave6-regdefine.h"
+#include "wave6-vdi.h"
+#include "wave6-vpu-ctrl.h"
+
+#define VPU_CTRL_PLATFORM_DEVICE_NAME "wave6-vpu-ctrl"
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+
+static bool wave6_cooling_disable;
+module_param(wave6_cooling_disable, bool, 0644);
+MODULE_PARM_DESC(wave6_cooling_disable, "enable or disable cooling");
+
+#define dprintk(dev, fmt, arg...) \
+ do { \
+ if (debug) \
+ dev_info(dev, fmt, ## arg); \
+ } while (0)
+
+#define wave6_wait_event_freezable_timeout(wq_head, condition, timeout) \
+({ \
+ int wave6_wait_ret = 0; \
+ unsigned long _timeout = timeout; \
+ unsigned long stop; \
+ stop = jiffies + _timeout; \
+ do { \
+ if (wave6_wait_ret == -ERESTARTSYS && freezing(current)) \
+ clear_thread_flag(TIF_SIGPENDING); \
+ _timeout = stop - jiffies; \
+ if ((long)_timeout <= 0) { \
+ wave6_wait_ret = -ERESTARTSYS; \
+ break; \
+ } \
+ wave6_wait_ret = wait_event_freezable_timeout(wq_head, condition, _timeout); \
+ } while (wave6_wait_ret == -ERESTARTSYS && freezing(current)); \
+ wave6_wait_ret; \
+})
+
+struct vpu_ctrl_resource {
+ const char *fw_name;
+ u32 sram_size;
+};
+
+struct vpu_ctrl_buf {
+ struct list_head list;
+ struct vpu_buf buf;
+};
+
+struct vpu_ctrl {
+ struct device *dev;
+ void __iomem *reg_base;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct vpu_dma_buf boot_mem;
+ u32 state;
+ struct mutex ctrl_lock; /* the lock for vpu control device */
+ struct wave6_vpu_entity *current_entity;
+ struct list_head entities;
+ const struct vpu_ctrl_resource *res;
+ struct gen_pool *sram_pool;
+ struct vpu_dma_buf sram_buf;
+ struct list_head buffers;
+ bool support_follower;
+ wait_queue_head_t load_fw_wq;
+ int thermal_event;
+ int thermal_max;
+ struct thermal_cooling_device *cooling;
+ struct dev_pm_domain_list *pd_list;
+ struct device *dev_perf;
+ int clk_id;
+ unsigned long *freq_table;
+};
+
+#define DOMAIN_VPU_PWR 0
+#define DOMAIN_VPU_PERF 1
+
+static const struct vpu_ctrl_resource wave633c_ctrl_data = {
+ .fw_name = "wave633c_codec_fw.bin",
+ /* For HEVC, AVC, 4096x4096, 8bit */
+ .sram_size = 0x14800,
+};
+
+static void wave6_vpu_ctrl_writel(struct device *dev, u32 addr, u32 data)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+
+ writel(data, ctrl->reg_base + addr);
+}
+
+int wave6_alloc_dma(struct device *dev, struct vpu_buf *vb)
+{
+ void *vaddr;
+ dma_addr_t daddr;
+
+ if (!vb || !vb->size)
+ return -EINVAL;
+
+ vaddr = dma_alloc_coherent(dev, vb->size, &daddr, GFP_KERNEL);
+ if (!vaddr)
+ return -ENOMEM;
+
+ vb->vaddr = vaddr;
+ vb->daddr = daddr;
+ vb->dev = dev;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wave6_alloc_dma);
+
+void wave6_free_dma(struct vpu_buf *vb)
+{
+ if (!vb || !vb->size || !vb->vaddr)
+ return;
+
+ dma_free_coherent(vb->dev, vb->size, vb->vaddr, vb->daddr);
+ memset(vb, 0, sizeof(*vb));
+}
+EXPORT_SYMBOL_GPL(wave6_free_dma);
+
+static const char *wave6_vpu_ctrl_state_name(u32 state)
+{
+ switch (state) {
+ case WAVE6_VPU_STATE_OFF:
+ return "off";
+ case WAVE6_VPU_STATE_PREPARE:
+ return "prepare";
+ case WAVE6_VPU_STATE_ON:
+ return "on";
+ case WAVE6_VPU_STATE_SLEEP:
+ return "sleep";
+ default:
+ return "unknown";
+ }
+}
+
+static void wave6_vpu_ctrl_set_state(struct vpu_ctrl *ctrl, u32 state)
+{
+ dprintk(ctrl->dev, "set state: %s -> %s\n",
+ wave6_vpu_ctrl_state_name(ctrl->state), wave6_vpu_ctrl_state_name(state));
+ ctrl->state = state;
+}
+
+static int wave6_vpu_ctrl_wait_busy(struct wave6_vpu_entity *entity)
+{
+ u32 val;
+
+ return read_poll_timeout(entity->read_reg, val, !val,
+ 10, W6_VPU_POLL_TIMEOUT, false,
+ entity->dev, W6_VPU_BUSY_STATUS);
+}
+
+static int wave6_vpu_ctrl_check_result(struct wave6_vpu_entity *entity)
+{
+ if (entity->read_reg(entity->dev, W6_RET_SUCCESS))
+ return 0;
+
+ return entity->read_reg(entity->dev, W6_RET_FAIL_REASON);
+}
+
+static u32 wave6_vpu_ctrl_get_code_buf_size(struct vpu_ctrl *ctrl)
+{
+ return min_t(u32, ctrl->boot_mem.size, WAVE6_MAX_CODE_BUF_SIZE);
+}
+
+static void wave6_vpu_ctrl_remap_code_buffer(struct vpu_ctrl *ctrl)
+{
+ dma_addr_t code_base = ctrl->boot_mem.dma_addr;
+ u32 i, reg_val, remap_size;
+
+ for (i = 0; i < wave6_vpu_ctrl_get_code_buf_size(ctrl) / W6_REMAP_MAX_SIZE; i++) {
+ remap_size = (W6_REMAP_MAX_SIZE >> 12) & 0x1ff;
+ reg_val = 0x80000000 |
+ (WAVE6_UPPER_PROC_AXI_ID << 20) |
+ (0 << 16) |
+ (i << 12) |
+ BIT(11) |
+ remap_size;
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_VPU_REMAP_CTRL_GB, reg_val);
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_VPU_REMAP_VADDR_GB, i * W6_REMAP_MAX_SIZE);
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_VPU_REMAP_PADDR_GB,
+ code_base + i * W6_REMAP_MAX_SIZE);
+ }
+}
+
+static int wave6_vpu_ctrl_init_vpu(struct vpu_ctrl *ctrl)
+{
+ struct wave6_vpu_entity *entity = ctrl->current_entity;
+ int ret;
+
+ dprintk(ctrl->dev, "cold boot vpu\n");
+
+ entity->write_reg(entity->dev, W6_VPU_BUSY_STATUS, 1);
+ entity->write_reg(entity->dev, W6_CMD_INIT_VPU_SEC_AXI_BASE_CORE0,
+ ctrl->sram_buf.dma_addr);
+ entity->write_reg(entity->dev, W6_CMD_INIT_VPU_SEC_AXI_SIZE_CORE0,
+ ctrl->sram_buf.size);
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_COMMAND_GB, W6_CMD_INIT_VPU);
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_VPU_REMAP_CORE_START_GB, 1);
+
+ ret = wave6_vpu_ctrl_wait_busy(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "init vpu timeout\n");
+ return -EINVAL;
+ }
+
+ ret = wave6_vpu_ctrl_check_result(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "init vpu fail, reason 0x%x\n", ret);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void wave6_vpu_ctrl_on_boot(struct wave6_vpu_entity *entity)
+{
+ if (!entity->on_boot)
+ return;
+
+ if (!entity->booted) {
+ entity->on_boot(entity->dev);
+ entity->booted = true;
+ }
+}
+
+static void wave6_vpu_ctrl_clear_firmware_buffers(struct vpu_ctrl *ctrl,
+ struct wave6_vpu_entity *entity)
+{
+ int ret;
+
+ dprintk(ctrl->dev, "clear firmware work buffers\n");
+
+ entity->write_reg(entity->dev, W6_VPU_BUSY_STATUS, 1);
+ entity->write_reg(entity->dev, W6_COMMAND, W6_CMD_INIT_WORK_BUF);
+ entity->write_reg(entity->dev, W6_VPU_HOST_INT_REQ, 1);
+
+ ret = wave6_vpu_ctrl_wait_busy(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "set buffer failed\n");
+ return;
+ }
+
+ ret = wave6_vpu_ctrl_check_result(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "set buffer failed, reason 0x%x\n", ret);
+ return;
+ }
+}
+
+int wave6_vpu_ctrl_require_buffer(struct device *dev, struct wave6_vpu_entity *entity)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+ struct vpu_ctrl_buf *pbuf;
+ u32 size;
+ int ret = -ENOMEM;
+
+ if (!ctrl || !entity)
+ return -EINVAL;
+
+ size = entity->read_reg(entity->dev, W6_CMD_SET_CTRL_WORK_BUF_SIZE);
+ if (!size)
+ return 0;
+
+ pbuf = kzalloc(sizeof(*pbuf), GFP_KERNEL);
+ if (!pbuf)
+ goto exit;
+
+ pbuf->buf.size = size;
+ ret = wave6_alloc_dma(ctrl->dev, &pbuf->buf);
+ if (ret) {
+ kfree(pbuf);
+ goto exit;
+ }
+
+ list_add_tail(&pbuf->list, &ctrl->buffers);
+ entity->write_reg(entity->dev, W6_CMD_SET_CTRL_WORK_BUF_ADDR, pbuf->buf.daddr);
+exit:
+ entity->write_reg(entity->dev, W6_CMD_SET_CTRL_WORK_BUF_SIZE, 0);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_require_buffer);
+
+static void wave6_vpu_ctrl_clear_buffers(struct vpu_ctrl *ctrl)
+{
+ struct wave6_vpu_entity *entity;
+ struct vpu_ctrl_buf *pbuf, *tmp;
+
+ dprintk(ctrl->dev, "clear all buffers\n");
+
+ entity = list_first_entry_or_null(&ctrl->entities,
+ struct wave6_vpu_entity, list);
+ if (entity)
+ wave6_vpu_ctrl_clear_firmware_buffers(ctrl, entity);
+
+ list_for_each_entry_safe(pbuf, tmp, &ctrl->buffers, list) {
+ list_del(&pbuf->list);
+ wave6_free_dma(&pbuf->buf);
+ kfree(pbuf);
+ }
+}
+
+static void wave6_vpu_ctrl_boot_done(struct vpu_ctrl *ctrl, int wakeup)
+{
+ struct wave6_vpu_entity *entity;
+
+ if (ctrl->state == WAVE6_VPU_STATE_ON)
+ return;
+
+ if (!wakeup)
+ wave6_vpu_ctrl_clear_buffers(ctrl);
+
+ list_for_each_entry(entity, &ctrl->entities, list)
+ wave6_vpu_ctrl_on_boot(entity);
+
+ dprintk(ctrl->dev, "boot done from %s\n", wakeup ? "wakeup" : "cold boot");
+
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_ON);
+}
+
+static bool wave6_vpu_ctrl_find_entity(struct vpu_ctrl *ctrl, struct wave6_vpu_entity *entity)
+{
+ struct wave6_vpu_entity *tmp;
+
+ list_for_each_entry(tmp, &ctrl->entities, list) {
+ if (tmp == entity)
+ return true;
+ }
+
+ return false;
+}
+
+static void wave6_vpu_ctrl_load_firmware(const struct firmware *fw, void *context)
+{
+ struct vpu_ctrl *ctrl = context;
+ struct wave6_vpu_entity *entity = ctrl->current_entity;
+ u32 product_code;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(ctrl->dev);
+ if (ret) {
+ dev_err(ctrl->dev, "pm runtime resume fail, ret = %d\n", ret);
+ mutex_lock(&ctrl->ctrl_lock);
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ ctrl->current_entity = NULL;
+ mutex_unlock(&ctrl->ctrl_lock);
+ release_firmware(fw);
+ return;
+ }
+
+ if (!fw || !fw->data) {
+ dev_err(ctrl->dev, "No firmware.\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (fw->size + WAVE6_EXTRA_CODE_BUF_SIZE > wave6_vpu_ctrl_get_code_buf_size(ctrl)) {
+ dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
+ fw->size, ctrl->boot_mem.size);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ product_code = entity->read_reg(entity->dev, W6_VPU_RET_PRODUCT_VERSION);
+ if (!PRODUCT_CODE_W_SERIES(product_code)) {
+ dev_err(ctrl->dev, "unknown product : %08x\n", product_code);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ memcpy(ctrl->boot_mem.vaddr, fw->data, fw->size);
+
+exit:
+ mutex_lock(&ctrl->ctrl_lock);
+ if (!ret && wave6_vpu_ctrl_find_entity(ctrl, ctrl->current_entity)) {
+ wave6_vpu_ctrl_remap_code_buffer(ctrl);
+ ret = wave6_vpu_ctrl_init_vpu(ctrl);
+ } else {
+ ret = -EINVAL;
+ }
+ mutex_unlock(&ctrl->ctrl_lock);
+
+ pm_runtime_put_sync(ctrl->dev);
+ release_firmware(fw);
+
+ mutex_lock(&ctrl->ctrl_lock);
+ ctrl->current_entity = NULL;
+ if (ret)
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ else
+ wave6_vpu_ctrl_boot_done(ctrl, 0);
+ mutex_unlock(&ctrl->ctrl_lock);
+
+ wake_up_interruptible_all(&ctrl->load_fw_wq);
+}
+
+static int wave6_vpu_ctrl_sleep(struct vpu_ctrl *ctrl, struct wave6_vpu_entity *entity)
+{
+ int ret;
+
+ dprintk(ctrl->dev, "sleep firmware\n");
+
+ entity->write_reg(entity->dev, W6_VPU_BUSY_STATUS, 1);
+ entity->write_reg(entity->dev, W6_CMD_INSTANCE_INFO, 0);
+ entity->write_reg(entity->dev, W6_COMMAND, W6_CMD_SLEEP_VPU);
+ entity->write_reg(entity->dev, W6_VPU_HOST_INT_REQ, 1);
+
+ ret = wave6_vpu_ctrl_wait_busy(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "sleep vpu timeout\n");
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ return -EINVAL;
+ }
+
+ ret = wave6_vpu_ctrl_check_result(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "sleep vpu fail, reason 0x%x\n", ret);
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ return -EIO;
+ }
+
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_SLEEP);
+
+ return 0;
+}
+
+static int wave6_vpu_ctrl_wakeup(struct vpu_ctrl *ctrl, struct wave6_vpu_entity *entity)
+{
+ int ret;
+
+ dprintk(ctrl->dev, "wakeup firmware\n");
+
+ wave6_vpu_ctrl_remap_code_buffer(ctrl);
+
+ entity->write_reg(entity->dev, W6_VPU_BUSY_STATUS, 1);
+ entity->write_reg(entity->dev, W6_CMD_INIT_VPU_SEC_AXI_BASE_CORE0,
+ ctrl->sram_buf.dma_addr);
+ entity->write_reg(entity->dev, W6_CMD_INIT_VPU_SEC_AXI_SIZE_CORE0,
+ ctrl->sram_buf.size);
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_COMMAND_GB, W6_CMD_WAKEUP_VPU);
+ wave6_vpu_ctrl_writel(ctrl->dev, W6_VPU_REMAP_CORE_START_GB, 1);
+
+ ret = wave6_vpu_ctrl_wait_busy(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "wakeup vpu timeout\n");
+ return -EINVAL;
+ }
+
+ ret = wave6_vpu_ctrl_check_result(entity);
+ if (ret) {
+ dev_err(ctrl->dev, "wakeup vpu fail, reason 0x%x\n", ret);
+ return -EIO;
+ }
+
+ wave6_vpu_ctrl_boot_done(ctrl, 1);
+
+ return 0;
+}
+
+static int wave6_vpu_ctrl_try_boot(struct vpu_ctrl *ctrl, struct wave6_vpu_entity *entity)
+{
+ int ret;
+
+ if (ctrl->state != WAVE6_VPU_STATE_OFF && ctrl->state != WAVE6_VPU_STATE_SLEEP)
+ return 0;
+
+ if (entity->read_reg(entity->dev, W6_VPU_VCPU_CUR_PC)) {
+ dprintk(ctrl->dev, "try boot directly as firmware is running\n");
+ wave6_vpu_ctrl_boot_done(ctrl, ctrl->state == WAVE6_VPU_STATE_SLEEP);
+ return 0;
+ }
+
+ if (ctrl->state == WAVE6_VPU_STATE_SLEEP) {
+ ret = wave6_vpu_ctrl_wakeup(ctrl, entity);
+ return ret;
+ }
+
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_PREPARE);
+ ctrl->current_entity = entity;
+ ret = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_UEVENT,
+ ctrl->res->fw_name,
+ ctrl->dev, GFP_KERNEL,
+ ctrl,
+ wave6_vpu_ctrl_load_firmware);
+ if (ret) {
+ dev_err(ctrl->dev, "request firmware %s fail, ret = %d\n", ctrl->res->fw_name, ret);
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ return ret;
+ }
+
+ return 0;
+}
+
+bool wave6_vpu_ctrl_support_follower(struct device *dev)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (!ctrl)
+ return false;
+
+ return ctrl->support_follower;
+}
+EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_support_follower);
+
+int wave6_vpu_ctrl_resume_and_get(struct device *dev, struct wave6_vpu_entity *entity)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+ bool boot;
+ int ret;
+
+ if (!ctrl)
+ return -EINVAL;
+
+ if (!entity || !entity->dev || !entity->read_reg || !entity->write_reg)
+ return -EINVAL;
+
+ mutex_lock(&ctrl->ctrl_lock);
+
+ ret = pm_runtime_resume_and_get(ctrl->dev);
+ if (ret) {
+ dev_err(dev, "pm runtime resume fail, ret = %d\n", ret);
+ mutex_unlock(&ctrl->ctrl_lock);
+ return ret;
+ }
+
+ entity->booted = false;
+
+ if (ctrl->current_entity)
+ boot = false;
+ else
+ boot = list_empty(&ctrl->entities) ? true : false;
+
+ list_add_tail(&entity->list, &ctrl->entities);
+ if (boot)
+ ret = wave6_vpu_ctrl_try_boot(ctrl, entity);
+
+ if (ctrl->state == WAVE6_VPU_STATE_ON)
+ wave6_vpu_ctrl_on_boot(entity);
+
+ if (ret)
+ pm_runtime_put_sync(ctrl->dev);
+
+ mutex_unlock(&ctrl->ctrl_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_resume_and_get);
+
+void wave6_vpu_ctrl_put_sync(struct device *dev, struct wave6_vpu_entity *entity)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (!ctrl)
+ return;
+
+ if (entity == ctrl->current_entity)
+ wave6_vpu_ctrl_wait_done(dev);
+
+ mutex_lock(&ctrl->ctrl_lock);
+
+ if (!wave6_vpu_ctrl_find_entity(ctrl, entity))
+ goto exit;
+
+ list_del_init(&entity->list);
+ if (list_empty(&ctrl->entities)) {
+ if (!entity->read_reg(entity->dev, W6_VPU_VCPU_CUR_PC))
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ else
+ wave6_vpu_ctrl_sleep(ctrl, entity);
+ }
+
+ if (!pm_runtime_suspended(ctrl->dev))
+ pm_runtime_put_sync(ctrl->dev);
+exit:
+ mutex_unlock(&ctrl->ctrl_lock);
+}
+EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_put_sync);
+
+int wave6_vpu_ctrl_wait_done(struct device *dev)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+ int ret;
+
+ if (!ctrl)
+ return -EINVAL;
+
+ if (ctrl->state == WAVE6_VPU_STATE_OFF)
+ return -EINVAL;
+
+ if (ctrl->state == WAVE6_VPU_STATE_ON)
+ return 0;
+
+ ret = wave6_wait_event_freezable_timeout(ctrl->load_fw_wq,
+ wave6_vpu_ctrl_get_state(dev) ==
+ WAVE6_VPU_STATE_ON,
+ msecs_to_jiffies(W6_BOOT_WAIT_TIMEOUT));
+ if (ret == -ERESTARTSYS || !ret) {
+ dev_err(ctrl->dev, "fail to wait vcpu boot done,ret %d\n", ret);
+ mutex_lock(&ctrl->ctrl_lock);
+ wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
+ mutex_unlock(&ctrl->ctrl_lock);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctrl->ctrl_lock);
+ wave6_vpu_ctrl_boot_done(ctrl, 0);
+ mutex_unlock(&ctrl->ctrl_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_wait_done);
+
+int wave6_vpu_ctrl_get_state(struct device *dev)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (!ctrl)
+ return -EINVAL;
+
+ return ctrl->state;
+}
+EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_get_state);
+
+static void wave6_vpu_ctrl_init_reserved_boot_region(struct vpu_ctrl *ctrl)
+{
+ if (ctrl->boot_mem.size < WAVE6_CODE_BUF_SIZE) {
+ dev_warn(ctrl->dev, "boot memory size (%zu) is too small\n", ctrl->boot_mem.size);
+ ctrl->boot_mem.phys_addr = 0;
+ ctrl->boot_mem.size = 0;
+ memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
+ return;
+ }
+
+ ctrl->boot_mem.vaddr = devm_memremap(ctrl->dev,
+ ctrl->boot_mem.phys_addr,
+ ctrl->boot_mem.size,
+ MEMREMAP_WC);
+ if (!ctrl->boot_mem.vaddr) {
+ memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
+ return;
+ }
+
+ ctrl->boot_mem.dma_addr = dma_map_resource(ctrl->dev,
+ ctrl->boot_mem.phys_addr,
+ ctrl->boot_mem.size,
+ DMA_BIDIRECTIONAL,
+ 0);
+ if (!ctrl->boot_mem.dma_addr) {
+ memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
+ return;
+ }
+
+ dev_info(ctrl->dev, "boot phys_addr: %pad, dma_addr: %pad, size: 0x%zx\n",
+ &ctrl->boot_mem.phys_addr,
+ &ctrl->boot_mem.dma_addr,
+ ctrl->boot_mem.size);
+}
+
+static int wave6_vpu_ctrl_thermal_update(struct device *dev, int state)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+ unsigned long new_clock_rate;
+ int ret;
+
+ if (wave6_cooling_disable || !ctrl->dev_perf || state > ctrl->thermal_max || !ctrl->cooling)
+ return 0;
+
+ new_clock_rate = DIV_ROUND_UP(ctrl->freq_table[state], HZ_PER_KHZ);
+ dev_dbg(dev, "receive cooling set state: %d, new clock rate %ld\n",
+ state, new_clock_rate);
+
+ ret = dev_pm_genpd_set_performance_state(ctrl->dev_perf, new_clock_rate);
+ dev_dbg(dev, "clk set to %lu\n", clk_get_rate(ctrl->clks[ctrl->clk_id].clk));
+ if (ret && !((ret == -ENODEV) || (ret == -EOPNOTSUPP))) {
+ dev_err(dev, "failed to set perf to %lu (ret = %d)\n", new_clock_rate, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wave6_cooling_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct vpu_ctrl *ctrl = cdev->devdata;
+
+ *state = ctrl->thermal_max;
+
+ return 0;
+}
+
+static int wave6_cooling_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct vpu_ctrl *ctrl = cdev->devdata;
+
+ *state = ctrl->thermal_event;
+
+ return 0;
+}
+
+static int wave6_cooling_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+{
+ struct vpu_ctrl *ctrl = cdev->devdata;
+ struct wave6_vpu_entity *entity;
+
+ ctrl->thermal_event = state;
+
+ list_for_each_entry(entity, &ctrl->entities, list) {
+ if (entity->pause)
+ entity->pause(entity->dev, 0);
+ }
+
+ wave6_vpu_ctrl_thermal_update(ctrl->dev, state);
+
+ list_for_each_entry(entity, &ctrl->entities, list) {
+ if (entity->pause)
+ entity->pause(entity->dev, 1);
+ }
+
+ return 0;
+}
+
+static struct thermal_cooling_device_ops wave6_cooling_ops = {
+ .get_max_state = wave6_cooling_get_max_state,
+ .get_cur_state = wave6_cooling_get_cur_state,
+ .set_cur_state = wave6_cooling_set_cur_state,
+};
+
+static void wave6_cooling_remove(struct vpu_ctrl *ctrl)
+{
+ int i;
+
+ if (!ctrl->pd_list)
+ return;
+
+ thermal_cooling_device_unregister(ctrl->cooling);
+
+ kfree(ctrl->freq_table);
+ ctrl->freq_table = NULL;
+
+ for (i = 0; i < ctrl->pd_list->num_pds; i++) {
+ struct device *pd_dev = ctrl->pd_list->pd_devs[i];
+
+ if (!pm_runtime_suspended(pd_dev))
+ pm_runtime_force_suspend(pd_dev);
+ }
+
+ dev_pm_domain_detach_list(ctrl->pd_list);
+ ctrl->pd_list = NULL;
+ ctrl->dev_perf = NULL;
+}
+
+static void wave6_cooling_init(struct vpu_ctrl *ctrl)
+{
+ struct dev_pm_domain_attach_data pd_data = {
+ .pd_names = (const char *[]) {"vpumix", "vpuperf"},
+ .num_pd_names = 2,
+ };
+ int ret;
+ int i;
+ int num_opps;
+ unsigned long freq;
+
+ ctrl->clk_id = -1;
+ for (i = 0; i < ctrl->num_clks; i++) {
+ if (!strcmp("vpu", ctrl->clks[i].id)) {
+ ctrl->clk_id = i;
+ break;
+ }
+ }
+ if (ctrl->clk_id == -1) {
+ dev_err(ctrl->dev, "cooling device unable to get clock\n");
+ return;
+ }
+
+ ret = dev_pm_domain_attach_list(ctrl->dev, &pd_data, &ctrl->pd_list);
+ ctrl->dev_perf = NULL;
+ if (ret < 0)
+ dev_err(ctrl->dev, "didn't attach perf power domains, ret=%d", ret);
+ else if (ret == 2)
+ ctrl->dev_perf = ctrl->pd_list->pd_devs[DOMAIN_VPU_PERF];
+ dev_dbg(ctrl->dev, "get perf domain ret=%d, perf=%p\n", ret, ctrl->dev_perf);
+ if (!ctrl->dev_perf)
+ return;
+
+ num_opps = dev_pm_opp_get_opp_count(ctrl->dev_perf);
+ if (num_opps <= 0) {
+ dev_err(ctrl->dev, "fail to get pm opp count, ret = %d\n", num_opps);
+ goto error;
+ }
+
+ ctrl->freq_table = kcalloc(num_opps, sizeof(*ctrl->freq_table), GFP_KERNEL);
+ if (!ctrl->freq_table)
+ goto error;
+
+ for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) {
+ struct dev_pm_opp *opp;
+
+ opp = dev_pm_opp_find_freq_floor(ctrl->dev_perf, &freq);
+ if (IS_ERR(opp))
+ break;
+
+ dev_pm_opp_put(opp);
+
+ dev_dbg(ctrl->dev, "[%d] = %ld\n", i, freq);
+ if (freq < 100 * HZ_PER_MHZ)
+ break;
+
+ ctrl->freq_table[i] = freq;
+ ctrl->thermal_max = i;
+ }
+
+ if (!ctrl->thermal_max)
+ goto error;
+
+ ctrl->thermal_event = 0;
+ ctrl->cooling = thermal_of_cooling_device_register(ctrl->dev->of_node,
+ (char *)dev_name(ctrl->dev),
+ ctrl,
+ &wave6_cooling_ops);
+ if (IS_ERR(ctrl->cooling)) {
+ dev_err(ctrl->dev, "register cooling device failed\n");
+ goto error;
+ }
+
+ return;
+error:
+ wave6_cooling_remove(ctrl);
+}
+
+static int wave6_vpu_ctrl_probe(struct platform_device *pdev)
+{
+ struct vpu_ctrl *ctrl;
+ struct device_node *np;
+ const struct vpu_ctrl_resource *res;
+ int ret;
+
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret < 0) {
+ dev_err(&pdev->dev, "dma_set_mask_and_coherent failed: %d\n", ret);
+ return ret;
+ }
+
+ res = of_device_get_match_data(&pdev->dev);
+ if (!res)
+ return -ENODEV;
+
+ ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ mutex_init(&ctrl->ctrl_lock);
+ init_waitqueue_head(&ctrl->load_fw_wq);
+ INIT_LIST_HEAD(&ctrl->entities);
+ INIT_LIST_HEAD(&ctrl->buffers);
+ dev_set_drvdata(&pdev->dev, ctrl);
+ ctrl->dev = &pdev->dev;
+ ctrl->res = res;
+ ctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ctrl->reg_base))
+ return PTR_ERR(ctrl->reg_base);
+ ret = devm_clk_bulk_get_all(&pdev->dev, &ctrl->clks);
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "unable to get clocks: %d\n", ret);
+ ret = 0;
+ }
+
+ ctrl->num_clks = ret;
+
+ np = of_parse_phandle(pdev->dev.of_node, "boot", 0);
+ if (np) {
+ struct resource mem;
+
+ ret = of_address_to_resource(np, 0, &mem);
+ of_node_put(np);
+ if (!ret) {
+ ctrl->boot_mem.phys_addr = mem.start;
+ ctrl->boot_mem.size = resource_size(&mem);
+ wave6_vpu_ctrl_init_reserved_boot_region(ctrl);
+ } else {
+ dev_warn(&pdev->dev, "boot resource is not available.\n");
+ }
+ }
+
+ ctrl->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
+ if (ctrl->sram_pool) {
+ ctrl->sram_buf.size = ctrl->res->sram_size;
+ ctrl->sram_buf.vaddr = gen_pool_dma_alloc(ctrl->sram_pool,
+ ctrl->sram_buf.size,
+ &ctrl->sram_buf.phys_addr);
+ if (!ctrl->sram_buf.vaddr)
+ ctrl->sram_buf.size = 0;
+ else
+ ctrl->sram_buf.dma_addr = dma_map_resource(&pdev->dev,
+ ctrl->sram_buf.phys_addr,
+ ctrl->sram_buf.size,
+ DMA_BIDIRECTIONAL,
+ 0);
+
+ dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
+ &ctrl->sram_buf.phys_addr, &ctrl->sram_buf.dma_addr, ctrl->sram_buf.size);
+ }
+
+ if (of_find_property(pdev->dev.of_node, "support-follower", NULL))
+ ctrl->support_follower = true;
+
+ wave6_cooling_init(ctrl);
+
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+}
+
+static void wave6_vpu_ctrl_remove(struct platform_device *pdev)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(&pdev->dev);
+
+ pm_runtime_disable(&pdev->dev);
+
+ wave6_vpu_ctrl_clear_buffers(ctrl);
+ wave6_cooling_remove(ctrl);
+ if (ctrl->sram_pool && ctrl->sram_buf.vaddr) {
+ dma_unmap_resource(&pdev->dev,
+ ctrl->sram_buf.dma_addr,
+ ctrl->sram_buf.size,
+ DMA_BIDIRECTIONAL,
+ 0);
+ gen_pool_free(ctrl->sram_pool,
+ (unsigned long)ctrl->sram_buf.vaddr,
+ ctrl->sram_buf.size);
+ }
+ if (ctrl->boot_mem.dma_addr)
+ dma_unmap_resource(&pdev->dev,
+ ctrl->boot_mem.dma_addr,
+ ctrl->boot_mem.size,
+ DMA_BIDIRECTIONAL,
+ 0);
+ mutex_destroy(&ctrl->ctrl_lock);
+}
+
+#ifdef CONFIG_PM
+static int wave6_vpu_ctrl_runtime_suspend(struct device *dev)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(ctrl->num_clks, ctrl->clks);
+ return 0;
+}
+
+static int wave6_vpu_ctrl_runtime_resume(struct device *dev)
+{
+ struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
+
+ return clk_bulk_prepare_enable(ctrl->num_clks, ctrl->clks);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int wave6_vpu_ctrl_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int wave6_vpu_ctrl_resume(struct device *dev)
+{
+ return 0;
+}
+#endif
+static const struct dev_pm_ops wave6_vpu_ctrl_pm_ops = {
+ SET_RUNTIME_PM_OPS(wave6_vpu_ctrl_runtime_suspend, wave6_vpu_ctrl_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(wave6_vpu_ctrl_suspend, wave6_vpu_ctrl_resume)
+};
+
+static const struct of_device_id wave6_ctrl_ids[] = {
+ { .compatible = "nxp,imx95-wave633c-ctrl", .data = &wave633c_ctrl_data },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, wave6_ctrl_ids);
+
+static struct platform_driver wave6_vpu_ctrl_driver = {
+ .driver = {
+ .name = VPU_CTRL_PLATFORM_DEVICE_NAME,
+ .of_match_table = of_match_ptr(wave6_ctrl_ids),
+ .pm = &wave6_vpu_ctrl_pm_ops,
+ },
+ .probe = wave6_vpu_ctrl_probe,
+ .remove = wave6_vpu_ctrl_remove,
+};
+
+module_platform_driver(wave6_vpu_ctrl_driver);
+MODULE_DESCRIPTION("chips&media VPU WAVE6 CTRL");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.h b/drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.h
new file mode 100644
index 000000000000..21cfd1d2e7d4
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - wave6 control driver
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE6_VPU_CTRL_H__
+#define __WAVE6_VPU_CTRL_H__
+
+#include <linux/device.h>
+
+enum wave6_vpu_state {
+ WAVE6_VPU_STATE_OFF,
+ WAVE6_VPU_STATE_PREPARE,
+ WAVE6_VPU_STATE_ON,
+ WAVE6_VPU_STATE_SLEEP
+};
+
+struct wave6_vpu_entity {
+ struct list_head list;
+ struct device *dev;
+ u32 (*read_reg)(struct device *dev, u32 addr);
+ void (*write_reg)(struct device *dev, u32 addr, u32 data);
+ void (*on_boot)(struct device *dev);
+ void (*pause)(struct device *dev, int resume);
+ bool booted;
+};
+
+int wave6_alloc_dma(struct device *dev, struct vpu_buf *vb);
+void wave6_free_dma(struct vpu_buf *vb);
+int wave6_vpu_ctrl_resume_and_get(struct device *dev, struct wave6_vpu_entity *entity);
+void wave6_vpu_ctrl_put_sync(struct device *dev, struct wave6_vpu_entity *entity);
+int wave6_vpu_ctrl_get_state(struct device *dev);
+int wave6_vpu_ctrl_wait_done(struct device *dev);
+int wave6_vpu_ctrl_require_buffer(struct device *dev, struct wave6_vpu_entity *entity);
+bool wave6_vpu_ctrl_support_follower(struct device *dev);
+#endif /* __WAVE6_VPU_CTRL_H__ */
--
2.31.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
` (4 preceding siblings ...)
2025-02-10 9:07 ` [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver Nas Chung
@ 2025-02-10 9:07 ` Nas Chung
2025-02-11 16:43 ` kernel test robot
2025-02-10 13:05 ` [PATCH 0/8] Add support for Wave6 video codec driver Sebastian Fricke
2025-02-11 6:07 ` [EXT] " Ming Qian
7 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-10 9:07 UTC (permalink / raw)
To: mchehab, hverkuil, sebastian.fricke, robh, krzk+dt, conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Add debugfs entries and trace events to provide detailed
debugging information.
These enhancements help diagnose issues and improve debugging
capabilities for the Wave6 driver.
Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
.../platform/chips-media/wave6/wave6-trace.h | 336 ++++++++++++++++++
.../chips-media/wave6/wave6-vpu-dbg.c | 230 ++++++++++++
.../chips-media/wave6/wave6-vpu-dbg.h | 22 ++
3 files changed, 588 insertions(+)
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-trace.h
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
diff --git a/drivers/media/platform/chips-media/wave6/wave6-trace.h b/drivers/media/platform/chips-media/wave6/wave6-trace.h
new file mode 100644
index 000000000000..8ddba6926c60
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-trace.h
@@ -0,0 +1,336 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - wave6 driver tracer
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM wave6
+
+#if !defined(__WAVE6_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __WAVE6_TRACE_H__
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
+
+DECLARE_EVENT_CLASS(register_access,
+ TP_PROTO(struct device *dev, u32 addr, u32 value),
+ TP_ARGS(dev, addr, value),
+ TP_STRUCT__entry(
+ __string(name, dev_name(dev))
+ __field(u32, addr)
+ __field(u32, value)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(dev));
+ __entry->addr = addr;
+ __entry->value = value;
+ ),
+ TP_printk("%s:0x%03x 0x%08x", __get_str(name), __entry->addr, __entry->value)
+);
+
+DEFINE_EVENT(register_access, writel,
+ TP_PROTO(struct device *dev, u32 addr, u32 value),
+ TP_ARGS(dev, addr, value));
+DEFINE_EVENT(register_access, readl,
+ TP_PROTO(struct device *dev, u32 addr, u32 value),
+ TP_ARGS(dev, addr, value));
+
+TRACE_EVENT(send_command,
+ TP_PROTO(struct vpu_device *vpu_dev, u32 id, u32 std, u32 cmd),
+ TP_ARGS(vpu_dev, id, std, cmd),
+ TP_STRUCT__entry(
+ __string(name, dev_name(vpu_dev->dev))
+ __field(u32, id)
+ __field(u32, std)
+ __field(u32, cmd)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(vpu_dev->dev));
+ __entry->id = id;
+ __entry->std = std;
+ __entry->cmd = cmd;
+ ),
+ TP_printk("%s: inst id %d, std 0x%x, cmd 0x%x",
+ __get_str(name), __entry->id, __entry->std, __entry->cmd)
+);
+
+TRACE_EVENT(irq,
+ TP_PROTO(struct vpu_device *vpu_dev, u32 irq),
+ TP_ARGS(vpu_dev, irq),
+ TP_STRUCT__entry(
+ __string(name, dev_name(vpu_dev->dev))
+ __field(u32, irq)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(vpu_dev->dev));
+ __entry->irq = irq;
+ ),
+ TP_printk("%s: irq 0x%x", __get_str(name), __entry->irq)
+);
+
+TRACE_EVENT(set_state,
+ TP_PROTO(struct vpu_instance *inst, u32 state),
+ TP_ARGS(inst, state),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __string(cur_state, wave6_vpu_instance_state_name(inst->state))
+ __string(nxt_state, wave6_vpu_instance_state_name(state))
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __assign_str(cur_state, wave6_vpu_instance_state_name(inst->state));
+ __assign_str(nxt_state, wave6_vpu_instance_state_name(state));
+ ),
+ TP_printk("%s: inst[%d] set state %s -> %s",
+ __get_str(name), __entry->id, __get_str(cur_state), __get_str(nxt_state))
+);
+
+DECLARE_EVENT_CLASS(inst_internal,
+ TP_PROTO(struct vpu_instance *inst, u32 type),
+ TP_ARGS(inst, type),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __string(type, V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture")
+ __field(u32, pixelformat)
+ __field(u32, width)
+ __field(u32, height)
+ __field(u32, buf_cnt_src)
+ __field(u32, buf_cnt_dst)
+ __field(u32, processed_cnt)
+ __field(u32, error_cnt)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __assign_str(type, V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture");
+ __entry->pixelformat = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.pixelformat :
+ inst->dst_fmt.pixelformat;
+ __entry->width = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.width :
+ inst->dst_fmt.width;
+ __entry->height = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.height :
+ inst->dst_fmt.height;
+ __entry->buf_cnt_src = inst->queued_src_buf_num;
+ __entry->buf_cnt_dst = inst->queued_dst_buf_num;
+ __entry->processed_cnt = inst->processed_buf_num;
+ __entry->error_cnt = inst->error_buf_num;
+ ),
+ TP_printk("%s: inst[%d] %s %c%c%c%c %dx%d, input %d, %d, process %d, error %d",
+ __get_str(name), __entry->id, __get_str(type),
+ __entry->pixelformat,
+ __entry->pixelformat >> 8,
+ __entry->pixelformat >> 16,
+ __entry->pixelformat >> 24,
+ __entry->width, __entry->height,
+ __entry->buf_cnt_src, __entry->buf_cnt_dst,
+ __entry->processed_cnt, __entry->error_cnt)
+);
+
+DEFINE_EVENT(inst_internal, start_streaming,
+ TP_PROTO(struct vpu_instance *inst, u32 type),
+ TP_ARGS(inst, type));
+
+DEFINE_EVENT(inst_internal, stop_streaming,
+ TP_PROTO(struct vpu_instance *inst, u32 type),
+ TP_ARGS(inst, type));
+
+TRACE_EVENT(dec_pic,
+ TP_PROTO(struct vpu_instance *inst, u32 srcidx, u32 size),
+ TP_ARGS(inst, srcidx, size),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __field(u32, srcidx)
+ __field(u32, start)
+ __field(u32, size)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __entry->srcidx = srcidx;
+ __entry->start = inst->codec_info->dec_info.stream_rd_ptr;
+ __entry->size = size;
+ ),
+ TP_printk("%s: inst[%d] src[%2d] %8x, %d",
+ __get_str(name), __entry->id, __entry->srcidx, __entry->start, __entry->size)
+);
+
+TRACE_EVENT(source_change,
+ TP_PROTO(struct vpu_instance *inst, struct dec_initial_info *info),
+ TP_ARGS(inst, info),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __field(u32, width)
+ __field(u32, height)
+ __field(u32, profile)
+ __field(u32, level)
+ __field(u32, tier)
+ __field(u32, min_fb_cnt)
+ __field(u32, disp_delay)
+ __field(u32, quantization)
+ __field(u32, colorspace)
+ __field(u32, xfer_func)
+ __field(u32, ycbcr_enc)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __entry->width = info->pic_width,
+ __entry->height = info->pic_height,
+ __entry->profile = info->profile,
+ __entry->level = info->level;
+ __entry->tier = info->tier;
+ __entry->min_fb_cnt = info->min_frame_buffer_count;
+ __entry->disp_delay = info->frame_buf_delay;
+ __entry->quantization = inst->quantization;
+ __entry->colorspace = inst->colorspace;
+ __entry->xfer_func = inst->xfer_func;
+ __entry->ycbcr_enc = inst->ycbcr_enc;
+ ),
+ TP_printk("%s: inst[%d] %dx%d profile %d, %d, %d min_fb %d, delay %d, color %d,%d,%d,%d",
+ __get_str(name), __entry->id,
+ __entry->width, __entry->height,
+ __entry->profile, __entry->level, __entry->tier,
+ __entry->min_fb_cnt, __entry->disp_delay,
+ __entry->quantization,
+ __entry->colorspace, __entry->xfer_func, __entry->ycbcr_enc)
+);
+
+TRACE_EVENT(dec_done,
+ TP_PROTO(struct vpu_instance *inst, struct dec_output_info *info),
+ TP_ARGS(inst, info),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __field(u32, dec_flag)
+ __field(u32, dec_poc)
+ __field(u32, disp_flag)
+ __field(u32, disp_cnt)
+ __field(u32, rel_cnt)
+ __field(u32, src_ch)
+ __field(u32, eos)
+ __field(u32, error)
+ __field(u32, warn)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __entry->dec_flag = info->frame_decoded;
+ __entry->dec_poc = info->decoded_poc;
+ __entry->disp_flag = info->frame_display;
+ __entry->disp_cnt = info->disp_frame_num;
+ __entry->rel_cnt = info->release_disp_frame_num;
+ __entry->src_ch = info->notification_flags & DEC_NOTI_FLAG_SEQ_CHANGE;
+ __entry->eos = info->stream_end;
+ __entry->error = info->error_reason;
+ __entry->warn = info->warn_info;
+ ),
+ TP_printk("%s: inst[%d] dec %d %d; disp %d(%d); rel %d, src_ch %d, eos %d, error 0x%x 0x%x",
+ __get_str(name), __entry->id,
+ __entry->dec_flag, __entry->dec_poc,
+ __entry->disp_flag, __entry->disp_cnt,
+ __entry->rel_cnt,
+ __entry->src_ch, __entry->eos,
+ __entry->error, __entry->warn)
+);
+
+TRACE_EVENT(enc_pic,
+ TP_PROTO(struct vpu_instance *inst, struct enc_param *param),
+ TP_ARGS(inst, param),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __field(u32, srcidx)
+ __field(u32, buf_y)
+ __field(u32, buf_cb)
+ __field(u32, buf_cr)
+ __field(u32, stride)
+ __field(u32, buf_strm)
+ __field(u32, size_strm)
+ __field(u32, force_type_enable)
+ __field(u32, force_type)
+ __field(u32, end_flag)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __entry->srcidx = param->src_idx;
+ __entry->buf_y = param->source_frame->buf_y;
+ __entry->buf_cb = param->source_frame->buf_cb;
+ __entry->buf_cr = param->source_frame->buf_cr;
+ __entry->stride = param->source_frame->stride;
+ __entry->buf_strm = param->pic_stream_buffer_addr;
+ __entry->size_strm = param->pic_stream_buffer_size;
+ __entry->force_type_enable = param->force_pic_type_enable;
+ __entry->force_type = param->force_pic_type;
+ __entry->end_flag = param->src_end;
+ ),
+ TP_printk("%s: inst[%d] src[%2d] %8x %8x %8x (%d); dst %8x(%d); force type %d(%d), end %d",
+ __get_str(name), __entry->id, __entry->srcidx,
+ __entry->buf_y, __entry->buf_cb, __entry->buf_cr, __entry->stride,
+ __entry->buf_strm, __entry->size_strm,
+ __entry->force_type_enable, __entry->force_type,
+ __entry->end_flag)
+);
+
+TRACE_EVENT(enc_done,
+ TP_PROTO(struct vpu_instance *inst, struct enc_output_info *info),
+ TP_ARGS(inst, info),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __field(u32, srcidx)
+ __field(u32, frmidx)
+ __field(u32, size)
+ __field(u32, type)
+ __field(u32, avg_qp)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __entry->srcidx = info->enc_src_idx;
+ __entry->frmidx = info->recon_frame_index;
+ __entry->size = info->bitstream_size;
+ __entry->type = info->pic_type;
+ __entry->avg_qp = info->avg_ctu_qp;
+ ),
+ TP_printk("%s: inst[%d] src %d, frame %d, size %d, type %d, qp %d, eos %d",
+ __get_str(name), __entry->id,
+ __entry->srcidx, __entry->frmidx,
+ __entry->size, __entry->type, __entry->avg_qp,
+ __entry->frmidx == RECON_IDX_FLAG_ENC_END)
+);
+
+TRACE_EVENT(s_ctrl,
+ TP_PROTO(struct vpu_instance *inst, struct v4l2_ctrl *ctrl),
+ TP_ARGS(inst, ctrl),
+ TP_STRUCT__entry(
+ __string(name, dev_name(inst->dev->dev))
+ __field(u32, id)
+ __string(ctrl_name, ctrl->name)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dev_name(inst->dev->dev));
+ __entry->id = inst->id;
+ __assign_str(ctrl_name, ctrl->name);
+ __entry->val = ctrl->val;
+ ),
+ TP_printk("%s: inst[%d] %s = %d",
+ __get_str(name), __entry->id, __get_str(ctrl_name), __entry->val)
+);
+
+#endif /* __WAVE6_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE wave6-trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
new file mode 100644
index 000000000000..40fe75c08eeb
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave6 series multi-standard codec IP - debug interface
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include "wave6-vpu.h"
+#include "wave6-vpu-dbg.h"
+
+static int wave6_vpu_dbg_instance(struct seq_file *s, void *data)
+{
+ struct vpu_instance *inst = s->private;
+ struct vpu_performance_info *perf = &inst->performance;
+ struct vb2_queue *vq;
+ char str[128];
+ int num;
+ s64 tmp;
+ s64 fps;
+
+ if (!inst->v4l2_fh.m2m_ctx)
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "[%s]\n",
+ inst->type == VPU_INST_TYPE_DEC ? "Decoder" : "Encoder");
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "%s : product 0x%x, fw_ver %d.%d.%d(r%d), hw_ver 0x%x\n",
+ dev_name(inst->dev->dev), inst->dev->product_code,
+ (inst->dev->fw_version >> 24) & 0xFF,
+ (inst->dev->fw_version >> 16) & 0xFF,
+ (inst->dev->fw_version >> 0) & 0xFFFF,
+ inst->dev->fw_revision, inst->dev->hw_version);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "state = %s, pause request %d\n",
+ wave6_vpu_instance_state_name(inst->state),
+ inst->dev->pause_request);
+ if (seq_write(s, str, num))
+ return 0;
+
+ vq = v4l2_m2m_get_src_vq(inst->v4l2_fh.m2m_ctx);
+ num = scnprintf(str, sizeof(str),
+ "output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+ vb2_is_streaming(vq),
+ vb2_get_num_buffers(vq),
+ inst->src_fmt.pixelformat,
+ inst->src_fmt.pixelformat >> 8,
+ inst->src_fmt.pixelformat >> 16,
+ inst->src_fmt.pixelformat >> 24,
+ inst->src_fmt.width,
+ inst->src_fmt.height,
+ vq->last_buffer_dequeued);
+ if (seq_write(s, str, num))
+ return 0;
+
+ vq = v4l2_m2m_get_dst_vq(inst->v4l2_fh.m2m_ctx);
+ num = scnprintf(str, sizeof(str),
+ "capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+ vb2_is_streaming(vq),
+ vb2_get_num_buffers(vq),
+ inst->dst_fmt.pixelformat,
+ inst->dst_fmt.pixelformat >> 8,
+ inst->dst_fmt.pixelformat >> 16,
+ inst->dst_fmt.pixelformat >> 24,
+ inst->dst_fmt.width,
+ inst->dst_fmt.height,
+ vq->last_buffer_dequeued);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str),
+ "capture queued %d, consumed %d, used %d\n",
+ v4l2_m2m_num_dst_bufs_ready(inst->v4l2_fh.m2m_ctx),
+ wave6_vpu_get_consumed_fb_num(inst),
+ wave6_vpu_get_used_fb_num(inst));
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n",
+ inst->crop.left,
+ inst->crop.top,
+ inst->crop.width,
+ inst->crop.height);
+ if (seq_write(s, str, num))
+ return 0;
+
+ if (inst->scaler_info.enable) {
+ num = scnprintf(str, sizeof(str), "scale: %d x %d\n",
+ inst->scaler_info.width, inst->scaler_info.height);
+ if (seq_write(s, str, num))
+ return 0;
+ }
+
+ num = scnprintf(str, sizeof(str),
+ "queued src %d, dst %d, process %d, sequence %d, error %d, drain %d:%d\n",
+ inst->queued_src_buf_num,
+ inst->queued_dst_buf_num,
+ inst->processed_buf_num,
+ inst->sequence,
+ inst->error_buf_num,
+ inst->v4l2_fh.m2m_ctx->out_q_ctx.buffered,
+ inst->eos);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "fps");
+ if (seq_write(s, str, num))
+ return 0;
+ tmp = MSEC_PER_SEC * inst->processed_buf_num;
+ if (perf->ts_last > perf->ts_first + NSEC_PER_MSEC) {
+ fps = DIV_ROUND_CLOSEST(tmp, (perf->ts_last - perf->ts_first) / NSEC_PER_MSEC);
+ num = scnprintf(str, sizeof(str), " actual: %lld;", fps);
+ if (seq_write(s, str, num))
+ return 0;
+ }
+ if (perf->total_sw_time) {
+ fps = DIV_ROUND_CLOSEST(tmp, perf->total_sw_time / NSEC_PER_MSEC);
+ num = scnprintf(str, sizeof(str), " sw: %lld;", fps);
+ if (seq_write(s, str, num))
+ return 0;
+ }
+ if (perf->total_hw_time) {
+ fps = DIV_ROUND_CLOSEST(tmp, perf->total_hw_time / NSEC_PER_MSEC);
+ num = scnprintf(str, sizeof(str), " hw: %lld", fps);
+ if (seq_write(s, str, num))
+ return 0;
+ }
+ num = scnprintf(str, sizeof(str), "\n");
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str),
+ "latency(ms) first: %llu.%06llu, max %llu.%06llu\n",
+ perf->latency_first / NSEC_PER_MSEC,
+ perf->latency_first % NSEC_PER_MSEC,
+ perf->latency_max / NSEC_PER_MSEC,
+ perf->latency_max % NSEC_PER_MSEC);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str),
+ "process frame time(ms) min: %llu.%06llu, max %llu.%06llu\n",
+ perf->min_process_time / NSEC_PER_MSEC,
+ perf->min_process_time % NSEC_PER_MSEC,
+ perf->max_process_time / NSEC_PER_MSEC,
+ perf->max_process_time % NSEC_PER_MSEC);
+ if (seq_write(s, str, num))
+ return 0;
+
+ if (inst->type == VPU_INST_TYPE_DEC) {
+ num = scnprintf(str, sizeof(str), "%s order\n",
+ inst->disp_mode == DISP_MODE_DISP_ORDER ? "display" : "decode");
+ if (seq_write(s, str, num))
+ return 0;
+ } else {
+ struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+ struct enc_codec_param *param = &p_enc_info->open_param.codec_param;
+
+ num = scnprintf(str, sizeof(str), "profile %d, level %d, tier %d\n",
+ param->profile, param->level, param->tier);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "frame_rate %d, idr_period %d, intra_period %d\n",
+ param->frame_rate, param->idr_period, param->intra_period);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str), "rc %d, mode %d, bitrate %d\n",
+ param->en_rate_control,
+ param->rc_mode,
+ param->bitrate);
+ if (seq_write(s, str, num))
+ return 0;
+
+ num = scnprintf(str, sizeof(str),
+ "qp %d, i_qp [%d, %d], p_qp [%d, %d], b_qp [%d, %d]\n",
+ param->qp,
+ param->min_qp_i, param->max_qp_i,
+ param->min_qp_p, param->max_qp_p,
+ param->min_qp_b, param->max_qp_b);
+ if (seq_write(s, str, num))
+ return 0;
+ }
+
+ return 0;
+}
+
+static int wave6_vpu_dbg_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, wave6_vpu_dbg_instance, inode->i_private);
+}
+
+static const struct file_operations wave6_vpu_dbg_fops = {
+ .owner = THIS_MODULE,
+ .open = wave6_vpu_dbg_open,
+ .release = single_release,
+ .read = seq_read,
+};
+
+int wave6_vpu_create_dbgfs_file(struct vpu_instance *inst)
+{
+ char name[64];
+
+ if (!inst || !inst->dev || IS_ERR_OR_NULL(inst->dev->debugfs))
+ return -EINVAL;
+
+ scnprintf(name, sizeof(name), "instance.%d", inst->id);
+ inst->debugfs = debugfs_create_file((const char *)name,
+ VERIFY_OCTAL_PERMISSIONS(0444),
+ inst->dev->debugfs,
+ inst,
+ &wave6_vpu_dbg_fops);
+
+ return 0;
+}
+
+void wave6_vpu_remove_dbgfs_file(struct vpu_instance *inst)
+{
+ if (!inst || !inst->debugfs)
+ return;
+
+ debugfs_remove(inst->debugfs);
+ inst->debugfs = NULL;
+}
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
new file mode 100644
index 000000000000..fd7da1670925
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - debug interface
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE6_VPU_DBG_H__
+#define __WAVE6_VPU_DBG_H__
+
+unsigned int wave6_vpu_debug(void);
+
+#define dprintk(dev, fmt, arg...) \
+ do { \
+ if (wave6_vpu_debug()) \
+ dev_info(dev, "%s: " fmt, __func__, ## arg); \
+ } while (0)
+
+int wave6_vpu_create_dbgfs_file(struct vpu_instance *inst);
+void wave6_vpu_remove_dbgfs_file(struct vpu_instance *inst);
+
+#endif /* __WAVE6_VPU_DBG_H__ */
--
2.31.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 0/8] Add support for Wave6 video codec driver
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
` (5 preceding siblings ...)
2025-02-10 9:07 ` [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities Nas Chung
@ 2025-02-10 13:05 ` Sebastian Fricke
2025-02-11 4:47 ` Nas Chung
2025-02-11 6:07 ` [EXT] " Ming Qian
7 siblings, 1 reply; 29+ messages in thread
From: Sebastian Fricke @ 2025-02-10 13:05 UTC (permalink / raw)
To: Nas Chung
Cc: mchehab, hverkuil, robh, krzk+dt, conor+dt, linux-media,
devicetree, linux-kernel, linux-imx, linux-arm-kernel,
jackson.lee, lafley.kim
Hey Nas,
On 10.02.2025 18:07, Nas Chung wrote:
>This patch series introduces support for the Chips&Media Wave6 video
>codec IP, a completely different hardware architecture compared to Wave5.
>
>The wave6 driver is a M2M stateful encoder/decoder driver.
>It supports various video formats, including H.264 and H.265,
>for both encoding and decoding.
Sounds like the hardware supports more formats.
What are the other video formats?
Regards,
Sebastian
>
>On NXP i.MX SoCs, the Wave6 IP functionality is split between two devices:
>VPU Control Device, Manages shared resources such as firmware access and
>power domains.
>VPU Device, Provides encoding and decoding capabilities.
>The VPU device cannot operate independently without the VPU control device.
>
>This driver has been tested with GStreamer on:
>- NXP i.MX95 board
>- pre-silicon FPGA environment
>
>Test results for decoder fluster:
>- JVT-AVC_V1, Ran 77/135 tests successfully in 35.929 secs
>- JVT-FR-EXT, Ran 25/69 tests successfully in 17.717 secs
>- JCT-VC-HEVC_V1, Ran 132/147 tests successfully in 81.568 secs
>- All failures are due to unsupported hardware features:
>-- 10bit, Resolutions higher than 4K, FMO, MBAFF
>-- Extended profile, Field encoding and High422 sreams.
>
>Test results for v4l2-compliance:
>v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t
>v4l2-compliance SHA: 77f5df419204 2025-02-07 08:59:59
>
>Compliance test for wave6-dec device /dev/video0:
>
>Driver Info:
> Driver name : wave6-dec
> Card type : wave6-dec
> Bus info : platform:wave6-dec
> Driver version : 6.9.2
> 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
> fail: ../utils/v4l2-compliance/v4l2-test-controls.cpp(1180): !have_source_change || !have_eos
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 7 Private Controls: 1
>
>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
>
>Total for wave6-dec device /dev/video0: 48, Succeeded: 47, Failed: 1, Warnings: 0
>
>v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t
>v4l2-compliance SHA: 77f5df419204 2025-02-07 08:59:59
>
>Compliance test for wave6-enc device /dev/video1:
>
>Driver Info:
> Driver name : wave6-enc
> Card type : wave6-enc
> Bus info : platform:wave6-enc
> Driver version : 6.9.2
> 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
> fail: ../utils/v4l2-compliance/v4l2-test-controls.cpp(1169): node->codec_mask & STATEFUL_ENCODER
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 53 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
>
>Total for wave6-enc device /dev/video1: 48, Succeeded: 47, Failed: 1, Warnings: 0
>
>Nas Chung (8):
> media: platform: chips-media: wave5: Rename Kconfig parameter
> media: v4l2-common: Add YUV24 format info
> dt-bindings: media: nxp: Add Wave6 video codec device
> media: chips-media: wave6: Add Wave6 codec driver
> media: chips-media: wave6: Add v4l2 m2m driver
> media: chips-media: wave6: Add Wave6 vpu interface
> media: chips-media: wave6: Add Wave6 control driver
> media: chips-media: wave6: Improve debugging capabilities
>
> .../bindings/media/nxp,wave633c.yaml | 202 ++
> MAINTAINERS | 8 +
> arch/arm64/configs/defconfig | 2 +-
> drivers/media/platform/chips-media/Kconfig | 1 +
> drivers/media/platform/chips-media/Makefile | 1 +
> .../media/platform/chips-media/wave5/Kconfig | 6 +-
> .../media/platform/chips-media/wave5/Makefile | 2 +-
> .../media/platform/chips-media/wave6/Kconfig | 26 +
> .../media/platform/chips-media/wave6/Makefile | 17 +
> .../platform/chips-media/wave6/wave6-hw.c | 3113 +++++++++++++++++
> .../platform/chips-media/wave6/wave6-hw.h | 69 +
> .../chips-media/wave6/wave6-regdefine.h | 675 ++++
> .../platform/chips-media/wave6/wave6-trace.h | 336 ++
> .../platform/chips-media/wave6/wave6-vdi.c | 52 +
> .../platform/chips-media/wave6/wave6-vdi.h | 59 +
> .../chips-media/wave6/wave6-vpu-ctrl.c | 1020 ++++++
> .../chips-media/wave6/wave6-vpu-ctrl.h | 38 +
> .../chips-media/wave6/wave6-vpu-dbg.c | 230 ++
> .../chips-media/wave6/wave6-vpu-dbg.h | 22 +
> .../chips-media/wave6/wave6-vpu-dec.c | 1883 ++++++++++
> .../chips-media/wave6/wave6-vpu-enc.c | 2698 ++++++++++++++
> .../chips-media/wave6/wave6-vpu-v4l2.c | 381 ++
> .../platform/chips-media/wave6/wave6-vpu.c | 487 +++
> .../platform/chips-media/wave6/wave6-vpu.h | 106 +
> .../platform/chips-media/wave6/wave6-vpuapi.c | 1001 ++++++
> .../platform/chips-media/wave6/wave6-vpuapi.h | 993 ++++++
> .../chips-media/wave6/wave6-vpuconfig.h | 80 +
> .../chips-media/wave6/wave6-vpuerror.h | 262 ++
> drivers/media/v4l2-core/v4l2-common.c | 1 +
> 29 files changed, 13766 insertions(+), 5 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/media/nxp,wave633c.yaml
> create mode 100644 drivers/media/platform/chips-media/wave6/Kconfig
> create mode 100644 drivers/media/platform/chips-media/wave6/Makefile
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-regdefine.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-trace.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-enc.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-v4l2.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuapi.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuapi.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuconfig.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpuerror.h
>
>--
>2.31.1
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/8] media: v4l2-common: Add YUV24 format info
2025-02-10 9:07 ` [PATCH 2/8] media: v4l2-common: Add YUV24 format info Nas Chung
@ 2025-02-10 14:00 ` Sebastian Fricke
2025-02-11 1:58 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Sebastian Fricke @ 2025-02-10 14:00 UTC (permalink / raw)
To: Nas Chung
Cc: mchehab, hverkuil, robh, krzk+dt, conor+dt, linux-media,
devicetree, linux-kernel, linux-imx, linux-arm-kernel,
jackson.lee, lafley.kim
Hey Nas,
On 10.02.2025 18:07, Nas Chung wrote:
>The YUV24 format is missing an entry in the v4l2_format_info().
>The YUV24 format is the packed YUV 4:4:4 formats with 8 bits
>per component.
>
That means that 0376a51fbe5e1 was incomplete, I think you should add a
fixes tag to this commit, to highlight that you basically complete the
previous commit.
Regards,
Sebastian
>Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
>---
> drivers/media/v4l2-core/v4l2-common.c | 1 +
> 1 file changed, 1 insertion(+)
>
>diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
>index 0a2f4f0d0a07..de3636f1cdf1 100644
>--- a/drivers/media/v4l2-core/v4l2-common.c
>+++ b/drivers/media/v4l2-core/v4l2-common.c
>@@ -269,6 +269,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
> { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
> { .format = V4L2_PIX_FMT_Y216, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
> { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
>+ { .format = V4L2_PIX_FMT_YUV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
> { .format = V4L2_PIX_FMT_MT2110T, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
> .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
> { .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
>--
>2.31.1
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter
2025-02-10 9:07 ` [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter Nas Chung
@ 2025-02-10 17:24 ` Krzysztof Kozlowski
2025-02-11 4:23 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-10 17:24 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim
On 10/02/2025 10:07, Nas Chung wrote:
> The existing Kconfig parameter VIDEO_WAVE_VPU is ambiguous,
> as it does not clearly indicate that it is specific to the Wave5 IP.
>
> Rename VIDEO_WAVE_VPU to VIDEO_WAVE5_VPU to make it explicit
> that the parameter is specific to the Wave5 IP.
>
> No functional changes, only the parameter name is updated.
That's unnecessary churn. Old name was fine. Kconfig does not match
hardware 1-to-1 but represents only the driver name (or not even that...).
If you solve any particular problem, then explain it. Otherwise this is
just unnecessarily affecting users and backports.
>
> Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
> ---
> arch/arm64/configs/defconfig | 2 +-
That's a SoC patch, don't mix up subsystems.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-10 9:07 ` [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device Nas Chung
@ 2025-02-10 17:30 ` Krzysztof Kozlowski
2025-02-13 7:50 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-10 17:30 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim
On 10/02/2025 10:07, Nas Chung wrote:
> Add documents for the Wave6 video codec on NXP i.MX SoCs.
>
> Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
> ---
> .../bindings/media/nxp,wave633c.yaml | 202 ++++++++++++++++++
> MAINTAINERS | 8 +
> 2 files changed, 210 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/nxp,wave633c.yaml b/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
> new file mode 100644
> index 000000000000..99c3008314c5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
Filename matching compatible.
> @@ -0,0 +1,202 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/nxp,wave633c.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Chips&Media Wave6 Series multi-standard codec IP on NXP i.MX SoCs.
> +
> +maintainers:
> + - Nas Chung <nas.chung@chipsnmedia.com>
> + - Jackson Lee <jackson.lee@chipsnmedia.com>
> +
> +description:
> + The Chips&Media Wave6 codec IP is a multi-standard video encoder/decoder.
> + On NXP i.MX SoCs, Wave6 codec IP functionality is split between the VPU control device
> + (vpu-ctrl) and the VPU device (vpu). The VPU control device manages shared resources
> + such as firmware access and power domains, while the VPU device provides encoding
> + and decoding capabilities. The VPU devie cannot operate independently
Typo
> + without the VPU control device.
> +
Please wrap code according to the preferred limit expressed in Kernel
coding style (checkpatch is not a coding style description, but only a
tool). Bindings use strict rule here.
> +properties:
> + compatible:
> + items:
> + - enum:
> + - nxp,imx95-wave633c-ctrl
> + - nxp,imx95-wave633c
I don't understand why you duplicated compatibles. You split this for
driver? That's a no. There are no two hardwares.
These compatibles are anyway weird - why imx95 is in chipmedia product?
Is this part of a SoC?
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: VPU clock
> + - description: VPU associated block clock
> +
> + clock-names:
> + items:
> + - const: vpu
> + - const: vpublk_wave
> +
> + power-domains:
> + minItems: 1
> + items:
> + - description: Main VPU power domain
> + - description: Performance power domain
> +
> + power-domain-names:
> + items:
> + - const: vpumix
> + - const: vpuperf
> +
> + cnm,ctrl:
What is this prefix about? Is this nxp or something else?
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle of the VPU control device node. Required for VPU operation.
Explain - required for what. Operation is too generic.
If this is phandle to second device, then it's proof your split is
really wrong.
> +
> + boot:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle of the boot memory region node for the VPU control device.
No clue what is this... if memory region then use existing bindings.
Anyway, wrap your code correctly.
> +
> + sram:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle of the SRAM memory region node for the VPU control device.
> +
> + '#cooling-cells':
> + const: 2
> +
> + support-follower:
> + type: boolean
> + description: Indicates whether the VPU domain power always on.
You cannot add new common properties in random way. Missing vendor
prefix but more important: does not look at all as hardware property but
OS policy.
> +
> +patternProperties:
> + "^vpu-ctrl@[0-9a-f]+$":
> + type: object
> + properties:
> + compatible:
> + items:
> + - enum:
> + - nxp,imx95-wave633c-ctrl
Really, what? How nxp,imx95-wave633c-ctrl node can have a child with
nxp,imx95-wave633c-ctrl compatible?
NAK.
> + reg: true
> + clocks: true
> + clock-names: true
> + power-domains:
> + items:
> + - description: Main VPU power domain
> + - description: Performance power domain
> + power-domain-names:
> + items:
> + - const: vpumix
> + - const: vpuperf
> + sram: true
> + boot: true
> + '#cooling-cells': true
> + support-follower: true
> + required:
> + - compatible
> + - reg
> + - clocks
> + - clock-names
> + - power-domains
> + - power-domain-names
> + - sram
> + - boot
> +
> + additionalProperties: false
> +
> + "^vpu@[0-9a-f]+$":
> + type: object
> + properties:
> + compatible:
> + items:
> + - enum:
> + - nxp,imx95-wave633c
> + reg: true
> + interrupts: true
> + clocks: true
> + clock-names: true
> + power-domains:
> + maxItems: 1
> + description: Main VPU power domain
> + cnm,ctrl: true
> + required:
> + - compatible
> + - reg
> + - interrupts
> + - clocks
> + - clock-names
> + - power-domains
> + - cnm,ctrl
All this is just incorrect.
> +
> + additionalProperties: false
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/clock/nxp,imx95-clock.h>
> +
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + vpuctrl: vpu-ctrl@4c4c0000 {
> + compatible = "nxp,imx95-wave633c-ctrl";
> + reg = <0x0 0x4c4c0000 0x0 0x10000>;
> + clocks = <&scmi_clk 115>,
> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> + clock-names = "vpu", "vpublk_wave";
> + power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
> + power-domain-names = "vpumix", "vpuperf";
> + #cooling-cells = <2>;
> + boot = <&vpu_boot>;
> + sram = <&sram1>;
> + };
> +
> + vpu0: vpu@4c480000 {
Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
> + compatible = "nxp,imx95-wave633c";
> + reg = <0x0 0x4c480000 0x0 0x10000>;
> + interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&scmi_clk 115>,
> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> + clock-names = "vpu", "vpublk_wave";
> + power-domains = <&scmi_devpd 21>;
> + cnm,ctrl = <&vpuctrl>;
> + };
> +
> + vpu1: vpu@4c490000 {
> + compatible = "nxp,imx95-wave633c";
Drop all duplicated examples.
> + reg = <0x0 0x4c490000 0x0 0x10000>;
> + interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&scmi_clk 115>,
> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> + clock-names = "vpu", "vpublk_wave";
> + power-domains = <&scmi_devpd 21>;
> + cnm,ctrl = <&vpuctrl>;
> + };
> +
> + vpu2: vpu@4c4a0000 {
> + compatible = "nxp,imx95-wave633c";
> + reg = <0x0 0x4c4a0000 0x0 0x10000>;
> + interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&scmi_clk 115>,
> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> + clock-names = "vpu", "vpublk_wave";
> + power-domains = <&scmi_devpd 21>;
> + cnm,ctrl = <&vpuctrl>;
> + };
> +
> + vpu3: vpu@4c4b0000 {
> + compatible = "nxp,imx95-wave633c";
> + reg = <0x0 0x4c4b0000 0x0 0x10000>;
> + interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&scmi_clk 115>,
> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> + clock-names = "vpu", "vpublk_wave";
> + power-domains = <&scmi_devpd 21>;
> + cnm,ctrl = <&vpuctrl>;
> + };
> + };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 896a307fa065..5ff5b1f1ced2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -25462,6 +25462,14 @@ S: Maintained
> F: Documentation/devicetree/bindings/media/cnm,wave521c.yaml
> F: drivers/media/platform/chips-media/wave5/
>
> +WAVE6 VPU CODEC DRIVER
> +M: Nas Chung <nas.chung@chipsnmedia.com>
> +M: Jackson Lee <jackson.lee@chipsnmedia.com>
> +L: linux-media@vger.kernel.org
> +S: Maintained
> +F: Documentation/devicetree/bindings/media/nxp,wave633c.yaml
> +F: drivers/media/platform/chips-media/wave6/
There is no such file/directory.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
2025-02-10 9:07 ` [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver Nas Chung
@ 2025-02-10 17:37 ` Krzysztof Kozlowski
2025-02-11 8:55 ` Nas Chung
2025-02-11 20:25 ` kernel test robot
2025-02-12 1:31 ` kernel test robot
2 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-10 17:37 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim
On 10/02/2025 10:07, Nas Chung wrote:
> +
> +int wave6_vpu_ctrl_resume_and_get(struct device *dev, struct wave6_vpu_entity *entity)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
> + bool boot;
> + int ret;
> +
> + if (!ctrl)
> + return -EINVAL;
> +
> + if (!entity || !entity->dev || !entity->read_reg || !entity->write_reg)
> + return -EINVAL;
> +
> + mutex_lock(&ctrl->ctrl_lock);
> +
> + ret = pm_runtime_resume_and_get(ctrl->dev);
> + if (ret) {
> + dev_err(dev, "pm runtime resume fail, ret = %d\n", ret);
> + mutex_unlock(&ctrl->ctrl_lock);
> + return ret;
> + }
> +
> + entity->booted = false;
> +
> + if (ctrl->current_entity)
> + boot = false;
> + else
> + boot = list_empty(&ctrl->entities) ? true : false;
> +
> + list_add_tail(&entity->list, &ctrl->entities);
> + if (boot)
> + ret = wave6_vpu_ctrl_try_boot(ctrl, entity);
> +
> + if (ctrl->state == WAVE6_VPU_STATE_ON)
> + wave6_vpu_ctrl_on_boot(entity);
> +
> + if (ret)
> + pm_runtime_put_sync(ctrl->dev);
> +
> + mutex_unlock(&ctrl->ctrl_lock);
> +
> + return ret;
> +}
Drop entire function.
> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_resume_and_get);
Drop.
> +
> +void wave6_vpu_ctrl_put_sync(struct device *dev, struct wave6_vpu_entity *entity)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
> +
> + if (!ctrl)
> + return;
> +
> + if (entity == ctrl->current_entity)
> + wave6_vpu_ctrl_wait_done(dev);
> +
> + mutex_lock(&ctrl->ctrl_lock);
> +
> + if (!wave6_vpu_ctrl_find_entity(ctrl, entity))
> + goto exit;
> +
> + list_del_init(&entity->list);
> + if (list_empty(&ctrl->entities)) {
> + if (!entity->read_reg(entity->dev, W6_VPU_VCPU_CUR_PC))
> + wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
> + else
> + wave6_vpu_ctrl_sleep(ctrl, entity);
> + }
> +
> + if (!pm_runtime_suspended(ctrl->dev))
> + pm_runtime_put_sync(ctrl->dev);
> +exit:
> + mutex_unlock(&ctrl->ctrl_lock);
> +}
> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_put_sync);
Drop entire function. Dead code.
... or you arranged your patches really incorrectly, but this I can't
really judge.
> +
> +int wave6_vpu_ctrl_wait_done(struct device *dev)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
> + int ret;
> +
> + if (!ctrl)
> + return -EINVAL;
> +
> + if (ctrl->state == WAVE6_VPU_STATE_OFF)
> + return -EINVAL;
> +
> + if (ctrl->state == WAVE6_VPU_STATE_ON)
> + return 0;
> +
> + ret = wave6_wait_event_freezable_timeout(ctrl->load_fw_wq,
> + wave6_vpu_ctrl_get_state(dev) ==
> + WAVE6_VPU_STATE_ON,
> + msecs_to_jiffies(W6_BOOT_WAIT_TIMEOUT));
> + if (ret == -ERESTARTSYS || !ret) {
> + dev_err(ctrl->dev, "fail to wait vcpu boot done,ret %d\n", ret);
> + mutex_lock(&ctrl->ctrl_lock);
> + wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
> + mutex_unlock(&ctrl->ctrl_lock);
> + return -EINVAL;
> + }
> +
> + mutex_lock(&ctrl->ctrl_lock);
> + wave6_vpu_ctrl_boot_done(ctrl, 0);
> + mutex_unlock(&ctrl->ctrl_lock);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_wait_done);
There is no user of this outside. Drop.
> +
> +int wave6_vpu_ctrl_get_state(struct device *dev)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
> +
> + if (!ctrl)
> + return -EINVAL;
> +
> + return ctrl->state;
> +}
> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_get_state);
There is no user of this outside. Drop.
Whatever export stays, must be used by a following patch. You *must* add
the kerneldoc for it.
> +
> +static void wave6_vpu_ctrl_init_reserved_boot_region(struct vpu_ctrl *ctrl)
> +{
> + if (ctrl->boot_mem.size < WAVE6_CODE_BUF_SIZE) {
> + dev_warn(ctrl->dev, "boot memory size (%zu) is too small\n", ctrl->boot_mem.size);
> + ctrl->boot_mem.phys_addr = 0;
> + ctrl->boot_mem.size = 0;
> + memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
> + return;
> + }
> +
> + ctrl->boot_mem.vaddr = devm_memremap(ctrl->dev,
> + ctrl->boot_mem.phys_addr,
> + ctrl->boot_mem.size,
> + MEMREMAP_WC);
> + if (!ctrl->boot_mem.vaddr) {
> + memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
> + return;
> + }
> +
> + ctrl->boot_mem.dma_addr = dma_map_resource(ctrl->dev,
> + ctrl->boot_mem.phys_addr,
> + ctrl->boot_mem.size,
> + DMA_BIDIRECTIONAL,
> + 0);
> + if (!ctrl->boot_mem.dma_addr) {
> + memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
> + return;
> + }
> +
> + dev_info(ctrl->dev, "boot phys_addr: %pad, dma_addr: %pad, size: 0x%zx\n",
> + &ctrl->boot_mem.phys_addr,
> + &ctrl->boot_mem.dma_addr,
> + ctrl->boot_mem.size);
No, drop. Reasoning further.
> +}
...
> +
> + ctrl->num_clks = ret;
> +
> + np = of_parse_phandle(pdev->dev.of_node, "boot", 0);
> + if (np) {
> + struct resource mem;
> +
> + ret = of_address_to_resource(np, 0, &mem);
> + of_node_put(np);
> + if (!ret) {
> + ctrl->boot_mem.phys_addr = mem.start;
> + ctrl->boot_mem.size = resource_size(&mem);
> + wave6_vpu_ctrl_init_reserved_boot_region(ctrl);
> + } else {
> + dev_warn(&pdev->dev, "boot resource is not available.\n");
> + }
> + }
> +
> + ctrl->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
> + if (ctrl->sram_pool) {
> + ctrl->sram_buf.size = ctrl->res->sram_size;
> + ctrl->sram_buf.vaddr = gen_pool_dma_alloc(ctrl->sram_pool,
> + ctrl->sram_buf.size,
> + &ctrl->sram_buf.phys_addr);
> + if (!ctrl->sram_buf.vaddr)
> + ctrl->sram_buf.size = 0;
> + else
> + ctrl->sram_buf.dma_addr = dma_map_resource(&pdev->dev,
> + ctrl->sram_buf.phys_addr,
> + ctrl->sram_buf.size,
> + DMA_BIDIRECTIONAL,
> + 0);
> +
> + dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
> + &ctrl->sram_buf.phys_addr, &ctrl->sram_buf.dma_addr, ctrl->sram_buf.size);
You are not supposed to print addresses. This look like fixed hardware
mappings, so probably harmless but dma_addr not. Drop entire dev_info,
this is really discouraged practice.
> + }
> +
> + if (of_find_property(pdev->dev.of_node, "support-follower", NULL))
> + ctrl->support_follower = true;
> +
> + wave6_cooling_init(ctrl);
> +
> + pm_runtime_enable(&pdev->dev);
> +
> + return 0;
> +}
> +
> +static void wave6_vpu_ctrl_remove(struct platform_device *pdev)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(&pdev->dev);
> +
> + pm_runtime_disable(&pdev->dev);
> +
> + wave6_vpu_ctrl_clear_buffers(ctrl);
> + wave6_cooling_remove(ctrl);
> + if (ctrl->sram_pool && ctrl->sram_buf.vaddr) {
> + dma_unmap_resource(&pdev->dev,
> + ctrl->sram_buf.dma_addr,
> + ctrl->sram_buf.size,
> + DMA_BIDIRECTIONAL,
> + 0);
> + gen_pool_free(ctrl->sram_pool,
> + (unsigned long)ctrl->sram_buf.vaddr,
> + ctrl->sram_buf.size);
> + }
> + if (ctrl->boot_mem.dma_addr)
> + dma_unmap_resource(&pdev->dev,
> + ctrl->boot_mem.dma_addr,
> + ctrl->boot_mem.size,
> + DMA_BIDIRECTIONAL,
> + 0);
> + mutex_destroy(&ctrl->ctrl_lock);
> +}
> +
> +#ifdef CONFIG_PM
> +static int wave6_vpu_ctrl_runtime_suspend(struct device *dev)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
> +
> + clk_bulk_disable_unprepare(ctrl->num_clks, ctrl->clks);
> + return 0;
> +}
> +
> +static int wave6_vpu_ctrl_runtime_resume(struct device *dev)
> +{
> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
> +
> + return clk_bulk_prepare_enable(ctrl->num_clks, ctrl->clks);
> +}
> +#endif
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int wave6_vpu_ctrl_suspend(struct device *dev)
> +{
> + return 0;
Why do you need empty callbacks?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver
2025-02-10 9:07 ` [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver Nas Chung
@ 2025-02-10 17:40 ` Krzysztof Kozlowski
2025-02-11 8:28 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-10 17:40 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim
On 10/02/2025 10:07, Nas Chung wrote:
> +
> + dev->debugfs = debugfs_lookup(WAVE6_VPU_DEBUGFS_DIR, NULL);
> + if (IS_ERR_OR_NULL(dev->debugfs))
> + dev->debugfs = debugfs_create_dir(WAVE6_VPU_DEBUGFS_DIR, NULL);
> +
> + pm_runtime_enable(&pdev->dev);
> +
> + if (dev->res->codec_types & WAVE6_IS_DEC) {
> + ret = wave6_vpu_dec_register_device(dev);
> + if (ret) {
> + dev_err(&pdev->dev, "wave6_vpu_dec_register_device fail: %d\n", ret);
> + goto err_temp_vbuf_free;
> + }
> + }
> + if (dev->res->codec_types & WAVE6_IS_ENC) {
> + ret = wave6_vpu_enc_register_device(dev);
> + if (ret) {
> + dev_err(&pdev->dev, "wave6_vpu_enc_register_device fail: %d\n", ret);
> + goto err_dec_unreg;
> + }
> + }
> +
> + if (dev->ctrl && wave6_vpu_ctrl_support_follower(dev->ctrl)) {
> + wave6_vpu_activate(dev);
> + ret = pm_runtime_resume_and_get(dev->dev);
> + if (ret)
> + goto err_enc_unreg;
> + }
> +
> + dev_dbg(&pdev->dev, "Added wave6 driver with caps %s %s\n",
> + dev->res->codec_types & WAVE6_IS_ENC ? "'ENCODE'" : "",
> + dev->res->codec_types & WAVE6_IS_DEC ? "'DECODE'" : "");
> +
> + return 0;
> +
> +err_enc_unreg:
> + if (dev->res->codec_types & WAVE6_IS_ENC)
> + wave6_vpu_enc_unregister_device(dev);
> +err_dec_unreg:
> + if (dev->res->codec_types & WAVE6_IS_DEC)
> + wave6_vpu_dec_unregister_device(dev);
> +err_temp_vbuf_free:
> + wave6_free_dma(&dev->temp_vbuf);
> +err_kfifo_free:
> + kfifo_free(&dev->irq_status);
> +err_m2m_dev_release:
> + wave6_vpu_release_m2m_dev(dev);
> +err_v4l2_unregister:
> + v4l2_device_unregister(&dev->v4l2_dev);
> +
> + return ret;
> +}
> +
> +static void wave6_vpu_remove(struct platform_device *pdev)
> +{
> + struct vpu_device *dev = dev_get_drvdata(&pdev->dev);
> +
> + if (dev->ctrl && wave6_vpu_ctrl_support_follower(dev->ctrl)) {
> + if (!pm_runtime_suspended(&pdev->dev))
> + pm_runtime_put_sync(&pdev->dev);
> + }
> + pm_runtime_disable(&pdev->dev);
> +
> + wave6_vpu_enc_unregister_device(dev);
> + wave6_vpu_dec_unregister_device(dev);
> + wave6_free_dma(&dev->temp_vbuf);
> + kfifo_free(&dev->irq_status);
> + wave6_vpu_release_m2m_dev(dev);
> + v4l2_device_unregister(&dev->v4l2_dev);
> +}
> +
> +#ifdef CONFIG_PM
> +static int wave6_vpu_runtime_suspend(struct device *dev)
> +{
> + struct vpu_device *vpu_dev = dev_get_drvdata(dev);
> +
> + if (!vpu_dev)
> + return -ENODEV;
> +
> + dprintk(dev, "runtime suspend\n");
Drop
> + if (vpu_dev->ctrl && vpu_dev->active)
> + wave6_vpu_ctrl_put_sync(vpu_dev->ctrl, &vpu_dev->entity);
> + if (vpu_dev->num_clks)
> + clk_bulk_disable_unprepare(vpu_dev->num_clks, vpu_dev->clks);
> +
> + return 0;
> +}
> +
> +static int wave6_vpu_runtime_resume(struct device *dev)
> +{
> + struct vpu_device *vpu_dev = dev_get_drvdata(dev);
> + int ret = 0;
> +
> + if (!vpu_dev)
> + return -ENODEV;
> +
> + dprintk(dev, "runtime resume\n");
Drop
> + if (vpu_dev->num_clks) {
> + ret = clk_bulk_prepare_enable(vpu_dev->num_clks, vpu_dev->clks);
> + if (ret) {
> + dev_err(dev, "failed to enable clocks: %d\n", ret);
> + return ret;
> + }
> + }
> +
> + if (vpu_dev->ctrl && vpu_dev->active) {
> + ret = wave6_vpu_ctrl_resume_and_get(vpu_dev->ctrl, &vpu_dev->entity);
> + if (ret && vpu_dev->num_clks)
> + clk_bulk_disable_unprepare(vpu_dev->num_clks, vpu_dev->clks);
> + } else {
> + wave6_vpu_check_state(vpu_dev);
> + }
> +
> + return ret;
> +}
> +#endif
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int wave6_vpu_suspend(struct device *dev)
> +{
> + int ret;
> +
> + dprintk(dev, "suspend\n");
Drop. Don't re-implement existing tracing.
> + wave6_vpu_pause(dev, 0);
> +
> + ret = pm_runtime_force_suspend(dev);
> + if (ret)
> + wave6_vpu_pause(dev, 1);
> +
> + return ret;
> +}
> +
> +static int wave6_vpu_resume(struct device *dev)
> +{
> + int ret;
> +
> + dprintk(dev, "resume\n");
Drop, useless.
> + ret = pm_runtime_force_resume(dev);
> + if (ret)
> + return ret;
> +
> + wave6_vpu_pause(dev, 1);
> + return 0;
> +}
> +#endif
> +static const struct dev_pm_ops wave6_vpu_pm_ops = {
> + SET_RUNTIME_PM_OPS(wave6_vpu_runtime_suspend, wave6_vpu_runtime_resume, NULL)
> + SET_SYSTEM_SLEEP_PM_OPS(wave6_vpu_suspend, wave6_vpu_resume)
> +};
> +
> +static const struct of_device_id wave6_dt_ids[] = {
> + { .compatible = "nxp,imx95-wave633c", .data = &wave633c_data },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, wave6_dt_ids);
> +
> +static struct platform_driver wave6_vpu_driver = {
> + .driver = {
> + .name = VPU_PLATFORM_DEVICE_NAME,
> + .of_match_table = of_match_ptr(wave6_dt_ids),
Drop of_match_ptr, you have here warnings.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 2/8] media: v4l2-common: Add YUV24 format info
2025-02-10 14:00 ` Sebastian Fricke
@ 2025-02-11 1:58 ` Nas Chung
0 siblings, 0 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-11 1:58 UTC (permalink / raw)
To: Sebastian Fricke
Cc: mchehab@kernel.org, hverkuil@xs4all.nl, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Sebastian!
>-----Original Message-----
>From: Sebastian Fricke <sebastian.fricke@collabora.com>
>Sent: Monday, February 10, 2025 11:00 PM
>To: Nas Chung <nas.chung@chipsnmedia.com>
>Cc: mchehab@kernel.org; hverkuil@xs4all.nl; robh@kernel.org;
>krzk+dt@kernel.org; conor+dt@kernel.org; linux-media@vger.kernel.org;
>devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; linux-imx@nxp.com;
>linux-arm-kernel@lists.infradead.org; jackson.lee
><jackson.lee@chipsnmedia.com>; lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 2/8] media: v4l2-common: Add YUV24 format info
>
>Hey Nas,
>
>On 10.02.2025 18:07, Nas Chung wrote:
>>The YUV24 format is missing an entry in the v4l2_format_info().
>>The YUV24 format is the packed YUV 4:4:4 formats with 8 bits
>>per component.
>>
>
>That means that 0376a51fbe5e1 was incomplete, I think you should add a
>fixes tag to this commit, to highlight that you basically complete the
>previous commit.
I agree. I will add the fixes tag in v2.
Thanks.
Nas.
>
>Regards,
>Sebastian
>
>>Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
>>---
>> drivers/media/v4l2-core/v4l2-common.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>>diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-
>core/v4l2-common.c
>>index 0a2f4f0d0a07..de3636f1cdf1 100644
>>--- a/drivers/media/v4l2-core/v4l2-common.c
>>+++ b/drivers/media/v4l2-core/v4l2-common.c
>>@@ -269,6 +269,7 @@ const struct v4l2_format_info *v4l2_format_info(u32
>format)
>> { .format = V4L2_PIX_FMT_Y212, .pixel_enc =
>V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0,
>0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
>> { .format = V4L2_PIX_FMT_Y216, .pixel_enc =
>V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0,
>0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
>> { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc =
>V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0,
>0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
>>+ { .format = V4L2_PIX_FMT_YUV24, .pixel_enc =
>V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0,
>0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
>> { .format = V4L2_PIX_FMT_MT2110T, .pixel_enc =
>V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0,
>0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
>> .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
>> { .format = V4L2_PIX_FMT_MT2110R, .pixel_enc =
>V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0,
>0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
>>--
>>2.31.1
>>
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter
2025-02-10 17:24 ` Krzysztof Kozlowski
@ 2025-02-11 4:23 ` Nas Chung
0 siblings, 0 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-11 4:23 UTC (permalink / raw)
To: Krzysztof Kozlowski, mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Tuesday, February 11, 2025 2:24 AM
>To: Nas Chung <nas.chung@chipsnmedia.com>; mchehab@kernel.org;
>hverkuil@xs4all.nl; sebastian.fricke@collabora.com; robh@kernel.org;
>krzk+dt@kernel.org; conor+dt@kernel.org
>Cc: linux-media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 1/8] media: platform: chips-media: wave5: Rename
>Kconfig parameter
>
>On 10/02/2025 10:07, Nas Chung wrote:
>> The existing Kconfig parameter VIDEO_WAVE_VPU is ambiguous,
>> as it does not clearly indicate that it is specific to the Wave5 IP.
>>
>> Rename VIDEO_WAVE_VPU to VIDEO_WAVE5_VPU to make it explicit
>> that the parameter is specific to the Wave5 IP.
>>
>> No functional changes, only the parameter name is updated.
>
>
>That's unnecessary churn. Old name was fine. Kconfig does not match
>hardware 1-to-1 but represents only the driver name (or not even that...).
>
>If you solve any particular problem, then explain it. Otherwise this is
>just unnecessarily affecting users and backports.
I understand your point.
To avoid unnecessary changes, I'll drop this patch.
Thank you for your feedback.
Thanks.
Nas.
>
>>
>> Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
>> ---
>> arch/arm64/configs/defconfig | 2 +-
>
>That's a SoC patch, don't mix up subsystems.
>
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 0/8] Add support for Wave6 video codec driver
2025-02-10 13:05 ` [PATCH 0/8] Add support for Wave6 video codec driver Sebastian Fricke
@ 2025-02-11 4:47 ` Nas Chung
0 siblings, 0 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-11 4:47 UTC (permalink / raw)
To: Sebastian Fricke
Cc: mchehab@kernel.org, hverkuil@xs4all.nl, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Sebastian.
>-----Original Message-----
>From: Sebastian Fricke <sebastian.fricke@collabora.com>
>Sent: Monday, February 10, 2025 10:05 PM
>To: Nas Chung <nas.chung@chipsnmedia.com>
>Cc: mchehab@kernel.org; hverkuil@xs4all.nl; robh@kernel.org;
>krzk+dt@kernel.org; conor+dt@kernel.org; linux-media@vger.kernel.org;
>devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; linux-imx@nxp.com;
>linux-arm-kernel@lists.infradead.org; jackson.lee
><jackson.lee@chipsnmedia.com>; lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 0/8] Add support for Wave6 video codec driver
>
>Hey Nas,
>
>On 10.02.2025 18:07, Nas Chung wrote:
>>This patch series introduces support for the Chips&Media Wave6 video
>>codec IP, a completely different hardware architecture compared to Wave5.
>>
>>The wave6 driver is a M2M stateful encoder/decoder driver.
>>It supports various video formats, including H.264 and H.265,
>>for both encoding and decoding.
>
>Sounds like the hardware supports more formats.
>What are the other video formats?
You are correct.
The Wave6 IP supports VP9/AV1 decoding and AV1 encoding.
However, the IP can be configured to support only specific formats.
The Wave6 driver currently being upstreamed has been validated with
the Wave633 configuration, which supports only H.264 and H.265.
Thanks.
Nas.
>
>Regards,
>Sebastian
>
>>
>>On NXP i.MX SoCs, the Wave6 IP functionality is split between two devices:
>>VPU Control Device, Manages shared resources such as firmware access and
>>power domains.
>>VPU Device, Provides encoding and decoding capabilities.
>>The VPU device cannot operate independently without the VPU control device.
>>
>>This driver has been tested with GStreamer on:
>>- NXP i.MX95 board
>>- pre-silicon FPGA environment
>>
>>Test results for decoder fluster:
>>- JVT-AVC_V1, Ran 77/135 tests successfully in 35.929 secs
>>- JVT-FR-EXT, Ran 25/69 tests successfully in 17.717 secs
>>- JCT-VC-HEVC_V1, Ran 132/147 tests successfully in 81.568 secs
>>- All failures are due to unsupported hardware features:
>>-- 10bit, Resolutions higher than 4K, FMO, MBAFF
>>-- Extended profile, Field encoding and High422 sreams.
>>
>>Test results for v4l2-compliance:
>>v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t
>>v4l2-compliance SHA: 77f5df419204 2025-02-07 08:59:59
>>
>>Compliance test for wave6-dec device /dev/video0:
>>
>>Driver Info:
>> Driver name : wave6-dec
>> Card type : wave6-dec
>> Bus info : platform:wave6-dec
>> Driver version : 6.9.2
>> 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
>> fail: ../utils/v4l2-compliance/v4l2-test-
>controls.cpp(1180): !have_source_change || !have_eos
>> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
>> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>> Standard Controls: 7 Private Controls: 1
>>
>>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
>>
>>Total for wave6-dec device /dev/video0: 48, Succeeded: 47, Failed: 1,
>Warnings: 0
>>
>>v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t
>>v4l2-compliance SHA: 77f5df419204 2025-02-07 08:59:59
>>
>>Compliance test for wave6-enc device /dev/video1:
>>
>>Driver Info:
>> Driver name : wave6-enc
>> Card type : wave6-enc
>> Bus info : platform:wave6-enc
>> Driver version : 6.9.2
>> 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
>> fail: ../utils/v4l2-compliance/v4l2-test-controls.cpp(1169):
>node->codec_mask & STATEFUL_ENCODER
>> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
>> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>> Standard Controls: 53 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
>>
>>Total for wave6-enc device /dev/video1: 48, Succeeded: 47, Failed: 1,
>Warnings: 0
>>
>>Nas Chung (8):
>> media: platform: chips-media: wave5: Rename Kconfig parameter
>> media: v4l2-common: Add YUV24 format info
>> dt-bindings: media: nxp: Add Wave6 video codec device
>> media: chips-media: wave6: Add Wave6 codec driver
>> media: chips-media: wave6: Add v4l2 m2m driver
>> media: chips-media: wave6: Add Wave6 vpu interface
>> media: chips-media: wave6: Add Wave6 control driver
>> media: chips-media: wave6: Improve debugging capabilities
>>
>> .../bindings/media/nxp,wave633c.yaml | 202 ++
>> MAINTAINERS | 8 +
>> arch/arm64/configs/defconfig | 2 +-
>> drivers/media/platform/chips-media/Kconfig | 1 +
>> drivers/media/platform/chips-media/Makefile | 1 +
>> .../media/platform/chips-media/wave5/Kconfig | 6 +-
>> .../media/platform/chips-media/wave5/Makefile | 2 +-
>> .../media/platform/chips-media/wave6/Kconfig | 26 +
>> .../media/platform/chips-media/wave6/Makefile | 17 +
>> .../platform/chips-media/wave6/wave6-hw.c | 3113 +++++++++++++++++
>> .../platform/chips-media/wave6/wave6-hw.h | 69 +
>> .../chips-media/wave6/wave6-regdefine.h | 675 ++++
>> .../platform/chips-media/wave6/wave6-trace.h | 336 ++
>> .../platform/chips-media/wave6/wave6-vdi.c | 52 +
>> .../platform/chips-media/wave6/wave6-vdi.h | 59 +
>> .../chips-media/wave6/wave6-vpu-ctrl.c | 1020 ++++++
>> .../chips-media/wave6/wave6-vpu-ctrl.h | 38 +
>> .../chips-media/wave6/wave6-vpu-dbg.c | 230 ++
>> .../chips-media/wave6/wave6-vpu-dbg.h | 22 +
>> .../chips-media/wave6/wave6-vpu-dec.c | 1883 ++++++++++
>> .../chips-media/wave6/wave6-vpu-enc.c | 2698 ++++++++++++++
>> .../chips-media/wave6/wave6-vpu-v4l2.c | 381 ++
>> .../platform/chips-media/wave6/wave6-vpu.c | 487 +++
>> .../platform/chips-media/wave6/wave6-vpu.h | 106 +
>> .../platform/chips-media/wave6/wave6-vpuapi.c | 1001 ++++++
>> .../platform/chips-media/wave6/wave6-vpuapi.h | 993 ++++++
>> .../chips-media/wave6/wave6-vpuconfig.h | 80 +
>> .../chips-media/wave6/wave6-vpuerror.h | 262 ++
>> drivers/media/v4l2-core/v4l2-common.c | 1 +
>> 29 files changed, 13766 insertions(+), 5 deletions(-)
>> create mode 100644
>Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>> create mode 100644 drivers/media/platform/chips-media/wave6/Kconfig
>> create mode 100644 drivers/media/platform/chips-media/wave6/Makefile
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>regdefine.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-trace.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>ctrl.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>ctrl.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>dbg.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>dbg.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>dec.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>enc.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>v4l2.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuapi.c
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuapi.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuconfig.h
>> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuerror.h
>>
>>--
>>2.31.1
>>
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [EXT] [PATCH 0/8] Add support for Wave6 video codec driver
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
` (6 preceding siblings ...)
2025-02-10 13:05 ` [PATCH 0/8] Add support for Wave6 video codec driver Sebastian Fricke
@ 2025-02-11 6:07 ` Ming Qian
7 siblings, 0 replies; 29+ messages in thread
From: Ming Qian @ 2025-02-11 6:07 UTC (permalink / raw)
To: Nas Chung, mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, dl-linux-imx,
linux-arm-kernel@lists.infradead.org, jackson.lee@chipsnmedia.com,
lafley.kim@chipsnmedia.com
Tested on i.MX95, the sanity test pass of encoder and decoder.
Only a v4l2-compliance issue about the deprecated behavior EOS event, other than that.
Tested-by: Ming Qian <ming.qian@oss.nxp.com>
>-----Original Message-----
>From: Nas Chung <nas.chung@chipsnmedia.com>
>Sent: Monday, February 10, 2025 5:07 PM
>To: mchehab@kernel.org; hverkuil@xs4all.nl; sebastian.fricke@collabora.com;
>robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org
>Cc: linux-media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>; linux-arm-
>kernel@lists.infradead.org; jackson.lee@chipsnmedia.com;
>lafley.kim@chipsnmedia.com; Nas Chung <nas.chung@chipsnmedia.com>
>Subject: [EXT] [PATCH 0/8] Add support for Wave6 video codec driver
>
>Caution: This is an external email. Please take care when clicking links or
>opening attachments. When in doubt, report the message using the 'Report
>this email' button
>
>
>This patch series introduces support for the Chips&Media Wave6 video codec
>IP, a completely different hardware architecture compared to Wave5.
>
>The wave6 driver is a M2M stateful encoder/decoder driver.
>It supports various video formats, including H.264 and H.265, for both
>encoding and decoding.
>
>On NXP i.MX SoCs, the Wave6 IP functionality is split between two devices:
>VPU Control Device, Manages shared resources such as firmware access and
>power domains.
>VPU Device, Provides encoding and decoding capabilities.
>The VPU device cannot operate independently without the VPU control device.
>
>This driver has been tested with GStreamer on:
>- NXP i.MX95 board
>- pre-silicon FPGA environment
>
>Test results for decoder fluster:
>- JVT-AVC_V1, Ran 77/135 tests successfully in 35.929 secs
>- JVT-FR-EXT, Ran 25/69 tests successfully in 17.717 secs
>- JCT-VC-HEVC_V1, Ran 132/147 tests successfully in 81.568 secs
>- All failures are due to unsupported hardware features:
>-- 10bit, Resolutions higher than 4K, FMO, MBAFF
>-- Extended profile, Field encoding and High422 sreams.
>
>Test results for v4l2-compliance:
>v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t v4l2-compliance SHA:
>77f5df419204 2025-02-07 08:59:59
>
>Compliance test for wave6-dec device /dev/video0:
>
>Driver Info:
> Driver name : wave6-dec
> Card type : wave6-dec
> Bus info : platform:wave6-dec
> Driver version : 6.9.2
> 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
> fail: ../utils/v4l2-compliance/v4l2-test-
>controls.cpp(1180): !have_source_change || !have_eos
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 7 Private Controls: 1
>
>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
>
>Total for wave6-dec device /dev/video0: 48, Succeeded: 47, Failed: 1, Warnings:
>0
>
>v4l2-compliance 1.29.0-5326, 64 bits, 64-bit time_t v4l2-compliance SHA:
>77f5df419204 2025-02-07 08:59:59
>
>Compliance test for wave6-enc device /dev/video1:
>
>Driver Info:
> Driver name : wave6-enc
> Card type : wave6-enc
> Bus info : platform:wave6-enc
> Driver version : 6.9.2
> 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
> fail: ../utils/v4l2-compliance/v4l2-test-controls.cpp(1169): node-
>>codec_mask & STATEFUL_ENCODER
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 53 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
>
>Total for wave6-enc device /dev/video1: 48, Succeeded: 47, Failed: 1, Warnings:
>0
>
>Nas Chung (8):
> media: platform: chips-media: wave5: Rename Kconfig parameter
> media: v4l2-common: Add YUV24 format info
> dt-bindings: media: nxp: Add Wave6 video codec device
> media: chips-media: wave6: Add Wave6 codec driver
> media: chips-media: wave6: Add v4l2 m2m driver
> media: chips-media: wave6: Add Wave6 vpu interface
> media: chips-media: wave6: Add Wave6 control driver
> media: chips-media: wave6: Improve debugging capabilities
>
> .../bindings/media/nxp,wave633c.yaml | 202 ++
> MAINTAINERS | 8 +
> arch/arm64/configs/defconfig | 2 +-
> drivers/media/platform/chips-media/Kconfig | 1 +
> drivers/media/platform/chips-media/Makefile | 1 +
> .../media/platform/chips-media/wave5/Kconfig | 6 +-
> .../media/platform/chips-media/wave5/Makefile | 2 +-
> .../media/platform/chips-media/wave6/Kconfig | 26 +
> .../media/platform/chips-media/wave6/Makefile | 17 +
> .../platform/chips-media/wave6/wave6-hw.c | 3113 +++++++++++++++++
> .../platform/chips-media/wave6/wave6-hw.h | 69 +
> .../chips-media/wave6/wave6-regdefine.h | 675 ++++
> .../platform/chips-media/wave6/wave6-trace.h | 336 ++
> .../platform/chips-media/wave6/wave6-vdi.c | 52 +
> .../platform/chips-media/wave6/wave6-vdi.h | 59 +
> .../chips-media/wave6/wave6-vpu-ctrl.c | 1020 ++++++
> .../chips-media/wave6/wave6-vpu-ctrl.h | 38 +
> .../chips-media/wave6/wave6-vpu-dbg.c | 230 ++
> .../chips-media/wave6/wave6-vpu-dbg.h | 22 +
> .../chips-media/wave6/wave6-vpu-dec.c | 1883 ++++++++++
> .../chips-media/wave6/wave6-vpu-enc.c | 2698 ++++++++++++++
> .../chips-media/wave6/wave6-vpu-v4l2.c | 381 ++
> .../platform/chips-media/wave6/wave6-vpu.c | 487 +++
> .../platform/chips-media/wave6/wave6-vpu.h | 106 +
> .../platform/chips-media/wave6/wave6-vpuapi.c | 1001
>++++++ .../platform/chips-media/wave6/wave6-vpuapi.h | 993 ++++++
> .../chips-media/wave6/wave6-vpuconfig.h | 80 +
> .../chips-media/wave6/wave6-vpuerror.h | 262 ++
> drivers/media/v4l2-core/v4l2-common.c | 1 +
> 29 files changed, 13766 insertions(+), 5 deletions(-) create mode 100644
>Documentation/devicetree/bindings/media/nxp,wave633c.yaml
> create mode 100644 drivers/media/platform/chips-media/wave6/Kconfig
> create mode 100644 drivers/media/platform/chips-media/wave6/Makefile
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-hw.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>regdefine.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>trace.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vdi.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>ctrl.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>ctrl.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>dbg.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>dbg.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>dec.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>enc.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-
>v4l2.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuapi.c
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuapi.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuconfig.h
> create mode 100644 drivers/media/platform/chips-media/wave6/wave6-
>vpuerror.h
>
>--
>2.31.1
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver
2025-02-10 17:40 ` Krzysztof Kozlowski
@ 2025-02-11 8:28 ` Nas Chung
0 siblings, 0 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-11 8:28 UTC (permalink / raw)
To: Krzysztof Kozlowski, mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Tuesday, February 11, 2025 2:41 AM
>To: Nas Chung <nas.chung@chipsnmedia.com>; mchehab@kernel.org;
>hverkuil@xs4all.nl; sebastian.fricke@collabora.com; robh@kernel.org;
>krzk+dt@kernel.org; conor+dt@kernel.org
>Cc: linux-media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver
>
>On 10/02/2025 10:07, Nas Chung wrote:
>> +
>> + dev->debugfs = debugfs_lookup(WAVE6_VPU_DEBUGFS_DIR, NULL);
>> + if (IS_ERR_OR_NULL(dev->debugfs))
>> + dev->debugfs = debugfs_create_dir(WAVE6_VPU_DEBUGFS_DIR,
>NULL);
>> +
>> + pm_runtime_enable(&pdev->dev);
>> +
>> + if (dev->res->codec_types & WAVE6_IS_DEC) {
>> + ret = wave6_vpu_dec_register_device(dev);
>> + if (ret) {
>> + dev_err(&pdev->dev, "wave6_vpu_dec_register_device
>fail: %d\n", ret);
>> + goto err_temp_vbuf_free;
>> + }
>> + }
>> + if (dev->res->codec_types & WAVE6_IS_ENC) {
>> + ret = wave6_vpu_enc_register_device(dev);
>> + if (ret) {
>> + dev_err(&pdev->dev, "wave6_vpu_enc_register_device
>fail: %d\n", ret);
>> + goto err_dec_unreg;
>> + }
>> + }
>> +
>> + if (dev->ctrl && wave6_vpu_ctrl_support_follower(dev->ctrl)) {
>> + wave6_vpu_activate(dev);
>> + ret = pm_runtime_resume_and_get(dev->dev);
>> + if (ret)
>> + goto err_enc_unreg;
>> + }
>> +
>> + dev_dbg(&pdev->dev, "Added wave6 driver with caps %s %s\n",
>> + dev->res->codec_types & WAVE6_IS_ENC ? "'ENCODE'" : "",
>> + dev->res->codec_types & WAVE6_IS_DEC ? "'DECODE'" : "");
>> +
>> + return 0;
>> +
>> +err_enc_unreg:
>> + if (dev->res->codec_types & WAVE6_IS_ENC)
>> + wave6_vpu_enc_unregister_device(dev);
>> +err_dec_unreg:
>> + if (dev->res->codec_types & WAVE6_IS_DEC)
>> + wave6_vpu_dec_unregister_device(dev);
>> +err_temp_vbuf_free:
>> + wave6_free_dma(&dev->temp_vbuf);
>> +err_kfifo_free:
>> + kfifo_free(&dev->irq_status);
>> +err_m2m_dev_release:
>> + wave6_vpu_release_m2m_dev(dev);
>> +err_v4l2_unregister:
>> + v4l2_device_unregister(&dev->v4l2_dev);
>> +
>> + return ret;
>> +}
>> +
>> +static void wave6_vpu_remove(struct platform_device *pdev)
>> +{
>> + struct vpu_device *dev = dev_get_drvdata(&pdev->dev);
>> +
>> + if (dev->ctrl && wave6_vpu_ctrl_support_follower(dev->ctrl)) {
>> + if (!pm_runtime_suspended(&pdev->dev))
>> + pm_runtime_put_sync(&pdev->dev);
>> + }
>> + pm_runtime_disable(&pdev->dev);
>> +
>> + wave6_vpu_enc_unregister_device(dev);
>> + wave6_vpu_dec_unregister_device(dev);
>> + wave6_free_dma(&dev->temp_vbuf);
>> + kfifo_free(&dev->irq_status);
>> + wave6_vpu_release_m2m_dev(dev);
>> + v4l2_device_unregister(&dev->v4l2_dev);
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int wave6_vpu_runtime_suspend(struct device *dev)
>> +{
>> + struct vpu_device *vpu_dev = dev_get_drvdata(dev);
>> +
>> + if (!vpu_dev)
>> + return -ENODEV;
>> +
>> + dprintk(dev, "runtime suspend\n");
>
>Drop
>
>> + if (vpu_dev->ctrl && vpu_dev->active)
>> + wave6_vpu_ctrl_put_sync(vpu_dev->ctrl, &vpu_dev->entity);
>> + if (vpu_dev->num_clks)
>> + clk_bulk_disable_unprepare(vpu_dev->num_clks, vpu_dev->clks);
>> +
>> + return 0;
>> +}
>> +
>> +static int wave6_vpu_runtime_resume(struct device *dev)
>> +{
>> + struct vpu_device *vpu_dev = dev_get_drvdata(dev);
>> + int ret = 0;
>> +
>> + if (!vpu_dev)
>> + return -ENODEV;
>> +
>> + dprintk(dev, "runtime resume\n");
>
>Drop
>
>> + if (vpu_dev->num_clks) {
>> + ret = clk_bulk_prepare_enable(vpu_dev->num_clks, vpu_dev-
>>clks);
>> + if (ret) {
>> + dev_err(dev, "failed to enable clocks: %d\n", ret);
>> + return ret;
>> + }
>> + }
>> +
>> + if (vpu_dev->ctrl && vpu_dev->active) {
>> + ret = wave6_vpu_ctrl_resume_and_get(vpu_dev->ctrl, &vpu_dev-
>>entity);
>> + if (ret && vpu_dev->num_clks)
>> + clk_bulk_disable_unprepare(vpu_dev->num_clks, vpu_dev-
>>clks);
>> + } else {
>> + wave6_vpu_check_state(vpu_dev);
>> + }
>> +
>> + return ret;
>> +}
>> +#endif
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int wave6_vpu_suspend(struct device *dev)
>> +{
>> + int ret;
>> +
>> + dprintk(dev, "suspend\n");
>
>Drop. Don't re-implement existing tracing.
>
>> + wave6_vpu_pause(dev, 0);
>> +
>> + ret = pm_runtime_force_suspend(dev);
>> + if (ret)
>> + wave6_vpu_pause(dev, 1);
>> +
>> + return ret;
>> +}
>> +
>> +static int wave6_vpu_resume(struct device *dev)
>> +{
>> + int ret;
>> +
>> + dprintk(dev, "resume\n");
>
>Drop, useless.
Okay. I will remove the redundant debug message and dprintk in v2.
>
>> + ret = pm_runtime_force_resume(dev);
>> + if (ret)
>> + return ret;
>> +
>> + wave6_vpu_pause(dev, 1);
>> + return 0;
>> +}
>> +#endif
>> +static const struct dev_pm_ops wave6_vpu_pm_ops = {
>> + SET_RUNTIME_PM_OPS(wave6_vpu_runtime_suspend,
>wave6_vpu_runtime_resume, NULL)
>> + SET_SYSTEM_SLEEP_PM_OPS(wave6_vpu_suspend, wave6_vpu_resume)
>> +};
>> +
>> +static const struct of_device_id wave6_dt_ids[] = {
>> + { .compatible = "nxp,imx95-wave633c", .data = &wave633c_data },
>> + { /* sentinel */ }
>> +};
>> +MODULE_DEVICE_TABLE(of, wave6_dt_ids);
>> +
>> +static struct platform_driver wave6_vpu_driver = {
>> + .driver = {
>> + .name = VPU_PLATFORM_DEVICE_NAME,
>> + .of_match_table = of_match_ptr(wave6_dt_ids),
>
>
>Drop of_match_ptr, you have here warnings.
I will address this in v2.
Thanks.
Nas.
>
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
2025-02-10 17:37 ` Krzysztof Kozlowski
@ 2025-02-11 8:55 ` Nas Chung
0 siblings, 0 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-11 8:55 UTC (permalink / raw)
To: Krzysztof Kozlowski, mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Tuesday, February 11, 2025 2:38 AM
>To: Nas Chung <nas.chung@chipsnmedia.com>; mchehab@kernel.org;
>hverkuil@xs4all.nl; sebastian.fricke@collabora.com; robh@kernel.org;
>krzk+dt@kernel.org; conor+dt@kernel.org
>Cc: linux-media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control
>driver
>
>On 10/02/2025 10:07, Nas Chung wrote:
>> +
>> +int wave6_vpu_ctrl_resume_and_get(struct device *dev, struct
>wave6_vpu_entity *entity)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
>> + bool boot;
>> + int ret;
>> +
>> + if (!ctrl)
>> + return -EINVAL;
>> +
>> + if (!entity || !entity->dev || !entity->read_reg || !entity-
>>write_reg)
>> + return -EINVAL;
>> +
>> + mutex_lock(&ctrl->ctrl_lock);
>> +
>> + ret = pm_runtime_resume_and_get(ctrl->dev);
>> + if (ret) {
>> + dev_err(dev, "pm runtime resume fail, ret = %d\n", ret);
>> + mutex_unlock(&ctrl->ctrl_lock);
>> + return ret;
>> + }
>> +
>> + entity->booted = false;
>> +
>> + if (ctrl->current_entity)
>> + boot = false;
>> + else
>> + boot = list_empty(&ctrl->entities) ? true : false;
>> +
>> + list_add_tail(&entity->list, &ctrl->entities);
>> + if (boot)
>> + ret = wave6_vpu_ctrl_try_boot(ctrl, entity);
>> +
>> + if (ctrl->state == WAVE6_VPU_STATE_ON)
>> + wave6_vpu_ctrl_on_boot(entity);
>> +
>> + if (ret)
>> + pm_runtime_put_sync(ctrl->dev);
>> +
>> + mutex_unlock(&ctrl->ctrl_lock);
>> +
>> + return ret;
>> +}
>
>Drop entire function.
>
>> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_resume_and_get);
>
>Drop.
>
>> +
>> +void wave6_vpu_ctrl_put_sync(struct device *dev, struct wave6_vpu_entity
>*entity)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
>> +
>> + if (!ctrl)
>> + return;
>> +
>> + if (entity == ctrl->current_entity)
>> + wave6_vpu_ctrl_wait_done(dev);
>> +
>> + mutex_lock(&ctrl->ctrl_lock);
>> +
>> + if (!wave6_vpu_ctrl_find_entity(ctrl, entity))
>> + goto exit;
>> +
>> + list_del_init(&entity->list);
>> + if (list_empty(&ctrl->entities)) {
>> + if (!entity->read_reg(entity->dev, W6_VPU_VCPU_CUR_PC))
>> + wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
>> + else
>> + wave6_vpu_ctrl_sleep(ctrl, entity);
>> + }
>> +
>> + if (!pm_runtime_suspended(ctrl->dev))
>> + pm_runtime_put_sync(ctrl->dev);
>> +exit:
>> + mutex_unlock(&ctrl->ctrl_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_put_sync);
>
>Drop entire function. Dead code.
>
>... or you arranged your patches really incorrectly, but this I can't
>really judge.
>
>
>
>> +
>> +int wave6_vpu_ctrl_wait_done(struct device *dev)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + if (!ctrl)
>> + return -EINVAL;
>> +
>> + if (ctrl->state == WAVE6_VPU_STATE_OFF)
>> + return -EINVAL;
>> +
>> + if (ctrl->state == WAVE6_VPU_STATE_ON)
>> + return 0;
>> +
>> + ret = wave6_wait_event_freezable_timeout(ctrl->load_fw_wq,
>> + wave6_vpu_ctrl_get_state(dev) ==
>> + WAVE6_VPU_STATE_ON,
>> +
>msecs_to_jiffies(W6_BOOT_WAIT_TIMEOUT));
>> + if (ret == -ERESTARTSYS || !ret) {
>> + dev_err(ctrl->dev, "fail to wait vcpu boot done,ret %d\n",
>ret);
>> + mutex_lock(&ctrl->ctrl_lock);
>> + wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
>> + mutex_unlock(&ctrl->ctrl_lock);
>> + return -EINVAL;
>> + }
>> +
>> + mutex_lock(&ctrl->ctrl_lock);
>> + wave6_vpu_ctrl_boot_done(ctrl, 0);
>> + mutex_unlock(&ctrl->ctrl_lock);
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_wait_done);
>
>There is no user of this outside. Drop.
>
>
>> +
>> +int wave6_vpu_ctrl_get_state(struct device *dev)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
>> +
>> + if (!ctrl)
>> + return -EINVAL;
>> +
>> + return ctrl->state;
>> +}
>> +EXPORT_SYMBOL_GPL(wave6_vpu_ctrl_get_state);
>
>There is no user of this outside. Drop.
>
>Whatever export stays, must be used by a following patch. You *must* add
>the kerneldoc for it.
I realize that my patch order was incorrect.
I will fix it and include the necessary kerneldoc in v2.
>
>> +
>> +static void wave6_vpu_ctrl_init_reserved_boot_region(struct vpu_ctrl
>*ctrl)
>> +{
>> + if (ctrl->boot_mem.size < WAVE6_CODE_BUF_SIZE) {
>> + dev_warn(ctrl->dev, "boot memory size (%zu) is too small\n",
>ctrl->boot_mem.size);
>> + ctrl->boot_mem.phys_addr = 0;
>> + ctrl->boot_mem.size = 0;
>> + memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
>> + return;
>> + }
>> +
>> + ctrl->boot_mem.vaddr = devm_memremap(ctrl->dev,
>> + ctrl->boot_mem.phys_addr,
>> + ctrl->boot_mem.size,
>> + MEMREMAP_WC);
>> + if (!ctrl->boot_mem.vaddr) {
>> + memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
>> + return;
>> + }
>> +
>> + ctrl->boot_mem.dma_addr = dma_map_resource(ctrl->dev,
>> + ctrl->boot_mem.phys_addr,
>> + ctrl->boot_mem.size,
>> + DMA_BIDIRECTIONAL,
>> + 0);
>> + if (!ctrl->boot_mem.dma_addr) {
>> + memset(&ctrl->boot_mem, 0, sizeof(ctrl->boot_mem));
>> + return;
>> + }
>> +
>> + dev_info(ctrl->dev, "boot phys_addr: %pad, dma_addr: %pad, size:
>0x%zx\n",
>> + &ctrl->boot_mem.phys_addr,
>> + &ctrl->boot_mem.dma_addr,
>> + ctrl->boot_mem.size);
>
>No, drop. Reasoning further.
>
>> +}
>...
>
>> +
>> + ctrl->num_clks = ret;
>> +
>> + np = of_parse_phandle(pdev->dev.of_node, "boot", 0);
>> + if (np) {
>> + struct resource mem;
>> +
>> + ret = of_address_to_resource(np, 0, &mem);
>> + of_node_put(np);
>> + if (!ret) {
>> + ctrl->boot_mem.phys_addr = mem.start;
>> + ctrl->boot_mem.size = resource_size(&mem);
>> + wave6_vpu_ctrl_init_reserved_boot_region(ctrl);
>> + } else {
>> + dev_warn(&pdev->dev, "boot resource is not
>available.\n");
>> + }
>> + }
>> +
>> + ctrl->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
>> + if (ctrl->sram_pool) {
>> + ctrl->sram_buf.size = ctrl->res->sram_size;
>> + ctrl->sram_buf.vaddr = gen_pool_dma_alloc(ctrl->sram_pool,
>> + ctrl->sram_buf.size,
>> + &ctrl->sram_buf.phys_addr);
>> + if (!ctrl->sram_buf.vaddr)
>> + ctrl->sram_buf.size = 0;
>> + else
>> + ctrl->sram_buf.dma_addr = dma_map_resource(&pdev->dev,
>> + ctrl-
>>sram_buf.phys_addr,
>> + ctrl->sram_buf.size,
>> + DMA_BIDIRECTIONAL,
>> + 0);
>> +
>> + dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
>> + &ctrl->sram_buf.phys_addr, &ctrl->sram_buf.dma_addr,
>ctrl->sram_buf.size);
>
>You are not supposed to print addresses. This look like fixed hardware
>mappings, so probably harmless but dma_addr not. Drop entire dev_info,
>this is really discouraged practice.
Thanks for the detailed explanation.
I will address this in v2.
>
>
>> + }
>> +
>> + if (of_find_property(pdev->dev.of_node, "support-follower", NULL))
>> + ctrl->support_follower = true;
>> +
>> + wave6_cooling_init(ctrl);
>> +
>> + pm_runtime_enable(&pdev->dev);
>> +
>> + return 0;
>> +}
>> +
>> +static void wave6_vpu_ctrl_remove(struct platform_device *pdev)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(&pdev->dev);
>> +
>> + pm_runtime_disable(&pdev->dev);
>> +
>> + wave6_vpu_ctrl_clear_buffers(ctrl);
>> + wave6_cooling_remove(ctrl);
>> + if (ctrl->sram_pool && ctrl->sram_buf.vaddr) {
>> + dma_unmap_resource(&pdev->dev,
>> + ctrl->sram_buf.dma_addr,
>> + ctrl->sram_buf.size,
>> + DMA_BIDIRECTIONAL,
>> + 0);
>> + gen_pool_free(ctrl->sram_pool,
>> + (unsigned long)ctrl->sram_buf.vaddr,
>> + ctrl->sram_buf.size);
>> + }
>> + if (ctrl->boot_mem.dma_addr)
>> + dma_unmap_resource(&pdev->dev,
>> + ctrl->boot_mem.dma_addr,
>> + ctrl->boot_mem.size,
>> + DMA_BIDIRECTIONAL,
>> + 0);
>> + mutex_destroy(&ctrl->ctrl_lock);
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int wave6_vpu_ctrl_runtime_suspend(struct device *dev)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
>> +
>> + clk_bulk_disable_unprepare(ctrl->num_clks, ctrl->clks);
>> + return 0;
>> +}
>> +
>> +static int wave6_vpu_ctrl_runtime_resume(struct device *dev)
>> +{
>> + struct vpu_ctrl *ctrl = dev_get_drvdata(dev);
>> +
>> + return clk_bulk_prepare_enable(ctrl->num_clks, ctrl->clks);
>> +}
>> +#endif
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int wave6_vpu_ctrl_suspend(struct device *dev)
>> +{
>> + return 0;
>
>Why do you need empty callbacks?
I forgot to remove it.
I will address this in v2.
Thanks.
Nas.
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities
2025-02-10 9:07 ` [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities Nas Chung
@ 2025-02-11 16:43 ` kernel test robot
0 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2025-02-11 16:43 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: oe-kbuild-all, linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Hi Nas,
kernel test robot noticed the following build warnings:
[auto build test WARNING on linuxtv-media-pending/master]
[also build test WARNING on arm64/for-next/core robh/for-next linus/master v6.14-rc2 next-20250210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Nas-Chung/media-platform-chips-media-wave5-Rename-Kconfig-parameter/20250210-171144
base: https://git.linuxtv.org/media-ci/media-pending.git master
patch link: https://lore.kernel.org/r/20250210090725.4580-9-nas.chung%40chipsnmedia.com
patch subject: [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities
config: loongarch-allyesconfig (https://download.01.org/0day-ci/archive/20250212/202502120017.COEwtixF-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250212/202502120017.COEwtixF-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502120017.COEwtixF-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c: In function 'wave6_vpu_dec_handle_dst_buffer':
>> drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c:261:13: warning: variable 'buf_size' set but not used [-Wunused-but-set-variable]
261 | u32 buf_size;
| ^~~~~~~~
--
drivers/media/platform/chips-media/wave6/wave6-hw.c: In function 'wave6_vpu_dec_flush':
>> drivers/media/platform/chips-media/wave6/wave6-hw.c:1022:37: warning: variable 'fb' set but not used [-Wunused-but-set-variable]
1022 | struct frame_buffer fb;
| ^~
vim +/buf_size +261 drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c
de204321b54004 Nas Chung 2025-02-10 254
de204321b54004 Nas Chung 2025-02-10 255 static void wave6_vpu_dec_handle_dst_buffer(struct vpu_instance *inst)
de204321b54004 Nas Chung 2025-02-10 256 {
de204321b54004 Nas Chung 2025-02-10 257 struct vb2_v4l2_buffer *dst_buf;
de204321b54004 Nas Chung 2025-02-10 258 struct v4l2_m2m_buffer *v4l2_m2m_buf;
de204321b54004 Nas Chung 2025-02-10 259 struct vpu_buffer *vpu_buf;
de204321b54004 Nas Chung 2025-02-10 260 dma_addr_t buf_addr_y, buf_addr_cb, buf_addr_cr;
de204321b54004 Nas Chung 2025-02-10 @261 u32 buf_size;
de204321b54004 Nas Chung 2025-02-10 262 u32 fb_stride = inst->dst_fmt.plane_fmt[0].bytesperline;
de204321b54004 Nas Chung 2025-02-10 263 u32 luma_size = fb_stride * inst->dst_fmt.height;
de204321b54004 Nas Chung 2025-02-10 264 u32 chroma_size = (fb_stride / 2) * (inst->dst_fmt.height / 2);
de204321b54004 Nas Chung 2025-02-10 265 struct frame_buffer disp_buffer = {0};
de204321b54004 Nas Chung 2025-02-10 266 struct dec_initial_info initial_info = {0};
de204321b54004 Nas Chung 2025-02-10 267 int consumed_num = wave6_vpu_get_consumed_fb_num(inst);
de204321b54004 Nas Chung 2025-02-10 268 int ret;
de204321b54004 Nas Chung 2025-02-10 269
de204321b54004 Nas Chung 2025-02-10 270 wave6_vpu_dec_give_command(inst, DEC_GET_SEQ_INFO, &initial_info);
de204321b54004 Nas Chung 2025-02-10 271
de204321b54004 Nas Chung 2025-02-10 272 v4l2_m2m_for_each_dst_buf(inst->v4l2_fh.m2m_ctx, v4l2_m2m_buf) {
de204321b54004 Nas Chung 2025-02-10 273 dst_buf = &v4l2_m2m_buf->vb;
de204321b54004 Nas Chung 2025-02-10 274 vpu_buf = wave6_to_vpu_buf(dst_buf);
de204321b54004 Nas Chung 2025-02-10 275
de204321b54004 Nas Chung 2025-02-10 276 if (vpu_buf->consumed)
de204321b54004 Nas Chung 2025-02-10 277 continue;
de204321b54004 Nas Chung 2025-02-10 278
de204321b54004 Nas Chung 2025-02-10 279 if (consumed_num >= WAVE6_MAX_FBS)
de204321b54004 Nas Chung 2025-02-10 280 break;
de204321b54004 Nas Chung 2025-02-10 281
de204321b54004 Nas Chung 2025-02-10 282 if (inst->dst_fmt.num_planes == 1) {
de204321b54004 Nas Chung 2025-02-10 283 buf_size = vb2_plane_size(&dst_buf->vb2_buf, 0);
de204321b54004 Nas Chung 2025-02-10 284 buf_addr_y = wave6_get_dma_addr(dst_buf, 0);
de204321b54004 Nas Chung 2025-02-10 285 buf_addr_cb = buf_addr_y + luma_size;
de204321b54004 Nas Chung 2025-02-10 286 buf_addr_cr = buf_addr_cb + chroma_size;
de204321b54004 Nas Chung 2025-02-10 287 } else if (inst->dst_fmt.num_planes == 2) {
de204321b54004 Nas Chung 2025-02-10 288 buf_size = vb2_plane_size(&dst_buf->vb2_buf, 0) +
de204321b54004 Nas Chung 2025-02-10 289 vb2_plane_size(&dst_buf->vb2_buf, 1);
de204321b54004 Nas Chung 2025-02-10 290 buf_addr_y = wave6_get_dma_addr(dst_buf, 0);
de204321b54004 Nas Chung 2025-02-10 291 buf_addr_cb = wave6_get_dma_addr(dst_buf, 1);
de204321b54004 Nas Chung 2025-02-10 292 buf_addr_cr = buf_addr_cb + chroma_size;
de204321b54004 Nas Chung 2025-02-10 293 } else if (inst->dst_fmt.num_planes == 3) {
de204321b54004 Nas Chung 2025-02-10 294 buf_size = vb2_plane_size(&dst_buf->vb2_buf, 0) +
de204321b54004 Nas Chung 2025-02-10 295 vb2_plane_size(&dst_buf->vb2_buf, 1) +
de204321b54004 Nas Chung 2025-02-10 296 vb2_plane_size(&dst_buf->vb2_buf, 2);
de204321b54004 Nas Chung 2025-02-10 297 buf_addr_y = wave6_get_dma_addr(dst_buf, 0);
de204321b54004 Nas Chung 2025-02-10 298 buf_addr_cb = wave6_get_dma_addr(dst_buf, 1);
de204321b54004 Nas Chung 2025-02-10 299 buf_addr_cr = wave6_get_dma_addr(dst_buf, 2);
de204321b54004 Nas Chung 2025-02-10 300 }
de204321b54004 Nas Chung 2025-02-10 301 disp_buffer.buf_y = buf_addr_y;
de204321b54004 Nas Chung 2025-02-10 302 disp_buffer.buf_cb = buf_addr_cb;
de204321b54004 Nas Chung 2025-02-10 303 disp_buffer.buf_cr = buf_addr_cr;
de204321b54004 Nas Chung 2025-02-10 304 disp_buffer.width = inst->src_fmt.width;
de204321b54004 Nas Chung 2025-02-10 305 disp_buffer.height = inst->src_fmt.height;
de204321b54004 Nas Chung 2025-02-10 306 disp_buffer.stride = fb_stride;
de204321b54004 Nas Chung 2025-02-10 307 disp_buffer.map_type = LINEAR_FRAME_MAP;
de204321b54004 Nas Chung 2025-02-10 308 disp_buffer.luma_bitdepth = initial_info.luma_bitdepth;
de204321b54004 Nas Chung 2025-02-10 309 disp_buffer.chroma_bitdepth = initial_info.chroma_bitdepth;
de204321b54004 Nas Chung 2025-02-10 310 disp_buffer.chroma_format_idc = initial_info.chroma_format_idc;
de204321b54004 Nas Chung 2025-02-10 311
de204321b54004 Nas Chung 2025-02-10 312 ret = wave6_vpu_dec_register_display_buffer_ex(inst, disp_buffer);
de204321b54004 Nas Chung 2025-02-10 313 if (ret) {
de204321b54004 Nas Chung 2025-02-10 314 dev_err(inst->dev->dev, "fail register display buffer %d", ret);
de204321b54004 Nas Chung 2025-02-10 315 break;
de204321b54004 Nas Chung 2025-02-10 316 }
de204321b54004 Nas Chung 2025-02-10 317
de204321b54004 Nas Chung 2025-02-10 318 vpu_buf->consumed = true;
de204321b54004 Nas Chung 2025-02-10 319 consumed_num++;
de204321b54004 Nas Chung 2025-02-10 320 }
de204321b54004 Nas Chung 2025-02-10 321 }
de204321b54004 Nas Chung 2025-02-10 322
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
2025-02-10 9:07 ` [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver Nas Chung
2025-02-10 17:37 ` Krzysztof Kozlowski
@ 2025-02-11 20:25 ` kernel test robot
2025-02-12 1:31 ` kernel test robot
2 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2025-02-11 20:25 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: oe-kbuild-all, linux-media, devicetree, linux-kernel, linux-imx,
linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Hi Nas,
kernel test robot noticed the following build warnings:
[auto build test WARNING on linuxtv-media-pending/master]
[also build test WARNING on arm64/for-next/core robh/for-next linus/master v6.14-rc2 next-20250210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Nas-Chung/media-platform-chips-media-wave5-Rename-Kconfig-parameter/20250210-171144
base: https://git.linuxtv.org/media-ci/media-pending.git master
patch link: https://lore.kernel.org/r/20250210090725.4580-8-nas.chung%40chipsnmedia.com
patch subject: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20250212/202502120449.ZTdCf6WQ-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250212/202502120449.ZTdCf6WQ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502120449.ZTdCf6WQ-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from include/linux/device.h:15,
from include/linux/platform_device.h:13,
from drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:10:
drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c: In function 'wave6_vpu_ctrl_load_firmware':
>> drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:383:36: warning: format '%ld' expects argument of type 'long int', but argument 3 has type 'size_t' {aka 'unsigned int'} [-Wformat=]
383 | dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ^~~
include/linux/dev_printk.h:154:56: note: in expansion of macro 'dev_fmt'
154 | dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~
drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:383:17: note: in expansion of macro 'dev_err'
383 | dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
| ^~~~~~~
drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:383:54: note: format string is defined here
383 | dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
| ~~^
| |
| long int
| %d
drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c: In function 'wave6_vpu_ctrl_probe':
>> drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:928:38: warning: format '%lx' expects argument of type 'long unsigned int', but argument 5 has type 'size_t' {aka 'unsigned int'} [-Wformat=]
928 | dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ^~~
include/linux/dev_printk.h:160:58: note: in expansion of macro 'dev_fmt'
160 | dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~
drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:928:17: note: in expansion of macro 'dev_info'
928 | dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
| ^~~~~~~~
drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:928:69: note: format string is defined here
928 | dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
| ~~^
| |
| long unsigned int
| %x
vim +383 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
357
358 static void wave6_vpu_ctrl_load_firmware(const struct firmware *fw, void *context)
359 {
360 struct vpu_ctrl *ctrl = context;
361 struct wave6_vpu_entity *entity = ctrl->current_entity;
362 u32 product_code;
363 int ret;
364
365 ret = pm_runtime_resume_and_get(ctrl->dev);
366 if (ret) {
367 dev_err(ctrl->dev, "pm runtime resume fail, ret = %d\n", ret);
368 mutex_lock(&ctrl->ctrl_lock);
369 wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
370 ctrl->current_entity = NULL;
371 mutex_unlock(&ctrl->ctrl_lock);
372 release_firmware(fw);
373 return;
374 }
375
376 if (!fw || !fw->data) {
377 dev_err(ctrl->dev, "No firmware.\n");
378 ret = -EINVAL;
379 goto exit;
380 }
381
382 if (fw->size + WAVE6_EXTRA_CODE_BUF_SIZE > wave6_vpu_ctrl_get_code_buf_size(ctrl)) {
> 383 dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
384 fw->size, ctrl->boot_mem.size);
385 ret = -EINVAL;
386 goto exit;
387 }
388
389 product_code = entity->read_reg(entity->dev, W6_VPU_RET_PRODUCT_VERSION);
390 if (!PRODUCT_CODE_W_SERIES(product_code)) {
391 dev_err(ctrl->dev, "unknown product : %08x\n", product_code);
392 ret = -EINVAL;
393 goto exit;
394 }
395
396 memcpy(ctrl->boot_mem.vaddr, fw->data, fw->size);
397
398 exit:
399 mutex_lock(&ctrl->ctrl_lock);
400 if (!ret && wave6_vpu_ctrl_find_entity(ctrl, ctrl->current_entity)) {
401 wave6_vpu_ctrl_remap_code_buffer(ctrl);
402 ret = wave6_vpu_ctrl_init_vpu(ctrl);
403 } else {
404 ret = -EINVAL;
405 }
406 mutex_unlock(&ctrl->ctrl_lock);
407
408 pm_runtime_put_sync(ctrl->dev);
409 release_firmware(fw);
410
411 mutex_lock(&ctrl->ctrl_lock);
412 ctrl->current_entity = NULL;
413 if (ret)
414 wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
415 else
416 wave6_vpu_ctrl_boot_done(ctrl, 0);
417 mutex_unlock(&ctrl->ctrl_lock);
418
419 wake_up_interruptible_all(&ctrl->load_fw_wq);
420 }
421
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
2025-02-10 9:07 ` [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver Nas Chung
2025-02-10 17:37 ` Krzysztof Kozlowski
2025-02-11 20:25 ` kernel test robot
@ 2025-02-12 1:31 ` kernel test robot
2 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2025-02-12 1:31 UTC (permalink / raw)
To: Nas Chung, mchehab, hverkuil, sebastian.fricke, robh, krzk+dt,
conor+dt
Cc: llvm, oe-kbuild-all, linux-media, devicetree, linux-kernel,
linux-imx, linux-arm-kernel, jackson.lee, lafley.kim, Nas Chung
Hi Nas,
kernel test robot noticed the following build warnings:
[auto build test WARNING on linuxtv-media-pending/master]
[also build test WARNING on arm64/for-next/core robh/for-next linus/master v6.14-rc2 next-20250210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Nas-Chung/media-platform-chips-media-wave5-Rename-Kconfig-parameter/20250210-171144
base: https://git.linuxtv.org/media-ci/media-pending.git master
patch link: https://lore.kernel.org/r/20250210090725.4580-8-nas.chung%40chipsnmedia.com
patch subject: [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20250212/202502120928.wbtfGrUk-lkp@intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 6807164500e9920638e2ab0cdb4bf8321d24f8eb)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250212/202502120928.wbtfGrUk-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502120928.wbtfGrUk-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:384:4: warning: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat]
383 | dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
| ~~~
| %zu
384 | fw->size, ctrl->boot_mem.size);
| ^~~~~~~~
include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
154 | dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ~~~ ^~~~~~~~~~~
>> drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c:929:58: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat]
928 | dev_info(&pdev->dev, "sram 0x%pad, 0x%pad, size 0x%lx\n",
| ~~~
| %zx
929 | &ctrl->sram_buf.phys_addr, &ctrl->sram_buf.dma_addr, ctrl->sram_buf.size);
| ^~~~~~~~~~~~~~~~~~~
include/linux/dev_printk.h:160:67: note: expanded from macro 'dev_info'
160 | dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ~~~ ^~~~~~~~~~~
2 warnings generated.
vim +384 drivers/media/platform/chips-media/wave6/wave6-vpu-ctrl.c
357
358 static void wave6_vpu_ctrl_load_firmware(const struct firmware *fw, void *context)
359 {
360 struct vpu_ctrl *ctrl = context;
361 struct wave6_vpu_entity *entity = ctrl->current_entity;
362 u32 product_code;
363 int ret;
364
365 ret = pm_runtime_resume_and_get(ctrl->dev);
366 if (ret) {
367 dev_err(ctrl->dev, "pm runtime resume fail, ret = %d\n", ret);
368 mutex_lock(&ctrl->ctrl_lock);
369 wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
370 ctrl->current_entity = NULL;
371 mutex_unlock(&ctrl->ctrl_lock);
372 release_firmware(fw);
373 return;
374 }
375
376 if (!fw || !fw->data) {
377 dev_err(ctrl->dev, "No firmware.\n");
378 ret = -EINVAL;
379 goto exit;
380 }
381
382 if (fw->size + WAVE6_EXTRA_CODE_BUF_SIZE > wave6_vpu_ctrl_get_code_buf_size(ctrl)) {
383 dev_err(ctrl->dev, "firmware size (%ld > %zd) is too big\n",
> 384 fw->size, ctrl->boot_mem.size);
385 ret = -EINVAL;
386 goto exit;
387 }
388
389 product_code = entity->read_reg(entity->dev, W6_VPU_RET_PRODUCT_VERSION);
390 if (!PRODUCT_CODE_W_SERIES(product_code)) {
391 dev_err(ctrl->dev, "unknown product : %08x\n", product_code);
392 ret = -EINVAL;
393 goto exit;
394 }
395
396 memcpy(ctrl->boot_mem.vaddr, fw->data, fw->size);
397
398 exit:
399 mutex_lock(&ctrl->ctrl_lock);
400 if (!ret && wave6_vpu_ctrl_find_entity(ctrl, ctrl->current_entity)) {
401 wave6_vpu_ctrl_remap_code_buffer(ctrl);
402 ret = wave6_vpu_ctrl_init_vpu(ctrl);
403 } else {
404 ret = -EINVAL;
405 }
406 mutex_unlock(&ctrl->ctrl_lock);
407
408 pm_runtime_put_sync(ctrl->dev);
409 release_firmware(fw);
410
411 mutex_lock(&ctrl->ctrl_lock);
412 ctrl->current_entity = NULL;
413 if (ret)
414 wave6_vpu_ctrl_set_state(ctrl, WAVE6_VPU_STATE_OFF);
415 else
416 wave6_vpu_ctrl_boot_done(ctrl, 0);
417 mutex_unlock(&ctrl->ctrl_lock);
418
419 wake_up_interruptible_all(&ctrl->load_fw_wq);
420 }
421
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-10 17:30 ` Krzysztof Kozlowski
@ 2025-02-13 7:50 ` Nas Chung
2025-02-13 8:49 ` Krzysztof Kozlowski
0 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-13 7:50 UTC (permalink / raw)
To: Krzysztof Kozlowski, mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Tuesday, February 11, 2025 2:31 AM
>To: Nas Chung <nas.chung@chipsnmedia.com>; mchehab@kernel.org;
>hverkuil@xs4all.nl; sebastian.fricke@collabora.com; robh@kernel.org;
>krzk+dt@kernel.org; conor+dt@kernel.org
>Cc: linux-media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec
>device
>
>On 10/02/2025 10:07, Nas Chung wrote:
>> Add documents for the Wave6 video codec on NXP i.MX SoCs.
>>
>> Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
>> ---
>> .../bindings/media/nxp,wave633c.yaml | 202 ++++++++++++++++++
>> MAINTAINERS | 8 +
>> 2 files changed, 210 insertions(+)
>> create mode 100644
>Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>b/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>> new file mode 100644
>> index 000000000000..99c3008314c5
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>
>Filename matching compatible.
>
>> @@ -0,0 +1,202 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/media/nxp,wave633c.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Chips&Media Wave6 Series multi-standard codec IP on NXP i.MX SoCs.
>> +
>> +maintainers:
>> + - Nas Chung <nas.chung@chipsnmedia.com>
>> + - Jackson Lee <jackson.lee@chipsnmedia.com>
>> +
>> +description:
>> + The Chips&Media Wave6 codec IP is a multi-standard video
>encoder/decoder.
>> + On NXP i.MX SoCs, Wave6 codec IP functionality is split between the
>VPU control device
>> + (vpu-ctrl) and the VPU device (vpu). The VPU control device manages
>shared resources
>> + such as firmware access and power domains, while the VPU device
>provides encoding
>> + and decoding capabilities. The VPU devie cannot operate independently
>
>Typo
I'll fix it in v2.
>
>> + without the VPU control device.
>> +
>
>Please wrap code according to the preferred limit expressed in Kernel
>coding style (checkpatch is not a coding style description, but only a
>tool). Bindings use strict rule here.
I'll address this in v2.
>
>
>
>> +properties:
>> + compatible:
>> + items:
>> + - enum:
>> + - nxp,imx95-wave633c-ctrl
>> + - nxp,imx95-wave633c
>
>I don't understand why you duplicated compatibles. You split this for
>driver? That's a no. There are no two hardwares.
Yes, I want to introduce two different devices and drivers,
even though there is only one hardware.
Wave6 IP has five independent register regions:
One register region is dedicated to the control device,
which manages shared resources such as firmware loading and power domains.
The remaining four register regions are assigned to
four independent VPU devices, each accessing its own dedicated region.
(to support 4 vms)
Would it be reasonable to split the YAML into separate files
for the VPU control device and the VPU device ?
(like nxp,wave633c-ctrl.yaml)
>
>These compatibles are anyway weird - why imx95 is in chipmedia product?
>Is this part of a SoC?
I want to represent that the Wave633 is part of the i.MX95.
Chips&Media's Wave633 can also be integrated into SoCs from other vendors.
By using the compatible name, the same Wave6 driver can distinguish
different implementations.
However, I agree that "imx95" is not strictly necessary in current status.
So, using "nxp,wave633c" would be a better choice, right ?
>
>> +
>> + reg:
>> + maxItems: 1
>> +
>> + interrupts:
>> + maxItems: 1
>> +
>> + clocks:
>> + items:
>> + - description: VPU clock
>> + - description: VPU associated block clock
>> +
>> + clock-names:
>> + items:
>> + - const: vpu
>> + - const: vpublk_wave
>> +
>> + power-domains:
>> + minItems: 1
>> + items:
>> + - description: Main VPU power domain
>> + - description: Performance power domain
>> +
>> + power-domain-names:
>> + items:
>> + - const: vpumix
>> + - const: vpuperf
>> +
>> + cnm,ctrl:
>
>What is this prefix about? Is this nxp or something else?
Yes, using "nxp" as the prefix seems more appropriate.
>
>> + $ref: /schemas/types.yaml#/definitions/phandle
>> + description: phandle of the VPU control device node. Required for VPU
>operation.
>
>Explain - required for what. Operation is too generic.
phandle of the VPU control device node, which manages shared resources
such as firmware access and power domains.
>
>If this is phandle to second device, then it's proof your split is
>really wrong.
Are you suggesting that I should separate them into two YAML files,
or that I should structure them in a parent-child hierarchy
within the same YAML file ?
I appreciate any guidance on the best approach to structure this in line
with existing bindings.
>
>> +
>> + boot:
>> + $ref: /schemas/types.yaml#/definitions/phandle
>> + description: phandle of the boot memory region node for the VPU
>control device.
>
>No clue what is this... if memory region then use existing bindings.
Boot is a memory region used for firmware upload.
Only the control device can access this region.
By "existing bindings," do you mean I should use "memory-region" instead ?
>
>Anyway, wrap your code correctly.
Okay.
>
>> +
>> + sram:
>> + $ref: /schemas/types.yaml#/definitions/phandle
>> + description: phandle of the SRAM memory region node for the VPU
>control device.
>> +
>> + '#cooling-cells':
>> + const: 2
>> +
>> + support-follower:
>> + type: boolean
>> + description: Indicates whether the VPU domain power always on.
>
>You cannot add new common properties in random way. Missing vendor
>prefix but more important: does not look at all as hardware property but
>OS policy.
I agree with you.
I'll remove it in v2.
>
>> +
>> +patternProperties:
>> + "^vpu-ctrl@[0-9a-f]+$":
>> + type: object
>> + properties:
>> + compatible:
>> + items:
>> + - enum:
>> + - nxp,imx95-wave633c-ctrl
>
>Really, what? How nxp,imx95-wave633c-ctrl node can have a child with
>nxp,imx95-wave633c-ctrl compatible?
>
>NAK.
Apologies, I misunderstood the meaning of 'patternProperties'.
I'll remove it in v2.
>
>
>> + reg: true
>> + clocks: true
>> + clock-names: true
>> + power-domains:
>> + items:
>> + - description: Main VPU power domain
>> + - description: Performance power domain
>> + power-domain-names:
>> + items:
>> + - const: vpumix
>> + - const: vpuperf
>> + sram: true
>> + boot: true
>> + '#cooling-cells': true
>> + support-follower: true
>> + required:
>> + - compatible
>> + - reg
>> + - clocks
>> + - clock-names
>> + - power-domains
>> + - power-domain-names
>> + - sram
>> + - boot
>> +
>> + additionalProperties: false
>> +
>> + "^vpu@[0-9a-f]+$":
>> + type: object
>> + properties:
>> + compatible:
>> + items:
>> + - enum:
>> + - nxp,imx95-wave633c
>> + reg: true
>> + interrupts: true
>> + clocks: true
>> + clock-names: true
>> + power-domains:
>> + maxItems: 1
>> + description: Main VPU power domain
>> + cnm,ctrl: true
>> + required:
>> + - compatible
>> + - reg
>> + - interrupts
>> + - clocks
>> + - clock-names
>> + - power-domains
>> + - cnm,ctrl
>
>All this is just incorrect.
I'll remove it in v2.
>
>> +
>> + additionalProperties: false
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> + - |
>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> + #include <dt-bindings/clock/nxp,imx95-clock.h>
>> +
>> + soc {
>> + #address-cells = <2>;
>> + #size-cells = <2>;
>> +
>> + vpuctrl: vpu-ctrl@4c4c0000 {
>> + compatible = "nxp,imx95-wave633c-ctrl";
>> + reg = <0x0 0x4c4c0000 0x0 0x10000>;
>> + clocks = <&scmi_clk 115>,
>> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> + clock-names = "vpu", "vpublk_wave";
>> + power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
>> + power-domain-names = "vpumix", "vpuperf";
>> + #cooling-cells = <2>;
>> + boot = <&vpu_boot>;
>> + sram = <&sram1>;
>> + };
>> +
>> + vpu0: vpu@4c480000 {
>
>Node names should be generic. See also an explanation and list of
>examples (not exhaustive) in DT specification:
>https://devicetree-specification.readthedocs.io/en/latest/chapter2-
>devicetree-basics.html#generic-names-recommendation
Thanks for sharing the link.
I'll use "video-codec" as the node name in v2.
>
>
>> + compatible = "nxp,imx95-wave633c";
>> + reg = <0x0 0x4c480000 0x0 0x10000>;
>> + interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&scmi_clk 115>,
>> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> + clock-names = "vpu", "vpublk_wave";
>> + power-domains = <&scmi_devpd 21>;
>> + cnm,ctrl = <&vpuctrl>;
>> + };
>> +
>> + vpu1: vpu@4c490000 {
>> + compatible = "nxp,imx95-wave633c";
>
>Drop all duplicated examples.
Wave6 HW is designed for simultaneous access,
as each VPU device has its own separate register space.
Therefore, I defined the 4 VPU devices as independent nodes in the example
to reflect this.
>
>
>> + reg = <0x0 0x4c490000 0x0 0x10000>;
>> + interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&scmi_clk 115>,
>> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> + clock-names = "vpu", "vpublk_wave";
>> + power-domains = <&scmi_devpd 21>;
>> + cnm,ctrl = <&vpuctrl>;
>> + };
>> +
>> + vpu2: vpu@4c4a0000 {
>> + compatible = "nxp,imx95-wave633c";
>> + reg = <0x0 0x4c4a0000 0x0 0x10000>;
>> + interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&scmi_clk 115>,
>> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> + clock-names = "vpu", "vpublk_wave";
>> + power-domains = <&scmi_devpd 21>;
>> + cnm,ctrl = <&vpuctrl>;
>> + };
>> +
>> + vpu3: vpu@4c4b0000 {
>> + compatible = "nxp,imx95-wave633c";
>> + reg = <0x0 0x4c4b0000 0x0 0x10000>;
>> + interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&scmi_clk 115>,
>> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> + clock-names = "vpu", "vpublk_wave";
>> + power-domains = <&scmi_devpd 21>;
>> + cnm,ctrl = <&vpuctrl>;
>> + };
>> + };
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 896a307fa065..5ff5b1f1ced2 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -25462,6 +25462,14 @@ S: Maintained
>> F: Documentation/devicetree/bindings/media/cnm,wave521c.yaml
>> F: drivers/media/platform/chips-media/wave5/
>>
>> +WAVE6 VPU CODEC DRIVER
>> +M: Nas Chung <nas.chung@chipsnmedia.com>
>> +M: Jackson Lee <jackson.lee@chipsnmedia.com>
>> +L: linux-media@vger.kernel.org
>> +S: Maintained
>> +F: Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>> +F: drivers/media/platform/chips-media/wave6/
>
>There is no such file/directory.
Understood. I'll move the MAINTAINERS update to the last patch in v2.
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-13 7:50 ` Nas Chung
@ 2025-02-13 8:49 ` Krzysztof Kozlowski
2025-02-18 9:21 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-13 8:49 UTC (permalink / raw)
To: Nas Chung
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
On Thu, Feb 13, 2025 at 07:50:53AM +0000, Nas Chung wrote:
> >> + items:
> >> + - enum:
> >> + - nxp,imx95-wave633c-ctrl
> >> + - nxp,imx95-wave633c
> >
> >I don't understand why you duplicated compatibles. You split this for
> >driver? That's a no. There are no two hardwares.
>
> Yes, I want to introduce two different devices and drivers,
> even though there is only one hardware.
That's a no. Bindings are for hardware, not drivers.
Linux driver design is independent of bindings.
>
> Wave6 IP has five independent register regions:
>
> One register region is dedicated to the control device,
> which manages shared resources such as firmware loading and power domains.
>
> The remaining four register regions are assigned to
> four independent VPU devices, each accessing its own dedicated region.
> (to support 4 vms)
This could be, but your binding said something completely opposite. Look
how other bindings do it, first.
>
> Would it be reasonable to split the YAML into separate files
> for the VPU control device and the VPU device ?
> (like nxp,wave633c-ctrl.yaml)
No, it changes nothing.
>
> >
> >These compatibles are anyway weird - why imx95 is in chipmedia product?
> >Is this part of a SoC?
>
> I want to represent that the Wave633 is part of the i.MX95.
> Chips&Media's Wave633 can also be integrated into SoCs from other vendors.
OK
> By using the compatible name, the same Wave6 driver can distinguish
> different implementations.
So you tell DT maintainer how DT works, brilliant...
>
> However, I agree that "imx95" is not strictly necessary in current status.
> So, using "nxp,wave633c" would be a better choice, right ?
No, NXP did not create wave633c. SoC components must have SoC prefix,
assuming this is a Soc component.
>
> >
> >> +
> >> + reg:
> >> + maxItems: 1
> >> +
> >> + interrupts:
> >> + maxItems: 1
> >> +
> >> + clocks:
> >> + items:
> >> + - description: VPU clock
> >> + - description: VPU associated block clock
> >> +
> >> + clock-names:
> >> + items:
> >> + - const: vpu
> >> + - const: vpublk_wave
> >> +
> >> + power-domains:
> >> + minItems: 1
> >> + items:
> >> + - description: Main VPU power domain
> >> + - description: Performance power domain
> >> +
> >> + power-domain-names:
> >> + items:
> >> + - const: vpumix
> >> + - const: vpuperf
> >> +
> >> + cnm,ctrl:
> >
> >What is this prefix about? Is this nxp or something else?
>
> Yes, using "nxp" as the prefix seems more appropriate.
>
> >
> >> + $ref: /schemas/types.yaml#/definitions/phandle
> >> + description: phandle of the VPU control device node. Required for VPU
> >operation.
> >
> >Explain - required for what. Operation is too generic.
>
> phandle of the VPU control device node, which manages shared resources
> such as firmware access and power domains.
Then NAK.
Use proper bindings for this, e.g. power-domains.
>
> >
> >If this is phandle to second device, then it's proof your split is
> >really wrong.
>
> Are you suggesting that I should separate them into two YAML files,
No. Splitting into separate files would change nothing - you still would
have here a phandle, right?
> or that I should structure them in a parent-child hierarchy
> within the same YAML file ?
You did not try hard enough to find similar devices, which there is a
ton of.
>
> I appreciate any guidance on the best approach to structure this in line
> with existing bindings.
Then look for them.
You have one device. If you have sub-blocks with their own
distinguishable address space, then they can be children. But you did
not write it that way. Just look at your example DTS - no children at
all!
>
> >
> >> +
> >> + boot:
> >> + $ref: /schemas/types.yaml#/definitions/phandle
> >> + description: phandle of the boot memory region node for the VPU
> >control device.
> >
> >No clue what is this... if memory region then use existing bindings.
>
> Boot is a memory region used for firmware upload.
> Only the control device can access this region.
> By "existing bindings," do you mean I should use "memory-region" instead ?
Look how other bindings do this and what property they use. Yes,
memory-region.
>
> >
> >Anyway, wrap your code correctly.
>
> Okay.
>
> >
> >> +
> >> + sram:
> >> + $ref: /schemas/types.yaml#/definitions/phandle
> >> + description: phandle of the SRAM memory region node for the VPU
> >control device.
> >> +
> >> + '#cooling-cells':
> >> + const: 2
> >> +
> >> + support-follower:
> >> + type: boolean
> >> + description: Indicates whether the VPU domain power always on.
> >
> >You cannot add new common properties in random way. Missing vendor
> >prefix but more important: does not look at all as hardware property but
> >OS policy.
>
> I agree with you.
> I'll remove it in v2.
>
> >
> >> +
> >> +patternProperties:
> >> + "^vpu-ctrl@[0-9a-f]+$":
> >> + type: object
> >> + properties:
> >> + compatible:
> >> + items:
> >> + - enum:
> >> + - nxp,imx95-wave633c-ctrl
> >
> >Really, what? How nxp,imx95-wave633c-ctrl node can have a child with
> >nxp,imx95-wave633c-ctrl compatible?
> >
> >NAK.
>
> Apologies, I misunderstood the meaning of 'patternProperties'.
> I'll remove it in v2.
>
> >
> >
> >> + reg: true
> >> + clocks: true
> >> + clock-names: true
> >> + power-domains:
> >> + items:
> >> + - description: Main VPU power domain
> >> + - description: Performance power domain
> >> + power-domain-names:
> >> + items:
> >> + - const: vpumix
> >> + - const: vpuperf
> >> + sram: true
> >> + boot: true
> >> + '#cooling-cells': true
> >> + support-follower: true
> >> + required:
> >> + - compatible
> >> + - reg
> >> + - clocks
> >> + - clock-names
> >> + - power-domains
> >> + - power-domain-names
> >> + - sram
> >> + - boot
> >> +
> >> + additionalProperties: false
> >> +
> >> + "^vpu@[0-9a-f]+$":
> >> + type: object
> >> + properties:
> >> + compatible:
> >> + items:
> >> + - enum:
> >> + - nxp,imx95-wave633c
> >> + reg: true
> >> + interrupts: true
> >> + clocks: true
> >> + clock-names: true
> >> + power-domains:
> >> + maxItems: 1
> >> + description: Main VPU power domain
> >> + cnm,ctrl: true
> >> + required:
> >> + - compatible
> >> + - reg
> >> + - interrupts
> >> + - clocks
> >> + - clock-names
> >> + - power-domains
> >> + - cnm,ctrl
> >
> >All this is just incorrect.
>
> I'll remove it in v2.
>
> >
> >> +
> >> + additionalProperties: false
> >> +
> >> +additionalProperties: false
> >> +
> >> +examples:
> >> + - |
> >> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> >> + #include <dt-bindings/clock/nxp,imx95-clock.h>
> >> +
> >> + soc {
> >> + #address-cells = <2>;
> >> + #size-cells = <2>;
> >> +
> >> + vpuctrl: vpu-ctrl@4c4c0000 {
So this is the parent device...
> >> + compatible = "nxp,imx95-wave633c-ctrl";
> >> + reg = <0x0 0x4c4c0000 0x0 0x10000>;
> >> + clocks = <&scmi_clk 115>,
> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> >> + clock-names = "vpu", "vpublk_wave";
> >> + power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
> >> + power-domain-names = "vpumix", "vpuperf";
> >> + #cooling-cells = <2>;
> >> + boot = <&vpu_boot>;
> >> + sram = <&sram1>;
> >> + };
> >> +
> >> + vpu0: vpu@4c480000 {
And here you have child which is not a child? Your binding and DTS
neither match nor make any sense.
> >
> >Node names should be generic. See also an explanation and list of
> >examples (not exhaustive) in DT specification:
> >https://devicetree-specification.readthedocs.io/en/latest/chapter2-
> >devicetree-basics.html#generic-names-recommendation
>
> Thanks for sharing the link.
> I'll use "video-codec" as the node name in v2.
>
> >
> >
> >> + compatible = "nxp,imx95-wave633c";
> >> + reg = <0x0 0x4c480000 0x0 0x10000>;
> >> + interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
> >> + clocks = <&scmi_clk 115>,
> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> >> + clock-names = "vpu", "vpublk_wave";
> >> + power-domains = <&scmi_devpd 21>;
> >> + cnm,ctrl = <&vpuctrl>;
> >> + };
> >> +
> >> + vpu1: vpu@4c490000 {
> >> + compatible = "nxp,imx95-wave633c";
> >
> >Drop all duplicated examples.
>
> Wave6 HW is designed for simultaneous access,
> as each VPU device has its own separate register space.
> Therefore, I defined the 4 VPU devices as independent nodes in the example
> to reflect this.
They are redundant in this example. Unless you wanted to express
something else, but you did not.
>
> >
> >
> >> + reg = <0x0 0x4c490000 0x0 0x10000>;
> >> + interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
> >> + clocks = <&scmi_clk 115>,
> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> >> + clock-names = "vpu", "vpublk_wave";
> >> + power-domains = <&scmi_devpd 21>;
> >> + cnm,ctrl = <&vpuctrl>;
> >> + };
> >> +
> >> + vpu2: vpu@4c4a0000 {
> >> + compatible = "nxp,imx95-wave633c";
> >> + reg = <0x0 0x4c4a0000 0x0 0x10000>;
> >> + interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>;
> >> + clocks = <&scmi_clk 115>,
> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> >> + clock-names = "vpu", "vpublk_wave";
> >> + power-domains = <&scmi_devpd 21>;
> >> + cnm,ctrl = <&vpuctrl>;
> >> + };
> >> +
> >> + vpu3: vpu@4c4b0000 {
> >> + compatible = "nxp,imx95-wave633c";
> >> + reg = <0x0 0x4c4b0000 0x0 0x10000>;
> >> + interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
> >> + clocks = <&scmi_clk 115>,
> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> >> + clock-names = "vpu", "vpublk_wave";
> >> + power-domains = <&scmi_devpd 21>;
> >> + cnm,ctrl = <&vpuctrl>;
> >> + };
> >> + };
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 896a307fa065..5ff5b1f1ced2 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -25462,6 +25462,14 @@ S: Maintained
> >> F: Documentation/devicetree/bindings/media/cnm,wave521c.yaml
> >> F: drivers/media/platform/chips-media/wave5/
> >>
> >> +WAVE6 VPU CODEC DRIVER
> >> +M: Nas Chung <nas.chung@chipsnmedia.com>
> >> +M: Jackson Lee <jackson.lee@chipsnmedia.com>
> >> +L: linux-media@vger.kernel.org
> >> +S: Maintained
> >> +F: Documentation/devicetree/bindings/media/nxp,wave633c.yaml
> >> +F: drivers/media/platform/chips-media/wave6/
> >
> >There is no such file/directory.
>
> Understood. I'll move the MAINTAINERS update to the last patch in v2.
No, just add entry per entry.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-13 8:49 ` Krzysztof Kozlowski
@ 2025-02-18 9:21 ` Nas Chung
2025-02-19 12:31 ` Krzysztof Kozlowski
0 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-18 9:21 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Thursday, February 13, 2025 5:50 PM
>To: Nas Chung <nas.chung@chipsnmedia.com>
>Cc: mchehab@kernel.org; hverkuil@xs4all.nl; sebastian.fricke@collabora.com;
>robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org; linux-
>media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec
>device
>
>On Thu, Feb 13, 2025 at 07:50:53AM +0000, Nas Chung wrote:
>> >> + items:
>> >> + - enum:
>> >> + - nxp,imx95-wave633c-ctrl
>> >> + - nxp,imx95-wave633c
>> >
>> >I don't understand why you duplicated compatibles. You split this for
>> >driver? That's a no. There are no two hardwares.
>>
>> Yes, I want to introduce two different devices and drivers,
>> even though there is only one hardware.
>
>That's a no. Bindings are for hardware, not drivers.
>Linux driver design is independent of bindings.
>
>>
>> Wave6 IP has five independent register regions:
>>
>> One register region is dedicated to the control device,
>> which manages shared resources such as firmware loading and power domains.
>>
>> The remaining four register regions are assigned to
>> four independent VPU devices, each accessing its own dedicated region.
>> (to support 4 vms)
>
>This could be, but your binding said something completely opposite. Look
>how other bindings do it, first.
>
>>
>> Would it be reasonable to split the YAML into separate files
>> for the VPU control device and the VPU device ?
>> (like nxp,wave633c-ctrl.yaml)
>
>No, it changes nothing.
>
>>
>> >
>> >These compatibles are anyway weird - why imx95 is in chipmedia product?
>> >Is this part of a SoC?
>>
>> I want to represent that the Wave633 is part of the i.MX95.
>> Chips&Media's Wave633 can also be integrated into SoCs from other vendors.
>
>OK
>
>
>> By using the compatible name, the same Wave6 driver can distinguish
>> different implementations.
>
>So you tell DT maintainer how DT works, brilliant...
>
>>
>> However, I agree that "imx95" is not strictly necessary in current status.
>> So, using "nxp,wave633c" would be a better choice, right ?
>
>No, NXP did not create wave633c. SoC components must have SoC prefix,
>assuming this is a Soc component.
Ah, I had completely misunderstood the purpose and role of DT.
My apologies for that.
Would it be okay to modify it as follows ?
items:
- enum:
- nxp,imx95-vpu
- const: cnm,wave633c
>
>>
>> >
>> >> +
>> >> + reg:
>> >> + maxItems: 1
>> >> +
>> >> + interrupts:
>> >> + maxItems: 1
>> >> +
>> >> + clocks:
>> >> + items:
>> >> + - description: VPU clock
>> >> + - description: VPU associated block clock
>> >> +
>> >> + clock-names:
>> >> + items:
>> >> + - const: vpu
>> >> + - const: vpublk_wave
>> >> +
>> >> + power-domains:
>> >> + minItems: 1
>> >> + items:
>> >> + - description: Main VPU power domain
>> >> + - description: Performance power domain
>> >> +
>> >> + power-domain-names:
>> >> + items:
>> >> + - const: vpumix
>> >> + - const: vpuperf
>> >> +
>> >> + cnm,ctrl:
>> >
>> >What is this prefix about? Is this nxp or something else?
>>
>> Yes, using "nxp" as the prefix seems more appropriate.
>>
>> >
>> >> + $ref: /schemas/types.yaml#/definitions/phandle
>> >> + description: phandle of the VPU control device node. Required for
>VPU
>> >operation.
>> >
>> >Explain - required for what. Operation is too generic.
>>
>> phandle of the VPU control device node, which manages shared resources
>> such as firmware access and power domains.
>
>Then NAK.
>
>Use proper bindings for this, e.g. power-domains.
>
>
>>
>> >
>> >If this is phandle to second device, then it's proof your split is
>> >really wrong.
>>
>> Are you suggesting that I should separate them into two YAML files,
>
>No. Splitting into separate files would change nothing - you still would
>have here a phandle, right?
>
>> or that I should structure them in a parent-child hierarchy
>> within the same YAML file ?
>
>You did not try hard enough to find similar devices, which there is a
>ton of.
>
>>
>> I appreciate any guidance on the best approach to structure this in line
>> with existing bindings.
>
>Then look for them.
>
>You have one device. If you have sub-blocks with their own
>distinguishable address space, then they can be children. But you did
>not write it that way. Just look at your example DTS - no children at
>all!
I see that I didn't review similar devices thoroughly enough.
Thanks for pointing this out.
Okay, I will remove the phandle for second device and handle it in
parent node.
I have left the modified structure in the example below.
>
>>
>> >
>> >> +
>> >> + boot:
>> >> + $ref: /schemas/types.yaml#/definitions/phandle
>> >> + description: phandle of the boot memory region node for the VPU
>> >control device.
>> >
>> >No clue what is this... if memory region then use existing bindings.
>>
>> Boot is a memory region used for firmware upload.
>> Only the control device can access this region.
>> By "existing bindings," do you mean I should use "memory-region" instead ?
>
>Look how other bindings do this and what property they use. Yes,
>memory-region.
>
>>
>> >
>> >Anyway, wrap your code correctly.
>>
>> Okay.
>>
>> >
>> >> +
>> >> + sram:
>> >> + $ref: /schemas/types.yaml#/definitions/phandle
>> >> + description: phandle of the SRAM memory region node for the VPU
>> >control device.
>> >> +
>> >> + '#cooling-cells':
>> >> + const: 2
>> >> +
>> >> + support-follower:
>> >> + type: boolean
>> >> + description: Indicates whether the VPU domain power always on.
>> >
>> >You cannot add new common properties in random way. Missing vendor
>> >prefix but more important: does not look at all as hardware property but
>> >OS policy.
>>
>> I agree with you.
>> I'll remove it in v2.
>>
>> >
>> >> +
>> >> +patternProperties:
>> >> + "^vpu-ctrl@[0-9a-f]+$":
>> >> + type: object
>> >> + properties:
>> >> + compatible:
>> >> + items:
>> >> + - enum:
>> >> + - nxp,imx95-wave633c-ctrl
>> >
>> >Really, what? How nxp,imx95-wave633c-ctrl node can have a child with
>> >nxp,imx95-wave633c-ctrl compatible?
>> >
>> >NAK.
>>
>> Apologies, I misunderstood the meaning of 'patternProperties'.
>> I'll remove it in v2.
>>
>> >
>> >
>> >> + reg: true
>> >> + clocks: true
>> >> + clock-names: true
>> >> + power-domains:
>> >> + items:
>> >> + - description: Main VPU power domain
>> >> + - description: Performance power domain
>> >> + power-domain-names:
>> >> + items:
>> >> + - const: vpumix
>> >> + - const: vpuperf
>> >> + sram: true
>> >> + boot: true
>> >> + '#cooling-cells': true
>> >> + support-follower: true
>> >> + required:
>> >> + - compatible
>> >> + - reg
>> >> + - clocks
>> >> + - clock-names
>> >> + - power-domains
>> >> + - power-domain-names
>> >> + - sram
>> >> + - boot
>> >> +
>> >> + additionalProperties: false
>> >> +
>> >> + "^vpu@[0-9a-f]+$":
>> >> + type: object
>> >> + properties:
>> >> + compatible:
>> >> + items:
>> >> + - enum:
>> >> + - nxp,imx95-wave633c
>> >> + reg: true
>> >> + interrupts: true
>> >> + clocks: true
>> >> + clock-names: true
>> >> + power-domains:
>> >> + maxItems: 1
>> >> + description: Main VPU power domain
>> >> + cnm,ctrl: true
>> >> + required:
>> >> + - compatible
>> >> + - reg
>> >> + - interrupts
>> >> + - clocks
>> >> + - clock-names
>> >> + - power-domains
>> >> + - cnm,ctrl
>> >
>> >All this is just incorrect.
>>
>> I'll remove it in v2.
>>
>> >
>> >> +
>> >> + additionalProperties: false
>> >> +
>> >> +additionalProperties: false
>> >> +
>> >> +examples:
>> >> + - |
>> >> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> >> + #include <dt-bindings/clock/nxp,imx95-clock.h>
>> >> +
>> >> + soc {
>> >> + #address-cells = <2>;
>> >> + #size-cells = <2>;
>> >> +
>> >> + vpuctrl: vpu-ctrl@4c4c0000 {
>
>So this is the parent device...
>
>> >> + compatible = "nxp,imx95-wave633c-ctrl";
>> >> + reg = <0x0 0x4c4c0000 0x0 0x10000>;
>> >> + clocks = <&scmi_clk 115>,
>> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> >> + clock-names = "vpu", "vpublk_wave";
>> >> + power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
>> >> + power-domain-names = "vpumix", "vpuperf";
>> >> + #cooling-cells = <2>;
>> >> + boot = <&vpu_boot>;
>> >> + sram = <&sram1>;
>> >> + };
>> >> +
>> >> + vpu0: vpu@4c480000 {
>
>
>And here you have child which is not a child? Your binding and DTS
>neither match nor make any sense.
Would it be reasonable to modify it as follows ?
For example:
vpu: video-codec@4c480000 {
compatible = "nxp,imx95-vpu";
reg = <0x0 0x4c480000 0x0 0x50000>;
ranges = <0x0 0x0 0x4c480000 0x50000>;
vpuctrl: vpu-ctrl@40000 {
compatible = "nxp,imx95-vpu-ctrl";
reg = <0x40000 0x10000>;
};
vpucore0: vpu-core@00000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x00000 0x10000>;
};
vpucore1: vpu-core@10000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x10000 0x10000>;
};
vpucore2: vpu-core@20000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x20000 0x10000>;
};
vpucore3: vpu-core@30000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x30000 0x10000>;
};
};
>
>> >
>> >Node names should be generic. See also an explanation and list of
>> >examples (not exhaustive) in DT specification:
>> >https://devicetree-specification.readthedocs.io/en/latest/chapter2-
>> >devicetree-basics.html#generic-names-recommendation
>>
>> Thanks for sharing the link.
>> I'll use "video-codec" as the node name in v2.
>>
>> >
>> >
>> >> + compatible = "nxp,imx95-wave633c";
>> >> + reg = <0x0 0x4c480000 0x0 0x10000>;
>> >> + interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
>> >> + clocks = <&scmi_clk 115>,
>> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> >> + clock-names = "vpu", "vpublk_wave";
>> >> + power-domains = <&scmi_devpd 21>;
>> >> + cnm,ctrl = <&vpuctrl>;
>> >> + };
>> >> +
>> >> + vpu1: vpu@4c490000 {
>> >> + compatible = "nxp,imx95-wave633c";
>> >
>> >Drop all duplicated examples.
>>
>> Wave6 HW is designed for simultaneous access,
>> as each VPU device has its own separate register space.
>> Therefore, I defined the 4 VPU devices as independent nodes in the
>example
>> to reflect this.
>
>They are redundant in this example. Unless you wanted to express
>something else, but you did not.
Got it.
>
>
>>
>> >
>> >
>> >> + reg = <0x0 0x4c490000 0x0 0x10000>;
>> >> + interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
>> >> + clocks = <&scmi_clk 115>,
>> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> >> + clock-names = "vpu", "vpublk_wave";
>> >> + power-domains = <&scmi_devpd 21>;
>> >> + cnm,ctrl = <&vpuctrl>;
>> >> + };
>> >> +
>> >> + vpu2: vpu@4c4a0000 {
>> >> + compatible = "nxp,imx95-wave633c";
>> >> + reg = <0x0 0x4c4a0000 0x0 0x10000>;
>> >> + interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>;
>> >> + clocks = <&scmi_clk 115>,
>> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> >> + clock-names = "vpu", "vpublk_wave";
>> >> + power-domains = <&scmi_devpd 21>;
>> >> + cnm,ctrl = <&vpuctrl>;
>> >> + };
>> >> +
>> >> + vpu3: vpu@4c4b0000 {
>> >> + compatible = "nxp,imx95-wave633c";
>> >> + reg = <0x0 0x4c4b0000 0x0 0x10000>;
>> >> + interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
>> >> + clocks = <&scmi_clk 115>,
>> >> + <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> >> + clock-names = "vpu", "vpublk_wave";
>> >> + power-domains = <&scmi_devpd 21>;
>> >> + cnm,ctrl = <&vpuctrl>;
>> >> + };
>> >> + };
>> >> diff --git a/MAINTAINERS b/MAINTAINERS
>> >> index 896a307fa065..5ff5b1f1ced2 100644
>> >> --- a/MAINTAINERS
>> >> +++ b/MAINTAINERS
>> >> @@ -25462,6 +25462,14 @@ S: Maintained
>> >> F: Documentation/devicetree/bindings/media/cnm,wave521c.yaml
>> >> F: drivers/media/platform/chips-media/wave5/
>> >>
>> >> +WAVE6 VPU CODEC DRIVER
>> >> +M: Nas Chung <nas.chung@chipsnmedia.com>
>> >> +M: Jackson Lee <jackson.lee@chipsnmedia.com>
>> >> +L: linux-media@vger.kernel.org
>> >> +S: Maintained
>> >> +F: Documentation/devicetree/bindings/media/nxp,wave633c.yaml
>> >> +F: drivers/media/platform/chips-media/wave6/
>> >
>> >There is no such file/directory.
>>
>> Understood. I'll move the MAINTAINERS update to the last patch in v2.
>
>No, just add entry per entry.
I'll add each entry separately in v2.
Thanks.
Nas.
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-18 9:21 ` Nas Chung
@ 2025-02-19 12:31 ` Krzysztof Kozlowski
2025-02-20 7:35 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-19 12:31 UTC (permalink / raw)
To: Nas Chung
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
On 18/02/2025 10:21, Nas Chung wrote:
> For example:
> vpu: video-codec@4c480000 {
> compatible = "nxp,imx95-vpu";
> reg = <0x0 0x4c480000 0x0 0x50000>;
> ranges = <0x0 0x0 0x4c480000 0x50000>;
>
> vpuctrl: vpu-ctrl@40000 {
> compatible = "nxp,imx95-vpu-ctrl";
> reg = <0x40000 0x10000>;
> };
>
> vpucore0: vpu-core@00000 {
> compatible = "nxp,imx95-vpu-core";
> reg = <0x00000 0x10000>;
> };
>
> vpucore1: vpu-core@10000 {
> compatible = "nxp,imx95-vpu-core";
> reg = <0x10000 0x10000>;
> };
>
> vpucore2: vpu-core@20000 {
> compatible = "nxp,imx95-vpu-core";
> reg = <0x20000 0x10000>;
> };
>
> vpucore3: vpu-core@30000 {
> compatible = "nxp,imx95-vpu-core";
Why do you need compatible here? Could it be anything else?
> reg = <0x30000 0x10000>;
Where is the rest of resources? You created children only for one
resource - address space?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-19 12:31 ` Krzysztof Kozlowski
@ 2025-02-20 7:35 ` Nas Chung
2025-02-20 8:32 ` Krzysztof Kozlowski
0 siblings, 1 reply; 29+ messages in thread
From: Nas Chung @ 2025-02-20 7:35 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Wednesday, February 19, 2025 9:32 PM
>To: Nas Chung <nas.chung@chipsnmedia.com>
>Cc: mchehab@kernel.org; hverkuil@xs4all.nl; sebastian.fricke@collabora.com;
>robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org; linux-
>media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec
>device
>
>On 18/02/2025 10:21, Nas Chung wrote:
>> For example:
>> vpu: video-codec@4c480000 {
>> compatible = "nxp,imx95-vpu";
>> reg = <0x0 0x4c480000 0x0 0x50000>;
>> ranges = <0x0 0x0 0x4c480000 0x50000>;
>>
>> vpuctrl: vpu-ctrl@40000 {
>> compatible = "nxp,imx95-vpu-ctrl";
>> reg = <0x40000 0x10000>;
>> };
>>
>> vpucore0: vpu-core@00000 {
>> compatible = "nxp,imx95-vpu-core";
>> reg = <0x00000 0x10000>;
>> };
>>
>> vpucore1: vpu-core@10000 {
>> compatible = "nxp,imx95-vpu-core";
>> reg = <0x10000 0x10000>;
>> };
>>
>> vpucore2: vpu-core@20000 {
>> compatible = "nxp,imx95-vpu-core";
>> reg = <0x20000 0x10000>;
>> };
>>
>> vpucore3: vpu-core@30000 {
>> compatible = "nxp,imx95-vpu-core";
>
>Why do you need compatible here? Could it be anything else?
I will update the driver based on the final DT.
>
>> reg = <0x30000 0x10000>;
>
>Where is the rest of resources? You created children only for one
>resource - address space?
Sorry for the confusion.
I believe the final example looks like the one below.
vpu: video-codec@4c480000 {
compatible = "nxp,imx95-vpu";
reg = <0x0 0x4c480000 0x0 0x50000>;
ranges = <0x0 0x0 0x4c480000 0x50000>;
vpuctrl: vpu-ctrl@40000 {
compatible = "nxp,imx95-vpu-ctrl";
reg = <0x40000 0x10000>;
clocks = <&scmi_clk 115>,
<&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
clock-names = "vpu", "vpublk_wave";
power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
power-domain-names = "vpumix", "vpuperf";
memory-region = <&vpu_boot>;
#cooling-cells = <2>;
sram = <&sram1>;
};
vpucore0: vpu-core@00000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x00000 0x10000>;
interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scmi_clk 115>,
<&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
clock-names = "vpu", "vpublk_wave";
power-domains = <&scmi_devpd 21>;
};
vpucore1: vpu-core@10000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x10000 0x10000>;
interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scmi_clk 115>,
<&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
clock-names = "vpu", "vpublk_wave";
power-domains = <&scmi_devpd 21>;
};
vpucore2: vpu-core@20000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x20000 0x10000>;
interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scmi_clk 115>,
<&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
clock-names = "vpu", "vpublk_wave";
power-domains = <&scmi_devpd 21>;
};
vpucore3: vpu-core@30000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x30000 0x10000>;
interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scmi_clk 115>,
<&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
clock-names = "vpu", "vpublk_wave";
power-domains = <&scmi_devpd 21>;
};
};
Thanks.
Nas.
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-20 7:35 ` Nas Chung
@ 2025-02-20 8:32 ` Krzysztof Kozlowski
2025-02-21 8:29 ` Nas Chung
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-20 8:32 UTC (permalink / raw)
To: Nas Chung
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
On 20/02/2025 08:35, Nas Chung wrote:
> Hi, Krzysztof.
>
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk@kernel.org>
>> Sent: Wednesday, February 19, 2025 9:32 PM
>> To: Nas Chung <nas.chung@chipsnmedia.com>
>> Cc: mchehab@kernel.org; hverkuil@xs4all.nl; sebastian.fricke@collabora.com;
>> robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org; linux-
>> media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>> kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>> kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>> lafley.kim <lafley.kim@chipsnmedia.com>
>> Subject: Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec
>> device
>>
>> On 18/02/2025 10:21, Nas Chung wrote:
>>> For example:
>>> vpu: video-codec@4c480000 {
>>> compatible = "nxp,imx95-vpu";
>>> reg = <0x0 0x4c480000 0x0 0x50000>;
>>> ranges = <0x0 0x0 0x4c480000 0x50000>;
>>>
>>> vpuctrl: vpu-ctrl@40000 {
>>> compatible = "nxp,imx95-vpu-ctrl";
>>> reg = <0x40000 0x10000>;
>>> };
>>>
>>> vpucore0: vpu-core@00000 {
>>> compatible = "nxp,imx95-vpu-core";
>>> reg = <0x00000 0x10000>;
>>> };
>>>
>>> vpucore1: vpu-core@10000 {
>>> compatible = "nxp,imx95-vpu-core";
>>> reg = <0x10000 0x10000>;
>>> };
>>>
>>> vpucore2: vpu-core@20000 {
>>> compatible = "nxp,imx95-vpu-core";
>>> reg = <0x20000 0x10000>;
>>> };
>>>
>>> vpucore3: vpu-core@30000 {
>>> compatible = "nxp,imx95-vpu-core";
>>
>> Why do you need compatible here? Could it be anything else?
>
> I will update the driver based on the final DT.
>
>>
>>> reg = <0x30000 0x10000>;
>>
>> Where is the rest of resources? You created children only for one
>> resource - address space?
>
> Sorry for the confusion.
> I believe the final example looks like the one below.
>
> vpu: video-codec@4c480000 {
> compatible = "nxp,imx95-vpu";
> reg = <0x0 0x4c480000 0x0 0x50000>;
> ranges = <0x0 0x0 0x4c480000 0x50000>;
>
> vpuctrl: vpu-ctrl@40000 {
> compatible = "nxp,imx95-vpu-ctrl";
> reg = <0x40000 0x10000>;
> clocks = <&scmi_clk 115>,
> <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
> clock-names = "vpu", "vpublk_wave";
> power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
> power-domain-names = "vpumix", "vpuperf";
> memory-region = <&vpu_boot>;
> #cooling-cells = <2>;
> sram = <&sram1>;
> };
>
> vpucore0: vpu-core@00000 {
> compatible = "nxp,imx95-vpu-core";
> reg = <0x00000 0x10000>;
> interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&scmi_clk 115>,
> <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
These are the same resources for every block so for entire device. Why
they are no in top level node?
> clock-names = "vpu", "vpublk_wave";
> power-domains = <&scmi_devpd 21>;
Same here
Everything else also looks duplicated... All my previous comments - from
first email - stand. Don't design DT to match your Linu driver structure.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device
2025-02-20 8:32 ` Krzysztof Kozlowski
@ 2025-02-21 8:29 ` Nas Chung
0 siblings, 0 replies; 29+ messages in thread
From: Nas Chung @ 2025-02-21 8:29 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: mchehab@kernel.org, hverkuil@xs4all.nl,
sebastian.fricke@collabora.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim
Hi, Krzysztof.
>-----Original Message-----
>From: Krzysztof Kozlowski <krzk@kernel.org>
>Sent: Thursday, February 20, 2025 5:32 PM
>To: Nas Chung <nas.chung@chipsnmedia.com>
>Cc: mchehab@kernel.org; hverkuil@xs4all.nl; sebastian.fricke@collabora.com;
>robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org; linux-
>media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>
>Subject: Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec
>device
>
>On 20/02/2025 08:35, Nas Chung wrote:
>> Hi, Krzysztof.
>>
>>> -----Original Message-----
>>> From: Krzysztof Kozlowski <krzk@kernel.org>
>>> Sent: Wednesday, February 19, 2025 9:32 PM
>>> To: Nas Chung <nas.chung@chipsnmedia.com>
>>> Cc: mchehab@kernel.org; hverkuil@xs4all.nl;
>sebastian.fricke@collabora.com;
>>> robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org; linux-
>>> media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>>> kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>>> kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>>> lafley.kim <lafley.kim@chipsnmedia.com>
>>> Subject: Re: [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec
>>> device
>>>
>>> On 18/02/2025 10:21, Nas Chung wrote:
>>>> For example:
>>>> vpu: video-codec@4c480000 {
>>>> compatible = "nxp,imx95-vpu";
>>>> reg = <0x0 0x4c480000 0x0 0x50000>;
>>>> ranges = <0x0 0x0 0x4c480000 0x50000>;
>>>>
>>>> vpuctrl: vpu-ctrl@40000 {
>>>> compatible = "nxp,imx95-vpu-ctrl";
>>>> reg = <0x40000 0x10000>;
>>>> };
>>>>
>>>> vpucore0: vpu-core@00000 {
>>>> compatible = "nxp,imx95-vpu-core";
>>>> reg = <0x00000 0x10000>;
>>>> };
>>>>
>>>> vpucore1: vpu-core@10000 {
>>>> compatible = "nxp,imx95-vpu-core";
>>>> reg = <0x10000 0x10000>;
>>>> };
>>>>
>>>> vpucore2: vpu-core@20000 {
>>>> compatible = "nxp,imx95-vpu-core";
>>>> reg = <0x20000 0x10000>;
>>>> };
>>>>
>>>> vpucore3: vpu-core@30000 {
>>>> compatible = "nxp,imx95-vpu-core";
>>>
>>> Why do you need compatible here? Could it be anything else?
>>
>> I will update the driver based on the final DT.
>>
>>>
>>>> reg = <0x30000 0x10000>;
>>>
>>> Where is the rest of resources? You created children only for one
>>> resource - address space?
>>
>> Sorry for the confusion.
>> I believe the final example looks like the one below.
>>
>> vpu: video-codec@4c480000 {
>> compatible = "nxp,imx95-vpu";
>> reg = <0x0 0x4c480000 0x0 0x50000>;
>> ranges = <0x0 0x0 0x4c480000 0x50000>;
>>
>> vpuctrl: vpu-ctrl@40000 {
>> compatible = "nxp,imx95-vpu-ctrl";
>> reg = <0x40000 0x10000>;
>> clocks = <&scmi_clk 115>,
>> <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>> clock-names = "vpu", "vpublk_wave";
>> power-domains = <&scmi_devpd 21>, <&scmi_perf 10>;
>> power-domain-names = "vpumix", "vpuperf";
>> memory-region = <&vpu_boot>;
>> #cooling-cells = <2>;
>> sram = <&sram1>;
>> };
>>
>> vpucore0: vpu-core@00000 {
>> compatible = "nxp,imx95-vpu-core";
>> reg = <0x00000 0x10000>;
>> interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
>> clocks = <&scmi_clk 115>,
>> <&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
>
>
>These are the same resources for every block so for entire device. Why
>they are no in top level node?
>
>> clock-names = "vpu", "vpublk_wave";
>> power-domains = <&scmi_devpd 21>;
>
>Same here
>
>Everything else also looks duplicated... All my previous comments - from
>first email - stand. Don't design DT to match your Linu driver structure.
I agree with you. Thanks again for your feedback.
I've moved the shared resources to the parent node while keeping the
independent resources within their respective child nodes, as shown below.
vpu: video-codec@4c480000 {
compatible = "nxp,imx95-vpu";
reg = <0x0 0x4c480000 0x0 0x50000>;
ranges = <0x0 0x0 0x4c480000 0x50000>;
clocks = <&scmi_clk IMX95_CLK_VPU>,
<&vpu_blk_ctrl IMX95_CLK_VPUBLK_WAVE>;
clock-names = "vpu", "vpublk_wave";
power-domains = <&scmi_devpd IMX95_PD_VPU>;
vpucore0: vpu-core@00000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x00000 0x10000>;
interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
};
vpucore1: vpu-core@10000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x10000 0x10000>;
interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
};
vpucore2: vpu-core@20000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x20000 0x10000>;
interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>;
};
vpucore3: vpu-core@30000 {
compatible = "nxp,imx95-vpu-core";
reg = <0x30000 0x10000>;
interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
};
vpuctrl: vpu-ctrl@40000 {
compatible = "nxp,imx95-vpu-ctrl";
reg = <0x40000 0x10000>;
power-domains = <&scmi_perf IMX95_PERF_VPU>;
memory-region = <&vpu_boot>;
#cooling-cells = <2>;
sram = <&sram1>;
};
};
Thanks.
Nas.
>
>Best regards,
>Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2025-02-21 8:31 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-10 9:07 [PATCH 0/8] Add support for Wave6 video codec driver Nas Chung
2025-02-10 9:07 ` [PATCH 1/8] media: platform: chips-media: wave5: Rename Kconfig parameter Nas Chung
2025-02-10 17:24 ` Krzysztof Kozlowski
2025-02-11 4:23 ` Nas Chung
2025-02-10 9:07 ` [PATCH 2/8] media: v4l2-common: Add YUV24 format info Nas Chung
2025-02-10 14:00 ` Sebastian Fricke
2025-02-11 1:58 ` Nas Chung
2025-02-10 9:07 ` [PATCH 3/8] dt-bindings: media: nxp: Add Wave6 video codec device Nas Chung
2025-02-10 17:30 ` Krzysztof Kozlowski
2025-02-13 7:50 ` Nas Chung
2025-02-13 8:49 ` Krzysztof Kozlowski
2025-02-18 9:21 ` Nas Chung
2025-02-19 12:31 ` Krzysztof Kozlowski
2025-02-20 7:35 ` Nas Chung
2025-02-20 8:32 ` Krzysztof Kozlowski
2025-02-21 8:29 ` Nas Chung
2025-02-10 9:07 ` [PATCH 4/8] media: chips-media: wave6: Add Wave6 codec driver Nas Chung
2025-02-10 17:40 ` Krzysztof Kozlowski
2025-02-11 8:28 ` Nas Chung
2025-02-10 9:07 ` [PATCH 7/8] media: chips-media: wave6: Add Wave6 control driver Nas Chung
2025-02-10 17:37 ` Krzysztof Kozlowski
2025-02-11 8:55 ` Nas Chung
2025-02-11 20:25 ` kernel test robot
2025-02-12 1:31 ` kernel test robot
2025-02-10 9:07 ` [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities Nas Chung
2025-02-11 16:43 ` kernel test robot
2025-02-10 13:05 ` [PATCH 0/8] Add support for Wave6 video codec driver Sebastian Fricke
2025-02-11 4:47 ` Nas Chung
2025-02-11 6:07 ` [EXT] " Ming Qian
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).