* [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code
@ 2025-08-13 9:37 Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 01/24] media: iris: Fix buffer count reporting in internal buffer check Dikshita Agarwal
` (24 more replies)
0 siblings, 25 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Hi All,
This patch series adds support for H.264 and H.265 encoder in iris
driver and includes a few fixes and cleanup in the common code that were
identified during encoder bring-up process.
The changes include:
- Enabling support for H.264 and H.265 encoding.
- Fixes and improvements in shared componenets used by both encoder and
decoder paths.
- Ensuring compatibility and stability with the existing decoder flow.
Changes in v2:
- Fixed sparse/coccinnelle issues.
- Fixed the kernel doc warning.
- Removed unsupported PEAK_BITRATE property from SM8250.
- Dropped patch 04/25 to fix quality issue with encoder.
- Enhanced command handling for encoder to allow start/stop commands.
- Expanded rate control condition checks to include additional rate
control types for HFI Gen2.
- Updated default value to MAX_QP for all caps related to max QP settings.
- Add support for INPUT/OUTPUT_BUF_HOST_MAX_COUNT caps for encoder.
- Link to v1: https://lore.kernel.org/r/20250704-iris-video-encoder-v1-0-b6ce24e273cf@quicinc.com
All patches have been tested with v4l2-compliance, v4l2-ctl and
Gstreamer on SM8250 and SM8550 for encoder, at the same time ensured
that the existing decoder functionality remains uneffected.
Commands used for V4l2-ctl validation:
v4l2-ctl --verbose --set-fmt-video-out=width=1280,height=720,pixelformat=NV12
--set-selection-output target=crop,top=0,left=0,width=1280,height=720
--set-fmt-video=pixelformat=H264 --stream-mmap --stream-out-mmap
--stream-from=/media/cyclists_1280x720_92frames.yuv
--stream-to=/tmp/cyclists_1280x720_92frames.h264 -d /dev/video1
v4l2-ctl --verbose --set-fmt-video-out=width=1280,height=720,pixelformat=NV12
--set-selection-output target=crop,top=0,left=0,width=1280,height=720
--set-fmt-video=pixelformat=HEVC --stream-mmap --stream-out-mmap
--stream-from=/media/cyclists_1280x720_92frames.yuv
--stream-to=/tmp/cyclists_1280x720_92frames.hevc -d /dev/video1
Commands used for GST validation:
gst-launch-1.0 -v filesrc location=/media/cyclists_1280x720_92frames.yuv !
rawvideoparse format=nv12 width=1280 height=720 framerate=30/1 ! v4l2h264enc
capture-io-mode=4 output-io-mode=4 ! filesink sync=true
location=/tmp/gst_cyclists_1280x720_92frames.h264
gst-launch-1.0 -v filesrc location=/media/cyclists_1280x720_92frames.yuv !
rawvideoparse format=nv12 width=1280 height=720 framerate=30/1 ! v4l2h265enc
capture-io-mode=4 output-io-mode=4 ! filesink sync=true
location=/tmp/gst_cyclists_1280x720_92frames.hevc
The result of v4l2-compliance on SM8550:
v4l2-compliance 1.29.0-5270, 64 bits, 64-bit time_t
v4l2-compliance SHA: dc947661089e 2024-11-11 10:25:38
Compliance test for iris_driver device /dev/video1:
Driver Info:
Driver name : iris_driver
Card type : Iris Encoder
Bus info : platform:aa00000.video-codec
Driver version : 6.16.0
Capabilities : 0x84204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Detected Stateful Encoder
Required ioctls:
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video1 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 37 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test CREATE_BUFS maximum buffers: OK
test VIDIOC_REMOVE_BUFS: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
test blocking wait: OK
Test input 0:
Streaming ioctls:
test read/write: OK (Not Supported)
Video Capture Multiplanar: Captured 61 buffers
test MMAP (select, REQBUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (epoll, REQBUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (select, CREATE_BUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (epoll, CREATE_BUFS): OK
test USERPTR (select): OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0, Warnings: 0
The result of v4l2-compliance on SM8250:
v4l2-compliance 1.29.0-5270, 64 bits, 64-bit time_t
v4l2-compliance SHA: dc947661089e 2024-11-11 10:25:38
Compliance test for iris_driver device /dev/video1:
Driver Info:
Driver name : iris_driver
Card type : Iris Encoder
Bus info : platform:aa00000.video-codec
Driver version : 6.16.0
Capabilities : 0x84204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Detected Stateful Encoder
Required ioctls:
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video1 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 19 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test CREATE_BUFS maximum buffers: OK
test VIDIOC_REMOVE_BUFS: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
test blocking wait: OK
Test input 0:
Streaming ioctls:
test read/write: OK (Not Supported)
Video Capture Multiplanar: Captured 61 buffers
test MMAP (select, REQBUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (epoll, REQBUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (select, CREATE_BUFS): OK
Video Capture Multiplanar: Captured 61 buffers
test MMAP (epoll, CREATE_BUFS): OK
test USERPTR (select): OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0, Warnings: 0
Looking forward to your review and feedback.
Thanks,
Dikshita
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
Dikshita Agarwal (24):
media: iris: Fix buffer count reporting in internal buffer check
media: iris: Report unreleased PERSIST buffers on session close
media: iris: Fix memory leak by freeing untracked persist buffer
media: iris: Fix port streaming handling
media: iris: Allow substate transition to load resources during output streaming
media: iris: Always destroy internal buffers on firmware release response
media: iris: Update vbuf flags before v4l2_m2m_buf_done
media: iris: Allow stop on firmware only if start was issued.
media: iris: Send dummy buffer address for all codecs during drain
media: iris: Fix missing LAST flag handling during drain
media: iris: Add support for video encoder device
media: iris: Initialize and deinitialize encoder instance structure
media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder
media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder
media: iris: Add support for VIDIOC_QUERYCAP for encoder video device
media: iris: Add encoder support for V4L2 event subscription
media: iris: Add support for G/S_SELECTION for encoder video device
media: iris: Add support for G/S_PARM for encoder video device
media: iris: Add platform-specific capabilities for encoder video device
media: iris: Add V4L2 streaming support for encoder video device
media: iris: Set platform capabilities to firmware for encoder video device
media: iris: Allocate and queue internal buffers for encoder video device
media: iris: Add support for buffer management ioctls for encoder device
media: iris: Add support for drain sequence in encoder video device
drivers/media/platform/qcom/iris/Makefile | 5 +-
drivers/media/platform/qcom/iris/iris_buffer.c | 220 ++++--
drivers/media/platform/qcom/iris/iris_buffer.h | 7 +-
drivers/media/platform/qcom/iris/iris_common.c | 232 ++++++
drivers/media/platform/qcom/iris/iris_common.h | 18 +
drivers/media/platform/qcom/iris/iris_core.h | 20 +-
drivers/media/platform/qcom/iris/iris_ctrls.c | 675 +++++++++++++++-
drivers/media/platform/qcom/iris/iris_ctrls.h | 15 +
drivers/media/platform/qcom/iris/iris_hfi_common.h | 2 +-
.../platform/qcom/iris/iris_hfi_gen1_command.c | 485 +++++++++---
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 112 ++-
.../platform/qcom/iris/iris_hfi_gen1_response.c | 60 +-
.../platform/qcom/iris/iris_hfi_gen2_command.c | 357 ++++++---
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 44 +-
.../platform/qcom/iris/iris_hfi_gen2_response.c | 46 +-
drivers/media/platform/qcom/iris/iris_instance.h | 24 +
.../platform/qcom/iris/iris_platform_common.h | 74 +-
.../media/platform/qcom/iris/iris_platform_gen2.c | 522 ++++++++++++-
.../platform/qcom/iris/iris_platform_qcs8300.h | 352 ++++++++-
.../platform/qcom/iris/iris_platform_sm8250.c | 234 +++++-
drivers/media/platform/qcom/iris/iris_probe.c | 39 +-
drivers/media/platform/qcom/iris/iris_state.c | 9 +-
drivers/media/platform/qcom/iris/iris_state.h | 1 +
drivers/media/platform/qcom/iris/iris_utils.c | 36 +
drivers/media/platform/qcom/iris/iris_utils.h | 2 +
drivers/media/platform/qcom/iris/iris_vb2.c | 58 +-
drivers/media/platform/qcom/iris/iris_vdec.c | 249 +-----
drivers/media/platform/qcom/iris/iris_vdec.h | 13 +-
drivers/media/platform/qcom/iris/iris_venc.c | 579 ++++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 27 +
drivers/media/platform/qcom/iris/iris_vidc.c | 299 +++++++-
drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 847 ++++++++++++++++++++-
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 20 +
33 files changed, 4970 insertions(+), 713 deletions(-)
---
base-commit: c26e8dcd9d4e86d788c5bf7a5dd0ea70a95ab067
change-id: 20250704-iris-video-encoder-b193350b487a
Best regards,
--
Dikshita Agarwal <quic_dikshita@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH v2 01/24] media: iris: Fix buffer count reporting in internal buffer check
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close Dikshita Agarwal
` (23 subsequent siblings)
24 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Initialize the count variable to zero before counting unreleased
internal buffers in iris_check_num_queued_internal_buffers().
This prevents stale values from previous iterations and ensures accurate
error reporting for each buffer type. Without this initialization, the
count could accumulate across types, leading to incorrect log messages.
Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release on close")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_vidc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index c417e8c31f806e03555cd5e2a662a6efe5d58f3e..8285bdaf9466d4bea0f89a3b1943ed7d6c014b7d 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -240,6 +240,7 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p
for (i = 0; i < internal_buffer_count; i++) {
buffers = &inst->buffers[internal_buf_type[i]];
+ count = 0;
list_for_each_entry_safe(buf, next, &buffers->list, list)
count++;
if (count)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 01/24] media: iris: Fix buffer count reporting in internal buffer check Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-13 10:53 ` Jorge Ramirez
2025-08-13 9:37 ` [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer Dikshita Agarwal
` (22 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add error reporting for unreleased PERSIST internal buffers in
iris_check_num_queued_internal_buffers(). This ensures all buffer types
are checked and logged if not freed during session close, helping to
detect memory leaks and improve driver robustness. No change to buffer
lifecycle or allocation logic.
Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release on close")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_vidc.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 8285bdaf9466d4bea0f89a3b1943ed7d6c014b7d..96313856a026efaff40da97eaaa63e847172cd57 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -247,6 +247,14 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p
dev_err(inst->core->dev, "%d buffer of type %d not released",
count, internal_buf_type[i]);
}
+
+ buffers = &inst->buffers[BUF_PERSIST];
+
+ count = 0;
+ list_for_each_entry_safe(buf, next, &buffers->list, list)
+ count++;
+ if (count)
+ dev_err(inst->core->dev, "%d buffer of type %d not released", count, buf->type);
}
int iris_close(struct file *filp)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 01/24] media: iris: Fix buffer count reporting in internal buffer check Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-16 10:15 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 04/24] media: iris: Fix port streaming handling Dikshita Agarwal
` (21 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
One internal buffer which is allocated only once per session was not
being freed during session close because it was not being tracked as
part of internal buffer list which resulted in a memory leak.
Add the necessary logic to explicitly free the untracked internal buffer
during session close to ensure all allocated memory is released
properly.
Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_buffer.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 6425e4919e3b0b849ba801ca9e01921c114144cd..9f664c241149362d44d3a8fa65e2266f9c2e80e0 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -413,6 +413,16 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool
}
}
+ if (force) {
+ buffers = &inst->buffers[BUF_PERSIST];
+
+ list_for_each_entry_safe(buf, next, &buffers->list, list) {
+ ret = iris_destroy_internal_buffer(inst, buf);
+ if (ret)
+ return ret;
+ }
+ }
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 04/24] media: iris: Fix port streaming handling
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (2 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-16 10:40 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming Dikshita Agarwal
` (20 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
The previous check to block capture port streaming before output port
was incorrect and caused some valid usecase to fail. While removing that
check allows capture port to enter streaming independently, it also
introduced firmware errors due to premature queuing of DPB buffers
before the firmware session was fully started which happens only when
streamon is called on output port.
Fix this by deferring DPB buffer queuing to the firmware until both
capture and output are streaming and state is 'STREAMING'.
Fixes: 11712ce70f8e ("media: iris: implement vb2 streaming ops")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_buffer.c | 27 ++++++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_buffer.h | 1 +
drivers/media/platform/qcom/iris/iris_vb2.c | 8 ++++----
3 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 9f664c241149362d44d3a8fa65e2266f9c2e80e0..23cac5d1312913b8dac44347ae66cb80a6a15deb 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -334,6 +334,29 @@ int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf)
return 0;
}
+int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type)
+{
+ struct iris_buffer *buffer, *next;
+ struct iris_buffers *buffers;
+ int ret = 0;
+
+ buffers = &inst->buffers[buffer_type];
+ list_for_each_entry_safe(buffer, next, &buffers->list, list) {
+ if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
+ continue;
+ if (buffer->attr & BUF_ATTR_QUEUED)
+ continue;
+
+ if (buffer->attr & BUF_ATTR_DEFERRED) {
+ ret = iris_queue_buffer(inst, buffer);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
{
const struct iris_platform_data *platform_data = inst->core->iris_platform_data;
@@ -358,6 +381,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
continue;
if (buffer->attr & BUF_ATTR_QUEUED)
continue;
+ if (buffer->type == BUF_DPB && inst->state != IRIS_INST_STREAMING) {
+ buffer->attr |= BUF_ATTR_DEFERRED;
+ continue;
+ }
ret = iris_queue_buffer(inst, buffer);
if (ret)
return ret;
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h
index 00825ad2dc3a4bd1ace32d7e95d15b95276315b0..b9b011faa13ae72e08545c191cdcc2f1bcaf9e0a 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_buffer.h
@@ -105,6 +105,7 @@ int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_ty
void iris_get_internal_buffers(struct iris_inst *inst, u32 plane);
int iris_create_internal_buffers(struct iris_inst *inst, u32 plane);
int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane);
+int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type);
int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer);
int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane);
int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane);
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index 8b17c7c3948798326ed4732ca50ebd98b833401f..e62ed7a57df2debf0a930ad8307e6d945f589922 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -173,9 +173,6 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
inst = vb2_get_drv_priv(q);
- if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT)
- return 0;
-
mutex_lock(&inst->lock);
if (inst->state == IRIS_INST_ERROR) {
ret = -EBUSY;
@@ -203,7 +200,10 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
buf_type = iris_v4l2_type_to_driver(q->type);
- ret = iris_queue_deferred_buffers(inst, buf_type);
+ if (inst->state == IRIS_INST_STREAMING)
+ ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB);
+ if (!ret)
+ ret = iris_queue_deferred_buffers(inst, buf_type);
if (ret)
goto error;
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (3 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 04/24] media: iris: Fix port streaming handling Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-13 21:51 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 06/24] media: iris: Always destroy internal buffers on firmware release response Dikshita Agarwal
` (19 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Previously, the transition to load resources substate was only allowed
when instance state was INIT, since capture port streaming was not
permitted before output port streaming in the driver.
However, now after removing that restriction, the instance state can be
OUTPUT_STREAMING when firmware start is triggered and substate needs to
be moved to LOAD_RESOURCES.
Fixes: 547f7b8c5090 ("media: iris: add check to allow sub states transitions")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_state.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index 104e1687ad39dab93ff66450ba3a97c309b1e1e1..a21238d2818f9606871953bd0bee25382cca0474 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -122,7 +122,8 @@ static bool iris_inst_allow_sub_state(struct iris_inst *inst, enum iris_inst_sub
return false;
case IRIS_INST_OUTPUT_STREAMING:
if (sub_state & (IRIS_INST_SUB_DRC_LAST |
- IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE))
+ IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE |
+ IRIS_INST_SUB_LOAD_RESOURCES))
return true;
return false;
case IRIS_INST_STREAMING:
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 06/24] media: iris: Always destroy internal buffers on firmware release response
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (4 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-16 10:44 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 07/24] media: iris: Update vbuf flags before v4l2_m2m_buf_done Dikshita Agarwal
` (18 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Currently, internal buffers are destroyed only if 'PENDING_RELEASE' flag
is set when a release response is received from the firmware, which is
incorrect. Internal buffers should always be destroyed when the firmware
explicitly releases it, regardless of whether the 'PENDING_RELEASE' flag
was set by the driver. This is specially important during force-stop
scenarios, where the firmware may release buffers without driver marking
them for release.
Fix this by removing the incorrect check and ensuring all buffers are
properly cleaned up.
Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
index a8c30fc5c0d0668cc9980f2fcfcf21072cf9ef0a..dda775d463e916f70da0b879702d96df18ea8bf7 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -424,7 +424,6 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
struct iris_buffers *buffers = &inst->buffers[buf_type];
struct iris_buffer *buf, *iter;
bool found = false;
- int ret = 0;
list_for_each_entry(iter, &buffers->list, list) {
if (iter->device_addr == buffer->base_address) {
@@ -437,10 +436,8 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
return -EINVAL;
buf->attr &= ~BUF_ATTR_QUEUED;
- if (buf->attr & BUF_ATTR_PENDING_RELEASE)
- ret = iris_destroy_internal_buffer(inst, buf);
- return ret;
+ return iris_destroy_internal_buffer(inst, buf);
}
static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst,
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 07/24] media: iris: Update vbuf flags before v4l2_m2m_buf_done
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (5 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 06/24] media: iris: Always destroy internal buffers on firmware release response Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-16 10:49 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued Dikshita Agarwal
` (17 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Update the vbuf flags appropriately in error cases before calling
v4l2_m2m_buf_done(). Previously, the flag update was skippied in error
scenario, which could result in incorrect state reporting for buffers.
Fixes: 17f2a485ca67 ("media: iris: implement vb2 ops for buf_queue and firmware response")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_buffer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 23cac5d1312913b8dac44347ae66cb80a6a15deb..38548ee4749ea7dd1addf2c9d0677cf5217e3546 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -651,6 +651,8 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
vb2 = &vbuf->vb2_buf;
+ vbuf->flags |= buf->flags;
+
if (buf->flags & V4L2_BUF_FLAG_ERROR) {
state = VB2_BUF_STATE_ERROR;
vb2_set_plane_payload(vb2, 0, 0);
@@ -659,8 +661,6 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
return 0;
}
- vbuf->flags |= buf->flags;
-
if (V4L2_TYPE_IS_CAPTURE(type)) {
vb2_set_plane_payload(vb2, 0, buf->data_size);
vbuf->sequence = inst->sequence_cap++;
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued.
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (6 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 07/24] media: iris: Update vbuf flags before v4l2_m2m_buf_done Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-16 11:07 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 09/24] media: iris: Send dummy buffer address for all codecs during drain Dikshita Agarwal
` (16 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
For HFI Gen1, the instances substate is changed to LOAD_RESOURCES only
when a START command is issues to the firmware. If STOP is called
without a prior START, the firmware may reject the command and throw
some erros.
Handle this by adding a substate check before issuing STOP command to
the firmware.
Fixes: 11712ce70f8e ("media: iris: implement vb2 streaming ops")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 5fc30d54af4dc34616cfd08813940aa0b7044a20..5f1748ab80f88393215fc2d82c5c6b4af1266090 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -184,11 +184,12 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane)
u32 flush_type = 0;
int ret = 0;
- if ((V4L2_TYPE_IS_OUTPUT(plane) &&
- inst->state == IRIS_INST_INPUT_STREAMING) ||
+ if (((V4L2_TYPE_IS_OUTPUT(plane) &&
+ inst->state == IRIS_INST_INPUT_STREAMING) ||
(V4L2_TYPE_IS_CAPTURE(plane) &&
inst->state == IRIS_INST_OUTPUT_STREAMING) ||
- inst->state == IRIS_INST_ERROR) {
+ inst->state == IRIS_INST_ERROR) &&
+ inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
reinit_completion(&inst->completion);
iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP);
ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 09/24] media: iris: Send dummy buffer address for all codecs during drain
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (7 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued Dikshita Agarwal
@ 2025-08-13 9:37 ` Dikshita Agarwal
2025-08-16 11:11 ` Bryan O'Donoghue
2025-08-13 9:38 ` [PATCH v2 10/24] media: iris: Fix missing LAST flag handling " Dikshita Agarwal
` (15 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:37 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Firmware can handle a dummy address for buffers with the EOS flag. To
ensure consistent behavior across all codecs, update the drain
command to always send a dummy buffer address.
This makes the drain handling uniform and avoids any codec specific
assumptions.
Fixes: 478c4478610d ("media: iris: Add codec specific check for VP9 decoder drain handling")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 5f1748ab80f88393215fc2d82c5c6b4af1266090..5097680ee14ebba3a126213c0584161627ca47d7 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -402,8 +402,7 @@ static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane)
ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
ip_pkt.shdr.session_id = inst->session_id;
ip_pkt.flags = HFI_BUFFERFLAG_EOS;
- if (inst->codec == V4L2_PIX_FMT_VP9)
- ip_pkt.packet_buffer = 0xdeadb000;
+ ip_pkt.packet_buffer = 0xdeadb000;
return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 10/24] media: iris: Fix missing LAST flag handling during drain
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (8 preceding siblings ...)
2025-08-13 9:37 ` [PATCH v2 09/24] media: iris: Send dummy buffer address for all codecs during drain Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-16 11:17 ` Bryan O'Donoghue
2025-08-13 9:38 ` [PATCH v2 11/24] media: iris: Add support for video encoder device Dikshita Agarwal
` (14 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Improve drain handling by ensuring the LAST flag is attached to final
capture buffer when drain response is received from the firmware.
Previously, the driver failed to attach the V4L2_BUF_FLAG_LAST flag when
a drain response was received from the firmware, relying on userspace to
mark the next queued buffer as LAST. This update fixes the issue by
checking the pending drain status, attaching the LAST flag to the
capture buffer received from the firmware (with EOS attached), and
returning it to the V4L2 layer correctly.
Fixes: d09100763bed ("media: iris: add support for drain sequence")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 4 +---
drivers/media/platform/qcom/iris/iris_state.c | 2 +-
drivers/media/platform/qcom/iris/iris_state.h | 1 +
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index 8d1ce8a19a45ebb2b29457e0fef7d72c1c0d9785..2a96458833835422d30c9386d15cc1e4fb226e3d 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -416,8 +416,6 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
inst->flush_responses_pending++;
iris_inst_sub_state_change_drain_last(inst);
-
- return;
}
if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) {
@@ -462,7 +460,7 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
timestamp_us = (timestamp_us << 32) | timestamp_lo;
} else {
if (pkt->stream_id == 1 && !inst->last_buffer_dequeued) {
- if (iris_drc_pending(inst)) {
+ if (iris_drc_pending(inst) || iris_drain_pending(inst)) {
flags |= V4L2_BUF_FLAG_LAST;
inst->last_buffer_dequeued = true;
}
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index a21238d2818f9606871953bd0bee25382cca0474..d1dc1a863da0b0b1af60974e9ed2ef68ea225cdd 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -252,7 +252,7 @@ bool iris_drc_pending(struct iris_inst *inst)
inst->sub_state & IRIS_INST_SUB_DRC_LAST;
}
-static inline bool iris_drain_pending(struct iris_inst *inst)
+bool iris_drain_pending(struct iris_inst *inst)
{
return inst->sub_state & IRIS_INST_SUB_DRAIN &&
inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h
index e718386dbe0402417f408d8fc696a33e5c7f23b3..b09fa54cf17eeee0c9ae254588964ad959c82c80 100644
--- a/drivers/media/platform/qcom/iris/iris_state.h
+++ b/drivers/media/platform/qcom/iris/iris_state.h
@@ -141,5 +141,6 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst);
int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane);
bool iris_allow_cmd(struct iris_inst *inst, u32 cmd);
bool iris_drc_pending(struct iris_inst *inst);
+bool iris_drain_pending(struct iris_inst *inst);
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 11/24] media: iris: Add support for video encoder device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (9 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 10/24] media: iris: Fix missing LAST flag handling " Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:11 ` Vikash Garodia
2025-08-16 11:21 ` Bryan O'Donoghue
2025-08-13 9:38 ` [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure Dikshita Agarwal
` (13 subsequent siblings)
24 siblings, 2 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for registering a V4L2 encoder video device to the iris
driver. The encoder device is registered with the name
"qcom-iris-encoder".
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_core.h | 7 ++++++
drivers/media/platform/qcom/iris/iris_probe.c | 36 ++++++++++++++++++++-------
2 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
index aeeac32a1f6d9a9fa7027e8e3db4d95f021c552e..09e83be4e00efb456b7098a499b6cce850134a06 100644
--- a/drivers/media/platform/qcom/iris/iris_core.h
+++ b/drivers/media/platform/qcom/iris/iris_core.h
@@ -25,6 +25,11 @@ struct icc_info {
#define IRIS_FW_VERSION_LENGTH 128
#define IFACEQ_CORE_PKT_SIZE (1024 * 4)
+enum domain_type {
+ ENCODER = BIT(0),
+ DECODER = BIT(1),
+};
+
/**
* struct iris_core - holds core parameters valid for all instances
*
@@ -33,6 +38,7 @@ struct icc_info {
* @irq: iris irq
* @v4l2_dev: a holder for v4l2 device structure
* @vdev_dec: iris video device structure for decoder
+ * @vdev_enc: iris video device structure for encoder
* @iris_v4l2_file_ops: iris v4l2 file ops
* @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops
* @iris_vb2_ops: iris vb2 ops
@@ -73,6 +79,7 @@ struct iris_core {
int irq;
struct v4l2_device v4l2_dev;
struct video_device *vdev_dec;
+ struct video_device *vdev_enc;
const struct v4l2_file_operations *iris_v4l2_file_ops;
const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops;
const struct vb2_ops *iris_vb2_ops;
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 4e6e92357968d7419f114cc0ffa9b571bad19e46..c3be9deb0a57cc2cf25d69784d54be5e4a5fe06c 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -146,7 +146,7 @@ static int iris_init_resources(struct iris_core *core)
return iris_init_resets(core);
}
-static int iris_register_video_device(struct iris_core *core)
+static int iris_register_video_device(struct iris_core *core, enum domain_type type)
{
struct video_device *vdev;
int ret;
@@ -155,7 +155,6 @@ static int iris_register_video_device(struct iris_core *core)
if (!vdev)
return -ENOMEM;
- strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
vdev->release = video_device_release;
vdev->fops = core->iris_v4l2_file_ops;
vdev->ioctl_ops = core->iris_v4l2_ioctl_ops;
@@ -163,11 +162,23 @@ static int iris_register_video_device(struct iris_core *core)
vdev->v4l2_dev = &core->v4l2_dev;
vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
- if (ret)
+ if (type == DECODER) {
+ strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+ if (ret)
+ goto err_vdev_release;
+ core->vdev_dec = vdev;
+ } else if (type == ENCODER) {
+ strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+ if (ret)
+ goto err_vdev_release;
+ core->vdev_enc = vdev;
+ } else {
+ ret = -EINVAL;
goto err_vdev_release;
+ }
- core->vdev_dec = vdev;
video_set_drvdata(vdev, core);
return 0;
@@ -189,6 +200,7 @@ static void iris_remove(struct platform_device *pdev)
iris_core_deinit(core);
video_unregister_device(core->vdev_dec);
+ video_unregister_device(core->vdev_enc);
v4l2_device_unregister(&core->v4l2_dev);
@@ -258,17 +270,21 @@ static int iris_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = iris_register_video_device(core);
+ ret = iris_register_video_device(core, DECODER);
if (ret)
goto err_v4l2_unreg;
+ ret = iris_register_video_device(core, ENCODER);
+ if (ret)
+ goto err_vdev_unreg_dec;
+
platform_set_drvdata(pdev, core);
dma_mask = core->iris_platform_data->dma_mask;
ret = dma_set_mask_and_coherent(dev, dma_mask);
if (ret)
- goto err_vdev_unreg;
+ goto err_vdev_unreg_enc;
dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32));
@@ -277,11 +293,13 @@ static int iris_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(core->dev);
ret = devm_pm_runtime_enable(core->dev);
if (ret)
- goto err_vdev_unreg;
+ goto err_vdev_unreg_enc;
return 0;
-err_vdev_unreg:
+err_vdev_unreg_enc:
+ video_unregister_device(core->vdev_enc);
+err_vdev_unreg_dec:
video_unregister_device(core->vdev_dec);
err_v4l2_unreg:
v4l2_device_unregister(&core->v4l2_dev);
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (10 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 11/24] media: iris: Add support for video encoder device Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:25 ` Vikash Garodia
2025-08-16 9:03 ` Bryan O'Donoghue
2025-08-13 9:38 ` [PATCH v2 13/24] media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder Dikshita Agarwal
` (12 subsequent siblings)
24 siblings, 2 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Introduce initialization and deinitialization for internal encoder
instance structure with necessary hooks.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/Makefile | 1 +
drivers/media/platform/qcom/iris/iris_buffer.c | 59 ++++++++++++++++----
.../platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++-
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
drivers/media/platform/qcom/iris/iris_instance.h | 7 +++
drivers/media/platform/qcom/iris/iris_vdec.c | 2 -
drivers/media/platform/qcom/iris/iris_venc.c | 65 ++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 14 +++++
drivers/media/platform/qcom/iris/iris_vidc.c | 27 ++++++++-
drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 +-
10 files changed, 170 insertions(+), 18 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
index e86d00ee6f15dda8bae2f25f726feb0d427b7684..ec32145e081b1fc3538dfa7d5113162a76a6068c 100644
--- a/drivers/media/platform/qcom/iris/Makefile
+++ b/drivers/media/platform/qcom/iris/Makefile
@@ -19,6 +19,7 @@ qcom-iris-objs += \
iris_vidc.o \
iris_vb2.o \
iris_vdec.o \
+ iris_venc.o \
iris_vpu2.o \
iris_vpu3x.o \
iris_vpu_buffer.o \
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 38548ee4749ea7dd1addf2c9d0677cf5217e3546..6bf9b0b35d206d51b927c824d5a5b327596251c6 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -63,7 +63,12 @@
static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
{
u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
- struct v4l2_format *f = inst->fmt_dst;
+ struct v4l2_format *f;
+
+ if (inst->domain == DECODER)
+ f = inst->fmt_dst;
+ else
+ f = inst->fmt_src;
y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
@@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst)
return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);
}
-static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
+static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
{
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
u32 base_res_mbs = NUM_MBS_4K;
@@ -219,18 +224,50 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
return ALIGN(frame_size, PIXELS_4K);
}
+static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
+{
+ u32 aligned_width, aligned_height, bitstream_size, yuv_size;
+ struct v4l2_format *f;
+
+ f = inst->fmt_dst;
+
+ aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
+ aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
+ bitstream_size = aligned_width * aligned_height * 3;
+ yuv_size = (aligned_width * aligned_height * 3) >> 1;
+ if (aligned_width * aligned_height > (4096 * 2176))
+ /* bitstream_size = 0.25 * yuv_size; */
+ bitstream_size = (bitstream_size >> 3);
+ else if (aligned_width * aligned_height > (1280 * 720))
+ /* bitstream_size = 0.5 * yuv_size; */
+ bitstream_size = (bitstream_size >> 2);
+
+ return ALIGN(bitstream_size, 4096);
+}
+
int iris_get_buffer_size(struct iris_inst *inst,
enum iris_buffer_type buffer_type)
{
- switch (buffer_type) {
- case BUF_INPUT:
- return iris_bitstream_buffer_size(inst);
- case BUF_OUTPUT:
- return iris_yuv_buffer_size_nv12(inst);
- case BUF_DPB:
- return iris_yuv_buffer_size_qc08c(inst);
- default:
- return 0;
+ if (inst->domain == DECODER) {
+ switch (buffer_type) {
+ case BUF_INPUT:
+ return iris_dec_bitstream_buffer_size(inst);
+ case BUF_OUTPUT:
+ return iris_yuv_buffer_size_nv12(inst);
+ case BUF_DPB:
+ return iris_yuv_buffer_size_qc08c(inst);
+ default:
+ return 0;
+ }
+ } else {
+ switch (buffer_type) {
+ case BUF_INPUT:
+ return iris_yuv_buffer_size_nv12(inst);
+ case BUF_OUTPUT:
+ return iris_enc_bitstream_buffer_size(inst);
+ default:
+ return 0;
+ }
}
}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 5097680ee14ebba3a126213c0584161627ca47d7..eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -109,7 +109,12 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst)
packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
packet.shdr.session_id = inst->session_id;
- packet.session_domain = HFI_SESSION_TYPE_DEC;
+
+ if (inst->domain == DECODER)
+ packet.session_domain = HFI_SESSION_TYPE_DEC;
+ else
+ packet.session_domain = HFI_SESSION_TYPE_ENC;
+
packet.session_codec = codec;
reinit_completion(&inst->completion);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index d4d119ca98b0cb313db351f3794bf278216bd539..5b7c641b727a16c3aa7196a6d49786133653279f 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -10,6 +10,7 @@
#define HFI_VIDEO_ARCH_OX 0x1
+#define HFI_SESSION_TYPE_ENC 1
#define HFI_SESSION_TYPE_DEC 2
#define HFI_VIDEO_CODEC_H264 0x00000002
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index 0e1f5799b72d993b25820608969e0011eabdb6bc..ff90f010f1d36690cbadeff0787b1fb7458d7f75 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -12,6 +12,9 @@
#include "iris_core.h"
#include "iris_utils.h"
+#define DEFAULT_WIDTH 320
+#define DEFAULT_HEIGHT 240
+
/**
* struct iris_inst - holds per video instance parameters
*
@@ -24,7 +27,9 @@
* @fmt_src: structure of v4l2_format for source
* @fmt_dst: structure of v4l2_format for destination
* @ctrl_handler: reference of v4l2 ctrl handler
+ * @domain: domain type: encoder or decoder
* @crop: structure of crop info
+ * @compose: structure of compose info
* @completion: structure of signal completions
* @flush_completion: structure of signal completions for flush cmd
* @flush_responses_pending: counter to track number of pending flush responses
@@ -57,7 +62,9 @@ struct iris_inst {
struct v4l2_format *fmt_src;
struct v4l2_format *fmt_dst;
struct v4l2_ctrl_handler ctrl_handler;
+ enum domain_type domain;
struct iris_hfi_rect_desc crop;
+ struct iris_hfi_rect_desc compose;
struct completion completion;
struct completion flush_completion;
u32 flush_responses_pending;
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index d670b51c5839d1fad54d34f373cf71d5f3973a96..3482ff3f18d2bcd592b7eb7d803bf98e29276ebb 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -13,8 +13,6 @@
#include "iris_vdec.h"
#include "iris_vpu_buffer.h"
-#define DEFAULT_WIDTH 320
-#define DEFAULT_HEIGHT 240
#define DEFAULT_CODEC_ALIGNMENT 16
int iris_vdec_inst_init(struct iris_inst *inst)
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
new file mode 100644
index 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_buffer.h"
+#include "iris_instance.h"
+#include "iris_venc.h"
+#include "iris_vpu_buffer.h"
+
+int iris_venc_inst_init(struct iris_inst *inst)
+{
+ struct v4l2_format *f;
+
+ inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
+ inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
+ if (!inst->fmt_src || !inst->fmt_dst)
+ return -ENOMEM;
+
+ f = inst->fmt_dst;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ f->fmt.pix_mp.width = DEFAULT_WIDTH;
+ f->fmt.pix_mp.height = DEFAULT_HEIGHT;
+ f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+ inst->codec = f->fmt.pix_mp.pixelformat;
+ f->fmt.pix_mp.num_planes = 1;
+ f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
+ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+ f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
+ f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
+ f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
+ inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
+ inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
+
+ f = inst->fmt_src;
+ f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
+ f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
+ f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
+ f->fmt.pix_mp.num_planes = 1;
+ f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
+ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+ f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
+ f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
+ f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
+ inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
+ inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
+
+ inst->crop.left = 0;
+ inst->crop.top = 0;
+ inst->crop.width = f->fmt.pix_mp.width;
+ inst->crop.height = f->fmt.pix_mp.height;
+
+ return 0;
+}
+
+void iris_venc_inst_deinit(struct iris_inst *inst)
+{
+ kfree(inst->fmt_dst);
+ kfree(inst->fmt_src);
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a4cbddd0114b6d0e4ea895362b01c302250c78b
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_VENC_H_
+#define _IRIS_VENC_H_
+
+struct iris_inst;
+
+int iris_venc_inst_init(struct iris_inst *inst);
+void iris_venc_inst_deinit(struct iris_inst *inst);
+
+#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 96313856a026efaff40da97eaaa63e847172cd57..11f27fc867dc610c18022b0942e65aa175a8567e 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -12,6 +12,7 @@
#include "iris_vidc.h"
#include "iris_instance.h"
#include "iris_vdec.h"
+#include "iris_venc.h"
#include "iris_vb2.h"
#include "iris_vpu_buffer.h"
#include "iris_platform_common.h"
@@ -23,7 +24,10 @@
static void iris_v4l2_fh_init(struct iris_inst *inst)
{
- v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
+ if (inst->domain == ENCODER)
+ v4l2_fh_init(&inst->fh, inst->core->vdev_enc);
+ else if (inst->domain == DECODER)
+ v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
inst->fh.ctrl_handler = &inst->ctrl_handler;
v4l2_fh_add(&inst->fh);
}
@@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_
int iris_open(struct file *filp)
{
struct iris_core *core = video_drvdata(filp);
+ struct video_device *vdev;
struct iris_inst *inst;
+ u32 session_type;
int ret;
+ vdev = video_devdata(filp);
+ if (strcmp(vdev->name, "qcom-iris-decoder") == 0)
+ session_type = DECODER;
+ else if (strcmp(vdev->name, "qcom-iris-encoder") == 0)
+ session_type = ENCODER;
+ else
+ return -EINVAL;
+
ret = pm_runtime_resume_and_get(core->dev);
if (ret < 0)
return ret;
@@ -147,6 +161,7 @@ int iris_open(struct file *filp)
return -ENOMEM;
inst->core = core;
+ inst->domain = session_type;
inst->session_id = hash32_ptr(inst);
inst->state = IRIS_INST_DEINIT;
@@ -178,7 +193,10 @@ int iris_open(struct file *filp)
goto fail_m2m_release;
}
- ret = iris_vdec_inst_init(inst);
+ if (inst->domain == DECODER)
+ ret = iris_vdec_inst_init(inst);
+ else if (inst->domain == ENCODER)
+ ret = iris_venc_inst_init(inst);
if (ret)
goto fail_m2m_ctx_release;
@@ -265,7 +283,10 @@ int iris_close(struct file *filp)
v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev);
mutex_lock(&inst->lock);
- iris_vdec_inst_deinit(inst);
+ if (inst->domain == DECODER)
+ iris_vdec_inst_deinit(inst);
+ else if (inst->domain == ENCODER)
+ iris_venc_inst_deinit(inst);
iris_session_close(inst);
iris_inst_change_state(inst, IRIS_INST_DEINIT);
iris_v4l2_fh_deinit(inst);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index f92fd39fe310b9661f892dcf1ff036ebbc102270..06d5afc3c641f0dfca3967e55273c4fa2614fdff 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -628,7 +628,10 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type
case BUF_INPUT:
return MIN_BUFFERS;
case BUF_OUTPUT:
- return output_min_count(inst);
+ if (inst->domain == ENCODER)
+ return MIN_BUFFERS;
+ else
+ return output_min_count(inst);
case BUF_BIN:
case BUF_COMV:
case BUF_NON_COMV:
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 13/24] media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (11 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:32 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder Dikshita Agarwal
` (11 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add V4L2 format handling support for the encoder by adding
implementation of ENUM/S/G/TRY_FMT with necessary hooks.
This ensures that the encoder supports format negotiation consistent
with V4L2 expectation, enabling userspace applications to configure
resolution, pixel format and buffer layout properly.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_core.h | 6 +-
drivers/media/platform/qcom/iris/iris_instance.h | 11 ++
drivers/media/platform/qcom/iris/iris_probe.c | 3 +-
drivers/media/platform/qcom/iris/iris_vdec.h | 11 --
drivers/media/platform/qcom/iris/iris_venc.c | 207 +++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 3 +
drivers/media/platform/qcom/iris/iris_vidc.c | 41 ++++-
7 files changed, 261 insertions(+), 21 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
index 09e83be4e00efb456b7098a499b6cce850134a06..827aee8dcec3ee17af5a90f5594b9315f663c0b3 100644
--- a/drivers/media/platform/qcom/iris/iris_core.h
+++ b/drivers/media/platform/qcom/iris/iris_core.h
@@ -40,7 +40,8 @@ enum domain_type {
* @vdev_dec: iris video device structure for decoder
* @vdev_enc: iris video device structure for encoder
* @iris_v4l2_file_ops: iris v4l2 file ops
- * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops
+ * @iris_v4l2_ioctl_ops_dec: iris v4l2 ioctl ops for decoder
+ * @iris_v4l2_ioctl_ops_enc: iris v4l2 ioctl ops for encoder
* @iris_vb2_ops: iris vb2 ops
* @icc_tbl: table of iris interconnects
* @icc_count: count of iris interconnects
@@ -81,7 +82,8 @@ struct iris_core {
struct video_device *vdev_dec;
struct video_device *vdev_enc;
const struct v4l2_file_operations *iris_v4l2_file_ops;
- const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops;
+ const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec;
+ const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc;
const struct vb2_ops *iris_vb2_ops;
struct icc_bulk_data *icc_tbl;
u32 icc_count;
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index ff90f010f1d36690cbadeff0787b1fb7458d7f75..55cf9702111829ef24189986ba5245c7684bfe11 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -15,6 +15,17 @@
#define DEFAULT_WIDTH 320
#define DEFAULT_HEIGHT 240
+enum iris_fmt_type {
+ IRIS_FMT_H264,
+ IRIS_FMT_HEVC,
+ IRIS_FMT_VP9,
+};
+
+struct iris_fmt {
+ u32 pixfmt;
+ u32 type;
+};
+
/**
* struct iris_inst - holds per video instance parameters
*
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index c3be9deb0a57cc2cf25d69784d54be5e4a5fe06c..0f2596427a773e5c9105b97cb234c8f0a3483226 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -157,19 +157,20 @@ static int iris_register_video_device(struct iris_core *core, enum domain_type t
vdev->release = video_device_release;
vdev->fops = core->iris_v4l2_file_ops;
- vdev->ioctl_ops = core->iris_v4l2_ioctl_ops;
vdev->vfl_dir = VFL_DIR_M2M;
vdev->v4l2_dev = &core->v4l2_dev;
vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
if (type == DECODER) {
strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
+ vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec;
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret)
goto err_vdev_release;
core->vdev_dec = vdev;
} else if (type == ENCODER) {
strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
+ vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc;
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret)
goto err_vdev_release;
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
index cd7aab66dc7c82dc50acef9e654a3d6c1ddb088f..b24932dc511a65017b1cadbcb984544475bd0723 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/iris/iris_vdec.h
@@ -8,17 +8,6 @@
struct iris_inst;
-enum iris_fmt_type {
- IRIS_FMT_H264,
- IRIS_FMT_HEVC,
- IRIS_FMT_VP9,
-};
-
-struct iris_fmt {
- u32 pixfmt;
- u32 type;
-};
-
int iris_vdec_inst_init(struct iris_inst *inst);
void iris_vdec_inst_deinit(struct iris_inst *inst);
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index e418d347ac111c1bc48304adafa259d697e49fed..6bb59ce4fc565d3dcc6185233ef25d2e4d85cb3e 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -3,6 +3,8 @@
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <media/v4l2-mem2mem.h>
+
#include "iris_buffer.h"
#include "iris_instance.h"
#include "iris_venc.h"
@@ -63,3 +65,208 @@ void iris_venc_inst_deinit(struct iris_inst *inst)
kfree(inst->fmt_dst);
kfree(inst->fmt_src);
}
+
+static const struct iris_fmt iris_venc_formats[] = {
+ [IRIS_FMT_H264] = {
+ .pixfmt = V4L2_PIX_FMT_H264,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ },
+ [IRIS_FMT_HEVC] = {
+ .pixfmt = V4L2_PIX_FMT_HEVC,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ },
+};
+
+static const struct iris_fmt *
+find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
+{
+ const struct iris_fmt *fmt = iris_venc_formats;
+ unsigned int size = ARRAY_SIZE(iris_venc_formats);
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ if (fmt[i].pixfmt == pixfmt)
+ break;
+ }
+
+ if (i == size || fmt[i].type != type)
+ return NULL;
+
+ return &fmt[i];
+}
+
+static const struct iris_fmt *
+find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
+{
+ const struct iris_fmt *fmt = iris_venc_formats;
+ unsigned int size = ARRAY_SIZE(iris_venc_formats);
+
+ if (index >= size || fmt[index].type != type)
+ return NULL;
+
+ return &fmt[index];
+}
+
+int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
+{
+ const struct iris_fmt *fmt;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_NV12;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ fmt = find_format_by_index(inst, f->index, f->type);
+ if (!fmt)
+ return -EINVAL;
+
+ f->pixelformat = fmt->pixfmt;
+ f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
+{
+ struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+ const struct iris_fmt *fmt;
+ struct v4l2_format *f_inst;
+
+ memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
+ fmt = find_format(inst, pixmp->pixelformat, f->type);
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) {
+ f_inst = inst->fmt_src;
+ f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
+ f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
+ f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
+ }
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ if (!fmt) {
+ f_inst = inst->fmt_dst;
+ f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
+ f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
+ f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (pixmp->field == V4L2_FIELD_ANY)
+ pixmp->field = V4L2_FIELD_NONE;
+
+ pixmp->num_planes = 1;
+
+ return 0;
+}
+
+static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f)
+{
+ struct v4l2_format *fmt;
+
+ iris_venc_try_fmt(inst, f);
+
+ if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
+ return -EINVAL;
+
+ fmt = inst->fmt_dst;
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt->fmt.pix_mp.num_planes = 1;
+ fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
+ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
+
+ if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT &&
+ f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709)
+ f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
+ fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
+ fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
+ fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+ fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
+
+ inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
+ inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
+ fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
+ inst->codec = f->fmt.pix_mp.pixelformat;
+ memcpy(f, fmt, sizeof(struct v4l2_format));
+
+ return 0;
+}
+
+static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f)
+{
+ struct v4l2_format *fmt, *output_fmt;
+
+ iris_venc_try_fmt(inst, f);
+
+ if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12)
+ return -EINVAL;
+
+ fmt = inst->fmt_src;
+ fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
+ fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
+ fmt->fmt.pix_mp.num_planes = 1;
+ fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
+ fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128);
+ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
+
+ fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
+ fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
+ fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+ fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
+
+ output_fmt = inst->fmt_dst;
+ output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width;
+ output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height;
+ output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace;
+ output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func;
+ output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc;
+ output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization;
+
+ inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
+ inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
+
+ if (f->fmt.pix_mp.width != inst->crop.width ||
+ f->fmt.pix_mp.height != inst->crop.height) {
+ inst->crop.top = 0;
+ inst->crop.left = 0;
+ inst->crop.width = fmt->fmt.pix_mp.width;
+ inst->crop.height = fmt->fmt.pix_mp.height;
+
+ iris_venc_s_fmt_output(inst, output_fmt);
+ }
+
+ memcpy(f, fmt, sizeof(struct v4l2_format));
+
+ return 0;
+}
+
+int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
+{
+ struct vb2_queue *q;
+
+ q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
+ if (!q)
+ return -EINVAL;
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return iris_venc_s_fmt_input(inst, f);
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ return iris_venc_s_fmt_output(inst, f);
+ default:
+ return -EINVAL;
+ }
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index 8a4cbddd0114b6d0e4ea895362b01c302250c78b..eb26a3ecbd98b3f02dfdea0dfc41bcd3a90904b6 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -10,5 +10,8 @@ struct iris_inst;
int iris_venc_inst_init(struct iris_inst *inst);
void iris_venc_inst_deinit(struct iris_inst *inst);
+int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
+int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
+int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 11f27fc867dc610c18022b0942e65aa175a8567e..06b2737c5892ebbcf43b4cff66062d85cf805c20 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -308,16 +308,26 @@ static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f)
{
struct iris_inst *inst = iris_get_inst(filp, NULL);
- return iris_vdec_enum_fmt(inst, f);
+ if (inst->domain == DECODER)
+ return iris_vdec_enum_fmt(inst, f);
+ else if (inst->domain == ENCODER)
+ return iris_venc_enum_fmt(inst, f);
+ else
+ return -EINVAL;
}
static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
{
struct iris_inst *inst = iris_get_inst(filp, NULL);
- int ret;
+ int ret = 0;
mutex_lock(&inst->lock);
- ret = iris_vdec_try_fmt(inst, f);
+
+ if (inst->domain == DECODER)
+ ret = iris_vdec_try_fmt(inst, f);
+ else if (inst->domain == ENCODER)
+ ret = iris_venc_try_fmt(inst, f);
+
mutex_unlock(&inst->lock);
return ret;
@@ -326,10 +336,15 @@ static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_form
static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
{
struct iris_inst *inst = iris_get_inst(filp, NULL);
- int ret;
+ int ret = 0;
mutex_lock(&inst->lock);
- ret = iris_vdec_s_fmt(inst, f);
+
+ if (inst->domain == DECODER)
+ ret = iris_vdec_s_fmt(inst, f);
+ else if (inst->domain == ENCODER)
+ ret = iris_venc_s_fmt(inst, f);
+
mutex_unlock(&inst->lock);
return ret;
@@ -473,7 +488,7 @@ static const struct vb2_ops iris_vb2_ops = {
.buf_queue = iris_vb2_buf_queue,
};
-static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
+static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_dec = {
.vidioc_enum_fmt_vid_cap = iris_enum_fmt,
.vidioc_enum_fmt_vid_out = iris_enum_fmt,
.vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane,
@@ -501,9 +516,21 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
.vidioc_decoder_cmd = iris_dec_cmd,
};
+static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
+ .vidioc_enum_fmt_vid_cap = iris_enum_fmt,
+ .vidioc_enum_fmt_vid_out = iris_enum_fmt,
+ .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane,
+ .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane,
+ .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane,
+ .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane,
+ .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane,
+ .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
+};
+
void iris_init_ops(struct iris_core *core)
{
core->iris_v4l2_file_ops = &iris_v4l2_file_ops;
core->iris_vb2_ops = &iris_vb2_ops;
- core->iris_v4l2_ioctl_ops = &iris_v4l2_ioctl_ops;
+ core->iris_v4l2_ioctl_ops_dec = &iris_v4l2_ioctl_ops_dec;
+ core->iris_v4l2_ioctl_ops_enc = &iris_v4l2_ioctl_ops_enc;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (12 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 13/24] media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:43 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 15/24] media: iris: Add support for VIDIOC_QUERYCAP for encoder video device Dikshita Agarwal
` (10 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for frame size and frame interval enumeration by
implementing ENUM_FRAMESIZES/FRAMEINTERVALS V4L2 ioctls for encoder
video device with necessary hooks.
This allows userspace application to query encoder capabilities and
adapt encoding configurations accordingly.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
.../platform/qcom/iris/iris_platform_common.h | 5 +-
.../media/platform/qcom/iris/iris_platform_gen2.c | 3 ++
.../platform/qcom/iris/iris_platform_sm8250.c | 1 +
drivers/media/platform/qcom/iris/iris_vdec.c | 13 +++++
drivers/media/platform/qcom/iris/iris_vdec.h | 1 +
drivers/media/platform/qcom/iris/iris_venc.c | 13 +++++
drivers/media/platform/qcom/iris/iris_venc.h | 1 +
drivers/media/platform/qcom/iris/iris_vidc.c | 58 ++++++++++++++++++++--
8 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index adafdce8a856f9c661aabc5ca28f0faceaa93551..792f46e2e34fd564a1ed61523f72826fc8f74582 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -21,7 +21,8 @@ struct iris_inst;
#define DEFAULT_MAX_HOST_BUF_COUNT 64
#define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256
#define DEFAULT_FPS 30
-#define NUM_MBS_8K ((8192 * 4352) / 256)
+#define MAXIMUM_FPS 480
+#define NUM_MBS_8K ((8192 * 4352) / 256)
enum stage_type {
STAGE_1 = 1,
@@ -179,6 +180,8 @@ struct iris_platform_data {
u32 max_session_count;
/* max number of macroblocks per frame supported */
u32 max_core_mbpf;
+ /* max number of macroblocks per second supported */
+ u32 max_core_mbps;
const u32 *input_config_params_default;
unsigned int input_config_params_default_size;
const u32 *input_config_params_hevc;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index d3026b2bcb708c7ec31f134f628df7e57b54af4f..1e2fadfe17672029b46e07ce00a8e31e0711fd58 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -354,6 +354,7 @@ struct iris_platform_data sm8550_data = {
.num_vpp_pipe = 4,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
+ .max_core_mbps = ((7680 * 4320) / 256) * 60,
.input_config_params_default =
sm8550_vdec_input_config_params_default,
.input_config_params_default_size =
@@ -429,6 +430,7 @@ struct iris_platform_data sm8650_data = {
.num_vpp_pipe = 4,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
+ .max_core_mbps = ((7680 * 4320) / 256) * 60,
.input_config_params_default =
sm8550_vdec_input_config_params_default,
.input_config_params_default_size =
@@ -500,6 +502,7 @@ struct iris_platform_data qcs8300_data = {
.num_vpp_pipe = 2,
.max_session_count = 16,
.max_core_mbpf = ((4096 * 2176) / 256) * 4,
+ .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
.input_config_params_default =
sm8550_vdec_input_config_params_default,
.input_config_params_default_size =
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index 8d0816a67ae0b6886204ce93fa5ccafaac10392a..2a3cbe1f2d4b27d3cce9e9cdad1525801d71a041 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -128,6 +128,7 @@ struct iris_platform_data sm8250_data = {
.num_vpp_pipe = 4,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K,
+ .max_core_mbps = ((7680 * 4320) / 256) * 60,
.input_config_params_default =
sm8250_vdec_input_config_param_default,
.input_config_params_default_size =
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 3482ff3f18d2bcd592b7eb7d803bf98e29276ebb..6afbd2f89260a233d75d7a0cdf3647236216c9ec 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -263,6 +263,19 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
return 0;
}
+int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat)
+{
+ const struct iris_fmt *fmt = NULL;
+
+ if (pixelformat != V4L2_PIX_FMT_NV12) {
+ fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (!fmt)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub)
{
int ret = 0;
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
index b24932dc511a65017b1cadbcb984544475bd0723..097e02bfa72b5ac4e46e66c61842df1d9dd4565b 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/iris/iris_vdec.h
@@ -13,6 +13,7 @@ void iris_vdec_inst_deinit(struct iris_inst *inst);
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
+int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat);
int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
void iris_vdec_src_change(struct iris_inst *inst);
int iris_vdec_streamon_input(struct iris_inst *inst);
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 6bb59ce4fc565d3dcc6185233ef25d2e4d85cb3e..301206253090962abbb4e4eac8ee88e7b359c98d 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -270,3 +270,16 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
return -EINVAL;
}
}
+
+int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat)
+{
+ const struct iris_fmt *fmt = NULL;
+
+ if (pixelformat != V4L2_PIX_FMT_NV12) {
+ fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (!fmt)
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index eb26a3ecbd98b3f02dfdea0dfc41bcd3a90904b6..04fd41275547c40c359c6ea04dfe4ee31d2d0df6 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -13,5 +13,6 @@ void iris_venc_inst_deinit(struct iris_inst *inst);
int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
+int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 06b2737c5892ebbcf43b4cff66062d85cf805c20..cb1280c0c6c82187243f0bda4d98e42370ee787c 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -373,13 +373,18 @@ static int iris_enum_framesizes(struct file *filp, void *fh,
{
struct iris_inst *inst = iris_get_inst(filp, NULL);
struct platform_inst_caps *caps;
+ int ret = 0;
if (fsize->index)
return -EINVAL;
- if (fsize->pixel_format != V4L2_PIX_FMT_H264 &&
- fsize->pixel_format != V4L2_PIX_FMT_NV12)
- return -EINVAL;
+ if (inst->domain == DECODER)
+ ret = iris_vdec_validate_format(inst, fsize->pixel_format);
+ else
+ ret = iris_venc_validate_format(inst, fsize->pixel_format);
+
+ if (ret)
+ return ret;
caps = inst->core->iris_platform_data->inst_caps;
@@ -391,6 +396,51 @@ static int iris_enum_framesizes(struct file *filp, void *fh,
fsize->stepwise.max_height = caps->max_frame_height;
fsize->stepwise.step_height = STEP_HEIGHT;
+ return ret;
+}
+
+static int iris_enum_frameintervals(struct file *filp, void *fh,
+ struct v4l2_frmivalenum *fival)
+
+{
+ struct iris_inst *inst = iris_get_inst(filp, NULL);
+ struct platform_inst_caps *caps;
+ struct iris_core *core = inst->core;
+ u32 fps, mbpf;
+ int ret = 0;
+
+ if (inst->domain == DECODER)
+ return -ENOTTY;
+
+ if (fival->index)
+ return -EINVAL;
+
+ ret = iris_venc_validate_format(inst, fival->pixel_format);
+ if (ret)
+ return ret;
+
+ if (!fival->width || !fival->height)
+ return -EINVAL;
+
+ caps = inst->core->iris_platform_data->inst_caps;
+ if (fival->width > caps->max_frame_width ||
+ fival->width < caps->min_frame_width ||
+ fival->height > caps->max_frame_height ||
+ fival->height < caps->min_frame_height)
+ return -EINVAL;
+
+ mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width);
+ fps = DIV_ROUND_UP(core->iris_platform_data->max_core_mbps, mbpf);
+
+ fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+ fival->stepwise.min.numerator = 1;
+ fival->stepwise.min.denominator =
+ min_t(u32, fps, MAXIMUM_FPS);
+ fival->stepwise.max.numerator = 1;
+ fival->stepwise.max.denominator = 1;
+ fival->stepwise.step.numerator = 1;
+ fival->stepwise.step.denominator = MAXIMUM_FPS;
+
return 0;
}
@@ -525,6 +575,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane,
.vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane,
.vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
+ .vidioc_enum_framesizes = iris_enum_framesizes,
+ .vidioc_enum_frameintervals = iris_enum_frameintervals,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 15/24] media: iris: Add support for VIDIOC_QUERYCAP for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (13 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:46 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 16/24] media: iris: Add encoder support for V4L2 event subscription Dikshita Agarwal
` (9 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for the VIDIOC_QUERYCAP V4L2 iocts for the encoder video
device to report core driver capabilities.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_vidc.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index cb1280c0c6c82187243f0bda4d98e42370ee787c..458773a2ed7f5e16d5bd5e79dba2f5c029036505 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -446,8 +446,14 @@ static int iris_enum_frameintervals(struct file *filp, void *fh,
static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap)
{
+ struct iris_inst *inst = iris_get_inst(filp, NULL);
+
strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver));
- strscpy(cap->card, "Iris Decoder", sizeof(cap->card));
+
+ if (inst->domain == DECODER)
+ strscpy(cap->card, "Iris Decoder", sizeof(cap->card));
+ else
+ strscpy(cap->card, "Iris Encoder", sizeof(cap->card));
return 0;
}
@@ -577,6 +583,7 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
.vidioc_enum_framesizes = iris_enum_framesizes,
.vidioc_enum_frameintervals = iris_enum_frameintervals,
+ .vidioc_querycap = iris_querycap,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 16/24] media: iris: Add encoder support for V4L2 event subscription
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (14 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 15/24] media: iris: Add support for VIDIOC_QUERYCAP for encoder video device Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:48 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device Dikshita Agarwal
` (8 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Implement support for V4L2 event subscription on the encoder device by
handling the SUBSCRIBE_EVENT and UNSUBSCRIBE_EVENT ioctls with the
necessary hooks.
This enables userspace applications to subscribe to V4L2 events,
allowing asynchronous notification mechanisms.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_venc.c | 14 ++++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 1 +
drivers/media/platform/qcom/iris/iris_vidc.c | 9 ++++++++-
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 301206253090962abbb4e4eac8ee88e7b359c98d..3dbcce23cbe94cf0edc4421694a3ba11faa5eb96 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -3,6 +3,7 @@
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
#include "iris_buffer.h"
@@ -283,3 +284,16 @@ int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat)
return 0;
}
+
+int iris_venc_subscribe_event(struct iris_inst *inst,
+ const struct v4l2_event_subscription *sub)
+{
+ switch (sub->type) {
+ case V4L2_EVENT_EOS:
+ return v4l2_event_subscribe(&inst->fh, sub, 0, NULL);
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subscribe_event(&inst->fh, sub);
+ default:
+ return -EINVAL;
+ }
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index 04fd41275547c40c359c6ea04dfe4ee31d2d0df6..2d9614ae18e8a2318df6673fbeae5ee33c99b596 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -14,5 +14,6 @@ int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
+int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 458773a2ed7f5e16d5bd5e79dba2f5c029036505..d8c94074153e9b1ceac4f911210ddbf89bbe3533 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -489,7 +489,12 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
{
struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
- return iris_vdec_subscribe_event(inst, sub);
+ if (inst->domain == DECODER)
+ return iris_vdec_subscribe_event(inst, sub);
+ else if (inst->domain == ENCODER)
+ return iris_venc_subscribe_event(inst, sub);
+
+ return -EINVAL;
}
static int iris_dec_cmd(struct file *filp, void *fh,
@@ -584,6 +589,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_enum_framesizes = iris_enum_framesizes,
.vidioc_enum_frameintervals = iris_enum_frameintervals,
.vidioc_querycap = iris_querycap,
+ .vidioc_subscribe_event = iris_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (15 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 16/24] media: iris: Add encoder support for V4L2 event subscription Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 14:54 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 18/24] media: iris: Add support for G/S_PARM " Dikshita Agarwal
` (7 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for G/S_SELECTION V4L2 ioctls for the encoder video
device with necessary hooks. This allows userspace to query and
configure rectangular selection areas such as crop.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_venc.c | 28 ++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 1 +
drivers/media/platform/qcom/iris/iris_vidc.c | 65 ++++++++++++++++++++++------
3 files changed, 80 insertions(+), 14 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 3dbcce23cbe94cf0edc4421694a3ba11faa5eb96..930f5afe9489d01be193f1dbe429d33f5401b468 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -297,3 +297,31 @@ int iris_venc_subscribe_event(struct iris_inst *inst,
return -EINVAL;
}
}
+
+int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
+{
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP:
+ s->r.left = 0;
+ s->r.top = 0;
+
+ if (s->r.width > inst->fmt_src->fmt.pix_mp.width ||
+ s->r.height > inst->fmt_src->fmt.pix_mp.height)
+ return -EINVAL;
+
+ inst->crop.left = s->r.left;
+ inst->crop.top = s->r.top;
+ inst->crop.width = s->r.width;
+ inst->crop.height = s->r.height;
+ inst->fmt_dst->fmt.pix_mp.width = inst->crop.width;
+ inst->fmt_dst->fmt.pix_mp.height = inst->crop.height;
+ return iris_venc_s_fmt_output(inst, inst->fmt_dst);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index 2d9614ae18e8a2318df6673fbeae5ee33c99b596..72c6e25d87113baa6d2219ae478b7d7df1aed7bf 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -15,5 +15,6 @@ int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
+int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index d8c94074153e9b1ceac4f911210ddbf89bbe3533..2074682a35fd1c4c9f5d29fdaee3392d98bf8923 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -462,29 +462,64 @@ static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *
{
struct iris_inst *inst = iris_get_inst(filp, NULL);
- if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ inst->domain == DECODER)
return -EINVAL;
- switch (s->target) {
- case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
- case V4L2_SEL_TGT_CROP:
- case V4L2_SEL_TGT_COMPOSE_BOUNDS:
- case V4L2_SEL_TGT_COMPOSE_PADDED:
- case V4L2_SEL_TGT_COMPOSE_DEFAULT:
- case V4L2_SEL_TGT_COMPOSE:
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ inst->domain == ENCODER)
+ return -EINVAL;
+
+ if (inst->domain == DECODER) {
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP:
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ case V4L2_SEL_TGT_COMPOSE_PADDED:
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ case V4L2_SEL_TGT_COMPOSE:
+ s->r.left = inst->crop.left;
+ s->r.top = inst->crop.top;
+ s->r.width = inst->crop.width;
+ s->r.height = inst->crop.height;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else if (inst->domain == ENCODER) {
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ s->r.width = inst->fmt_src->fmt.pix_mp.width;
+ s->r.height = inst->fmt_src->fmt.pix_mp.height;
+ break;
+ case V4L2_SEL_TGT_CROP:
+ s->r.width = inst->crop.width;
+ s->r.height = inst->crop.height;
+ break;
+ default:
+ return -EINVAL;
+ }
s->r.left = inst->crop.left;
s->r.top = inst->crop.top;
- s->r.width = inst->crop.width;
- s->r.height = inst->crop.height;
- break;
- default:
- return -EINVAL;
}
return 0;
}
+static int iris_s_selection(struct file *filp, void *fh, struct v4l2_selection *s)
+{
+ struct iris_inst *inst = iris_get_inst(filp, NULL);
+
+ if (inst->domain == DECODER)
+ return -EINVAL;
+ else if (inst->domain == ENCODER)
+ return iris_venc_s_selection(inst, s);
+
+ return -EINVAL;
+}
+
static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
{
struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
@@ -591,6 +626,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_querycap = iris_querycap,
.vidioc_subscribe_event = iris_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_g_selection = iris_g_selection,
+ .vidioc_s_selection = iris_s_selection,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 18/24] media: iris: Add support for G/S_PARM for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (16 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 15:01 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 19/24] media: iris: Add platform-specific capabilities " Dikshita Agarwal
` (6 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add supports for the G/S_PARM V4L2 ioctls for encoder video device with
necessary hooks. This allows userspace to query the current streaming
parameters such as frame intervals and set desired streaming parameters
primarily the frame rate.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_instance.h | 5 ++
.../platform/qcom/iris/iris_platform_common.h | 2 +
.../media/platform/qcom/iris/iris_platform_gen2.c | 4 +-
.../platform/qcom/iris/iris_platform_qcs8300.h | 2 +
.../platform/qcom/iris/iris_platform_sm8250.c | 2 +
drivers/media/platform/qcom/iris/iris_utils.c | 36 ++++++++
drivers/media/platform/qcom/iris/iris_utils.h | 2 +
drivers/media/platform/qcom/iris/iris_vb2.c | 17 ----
drivers/media/platform/qcom/iris/iris_venc.c | 95 ++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 2 +
drivers/media/platform/qcom/iris/iris_vidc.c | 30 +++++++
11 files changed, 179 insertions(+), 18 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index 55cf9702111829ef24189986ba5245c7684bfe11..b75549718df3c87cd85aecfc74c873c60cd4bde5 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -61,6 +61,9 @@ struct iris_fmt {
* @metadata_idx: index for metadata buffer
* @codec: codec type
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
+ * @frame_rate: frame rate of current instance
+ * @operating_rate: operating rate of current instance
+
*/
struct iris_inst {
@@ -96,6 +99,8 @@ struct iris_inst {
u32 metadata_idx;
u32 codec;
bool last_buffer_dequeued;
+ u32 frame_rate;
+ u32 operating_rate;
};
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 792f46e2e34fd564a1ed61523f72826fc8f74582..d0b84c93aef409b51a767ba11f91c6ce2533f27f 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -79,6 +79,8 @@ struct platform_inst_caps {
u32 mb_cycles_fw;
u32 mb_cycles_fw_vpp;
u32 num_comv;
+ u32 max_frame_rate;
+ u32 max_operating_rate;
};
enum platform_inst_fw_cap_type {
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index 1e2fadfe17672029b46e07ce00a8e31e0711fd58..e047fb75a99a6372dac4ad029baea16034cac633 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -209,6 +209,8 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = {
.mb_cycles_fw = 489583,
.mb_cycles_fw_vpp = 66234,
.num_comv = 0,
+ .max_frame_rate = MAXIMUM_FPS << 16,
+ .max_operating_rate = MAXIMUM_FPS << 16,
};
static void iris_set_sm8550_preset_registers(struct iris_core *core)
@@ -502,7 +504,7 @@ struct iris_platform_data qcs8300_data = {
.num_vpp_pipe = 2,
.max_session_count = 16,
.max_core_mbpf = ((4096 * 2176) / 256) * 4,
- .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
+ .max_core_mbps = (((3840 * 2176) / 256) * 120),
.input_config_params_default =
sm8550_vdec_input_config_params_default,
.input_config_params_default_size =
diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
index a8d66ed388a34e6bb45d4a089d981bb7d135fb50..22e485b0b2ae8f110d2f3b817e202d1aa7d227fd 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
@@ -197,4 +197,6 @@ static struct platform_inst_caps platform_inst_cap_qcs8300 = {
.mb_cycles_fw = 326389,
.mb_cycles_fw_vpp = 44156,
.num_comv = 0,
+ .max_frame_rate = MAXIMUM_FPS << 16,
+ .max_operating_rate = MAXIMUM_FPS << 16,
};
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index 2a3cbe1f2d4b27d3cce9e9cdad1525801d71a041..5d59a5a3172a510b3a38f7c9c29dffd919fafce7 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -40,6 +40,8 @@ static struct platform_inst_caps platform_inst_cap_sm8250 = {
.max_mbpf = 138240,
.mb_cycles_vsp = 25,
.mb_cycles_vpp = 200,
+ .max_frame_rate = MAXIMUM_FPS << 16,
+ .max_operating_rate = MAXIMUM_FPS << 16,
};
static void iris_set_sm8250_preset_registers(struct iris_core *core)
diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c
index 83c70d6a2d9092615dcf1b7d0fc85110f0df1aa0..f0af926879d5d90c56222aa8d48998a34be1c636 100644
--- a/drivers/media/platform/qcom/iris/iris_utils.c
+++ b/drivers/media/platform/qcom/iris/iris_utils.c
@@ -88,3 +88,39 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id)
mutex_unlock(&core->lock);
return NULL;
}
+
+int iris_check_core_mbpf(struct iris_inst *inst)
+{
+ struct iris_core *core = inst->core;
+ struct iris_inst *instance;
+ u32 total_mbpf = 0;
+
+ mutex_lock(&core->lock);
+ list_for_each_entry(instance, &core->instances, list)
+ total_mbpf += iris_get_mbpf(instance);
+ mutex_unlock(&core->lock);
+
+ if (total_mbpf > core->iris_platform_data->max_core_mbpf)
+ return -ENOMEM;
+
+ return 0;
+}
+
+int iris_check_core_mbps(struct iris_inst *inst)
+{
+ struct iris_core *core = inst->core;
+ struct iris_inst *instance;
+ u32 total_mbps = 0, fps = 0;
+
+ mutex_lock(&core->lock);
+ list_for_each_entry(instance, &core->instances, list) {
+ fps = max(instance->frame_rate >> 16, instance->operating_rate >> 16);
+ total_mbps += iris_get_mbpf(instance) * fps;
+ }
+ mutex_unlock(&core->lock);
+
+ if (total_mbps > core->iris_platform_data->max_core_mbps)
+ return -ENOMEM;
+
+ return 0;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h
index 49869cf7a376880a026f44ff3883a6b13c6fcfbb..75740181122f5bdf93d64d3f43b3a26a9fe97919 100644
--- a/drivers/media/platform/qcom/iris/iris_utils.h
+++ b/drivers/media/platform/qcom/iris/iris_utils.h
@@ -49,5 +49,7 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id);
void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type,
enum vb2_buffer_state state);
int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush);
+int iris_check_core_mbpf(struct iris_inst *inst);
+int iris_check_core_mbps(struct iris_inst *inst);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index e62ed7a57df2debf0a930ad8307e6d945f589922..e32f7e1f007228a3b2b51cd76cd193d852f16080 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -12,23 +12,6 @@
#include "iris_vdec.h"
#include "iris_power.h"
-static int iris_check_core_mbpf(struct iris_inst *inst)
-{
- struct iris_core *core = inst->core;
- struct iris_inst *instance;
- u32 total_mbpf = 0;
-
- mutex_lock(&core->lock);
- list_for_each_entry(instance, &core->instances, list)
- total_mbpf += iris_get_mbpf(instance);
- mutex_unlock(&core->lock);
-
- if (total_mbpf > core->iris_platform_data->max_core_mbpf)
- return -ENOMEM;
-
- return 0;
-}
-
static int iris_check_inst_mbpf(struct iris_inst *inst)
{
struct platform_inst_caps *caps;
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 930f5afe9489d01be193f1dbe429d33f5401b468..11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -58,6 +58,9 @@ int iris_venc_inst_init(struct iris_inst *inst)
inst->crop.width = f->fmt.pix_mp.width;
inst->crop.height = f->fmt.pix_mp.height;
+ inst->operating_rate = DEFAULT_FPS << 16;
+ inst->frame_rate = DEFAULT_FPS << 16;
+
return 0;
}
@@ -325,3 +328,95 @@ int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
return 0;
}
+
+int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
+{
+ struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
+ struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
+ struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
+ struct v4l2_fract *timeperframe = NULL;
+ u32 default_rate = DEFAULT_FPS;
+ bool is_frame_rate = false;
+ u32 q16_rate, max_rate;
+ u64 us_per_frame, fps;
+ int ret = 0;
+
+ if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ timeperframe = &s_parm->parm.output.timeperframe;
+ max_rate = caps->max_operating_rate >> 16;
+ s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+ } else {
+ timeperframe = &s_parm->parm.capture.timeperframe;
+ is_frame_rate = true;
+ max_rate = caps->max_frame_rate >> 16;
+ s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ }
+
+ if (!timeperframe->denominator || !timeperframe->numerator) {
+ if (!timeperframe->numerator)
+ timeperframe->numerator = 1;
+ if (!timeperframe->denominator)
+ timeperframe->denominator = default_rate;
+ }
+
+ us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
+ do_div(us_per_frame, timeperframe->denominator);
+
+ if (!us_per_frame)
+ return -EINVAL;
+
+ fps = (u64)USEC_PER_SEC;
+ do_div(fps, us_per_frame);
+ ret = fps > max_rate;
+ if (ret) {
+ ret = -ENOMEM;
+ goto reset_rate;
+ }
+
+ q16_rate = (u32)fps << 16;
+ if (is_frame_rate)
+ inst->frame_rate = q16_rate;
+ else
+ inst->operating_rate = q16_rate;
+
+ if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) ||
+ (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) {
+ ret = iris_check_core_mbpf(inst);
+ if (ret)
+ goto reset_rate;
+ ret = iris_check_core_mbps(inst);
+ if (ret)
+ goto reset_rate;
+ }
+
+ return 0;
+
+reset_rate:
+ if (ret) {
+ if (is_frame_rate)
+ inst->frame_rate = default_rate << 16;
+ else
+ inst->operating_rate = default_rate << 16;
+ }
+
+ return ret;
+}
+
+int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
+{
+ struct v4l2_fract *timeperframe = NULL;
+
+ if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ timeperframe = &s_parm->parm.output.timeperframe;
+ timeperframe->numerator = 1;
+ timeperframe->denominator = inst->operating_rate >> 16;
+ s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+ } else {
+ timeperframe = &s_parm->parm.capture.timeperframe;
+ timeperframe->numerator = 1;
+ timeperframe->denominator = inst->frame_rate >> 16;
+ s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index 72c6e25d87113baa6d2219ae478b7d7df1aed7bf..0d566b7fc89b96b8fbc62a35b2ba795ca0bcf460 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -16,5 +16,7 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
+int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
+int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 2074682a35fd1c4c9f5d29fdaee3392d98bf8923..4c11cdac19f97d08a9e6242eea74649aad0242cf 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -532,6 +532,34 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
return -EINVAL;
}
+static int iris_s_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
+{
+ struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+ a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return -EINVAL;
+
+ if (inst->domain == ENCODER)
+ return iris_venc_s_param(inst, a);
+ else
+ return -EINVAL;
+}
+
+static int iris_g_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
+{
+ struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+ a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return -EINVAL;
+
+ if (inst->domain == ENCODER)
+ return iris_venc_g_param(inst, a);
+ else
+ return -EINVAL;
+}
+
static int iris_dec_cmd(struct file *filp, void *fh,
struct v4l2_decoder_cmd *dec)
{
@@ -628,6 +656,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
.vidioc_g_selection = iris_g_selection,
.vidioc_s_selection = iris_s_selection,
+ .vidioc_s_parm = iris_s_parm,
+ .vidioc_g_parm = iris_g_parm,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 19/24] media: iris: Add platform-specific capabilities for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (17 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 18/24] media: iris: Add support for G/S_PARM " Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-14 15:05 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 20/24] media: iris: Add V4L2 streaming support " Dikshita Agarwal
` (5 subsequent siblings)
24 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add platform-specific capabilities for the encoder video device and
initialize the corresponding controls in the control handler.
This enables proper configuration and handling of encoder-specific
features based on platform requirements.
Co-developed-by: Wangao Wang <quic_wangaow@quicinc.com>
Signed-off-by: Wangao Wang <quic_wangaow@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_core.h | 7 +-
drivers/media/platform/qcom/iris/iris_ctrls.c | 175 +++++++++-
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 7 +
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 +
.../platform/qcom/iris/iris_platform_common.h | 43 ++-
.../media/platform/qcom/iris/iris_platform_gen2.c | 385 ++++++++++++++++++++-
.../platform/qcom/iris/iris_platform_qcs8300.h | 350 ++++++++++++++++++-
.../platform/qcom/iris/iris_platform_sm8250.c | 185 +++++++++-
drivers/media/platform/qcom/iris/iris_vdec.c | 2 +-
drivers/media/platform/qcom/iris/iris_venc.c | 7 +-
10 files changed, 1140 insertions(+), 30 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
index 827aee8dcec3ee17af5a90f5594b9315f663c0b3..fb194c967ad4f9b5e00cd74f0d41e0b827ef14db 100644
--- a/drivers/media/platform/qcom/iris/iris_core.h
+++ b/drivers/media/platform/qcom/iris/iris_core.h
@@ -71,7 +71,8 @@ enum domain_type {
* @intr_status: interrupt status
* @sys_error_handler: a delayed work for handling system fatal error
* @instances: a list_head of all instances
- * @inst_fw_caps: an array of supported instance capabilities
+ * @inst_fw_caps_dec: an array of supported instance capabilities by decoder
+ * @inst_fw_caps_enc: an array of supported instance capabilities by encoder
*/
struct iris_core {
@@ -113,7 +114,9 @@ struct iris_core {
u32 intr_status;
struct delayed_work sys_error_handler;
struct list_head instances;
- struct platform_inst_fw_cap inst_fw_caps[INST_FW_CAP_MAX];
+ /* encoder and decoder have overlapping caps, so two different arrays are required */
+ struct platform_inst_fw_cap inst_fw_caps_dec[INST_FW_CAP_MAX];
+ struct platform_inst_fw_cap inst_fw_caps_enc[INST_FW_CAP_MAX];
};
int iris_core_init(struct iris_core *core);
diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
index 9136b723c0f2a3d5833af32ae2735ccdb244f60f..797386cb96ab1d24be6cc1819e2f9202ab4cc224 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
@@ -31,6 +31,68 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id)
return LEVEL_VP9;
case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
return TIER;
+ case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+ return HEADER_MODE;
+ case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
+ return PREPEND_SPSPPS_TO_IDR;
+ case V4L2_CID_MPEG_VIDEO_BITRATE:
+ return BITRATE;
+ case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+ return BITRATE_PEAK;
+ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+ return BITRATE_MODE;
+ case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
+ return FRAME_SKIP_MODE;
+ case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+ return FRAME_RC_ENABLE;
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ return GOP_SIZE;
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ return ENTROPY_MODE;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ return MIN_FRAME_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+ return MIN_FRAME_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ return MAX_FRAME_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+ return MAX_FRAME_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP:
+ return I_FRAME_MIN_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP:
+ return I_FRAME_MIN_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP:
+ return P_FRAME_MIN_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP:
+ return P_FRAME_MIN_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP:
+ return B_FRAME_MIN_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP:
+ return B_FRAME_MIN_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP:
+ return I_FRAME_MAX_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP:
+ return I_FRAME_MAX_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP:
+ return P_FRAME_MAX_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP:
+ return P_FRAME_MAX_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP:
+ return B_FRAME_MAX_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP:
+ return B_FRAME_MAX_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+ return I_FRAME_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
+ return I_FRAME_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+ return P_FRAME_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
+ return P_FRAME_QP_HEVC;
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+ return B_FRAME_QP_H264;
+ case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
+ return B_FRAME_QP_HEVC;
default:
return INST_FW_CAP_MAX;
}
@@ -56,6 +118,68 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)
return V4L2_CID_MPEG_VIDEO_VP9_LEVEL;
case TIER:
return V4L2_CID_MPEG_VIDEO_HEVC_TIER;
+ case HEADER_MODE:
+ return V4L2_CID_MPEG_VIDEO_HEADER_MODE;
+ case PREPEND_SPSPPS_TO_IDR:
+ return V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR;
+ case BITRATE:
+ return V4L2_CID_MPEG_VIDEO_BITRATE;
+ case BITRATE_PEAK:
+ return V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
+ case BITRATE_MODE:
+ return V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
+ case FRAME_SKIP_MODE:
+ return V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE;
+ case FRAME_RC_ENABLE:
+ return V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
+ case GOP_SIZE:
+ return V4L2_CID_MPEG_VIDEO_GOP_SIZE;
+ case ENTROPY_MODE:
+ return V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
+ case MIN_FRAME_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_MIN_QP;
+ case MIN_FRAME_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP;
+ case MAX_FRAME_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_MAX_QP;
+ case MAX_FRAME_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP;
+ case I_FRAME_MIN_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP;
+ case I_FRAME_MIN_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP;
+ case P_FRAME_MIN_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP;
+ case P_FRAME_MIN_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP;
+ case B_FRAME_MIN_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP;
+ case B_FRAME_MIN_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP;
+ case I_FRAME_MAX_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP;
+ case I_FRAME_MAX_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP;
+ case P_FRAME_MAX_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP;
+ case P_FRAME_MAX_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP;
+ case B_FRAME_MAX_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP;
+ case B_FRAME_MAX_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP;
+ case I_FRAME_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP;
+ case I_FRAME_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP;
+ case P_FRAME_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP;
+ case P_FRAME_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP;
+ case B_FRAME_QP_H264:
+ return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP;
+ case B_FRAME_QP_HEVC:
+ return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP;
default:
return 0;
}
@@ -101,7 +225,10 @@ int iris_ctrls_init(struct iris_inst *inst)
num_ctrls++;
}
- /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */
+ /* Adding 1 to num_ctrls to include
+ * V4L2_CID_MIN_BUFFERS_FOR_CAPTURE for decoder and
+ * V4L2_CID_MIN_BUFFERS_FOR_OUTPUT for encoder
+ */
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1);
if (ret)
@@ -143,8 +270,13 @@ int iris_ctrls_init(struct iris_inst *inst)
ctrl_idx++;
}
- v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
- V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
+ if (inst->domain == DECODER) {
+ v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
+ } else {
+ v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
+ V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 4);
+ }
ret = inst->ctrl_handler.error;
if (ret)
@@ -162,22 +294,39 @@ void iris_session_init_caps(struct iris_core *core)
struct platform_inst_fw_cap *caps;
u32 i, num_cap, cap_id;
- caps = core->iris_platform_data->inst_fw_caps;
- num_cap = core->iris_platform_data->inst_fw_caps_size;
+ caps = core->iris_platform_data->inst_fw_caps_dec;
+ num_cap = core->iris_platform_data->inst_fw_caps_dec_size;
+
+ for (i = 0; i < num_cap; i++) {
+ cap_id = caps[i].cap_id;
+ if (!iris_valid_cap_id(cap_id))
+ continue;
+
+ core->inst_fw_caps_dec[cap_id].cap_id = caps[i].cap_id;
+ core->inst_fw_caps_dec[cap_id].min = caps[i].min;
+ core->inst_fw_caps_dec[cap_id].max = caps[i].max;
+ core->inst_fw_caps_dec[cap_id].step_or_mask = caps[i].step_or_mask;
+ core->inst_fw_caps_dec[cap_id].value = caps[i].value;
+ core->inst_fw_caps_dec[cap_id].flags = caps[i].flags;
+ core->inst_fw_caps_dec[cap_id].hfi_id = caps[i].hfi_id;
+ core->inst_fw_caps_dec[cap_id].set = caps[i].set;
+ }
+
+ caps = core->iris_platform_data->inst_fw_caps_enc;
+ num_cap = core->iris_platform_data->inst_fw_caps_enc_size;
for (i = 0; i < num_cap; i++) {
cap_id = caps[i].cap_id;
if (!iris_valid_cap_id(cap_id))
continue;
- core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id;
- core->inst_fw_caps[cap_id].min = caps[i].min;
- core->inst_fw_caps[cap_id].max = caps[i].max;
- core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask;
- core->inst_fw_caps[cap_id].value = caps[i].value;
- core->inst_fw_caps[cap_id].flags = caps[i].flags;
- core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id;
- core->inst_fw_caps[cap_id].set = caps[i].set;
+ core->inst_fw_caps_enc[cap_id].cap_id = caps[i].cap_id;
+ core->inst_fw_caps_enc[cap_id].min = caps[i].min;
+ core->inst_fw_caps_enc[cap_id].max = caps[i].max;
+ core->inst_fw_caps_enc[cap_id].step_or_mask = caps[i].step_or_mask;
+ core->inst_fw_caps_enc[cap_id].value = caps[i].value;
+ core->inst_fw_caps_enc[cap_id].flags = caps[i].flags;
+ core->inst_fw_caps_enc[cap_id].hfi_id = caps[i].hfi_id;
}
}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index 5b7c641b727a16c3aa7196a6d49786133653279f..a7f4379c5973fdc4366969139bef25472e8f11a5 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -121,6 +121,13 @@
#define HFI_UNUSED_PICT 0x10000000
#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008
#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000
+#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL 0x2005002
+#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL 0x2005003
+#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL 0x2005004
+#define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2 0x2005009
+#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020
+#define HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE 0x2006001
+#define HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER 0x2006008
struct hfi_pkt_hdr {
u32 size;
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
index 5f13dc11bea532600cc9b15db57e8981a1f3eb93..fb6724d7f95ff8858aa9ba093fefb642e89de279 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -55,12 +55,21 @@
#define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123
#define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124
#define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128
+#define HFI_PROP_RATE_CONTROL 0x0300012a
+#define HFI_PROP_QP_PACKED 0x0300012e
+#define HFI_PROP_MIN_QP_PACKED 0x0300012f
+#define HFI_PROP_MAX_QP_PACKED 0x03000130
+#define HFI_PROP_TOTAL_BITRATE 0x0300013b
+#define HFI_PROP_MAX_GOP_FRAMES 0x03000146
+#define HFI_PROP_MAX_B_FRAMES 0x03000147
#define HFI_PROP_QUALITY_MODE 0x03000148
+#define HFI_PROP_SEQ_HEADER_MODE 0x03000149
#define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155
#define HFI_PROP_PICTURE_TYPE 0x03000162
#define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168
#define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169
#define HFI_PROP_NO_OUTPUT 0x0300016a
+#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C
#define HFI_PROP_COMV_BUFFER_COUNT 0x03000193
#define HFI_PROP_END 0x03FFFFFF
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index d0b84c93aef409b51a767ba11f91c6ce2533f27f..6d6a8f3b38271d928d753dd180e6e9a991991d24 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -23,6 +23,11 @@ struct iris_inst;
#define DEFAULT_FPS 30
#define MAXIMUM_FPS 480
#define NUM_MBS_8K ((8192 * 4352) / 256)
+#define MIN_QP_8BIT 1
+#define MAX_QP 51
+#define MAX_QP_HEVC 63
+#define DEFAULT_QP 20
+#define BITRATE_DEFAULT 20000000
enum stage_type {
STAGE_1 = 1,
@@ -91,6 +96,7 @@ enum platform_inst_fw_cap_type {
LEVEL_HEVC,
LEVEL_VP9,
INPUT_BUF_HOST_MAX_COUNT,
+ OUTPUT_BUF_HOST_MAX_COUNT,
STAGE,
PIPE,
POC,
@@ -98,6 +104,37 @@ enum platform_inst_fw_cap_type {
BIT_DEPTH,
RAP_FRAME,
TIER,
+ HEADER_MODE,
+ PREPEND_SPSPPS_TO_IDR,
+ BITRATE,
+ BITRATE_PEAK,
+ BITRATE_MODE,
+ FRAME_SKIP_MODE,
+ FRAME_RC_ENABLE,
+ GOP_SIZE,
+ ENTROPY_MODE,
+ MIN_FRAME_QP_H264,
+ MIN_FRAME_QP_HEVC,
+ MAX_FRAME_QP_H264,
+ MAX_FRAME_QP_HEVC,
+ I_FRAME_MIN_QP_H264,
+ I_FRAME_MIN_QP_HEVC,
+ P_FRAME_MIN_QP_H264,
+ P_FRAME_MIN_QP_HEVC,
+ B_FRAME_MIN_QP_H264,
+ B_FRAME_MIN_QP_HEVC,
+ I_FRAME_MAX_QP_H264,
+ I_FRAME_MAX_QP_HEVC,
+ P_FRAME_MAX_QP_H264,
+ P_FRAME_MAX_QP_HEVC,
+ B_FRAME_MAX_QP_H264,
+ B_FRAME_MAX_QP_HEVC,
+ I_FRAME_QP_H264,
+ I_FRAME_QP_HEVC,
+ P_FRAME_QP_H264,
+ P_FRAME_QP_HEVC,
+ B_FRAME_QP_H264,
+ B_FRAME_QP_HEVC,
INST_FW_CAP_MAX,
};
@@ -172,8 +209,10 @@ struct iris_platform_data {
const char *fwname;
u32 pas_id;
struct platform_inst_caps *inst_caps;
- struct platform_inst_fw_cap *inst_fw_caps;
- u32 inst_fw_caps_size;
+ struct platform_inst_fw_cap *inst_fw_caps_dec;
+ u32 inst_fw_caps_dec_size;
+ struct platform_inst_fw_cap *inst_fw_caps_enc;
+ u32 inst_fw_caps_enc_size;
struct tz_cp_config *tz_cp_config_data;
u32 core_arch;
u32 hw_response_timeout;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index e047fb75a99a6372dac4ad029baea16034cac633..1bf289d322c86a8f8c03c80697c08af5d9067769 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -14,8 +14,9 @@
#include "iris_platform_sm8650.h"
#define VIDEO_ARCH_LX 1
+#define BITRATE_MAX 245000000
-static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = {
+static struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = {
{
.cap_id = PROFILE_H264,
.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
@@ -199,6 +200,370 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = {
},
};
+static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
+ {
+ .cap_id = PROFILE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+ .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
+ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = PROFILE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
+ .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LEVEL_H264,
+ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LEVEL_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
+ .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROP_STAGE,
+ },
+ {
+ .cap_id = HEADER_MODE,
+ .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+ .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+ BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
+ .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = PREPEND_SPSPPS_TO_IDR,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 0,
+ },
+ {
+ .cap_id = BITRATE,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .hfi_id = HFI_PROP_TOTAL_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = BITRATE_PEAK,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = BITRATE_MODE,
+ .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
+ BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
+ .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .hfi_id = HFI_PROP_RATE_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_SKIP_MODE,
+ .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
+ .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_RC_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 1,
+ },
+ {
+ .cap_id = GOP_SIZE,
+ .min = 0,
+ .max = INT_MAX,
+ .step_or_mask = 1,
+ .value = 2 * DEFAULT_FPS - 1,
+ .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = ENTROPY_MODE,
+ .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
+ BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
+ .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .hfi_id = HFI_PROP_CABAC_SESSION,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ .hfi_id = HFI_PROP_MIN_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ .hfi_id = HFI_PROP_MIN_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROP_MAX_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROP_MAX_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = I_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = I_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = P_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = P_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = B_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = B_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = I_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = I_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = P_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = P_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = B_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = B_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = I_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = I_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = P_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = P_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = B_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = B_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = INPUT_BUF_HOST_MAX_COUNT,
+ .min = DEFAULT_MAX_HOST_BUF_COUNT,
+ .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
+ .step_or_mask = 1,
+ .value = DEFAULT_MAX_HOST_BUF_COUNT,
+ .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
+ .flags = CAP_FLAG_INPUT_PORT,
+ },
+ {
+ .cap_id = OUTPUT_BUF_HOST_MAX_COUNT,
+ .min = DEFAULT_MAX_HOST_BUF_COUNT,
+ .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
+ .step_or_mask = 1,
+ .value = DEFAULT_MAX_HOST_BUF_COUNT,
+ .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+};
+
static struct platform_inst_caps platform_inst_cap_sm8550 = {
.min_frame_width = 96,
.max_frame_width = 8192,
@@ -347,8 +712,10 @@ struct iris_platform_data sm8550_data = {
.fwname = "qcom/vpu/vpu30_p4.mbn",
.pas_id = IRIS_PAS_ID,
.inst_caps = &platform_inst_cap_sm8550,
- .inst_fw_caps = inst_fw_cap_sm8550,
- .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550),
+ .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
+ .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
.tz_cp_config_data = &tz_cp_config_sm8550,
.core_arch = VIDEO_ARCH_LX,
.hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
@@ -423,8 +790,10 @@ struct iris_platform_data sm8650_data = {
.fwname = "qcom/vpu/vpu33_p4.mbn",
.pas_id = IRIS_PAS_ID,
.inst_caps = &platform_inst_cap_sm8550,
- .inst_fw_caps = inst_fw_cap_sm8550,
- .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550),
+ .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
+ .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
.tz_cp_config_data = &tz_cp_config_sm8550,
.core_arch = VIDEO_ARCH_LX,
.hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
@@ -495,8 +864,10 @@ struct iris_platform_data qcs8300_data = {
.fwname = "qcom/vpu/vpu30_p4_s6.mbn",
.pas_id = IRIS_PAS_ID,
.inst_caps = &platform_inst_cap_qcs8300,
- .inst_fw_caps = inst_fw_cap_qcs8300,
- .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_qcs8300),
+ .inst_fw_caps_dec = inst_fw_cap_qcs8300_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_qcs8300_dec),
+ .inst_fw_caps_enc = inst_fw_cap_qcs8300_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_qcs8300_enc),
.tz_cp_config_data = &tz_cp_config_sm8550,
.core_arch = VIDEO_ARCH_LX,
.hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
index 22e485b0b2ae8f110d2f3b817e202d1aa7d227fd..624e3a442b06aabf3241d0b364b1d12fe937d6be 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
@@ -3,7 +3,9 @@
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
-static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = {
+#define BITRATE_MAX 245000000
+
+static struct platform_inst_fw_cap inst_fw_cap_qcs8300_dec[] = {
{
.cap_id = PROFILE_H264,
.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
@@ -187,6 +189,352 @@ static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = {
},
};
+static struct platform_inst_fw_cap inst_fw_cap_qcs8300_enc[] = {
+ {
+ .cap_id = PROFILE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+ .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
+ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = PROFILE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
+ .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LEVEL_H264,
+ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LEVEL_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
+ .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROP_STAGE,
+ },
+ {
+ .cap_id = HEADER_MODE,
+ .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+ .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+ BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
+ .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = PREPEND_SPSPPS_TO_IDR,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 0,
+ },
+ {
+ .cap_id = BITRATE,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .hfi_id = HFI_PROP_TOTAL_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = BITRATE_PEAK,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = BITRATE_MODE,
+ .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
+ BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
+ .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .hfi_id = HFI_PROP_RATE_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_SKIP_MODE,
+ .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
+ .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_RC_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 1,
+ },
+ {
+ .cap_id = GOP_SIZE,
+ .min = 0,
+ .max = INT_MAX,
+ .step_or_mask = 1,
+ .value = 2 * DEFAULT_FPS - 1,
+ .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = ENTROPY_MODE,
+ .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
+ BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
+ .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .hfi_id = HFI_PROP_CABAC_SESSION,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ .hfi_id = HFI_PROP_MIN_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ .hfi_id = HFI_PROP_MIN_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROP_MAX_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROP_MAX_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = I_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = I_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = P_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = P_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = B_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = B_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ },
+ {
+ .cap_id = I_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = I_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = P_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = P_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = B_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = B_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = I_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = I_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = P_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = P_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = B_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = B_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+};
+
static struct platform_inst_caps platform_inst_cap_qcs8300 = {
.min_frame_width = 96,
.max_frame_width = 4096,
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index 5d59a5a3172a510b3a38f7c9c29dffd919fafce7..b1ed6a140980ab6ca27f372f6f5851569a93ceed 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -11,7 +11,12 @@
#include "iris_hfi_gen1_defines.h"
#include "iris_vpu_common.h"
-static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = {
+#define BITRATE_MIN 32000
+#define BITRATE_MAX 160000000
+#define BITRATE_PEAK_DEFAULT (BITRATE_DEFAULT * 2)
+#define BITRATE_STEP 100
+
+static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = {
{
.cap_id = PIPE,
.min = PIPE_1,
@@ -32,6 +37,178 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = {
},
};
+static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
+ {
+ .cap_id = PROFILE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+ .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH),
+ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = PROFILE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
+ .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LEVEL_H264,
+ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LEVEL_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = HEADER_MODE,
+ .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+ .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+ BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
+ .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = BITRATE,
+ .min = BITRATE_MIN,
+ .max = BITRATE_MAX,
+ .step_or_mask = BITRATE_STEP,
+ .value = BITRATE_DEFAULT,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ },
+ {
+ .cap_id = BITRATE_MODE,
+ .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
+ BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
+ .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_SKIP_MODE,
+ .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
+ .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_RC_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 1,
+ },
+ {
+ .cap_id = GOP_SIZE,
+ .min = 0,
+ .max = (1 << 16) - 1,
+ .step_or_mask = 1,
+ .value = 30,
+ },
+ {
+ .cap_id = ENTROPY_MODE,
+ .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
+ BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
+ .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP_HEVC,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_H264,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT,
+ .max = MAX_QP_HEVC,
+ .step_or_mask = 1,
+ .value = MAX_QP_HEVC,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+};
+
static struct platform_inst_caps platform_inst_cap_sm8250 = {
.min_frame_width = 128,
.max_frame_width = 8192,
@@ -123,8 +300,10 @@ struct iris_platform_data sm8250_data = {
.fwname = "qcom/vpu-1.0/venus.mbn",
.pas_id = IRIS_PAS_ID,
.inst_caps = &platform_inst_cap_sm8250,
- .inst_fw_caps = inst_fw_cap_sm8250,
- .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8250),
+ .inst_fw_caps_dec = inst_fw_cap_sm8250_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8250_dec),
+ .inst_fw_caps_enc = inst_fw_cap_sm8250_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8250_enc),
.tz_cp_config_data = &tz_cp_config_sm8250,
.hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
.num_vpp_pipe = 4,
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 6afbd2f89260a233d75d7a0cdf3647236216c9ec..fcefd7c36335efd4154159d8a7fab31fae33a2fe 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -54,7 +54,7 @@ int iris_vdec_inst_init(struct iris_inst *inst)
inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
- memcpy(&inst->fw_caps[0], &core->inst_fw_caps[0],
+ memcpy(&inst->fw_caps[0], &core->inst_fw_caps_dec[0],
INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
return iris_ctrls_init(inst);
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67..4630ba12349a62a37515e93ed5efa2df197bce17 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -7,12 +7,14 @@
#include <media/v4l2-mem2mem.h>
#include "iris_buffer.h"
+#include "iris_ctrls.h"
#include "iris_instance.h"
#include "iris_venc.h"
#include "iris_vpu_buffer.h"
int iris_venc_inst_init(struct iris_inst *inst)
{
+ struct iris_core *core = inst->core;
struct v4l2_format *f;
inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
@@ -61,7 +63,10 @@ int iris_venc_inst_init(struct iris_inst *inst)
inst->operating_rate = DEFAULT_FPS << 16;
inst->frame_rate = DEFAULT_FPS << 16;
- return 0;
+ memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0],
+ INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
+
+ return iris_ctrls_init(inst);
}
void iris_venc_inst_deinit(struct iris_inst *inst)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 20/24] media: iris: Add V4L2 streaming support for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (18 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 19/24] media: iris: Add platform-specific capabilities " Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 21/24] media: iris: Set platform capabilities to firmware " Dikshita Agarwal
` (4 subsequent siblings)
24 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for V4L2 streaming operations on the encoder video device.
During stream-on, configure mandatory properties on the respective
planes and notify the firmware to initiate an encode session.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/Makefile | 4 +-
drivers/media/platform/qcom/iris/iris_common.c | 196 ++++++++++++++
drivers/media/platform/qcom/iris/iris_common.h | 16 ++
drivers/media/platform/qcom/iris/iris_hfi_common.h | 2 +-
.../platform/qcom/iris/iris_hfi_gen1_command.c | 281 ++++++++++++++-------
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 18 ++
.../platform/qcom/iris/iris_hfi_gen2_command.c | 278 +++++++++++++-------
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 3 +
.../platform/qcom/iris/iris_platform_common.h | 20 +-
.../media/platform/qcom/iris/iris_platform_gen2.c | 92 +++++--
.../platform/qcom/iris/iris_platform_sm8250.c | 23 +-
drivers/media/platform/qcom/iris/iris_vb2.c | 36 ++-
drivers/media/platform/qcom/iris/iris_vdec.c | 190 +-------------
drivers/media/platform/qcom/iris/iris_vdec.h | 1 -
drivers/media/platform/qcom/iris/iris_venc.c | 32 +++
drivers/media/platform/qcom/iris/iris_venc.h | 2 +
drivers/media/platform/qcom/iris/iris_vidc.c | 2 +
17 files changed, 782 insertions(+), 414 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
index ec32145e081b1fc3538dfa7d5113162a76a6068c..13270cd6d899852dded675b33d37f5919b81ccba 100644
--- a/drivers/media/platform/qcom/iris/Makefile
+++ b/drivers/media/platform/qcom/iris/Makefile
@@ -1,5 +1,5 @@
-qcom-iris-objs += \
- iris_buffer.o \
+qcom-iris-objs += iris_buffer.o \
+ iris_common.o \
iris_core.o \
iris_ctrls.o \
iris_firmware.o \
diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..d6a9271bcec77f142919070bf0566d0cf8a39562
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_common.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <media/v4l2-mem2mem.h>
+
+#include "iris_common.h"
+#include "iris_ctrls.h"
+#include "iris_instance.h"
+#include "iris_power.h"
+
+int iris_process_streamon_input(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ enum iris_inst_sub_state set_sub_state = 0;
+ int ret;
+
+ iris_scale_power(inst);
+
+ ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+ ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0);
+ if (ret)
+ return ret;
+ }
+
+ if (inst->domain == DECODER &&
+ (inst->sub_state & IRIS_INST_SUB_DRC ||
+ inst->sub_state & IRIS_INST_SUB_DRAIN ||
+ inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) {
+ if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
+ if (hfi_ops->session_pause) {
+ ret = hfi_ops->session_pause(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ }
+ set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
+ }
+ }
+
+ ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ inst->last_buffer_dequeued = false;
+
+ return iris_inst_change_sub_state(inst, 0, set_sub_state);
+}
+
+int iris_process_streamon_output(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ bool drain_active = false, drc_active = false;
+ enum iris_inst_sub_state clear_sub_state = 0;
+ int ret = 0;
+
+ iris_scale_power(inst);
+
+ drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN &&
+ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
+
+ drc_active = inst->sub_state & IRIS_INST_SUB_DRC &&
+ inst->sub_state & IRIS_INST_SUB_DRC_LAST;
+
+ if (drc_active)
+ clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
+ else if (drain_active)
+ clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
+
+ if (inst->domain == DECODER && inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+ ret = iris_alloc_and_queue_input_int_bufs(inst);
+ if (ret)
+ return ret;
+ ret = iris_set_stage(inst, STAGE);
+ if (ret)
+ return ret;
+ ret = iris_set_pipe(inst, PIPE);
+ if (ret)
+ return ret;
+ }
+
+ if (inst->state == IRIS_INST_INPUT_STREAMING &&
+ inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+ if (!drain_active)
+ ret = hfi_ops->session_resume_drc(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ else if (hfi_ops->session_resume_drain)
+ ret = hfi_ops->session_resume_drain(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
+ }
+
+ if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)
+ clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC;
+
+ ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ return ret;
+
+ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE)
+ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
+
+ ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ return ret;
+
+ inst->last_buffer_dequeued = false;
+
+ return iris_inst_change_sub_state(inst, clear_sub_state, 0);
+}
+
+static void iris_flush_deferred_buffers(struct iris_inst *inst,
+ enum iris_buffer_type type)
+{
+ struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
+ struct v4l2_m2m_buffer *buffer, *n;
+ struct iris_buffer *buf;
+
+ if (type == BUF_INPUT) {
+ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) {
+ buf = to_iris_buffer(&buffer->vb);
+ if (buf->attr & BUF_ATTR_DEFERRED) {
+ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) {
+ buf->attr |= BUF_ATTR_BUFFER_DONE;
+ buf->data_size = 0;
+ iris_vb2_buffer_done(inst, buf);
+ }
+ }
+ }
+ } else {
+ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) {
+ buf = to_iris_buffer(&buffer->vb);
+ if (buf->attr & BUF_ATTR_DEFERRED) {
+ if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) {
+ buf->attr |= BUF_ATTR_BUFFER_DONE;
+ buf->data_size = 0;
+ iris_vb2_buffer_done(inst, buf);
+ }
+ }
+ }
+ }
+}
+
+static void iris_kill_session(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+
+ if (!inst->session_id)
+ return;
+
+ hfi_ops->session_close(inst);
+ iris_inst_change_state(inst, IRIS_INST_ERROR);
+}
+
+int iris_session_streamoff(struct iris_inst *inst, u32 plane)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ enum iris_buffer_type buffer_type;
+ int ret;
+
+ switch (plane) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ buffer_type = BUF_INPUT;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ buffer_type = BUF_OUTPUT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = hfi_ops->session_stop(inst, plane);
+ if (ret)
+ goto error;
+
+ ret = iris_inst_state_change_streamoff(inst, plane);
+ if (ret)
+ goto error;
+
+ iris_flush_deferred_buffers(inst, buffer_type);
+
+ return 0;
+
+error:
+ iris_kill_session(inst);
+ iris_flush_deferred_buffers(inst, buffer_type);
+
+ return ret;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..f385eeb53910555f17602f3951e7a6e9636a9ba2
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_common.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __IRIS_COMMON_H__
+#define __IRIS_COMMON_H__
+
+struct iris_inst;
+struct iris_buffer;
+
+int iris_process_streamon_input(struct iris_inst *inst);
+int iris_process_streamon_output(struct iris_inst *inst);
+int iris_session_streamoff(struct iris_inst *inst, u32 plane);
+
+#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h
index 9e6aadb837830b46e4a68865583e28fc427cef0d..b51471fb32c70acee44c37f8e9dce0c6bc0b6ccc 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
@@ -102,7 +102,7 @@ enum hfi_matrix_coefficients {
struct iris_hfi_prop_type_handle {
u32 type;
- int (*handle)(struct iris_inst *inst);
+ int (*handle)(struct iris_inst *inst, u32 plane);
};
struct iris_hfi_command_ops {
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb..fead3318743a09ecdc363eda4cbf252f640eb6e0 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -189,48 +189,75 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane)
u32 flush_type = 0;
int ret = 0;
- if (((V4L2_TYPE_IS_OUTPUT(plane) &&
- inst->state == IRIS_INST_INPUT_STREAMING) ||
- (V4L2_TYPE_IS_CAPTURE(plane) &&
- inst->state == IRIS_INST_OUTPUT_STREAMING) ||
- inst->state == IRIS_INST_ERROR) &&
- inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
- reinit_completion(&inst->completion);
- iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP);
- ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
- if (!ret)
- ret = iris_wait_for_session_response(inst, false);
-
- reinit_completion(&inst->completion);
- iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_RELEASE_RESOURCES);
- ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
- if (!ret)
- ret = iris_wait_for_session_response(inst, false);
-
- iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0);
+ if (inst->domain == DECODER) {
+ if (((V4L2_TYPE_IS_OUTPUT(plane) &&
+ inst->state == IRIS_INST_INPUT_STREAMING) ||
+ (V4L2_TYPE_IS_CAPTURE(plane) &&
+ inst->state == IRIS_INST_OUTPUT_STREAMING) ||
+ inst->state == IRIS_INST_ERROR) &&
+ inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
+ reinit_completion(&inst->completion);
+ iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP);
+ ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
+ if (!ret)
+ ret = iris_wait_for_session_response(inst, false);
+
+ reinit_completion(&inst->completion);
+ iris_hfi_gen1_packet_session_cmd(inst, &pkt,
+ HFI_CMD_SESSION_RELEASE_RESOURCES);
+ ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
+ if (!ret)
+ ret = iris_wait_for_session_response(inst, false);
+
+ iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0);
+
+ iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ VB2_BUF_STATE_ERROR);
+ iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ VB2_BUF_STATE_ERROR);
+ } else if (inst->state == IRIS_INST_STREAMING) {
+ if (V4L2_TYPE_IS_OUTPUT(plane))
+ flush_type = HFI_FLUSH_ALL;
+ else if (V4L2_TYPE_IS_CAPTURE(plane))
+ flush_type = HFI_FLUSH_OUTPUT;
+
+ reinit_completion(&inst->flush_completion);
+
+ flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt);
+ flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH;
+ flush_pkt.shdr.session_id = inst->session_id;
+ flush_pkt.flush_type = flush_type;
+
+ ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size);
+ if (!ret) {
+ inst->flush_responses_pending++;
+ ret = iris_wait_for_session_response(inst, true);
+ }
+ }
+ } else {
+ if (inst->state == IRIS_INST_STREAMING ||
+ inst->state == IRIS_INST_INPUT_STREAMING ||
+ inst->state == IRIS_INST_ERROR) {
+ reinit_completion(&inst->completion);
+ iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP);
+ ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
+ if (!ret)
+ ret = iris_wait_for_session_response(inst, false);
+
+ reinit_completion(&inst->completion);
+ iris_hfi_gen1_packet_session_cmd(inst, &pkt,
+ HFI_CMD_SESSION_RELEASE_RESOURCES);
+ ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
+ if (!ret)
+ ret = iris_wait_for_session_response(inst, false);
+
+ iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0);
+ }
iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
VB2_BUF_STATE_ERROR);
iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
VB2_BUF_STATE_ERROR);
- } else if (inst->state == IRIS_INST_STREAMING) {
- if (V4L2_TYPE_IS_OUTPUT(plane))
- flush_type = HFI_FLUSH_ALL;
- else if (V4L2_TYPE_IS_CAPTURE(plane))
- flush_type = HFI_FLUSH_OUTPUT;
-
- reinit_completion(&inst->flush_completion);
-
- flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt);
- flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH;
- flush_pkt.shdr.session_id = inst->session_id;
- flush_pkt.flush_type = flush_type;
-
- ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size);
- if (!ret) {
- inst->flush_responses_pending++;
- ret = iris_wait_for_session_response(inst, true);
- }
}
return ret;
@@ -554,7 +581,7 @@ static int iris_hfi_gen1_session_set_property(struct iris_inst *inst, u32 packet
return hfi_gen1_set_property(inst, packet_type, payload, payload_size);
}
-static int iris_hfi_gen1_set_resolution(struct iris_inst *inst)
+static int iris_hfi_gen1_set_resolution(struct iris_inst *inst, u32 plane)
{
u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
struct hfi_framesize fs;
@@ -569,14 +596,18 @@ static int iris_hfi_gen1_set_resolution(struct iris_inst *inst)
if (ret)
return ret;
}
- fs.buffer_type = HFI_BUFFER_OUTPUT2;
+ if (inst->domain == DECODER)
+ fs.buffer_type = HFI_BUFFER_OUTPUT2;
+ else
+ fs.buffer_type = HFI_BUFFER_OUTPUT;
+
fs.width = inst->fmt_dst->fmt.pix_mp.width;
fs.height = inst->fmt_dst->fmt.pix_mp.height;
return hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs));
}
-static int iris_hfi_gen1_decide_core(struct iris_inst *inst)
+static int iris_hfi_gen1_decide_core(struct iris_inst *inst, u32 plane)
{
const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
struct hfi_videocores_usage_type cu;
@@ -586,36 +617,45 @@ static int iris_hfi_gen1_decide_core(struct iris_inst *inst)
return hfi_gen1_set_property(inst, ptype, &cu, sizeof(cu));
}
-static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst)
+static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst, u32 plane)
{
const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
- u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
struct hfi_uncompressed_format_select fmt;
+ u32 pixelformat;
int ret;
- if (iris_split_mode_enabled(inst)) {
- fmt.buffer_type = HFI_BUFFER_OUTPUT;
- fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12_UBWC : 0;
+ if (inst->domain == DECODER) {
+ pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
+ if (iris_split_mode_enabled(inst)) {
+ fmt.buffer_type = HFI_BUFFER_OUTPUT;
+ fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ?
+ HFI_COLOR_FORMAT_NV12_UBWC : 0;
- ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
- if (ret)
- return ret;
+ ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
+ if (ret)
+ return ret;
- fmt.buffer_type = HFI_BUFFER_OUTPUT2;
- fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;
+ fmt.buffer_type = HFI_BUFFER_OUTPUT2;
+ fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;
- ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
+ ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
+ } else {
+ fmt.buffer_type = HFI_BUFFER_OUTPUT;
+ fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;
+
+ ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
+ }
} else {
- fmt.buffer_type = HFI_BUFFER_OUTPUT;
+ pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat;
+ fmt.buffer_type = HFI_BUFFER_INPUT;
fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;
-
ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
}
return ret;
}
-static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst)
+static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst, u32 plane)
{
const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO;
struct hfi_uncompressed_plane_actual_constraints_info pconstraint;
@@ -635,7 +675,7 @@ static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst)
return hfi_gen1_set_property(inst, ptype, &pconstraint, sizeof(pconstraint));
}
-static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst)
+static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst, u32 plane)
{
u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
struct hfi_buffer_count_actual buf_count;
@@ -649,20 +689,28 @@ static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst)
if (ret)
return ret;
- if (iris_split_mode_enabled(inst)) {
- buf_count.type = HFI_BUFFER_OUTPUT;
- buf_count.count_actual = VIDEO_MAX_FRAME;
- buf_count.count_min_host = VIDEO_MAX_FRAME;
+ if (inst->domain == DECODER) {
+ if (iris_split_mode_enabled(inst)) {
+ buf_count.type = HFI_BUFFER_OUTPUT;
+ buf_count.count_actual = VIDEO_MAX_FRAME;
+ buf_count.count_min_host = VIDEO_MAX_FRAME;
- ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
- if (ret)
- return ret;
+ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
+ if (ret)
+ return ret;
- buf_count.type = HFI_BUFFER_OUTPUT2;
- buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB);
- buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB);
+ buf_count.type = HFI_BUFFER_OUTPUT2;
+ buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB);
+ buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB);
- ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
+ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
+ } else {
+ buf_count.type = HFI_BUFFER_OUTPUT;
+ buf_count.count_actual = VIDEO_MAX_FRAME;
+ buf_count.count_min_host = VIDEO_MAX_FRAME;
+
+ ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
+ }
} else {
buf_count.type = HFI_BUFFER_OUTPUT;
buf_count.count_actual = VIDEO_MAX_FRAME;
@@ -674,7 +722,7 @@ static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst)
return ret;
}
-static int iris_hfi_gen1_set_multistream(struct iris_inst *inst)
+static int iris_hfi_gen1_set_multistream(struct iris_inst *inst, u32 plane)
{
u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
struct hfi_multi_stream multi = {0};
@@ -709,7 +757,7 @@ static int iris_hfi_gen1_set_multistream(struct iris_inst *inst)
return ret;
}
-static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst)
+static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst, u32 plane)
{
const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
struct hfi_buffer_size_actual bufsz;
@@ -744,14 +792,49 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst)
return ret;
}
+static int iris_hfi_gen1_set_frame_rate(struct iris_inst *inst, u32 plane)
+{
+ const u32 ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
+ struct hfi_framerate frate;
+
+ if (V4L2_TYPE_IS_OUTPUT(plane))
+ return 0;
+
+ frate.buffer_type = HFI_BUFFER_OUTPUT;
+ frate.framerate = inst->frame_rate;
+
+ return hfi_gen1_set_property(inst, ptype, &frate, sizeof(frate));
+}
+
+static int iris_hfi_gen1_set_stride(struct iris_inst *inst, u32 plane)
+{
+ const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO;
+ struct hfi_uncompressed_plane_actual_info plane_actual_info;
+
+ plane_actual_info.buffer_type = HFI_BUFFER_INPUT;
+ plane_actual_info.num_planes = 2;
+ plane_actual_info.plane_format[0].actual_stride =
+ ALIGN(inst->fmt_src->fmt.pix_mp.width, 128);
+ plane_actual_info.plane_format[0].actual_plane_buffer_height =
+ ALIGN(inst->fmt_src->fmt.pix_mp.height, 32);
+ plane_actual_info.plane_format[1].actual_stride =
+ ALIGN(inst->fmt_src->fmt.pix_mp.width, 128);
+ plane_actual_info.plane_format[1].actual_plane_buffer_height =
+ (ALIGN(inst->fmt_src->fmt.pix_mp.height, 32)) / 2;
+
+ return hfi_gen1_set_property(inst, ptype, &plane_actual_info, sizeof(plane_actual_info));
+}
+
static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 plane)
{
+ struct iris_hfi_prop_type_handle const *handler = NULL;
+ u32 handler_size = 0;
struct iris_core *core = inst->core;
u32 config_params_size, i, j;
const u32 *config_params;
int ret;
- static const struct iris_hfi_prop_type_handle prop_type_handle_inp_arr[] = {
+ static const struct iris_hfi_prop_type_handle vdec_prop_type_handle_inp_arr[] = {
{HFI_PROPERTY_PARAM_FRAME_SIZE,
iris_hfi_gen1_set_resolution},
{HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE,
@@ -768,7 +851,7 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p
iris_hfi_gen1_set_bufsize},
};
- static const struct iris_hfi_prop_type_handle prop_type_handle_out_arr[] = {
+ static const struct iris_hfi_prop_type_handle vdec_prop_type_handle_out_arr[] = {
{HFI_PROPERTY_PARAM_FRAME_SIZE,
iris_hfi_gen1_set_resolution},
{HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT,
@@ -783,29 +866,43 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p
iris_hfi_gen1_set_bufsize},
};
- config_params = core->iris_platform_data->input_config_params_default;
- config_params_size = core->iris_platform_data->input_config_params_default_size;
-
- if (V4L2_TYPE_IS_OUTPUT(plane)) {
- for (i = 0; i < config_params_size; i++) {
- for (j = 0; j < ARRAY_SIZE(prop_type_handle_inp_arr); j++) {
- if (prop_type_handle_inp_arr[j].type == config_params[i]) {
- ret = prop_type_handle_inp_arr[j].handle(inst);
- if (ret)
- return ret;
- break;
- }
- }
+ static const struct iris_hfi_prop_type_handle venc_prop_type_handle_inp_arr[] = {
+ {HFI_PROPERTY_CONFIG_FRAME_RATE,
+ iris_hfi_gen1_set_frame_rate},
+ {HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO,
+ iris_hfi_gen1_set_stride},
+ {HFI_PROPERTY_PARAM_FRAME_SIZE,
+ iris_hfi_gen1_set_resolution},
+ {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT,
+ iris_hfi_gen1_set_raw_format},
+ {HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL,
+ iris_hfi_gen1_set_num_bufs},
+ };
+
+ if (inst->domain == DECODER) {
+ config_params = core->iris_platform_data->dec_input_config_params_default;
+ config_params_size = core->iris_platform_data->dec_input_config_params_default_size;
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ handler = vdec_prop_type_handle_inp_arr;
+ handler_size = ARRAY_SIZE(vdec_prop_type_handle_inp_arr);
+ } else if (V4L2_TYPE_IS_CAPTURE(plane)) {
+ handler = vdec_prop_type_handle_out_arr;
+ handler_size = ARRAY_SIZE(vdec_prop_type_handle_out_arr);
}
- } else if (V4L2_TYPE_IS_CAPTURE(plane)) {
- for (i = 0; i < config_params_size; i++) {
- for (j = 0; j < ARRAY_SIZE(prop_type_handle_out_arr); j++) {
- if (prop_type_handle_out_arr[j].type == config_params[i]) {
- ret = prop_type_handle_out_arr[j].handle(inst);
- if (ret)
- return ret;
- break;
- }
+ } else {
+ config_params = core->iris_platform_data->enc_input_config_params;
+ config_params_size = core->iris_platform_data->enc_input_config_params_size;
+ handler = venc_prop_type_handle_inp_arr;
+ handler_size = ARRAY_SIZE(venc_prop_type_handle_inp_arr);
+ }
+
+ for (i = 0; i < config_params_size; i++) {
+ for (j = 0; j < handler_size; j++) {
+ if (handler[j].type == config_params[i]) {
+ ret = handler[j].handle(inst, plane);
+ if (ret)
+ return ret;
+ break;
}
}
}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index a7f4379c5973fdc4366969139bef25472e8f11a5..81116420b6a3d86cca7229bdd3a875d95c1a7936 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -82,10 +82,12 @@
#define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6
#define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO 0x1002
#define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003
#define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT 0x1005
#define HFI_PROPERTY_PARAM_WORK_MODE 0x1015
#define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017
+#define HFI_PROPERTY_CONFIG_FRAME_RATE 0x2001
#define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002
#define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001
@@ -348,6 +350,17 @@ struct hfi_uncompressed_plane_actual_constraints_info {
struct hfi_uncompressed_plane_constraints plane_format[2];
};
+struct hfi_uncompressed_plane_actual {
+ int actual_stride;
+ u32 actual_plane_buffer_height;
+};
+
+struct hfi_uncompressed_plane_actual_info {
+ u32 buffer_type;
+ u32 num_planes;
+ struct hfi_uncompressed_plane_actual plane_format[2];
+};
+
struct hfi_buffer_count_actual {
u32 type;
u32 count_actual;
@@ -375,6 +388,11 @@ struct hfi_buffer_requirements {
u32 alignment;
};
+struct hfi_framerate {
+ u32 buffer_type;
+ u32 framerate;
+};
+
struct hfi_event_data {
u32 error;
u32 height;
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
index 7ca5ae13d62b95fdcf71ef70cb6abf446b2c6e5a..4cdceca3f8a05a6ec9ad76e7cbaa138daba0e958 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -88,15 +88,26 @@ static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core)
return ret;
}
-static u32 iris_hfi_gen2_get_port(u32 plane)
+static u32 iris_hfi_gen2_get_port(struct iris_inst *inst, u32 plane)
{
- switch (plane) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- return HFI_PORT_BITSTREAM;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- return HFI_PORT_RAW;
- default:
- return HFI_PORT_NONE;
+ if (inst->domain == DECODER) {
+ switch (plane) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return HFI_PORT_BITSTREAM;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ return HFI_PORT_RAW;
+ default:
+ return HFI_PORT_NONE;
+ }
+ } else {
+ switch (plane) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return HFI_PORT_RAW;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ return HFI_PORT_BITSTREAM;
+ default:
+ return HFI_PORT_NONE;
+ }
}
}
@@ -136,34 +147,76 @@ static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet
inst_hfi_gen2->packet->size);
}
-static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst)
+static int iris_hfi_gen2_set_raw_resolution(struct iris_inst *inst, u32 plane)
{
- struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
u32 resolution = inst->fmt_src->fmt.pix_mp.width << 16 |
inst->fmt_src->fmt.pix_mp.height;
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
- inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution;
+ return iris_hfi_gen2_session_set_property(inst,
+ HFI_PROP_RAW_RESOLUTION,
+ HFI_HOST_FLAGS_NONE,
+ port,
+ HFI_PAYLOAD_32_PACKED,
+ &resolution,
+ sizeof(u32));
+}
+
+static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst, u32 plane)
+{
+ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
+ enum hfi_packet_payload_info payload_type;
+ u32 resolution;
+
+ if (inst->domain == DECODER) {
+ resolution = inst->fmt_src->fmt.pix_mp.width << 16 |
+ inst->fmt_src->fmt.pix_mp.height;
+ inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution;
+ payload_type = HFI_PAYLOAD_U32;
+ } else {
+ resolution = inst->fmt_dst->fmt.pix_mp.width << 16 |
+ inst->fmt_dst->fmt.pix_mp.height;
+ inst_hfi_gen2->dst_subcr_params.bitstream_resolution = resolution;
+ payload_type = HFI_PAYLOAD_32_PACKED;
+ }
return iris_hfi_gen2_session_set_property(inst,
HFI_PROP_BITSTREAM_RESOLUTION,
HFI_HOST_FLAGS_NONE,
port,
- HFI_PAYLOAD_U32,
+ payload_type,
&resolution,
sizeof(u32));
}
-static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst)
+static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst, u32 plane)
{
- u32 bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height);
- u32 right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width);
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- u32 left_offset = inst->crop.left;
- u32 top_offset = inst->crop.top;
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
+ u32 bottom_offset, right_offset;
+ u32 left_offset, top_offset;
u32 payload[2];
+ if (inst->domain == DECODER) {
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height);
+ right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width);
+ left_offset = inst->crop.left;
+ top_offset = inst->crop.top;
+ } else {
+ bottom_offset = (inst->fmt_dst->fmt.pix_mp.height - inst->compose.height);
+ right_offset = (inst->fmt_dst->fmt.pix_mp.width - inst->compose.width);
+ left_offset = inst->compose.left;
+ top_offset = inst->compose.top;
+ }
+ } else {
+ bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height);
+ right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width);
+ left_offset = inst->crop.left;
+ top_offset = inst->crop.top;
+ }
+
payload[0] = FIELD_PREP(GENMASK(31, 16), left_offset) | top_offset;
payload[1] = FIELD_PREP(GENMASK(31, 16), right_offset) | bottom_offset;
inst_hfi_gen2->src_subcr_params.crop_offsets[0] = payload[0];
@@ -178,10 +231,10 @@ static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst)
sizeof(u64));
}
-static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst)
+static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
u32 bitdepth = BIT_DEPTH_8;
inst_hfi_gen2->src_subcr_params.bit_depth = bitdepth;
@@ -195,10 +248,10 @@ static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst)
+static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
u32 coded_frames = 0;
if (inst->fw_caps[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE)
@@ -214,11 +267,11 @@ static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst)
+static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
u32 min_output = inst->buffers[BUF_OUTPUT].min_count;
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
inst_hfi_gen2->src_subcr_params.fw_min_count = min_output;
@@ -231,10 +284,10 @@ static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst)
+static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
u32 poc = 0;
inst_hfi_gen2->src_subcr_params.pic_order_cnt = poc;
@@ -248,16 +301,16 @@ static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst)
+static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp;
u32 video_signal_type_present_flag = 0, color_info;
u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED;
u32 video_format = UNSPECIFIED_COLOR_FORMAT;
u32 full_range = V4L2_QUANTIZATION_DEFAULT;
u32 transfer_char = HFI_TRANSFER_RESERVED;
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
u32 colour_description_present_flag = 0;
u32 primaries = HFI_PRIMARIES_RESERVED;
@@ -291,10 +344,10 @@ static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_profile(struct iris_inst *inst)
+static int iris_hfi_gen2_set_profile(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
u32 profile = 0;
switch (inst->codec) {
@@ -320,10 +373,10 @@ static int iris_hfi_gen2_set_profile(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_level(struct iris_inst *inst)
+static int iris_hfi_gen2_set_level(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
u32 level = 0;
switch (inst->codec) {
@@ -349,33 +402,47 @@ static int iris_hfi_gen2_set_level(struct iris_inst *inst)
sizeof(u32));
}
-static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst)
+static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst, u32 plane)
{
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
u32 hfi_colorformat, pixelformat;
- pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
- hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;
+ if (inst->domain == DECODER) {
+ pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
+ hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;
+ } else {
+ pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat;
+ hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;
+ }
return iris_hfi_gen2_session_set_property(inst,
HFI_PROP_COLOR_FORMAT,
HFI_HOST_FLAGS_NONE,
port,
- HFI_PAYLOAD_U32,
+ HFI_PAYLOAD_U32_ENUM,
&hfi_colorformat,
sizeof(u32));
}
-static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst)
+static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst, u32 plane)
{
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
- u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
- u32 scanline_y = inst->fmt_dst->fmt.pix_mp.height;
- u32 stride_y = inst->fmt_dst->fmt.pix_mp.width;
- u32 scanline_uv = scanline_y / 2;
- u32 stride_uv = stride_y;
+ u32 pixelformat, stride_y, stride_uv, scanline_y, scanline_uv;
+ u32 port = iris_hfi_gen2_get_port(inst, plane);
u32 payload[2];
+ if (inst->domain == DECODER) {
+ pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
+ stride_y = inst->fmt_dst->fmt.pix_mp.width;
+ scanline_y = inst->fmt_dst->fmt.pix_mp.height;
+ } else {
+ pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat;
+ stride_y = ALIGN(inst->fmt_src->fmt.pix_mp.width, 128);
+ scanline_y = ALIGN(inst->fmt_src->fmt.pix_mp.height, 32);
+ }
+
+ stride_uv = stride_y;
+ scanline_uv = scanline_y / 2;
+
if (pixelformat != V4L2_PIX_FMT_NV12)
return 0;
@@ -386,15 +453,15 @@ static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst)
HFI_PROP_LINEAR_STRIDE_SCANLINE,
HFI_HOST_FLAGS_NONE,
port,
- HFI_PAYLOAD_U64,
+ HFI_PAYLOAD_64_PACKED,
&payload,
sizeof(u64));
}
-static int iris_hfi_gen2_set_tier(struct iris_inst *inst)
+static int iris_hfi_gen2_set_tier(struct iris_inst *inst, u32 plane)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
u32 tier = inst->fw_caps[TIER].value;
inst_hfi_gen2->src_subcr_params.tier = tier;
@@ -408,14 +475,28 @@ static int iris_hfi_gen2_set_tier(struct iris_inst *inst)
sizeof(u32));
}
+static int iris_hfi_gen2_set_frame_rate(struct iris_inst *inst, u32 plane)
+{
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+ return iris_hfi_gen2_session_set_property(inst,
+ HFI_PROP_FRAME_RATE,
+ HFI_HOST_FLAGS_NONE,
+ port,
+ HFI_PAYLOAD_Q16,
+ &inst->frame_rate,
+ sizeof(u32));
+}
+
static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane)
{
- struct iris_core *core = inst->core;
+ const struct iris_platform_data *pdata = inst->core->iris_platform_data;
u32 config_params_size = 0, i, j;
const u32 *config_params = NULL;
int ret;
static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = {
+ {HFI_PROP_RAW_RESOLUTION, iris_hfi_gen2_set_raw_resolution },
{HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution },
{HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets },
{HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames },
@@ -428,29 +509,35 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p
{HFI_PROP_COLOR_FORMAT, iris_hfi_gen2_set_colorformat },
{HFI_PROP_LINEAR_STRIDE_SCANLINE, iris_hfi_gen2_set_linear_stride_scanline },
{HFI_PROP_TIER, iris_hfi_gen2_set_tier },
+ {HFI_PROP_FRAME_RATE, iris_hfi_gen2_set_frame_rate },
};
- if (V4L2_TYPE_IS_OUTPUT(plane)) {
- switch (inst->codec) {
- case V4L2_PIX_FMT_H264:
- config_params = core->iris_platform_data->input_config_params_default;
- config_params_size =
- core->iris_platform_data->input_config_params_default_size;
- break;
- case V4L2_PIX_FMT_HEVC:
- config_params = core->iris_platform_data->input_config_params_hevc;
- config_params_size =
- core->iris_platform_data->input_config_params_hevc_size;
- break;
- case V4L2_PIX_FMT_VP9:
- config_params = core->iris_platform_data->input_config_params_vp9;
- config_params_size =
- core->iris_platform_data->input_config_params_vp9_size;
- break;
+ if (inst->domain == DECODER) {
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ config_params = pdata->dec_input_config_params_default;
+ config_params_size = pdata->dec_input_config_params_default_size;
+ } else if (inst->codec == V4L2_PIX_FMT_HEVC) {
+ config_params = pdata->dec_input_config_params_hevc;
+ config_params_size = pdata->dec_input_config_params_hevc_size;
+ } else if (inst->codec == V4L2_PIX_FMT_VP9) {
+ config_params = pdata->dec_input_config_params_vp9;
+ config_params_size = pdata->dec_input_config_params_vp9_size;
+ } else {
+ return -EINVAL;
+ }
+ } else {
+ config_params = pdata->dec_output_config_params;
+ config_params_size = pdata->dec_output_config_params_size;
}
} else {
- config_params = core->iris_platform_data->output_config_params;
- config_params_size = core->iris_platform_data->output_config_params_size;
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ config_params = pdata->enc_input_config_params;
+ config_params_size = pdata->enc_input_config_params_size;
+ } else {
+ config_params = pdata->enc_output_config_params;
+ config_params_size = pdata->enc_output_config_params_size;
+ }
}
if (!config_params || !config_params_size)
@@ -459,7 +546,7 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p
for (i = 0; i < config_params_size; i++) {
for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) {
if (prop_type_handle_arr[j].type == config_params[i]) {
- ret = prop_type_handle_arr[j].handle(inst);
+ ret = prop_type_handle_arr[j].handle(inst, plane);
if (ret)
return ret;
break;
@@ -477,14 +564,19 @@ static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
switch (inst->codec) {
case V4L2_PIX_FMT_H264:
- codec = HFI_CODEC_DECODE_AVC;
+ if (inst->domain == ENCODER)
+ codec = HFI_CODEC_ENCODE_AVC;
+ else
+ codec = HFI_CODEC_DECODE_AVC;
break;
case V4L2_PIX_FMT_HEVC:
- codec = HFI_CODEC_DECODE_HEVC;
+ if (inst->domain == ENCODER)
+ codec = HFI_CODEC_ENCODE_HEVC;
+ else
+ codec = HFI_CODEC_DECODE_HEVC;
break;
case V4L2_PIX_FMT_VP9:
codec = HFI_CODEC_DECODE_VP9;
- break;
}
iris_hfi_gen2_packet_session_property(inst,
@@ -550,9 +642,11 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst)
if (ret)
goto fail_free_packet;
- ret = iris_hfi_gen2_session_set_default_header(inst);
- if (ret)
- goto fail_free_packet;
+ if (inst->domain == DECODER) {
+ ret = iris_hfi_gen2_session_set_default_header(inst);
+ if (ret)
+ goto fail_free_packet;
+ }
return 0;
@@ -601,7 +695,7 @@ static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst,
cmd,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
payload_type,
payload,
@@ -623,6 +717,9 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan
u32 hfi_port = 0, i;
int ret;
+ if (inst->domain == ENCODER)
+ return 0;
+
if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) ||
(V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) {
dev_err(core->dev, "invalid plane\n");
@@ -631,19 +728,19 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan
switch (inst->codec) {
case V4L2_PIX_FMT_H264:
- change_param = core->iris_platform_data->input_config_params_default;
+ change_param = core->iris_platform_data->dec_input_config_params_default;
change_param_size =
- core->iris_platform_data->input_config_params_default_size;
+ core->iris_platform_data->dec_input_config_params_default_size;
break;
case V4L2_PIX_FMT_HEVC:
- change_param = core->iris_platform_data->input_config_params_hevc;
+ change_param = core->iris_platform_data->dec_input_config_params_hevc;
change_param_size =
- core->iris_platform_data->input_config_params_hevc_size;
+ core->iris_platform_data->dec_input_config_params_hevc_size;
break;
case V4L2_PIX_FMT_VP9:
- change_param = core->iris_platform_data->input_config_params_vp9;
+ change_param = core->iris_platform_data->dec_input_config_params_vp9;
change_param_size =
- core->iris_platform_data->input_config_params_vp9_size;
+ core->iris_platform_data->dec_input_config_params_vp9_size;
break;
}
@@ -664,7 +761,7 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan
if (V4L2_TYPE_IS_OUTPUT(plane)) {
inst_hfi_gen2->ipsc_properties_set = true;
} else {
- hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ hfi_port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
memcpy(&inst_hfi_gen2->dst_subcr_params,
&inst_hfi_gen2->src_subcr_params,
sizeof(inst_hfi_gen2->src_subcr_params));
@@ -759,6 +856,9 @@ static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane)
payload[0] = HFI_MODE_PROPERTY;
+ if (inst->domain == ENCODER)
+ return 0;
+
if (V4L2_TYPE_IS_OUTPUT(plane)) {
subscribe_prop_size = core->iris_platform_data->dec_input_prop_size;
subcribe_prop = core->iris_platform_data->dec_input_prop;
@@ -810,7 +910,7 @@ static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane)
HFI_CMD_START,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
HFI_PAYLOAD_NONE,
NULL,
@@ -832,7 +932,7 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane)
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED |
HFI_HOST_FLAGS_NON_DISCARDABLE),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
HFI_PAYLOAD_NONE,
NULL,
@@ -854,7 +954,7 @@ static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane)
HFI_CMD_PAUSE,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
HFI_PAYLOAD_NONE,
NULL,
@@ -873,7 +973,7 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane)
HFI_CMD_RESUME,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
HFI_PAYLOAD_U32,
&payload,
@@ -892,7 +992,7 @@ static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane)
HFI_CMD_RESUME,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
HFI_PAYLOAD_U32,
&payload,
@@ -914,7 +1014,7 @@ static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane)
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED |
HFI_HOST_FLAGS_NON_DISCARDABLE),
- iris_hfi_gen2_get_port(plane),
+ iris_hfi_gen2_get_port(inst, plane),
inst->session_id,
HFI_PAYLOAD_NONE,
NULL,
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
index fb6724d7f95ff8858aa9ba093fefb642e89de279..b3d1c966958e516d940a7795e5cbe2f8e8bada57 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -49,6 +49,7 @@
#define HFI_PROP_TIER 0x03000109
#define HFI_PROP_STAGE 0x0300010a
#define HFI_PROP_PIPE 0x0300010b
+#define HFI_PROP_FRAME_RATE 0x0300010c
#define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f
#define HFI_PROP_CODED_FRAMES 0x03000120
#define HFI_PROP_CABAC_SESSION 0x03000121
@@ -69,6 +70,8 @@
#define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168
#define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169
#define HFI_PROP_NO_OUTPUT 0x0300016a
+#define HFI_PROP_BUFFER_MARK 0x0300016c
+#define HFI_PROP_RAW_RESOLUTION 0x03000178
#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C
#define HFI_PROP_COMV_BUFFER_COUNT 0x03000193
#define HFI_PROP_END 0x03FFFFFF
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 6d6a8f3b38271d928d753dd180e6e9a991991d24..0064a90e0e111075341d389fef7adb8f6b46b46f 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -223,14 +223,18 @@ struct iris_platform_data {
u32 max_core_mbpf;
/* max number of macroblocks per second supported */
u32 max_core_mbps;
- const u32 *input_config_params_default;
- unsigned int input_config_params_default_size;
- const u32 *input_config_params_hevc;
- unsigned int input_config_params_hevc_size;
- const u32 *input_config_params_vp9;
- unsigned int input_config_params_vp9_size;
- const u32 *output_config_params;
- unsigned int output_config_params_size;
+ const u32 *dec_input_config_params_default;
+ unsigned int dec_input_config_params_default_size;
+ const u32 *dec_input_config_params_hevc;
+ unsigned int dec_input_config_params_hevc_size;
+ const u32 *dec_input_config_params_vp9;
+ unsigned int dec_input_config_params_vp9_size;
+ const u32 *dec_output_config_params;
+ unsigned int dec_output_config_params_size;
+ const u32 *enc_input_config_params;
+ unsigned int enc_input_config_params_size;
+ const u32 *enc_output_config_params;
+ unsigned int enc_output_config_params_size;
const u32 *dec_input_prop;
unsigned int dec_input_prop_size;
const u32 *dec_output_prop_avc;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index 1bf289d322c86a8f8c03c80697c08af5d9067769..e36c5609507504cb79ef6a16decada062335aaf1 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -656,11 +656,25 @@ static const u32 sm8550_vdec_input_config_param_vp9[] = {
HFI_PROP_LEVEL,
};
+static const u32 sm8550_venc_input_config_params[] = {
+ HFI_PROP_COLOR_FORMAT,
+ HFI_PROP_RAW_RESOLUTION,
+ HFI_PROP_CROP_OFFSETS,
+ HFI_PROP_LINEAR_STRIDE_SCANLINE,
+ HFI_PROP_SIGNAL_COLOR_INFO,
+};
+
static const u32 sm8550_vdec_output_config_params[] = {
HFI_PROP_COLOR_FORMAT,
HFI_PROP_LINEAR_STRIDE_SCANLINE,
};
+static const u32 sm8550_venc_output_config_params[] = {
+ HFI_PROP_BITSTREAM_RESOLUTION,
+ HFI_PROP_CROP_OFFSETS,
+ HFI_PROP_FRAME_RATE,
+};
+
static const u32 sm8550_vdec_subscribe_input_properties[] = {
HFI_PROP_NO_OUTPUT,
};
@@ -724,22 +738,32 @@ struct iris_platform_data sm8550_data = {
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
- .input_config_params_default =
+ .dec_input_config_params_default =
sm8550_vdec_input_config_params_default,
- .input_config_params_default_size =
+ .dec_input_config_params_default_size =
ARRAY_SIZE(sm8550_vdec_input_config_params_default),
- .input_config_params_hevc =
+ .dec_input_config_params_hevc =
sm8550_vdec_input_config_param_hevc,
- .input_config_params_hevc_size =
+ .dec_input_config_params_hevc_size =
ARRAY_SIZE(sm8550_vdec_input_config_param_hevc),
- .input_config_params_vp9 =
+ .dec_input_config_params_vp9 =
sm8550_vdec_input_config_param_vp9,
- .input_config_params_vp9_size =
+ .dec_input_config_params_vp9_size =
ARRAY_SIZE(sm8550_vdec_input_config_param_vp9),
- .output_config_params =
+ .dec_output_config_params =
sm8550_vdec_output_config_params,
- .output_config_params_size =
+ .dec_output_config_params_size =
ARRAY_SIZE(sm8550_vdec_output_config_params),
+
+ .enc_input_config_params =
+ sm8550_venc_input_config_params,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8550_venc_input_config_params),
+ .enc_output_config_params =
+ sm8550_venc_output_config_params,
+ .enc_output_config_params_size =
+ ARRAY_SIZE(sm8550_venc_output_config_params),
+
.dec_input_prop = sm8550_vdec_subscribe_input_properties,
.dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties),
.dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc,
@@ -802,22 +826,32 @@ struct iris_platform_data sm8650_data = {
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
- .input_config_params_default =
+ .dec_input_config_params_default =
sm8550_vdec_input_config_params_default,
- .input_config_params_default_size =
+ .dec_input_config_params_default_size =
ARRAY_SIZE(sm8550_vdec_input_config_params_default),
- .input_config_params_hevc =
+ .dec_input_config_params_hevc =
sm8550_vdec_input_config_param_hevc,
- .input_config_params_hevc_size =
+ .dec_input_config_params_hevc_size =
ARRAY_SIZE(sm8550_vdec_input_config_param_hevc),
- .input_config_params_vp9 =
+ .dec_input_config_params_vp9 =
sm8550_vdec_input_config_param_vp9,
- .input_config_params_vp9_size =
+ .dec_input_config_params_vp9_size =
ARRAY_SIZE(sm8550_vdec_input_config_param_vp9),
- .output_config_params =
+ .dec_output_config_params =
sm8550_vdec_output_config_params,
- .output_config_params_size =
+ .dec_output_config_params_size =
ARRAY_SIZE(sm8550_vdec_output_config_params),
+
+ .enc_input_config_params =
+ sm8550_venc_input_config_params,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8550_venc_input_config_params),
+ .enc_output_config_params =
+ sm8550_venc_output_config_params,
+ .enc_output_config_params_size =
+ ARRAY_SIZE(sm8550_venc_output_config_params),
+
.dec_input_prop = sm8550_vdec_subscribe_input_properties,
.dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties),
.dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc,
@@ -876,22 +910,32 @@ struct iris_platform_data qcs8300_data = {
.max_session_count = 16,
.max_core_mbpf = ((4096 * 2176) / 256) * 4,
.max_core_mbps = (((3840 * 2176) / 256) * 120),
- .input_config_params_default =
+ .dec_input_config_params_default =
sm8550_vdec_input_config_params_default,
- .input_config_params_default_size =
+ .dec_input_config_params_default_size =
ARRAY_SIZE(sm8550_vdec_input_config_params_default),
- .input_config_params_hevc =
+ .dec_input_config_params_hevc =
sm8550_vdec_input_config_param_hevc,
- .input_config_params_hevc_size =
+ .dec_input_config_params_hevc_size =
ARRAY_SIZE(sm8550_vdec_input_config_param_hevc),
- .input_config_params_vp9 =
+ .dec_input_config_params_vp9 =
sm8550_vdec_input_config_param_vp9,
- .input_config_params_vp9_size =
+ .dec_input_config_params_vp9_size =
ARRAY_SIZE(sm8550_vdec_input_config_param_vp9),
- .output_config_params =
+ .dec_output_config_params =
sm8550_vdec_output_config_params,
- .output_config_params_size =
+ .dec_output_config_params_size =
ARRAY_SIZE(sm8550_vdec_output_config_params),
+
+ .enc_input_config_params =
+ sm8550_venc_input_config_params,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8550_venc_input_config_params),
+ .enc_output_config_params =
+ sm8550_venc_output_config_params,
+ .enc_output_config_params_size =
+ ARRAY_SIZE(sm8550_venc_output_config_params),
+
.dec_input_prop = sm8550_vdec_subscribe_input_properties,
.dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties),
.dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc,
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index b1ed6a140980ab6ca27f372f6f5851569a93ceed..90788b78802a589cbd9a25e95ee7766d3a3bb87f 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -38,6 +38,14 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = {
};
static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE,
+ },
{
.cap_id = PROFILE_H264,
.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
@@ -268,6 +276,14 @@ static const u32 sm8250_vdec_input_config_param_default[] = {
HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE,
};
+static const u32 sm8250_venc_input_config_param[] = {
+ HFI_PROPERTY_CONFIG_FRAME_RATE,
+ HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO,
+ HFI_PROPERTY_PARAM_FRAME_SIZE,
+ HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT,
+ HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL,
+};
+
static const u32 sm8250_dec_ip_int_buf_tbl[] = {
BUF_BIN,
BUF_SCRATCH_1,
@@ -310,10 +326,13 @@ struct iris_platform_data sm8250_data = {
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
- .input_config_params_default =
+ .dec_input_config_params_default =
sm8250_vdec_input_config_param_default,
- .input_config_params_default_size =
+ .dec_input_config_params_default_size =
ARRAY_SIZE(sm8250_vdec_input_config_param_default),
+ .enc_input_config_params = sm8250_venc_input_config_param,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8250_venc_input_config_param),
.dec_ip_int_buf_tbl = sm8250_dec_ip_int_buf_tbl,
.dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_ip_int_buf_tbl),
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index e32f7e1f007228a3b2b51cd76cd193d852f16080..fbf8ebb74193284dc847c54f76f908656b3098c9 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -7,9 +7,11 @@
#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
+#include "iris_common.h"
#include "iris_instance.h"
#include "iris_vb2.h"
#include "iris_vdec.h"
+#include "iris_venc.h"
#include "iris_power.h"
static int iris_check_inst_mbpf(struct iris_inst *inst)
@@ -174,19 +176,35 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
if (ret)
goto error;
- if (V4L2_TYPE_IS_OUTPUT(q->type))
- ret = iris_vdec_streamon_input(inst);
- else if (V4L2_TYPE_IS_CAPTURE(q->type))
- ret = iris_vdec_streamon_output(inst);
+ if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+ if (inst->domain == DECODER)
+ ret = iris_vdec_streamon_input(inst);
+ else
+ ret = iris_venc_streamon_input(inst);
+ } else if (V4L2_TYPE_IS_CAPTURE(q->type)) {
+ if (inst->domain == DECODER)
+ ret = iris_vdec_streamon_output(inst);
+ else
+ ret = iris_venc_streamon_output(inst);
+ }
if (ret)
goto error;
buf_type = iris_v4l2_type_to_driver(q->type);
- if (inst->state == IRIS_INST_STREAMING)
- ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB);
- if (!ret)
- ret = iris_queue_deferred_buffers(inst, buf_type);
+ if (inst->domain == DECODER) {
+ if (inst->state == IRIS_INST_STREAMING)
+ ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB);
+ if (!ret)
+ ret = iris_queue_deferred_buffers(inst, buf_type);
+ } else {
+ if (inst->state == IRIS_INST_STREAMING) {
+ ret = iris_queue_deferred_buffers(inst, BUF_INPUT);
+ if (!ret)
+ ret = iris_queue_deferred_buffers(inst, BUF_OUTPUT);
+ }
+ }
+
if (ret)
goto error;
@@ -218,7 +236,7 @@ void iris_vb2_stop_streaming(struct vb2_queue *q)
!V4L2_TYPE_IS_CAPTURE(q->type))
goto exit;
- ret = iris_vdec_session_streamoff(inst, q->type);
+ ret = iris_session_streamoff(inst, q->type);
if (ret)
goto exit;
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index fcefd7c36335efd4154159d8a7fab31fae33a2fe..81ef8254c914c9b0980e3c1537a44f57328e5789 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -7,6 +7,7 @@
#include <media/v4l2-mem2mem.h>
#include "iris_buffer.h"
+#include "iris_common.h"
#include "iris_ctrls.h"
#include "iris_instance.h"
#include "iris_power.h"
@@ -312,125 +313,6 @@ void iris_vdec_src_change(struct iris_inst *inst)
v4l2_event_queue_fh(&inst->fh, &event);
}
-
-static void iris_vdec_flush_deferred_buffers(struct iris_inst *inst,
- enum iris_buffer_type type)
-{
- struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
- struct v4l2_m2m_buffer *buffer, *n;
- struct iris_buffer *buf;
-
- if (type == BUF_INPUT) {
- v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) {
- buf = to_iris_buffer(&buffer->vb);
- if (buf->attr & BUF_ATTR_DEFERRED) {
- if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) {
- buf->attr |= BUF_ATTR_BUFFER_DONE;
- buf->data_size = 0;
- iris_vb2_buffer_done(inst, buf);
- }
- }
- }
- } else {
- v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) {
- buf = to_iris_buffer(&buffer->vb);
- if (buf->attr & BUF_ATTR_DEFERRED) {
- if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) {
- buf->attr |= BUF_ATTR_BUFFER_DONE;
- buf->data_size = 0;
- iris_vb2_buffer_done(inst, buf);
- }
- }
- }
- }
-}
-
-static void iris_vdec_kill_session(struct iris_inst *inst)
-{
- const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
-
- if (!inst->session_id)
- return;
-
- hfi_ops->session_close(inst);
- iris_inst_change_state(inst, IRIS_INST_ERROR);
-}
-
-int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane)
-{
- const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
- enum iris_buffer_type buffer_type;
- int ret;
-
- switch (plane) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- buffer_type = BUF_INPUT;
- break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- buffer_type = BUF_OUTPUT;
- break;
- default:
- return -EINVAL;
- }
-
- ret = hfi_ops->session_stop(inst, plane);
- if (ret)
- goto error;
-
- ret = iris_inst_state_change_streamoff(inst, plane);
- if (ret)
- goto error;
-
- iris_vdec_flush_deferred_buffers(inst, buffer_type);
-
- return 0;
-
-error:
- iris_vdec_kill_session(inst);
- iris_vdec_flush_deferred_buffers(inst, buffer_type);
-
- return ret;
-}
-
-static int iris_vdec_process_streamon_input(struct iris_inst *inst)
-{
- const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
- enum iris_inst_sub_state set_sub_state = 0;
- int ret;
-
- iris_scale_power(inst);
-
- ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- if (ret)
- return ret;
-
- if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
- ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0);
- if (ret)
- return ret;
- }
-
- if (inst->sub_state & IRIS_INST_SUB_DRC ||
- inst->sub_state & IRIS_INST_SUB_DRAIN ||
- inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) {
- if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
- if (hfi_ops->session_pause) {
- ret = hfi_ops->session_pause(inst,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- if (ret)
- return ret;
- }
- set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
- }
- }
-
- ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- if (ret)
- return ret;
-
- return iris_inst_change_sub_state(inst, 0, set_sub_state);
-}
-
int iris_vdec_streamon_input(struct iris_inst *inst)
{
int ret;
@@ -457,71 +339,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst)
if (ret)
return ret;
- return iris_vdec_process_streamon_input(inst);
-}
-
-static int iris_vdec_process_streamon_output(struct iris_inst *inst)
-{
- const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
- bool drain_active = false, drc_active = false;
- enum iris_inst_sub_state clear_sub_state = 0;
- int ret = 0;
-
- iris_scale_power(inst);
-
- drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN &&
- inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
-
- drc_active = inst->sub_state & IRIS_INST_SUB_DRC &&
- inst->sub_state & IRIS_INST_SUB_DRC_LAST;
-
- if (drc_active)
- clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
- else if (drain_active)
- clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
-
- if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
- ret = iris_alloc_and_queue_input_int_bufs(inst);
- if (ret)
- return ret;
- ret = iris_set_stage(inst, STAGE);
- if (ret)
- return ret;
- ret = iris_set_pipe(inst, PIPE);
- if (ret)
- return ret;
- }
-
- if (inst->state == IRIS_INST_INPUT_STREAMING &&
- inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
- if (!drain_active)
- ret = hfi_ops->session_resume_drc(inst,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- else if (hfi_ops->session_resume_drain)
- ret = hfi_ops->session_resume_drain(inst,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- if (ret)
- return ret;
- clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
- }
-
- if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)
- clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC;
-
- ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
- if (ret)
- return ret;
-
- if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE)
- clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
-
- ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
- if (ret)
- return ret;
-
- inst->last_buffer_dequeued = false;
-
- return iris_inst_change_sub_state(inst, clear_sub_state, 0);
+ return iris_process_streamon_input(inst);
}
int iris_vdec_streamon_output(struct iris_inst *inst)
@@ -543,7 +361,7 @@ int iris_vdec_streamon_output(struct iris_inst *inst)
if (ret)
return ret;
- ret = iris_vdec_process_streamon_output(inst);
+ ret = iris_process_streamon_output(inst);
if (ret)
goto error;
@@ -554,7 +372,7 @@ int iris_vdec_streamon_output(struct iris_inst *inst)
return ret;
error:
- iris_vdec_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
return ret;
}
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
index 097e02bfa72b5ac4e46e66c61842df1d9dd4565b..ec1ce55d1375fd6518983baae2acf0fc43b6cabd 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/iris/iris_vdec.h
@@ -21,6 +21,5 @@ int iris_vdec_streamon_output(struct iris_inst *inst);
int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);
int iris_vdec_start_cmd(struct iris_inst *inst);
int iris_vdec_stop_cmd(struct iris_inst *inst);
-int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 4630ba12349a62a37515e93ed5efa2df197bce17..4b0da51e0477ab00019396242be9fd585c11ded3 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -7,6 +7,7 @@
#include <media/v4l2-mem2mem.h>
#include "iris_buffer.h"
+#include "iris_common.h"
#include "iris_ctrls.h"
#include "iris_instance.h"
#include "iris_venc.h"
@@ -425,3 +426,34 @@ int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
return 0;
}
+
+int iris_venc_streamon_input(struct iris_inst *inst)
+{
+ int ret;
+
+ ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ return iris_process_streamon_input(inst);
+}
+
+int iris_venc_streamon_output(struct iris_inst *inst)
+{
+ int ret;
+
+ ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ goto error;
+
+ ret = iris_process_streamon_output(inst);
+ if (ret)
+ goto error;
+
+ return ret;
+
+error:
+ iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+ return ret;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index 0d566b7fc89b96b8fbc62a35b2ba795ca0bcf460..941b5c186e4550e3eb6325d5ae3eeac4fcee4675 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -18,5 +18,7 @@ int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_su
int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
+int iris_venc_streamon_input(struct iris_inst *inst);
+int iris_venc_streamon_output(struct iris_inst *inst);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 4c11cdac19f97d08a9e6242eea74649aad0242cf..be8688140fd22ffd02e8c286bfc5f62e050ceb5b 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -658,6 +658,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_s_selection = iris_s_selection,
.vidioc_s_parm = iris_s_parm,
.vidioc_g_parm = iris_g_parm,
+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 21/24] media: iris: Set platform capabilities to firmware for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (19 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 20/24] media: iris: Add V4L2 streaming support " Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 22/24] media: iris: Allocate and queue internal buffers " Dikshita Agarwal
` (3 subsequent siblings)
24 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Initialize and configure platform-specific capabilities for the encoder
in the firmware during stream-on, to tailor encoding behavior to the
current session's requirements. Some of these capabilities can also be
updated dynamically when V4L2 controls are modified by the client after
stream-on.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_buffer.c | 8 +
drivers/media/platform/qcom/iris/iris_ctrls.c | 500 ++++++++++++++++++++-
drivers/media/platform/qcom/iris/iris_ctrls.h | 15 +
.../platform/qcom/iris/iris_hfi_gen1_command.c | 108 +++++
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 47 +-
.../platform/qcom/iris/iris_hfi_gen1_response.c | 8 +-
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 32 +-
.../platform/qcom/iris/iris_hfi_gen2_response.c | 9 +-
drivers/media/platform/qcom/iris/iris_instance.h | 3 +-
.../media/platform/qcom/iris/iris_platform_gen2.c | 23 +
.../platform/qcom/iris/iris_platform_sm8250.c | 14 +
11 files changed, 737 insertions(+), 30 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 6bf9b0b35d206d51b927c824d5a5b327596251c6..8811174bfdc0ad5288aa4eb5fab9d9df876c78c9 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -227,10 +227,14 @@ static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
{
u32 aligned_width, aligned_height, bitstream_size, yuv_size;
+ int bitrate_mode, frame_rc;
struct v4l2_format *f;
f = inst->fmt_dst;
+ bitrate_mode = inst->fw_caps[BITRATE_MODE].value;
+ frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value;
+
aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
bitstream_size = aligned_width * aligned_height * 3;
@@ -242,6 +246,10 @@ static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
/* bitstream_size = 0.5 * yuv_size; */
bitstream_size = (bitstream_size >> 2);
+ if ((!frame_rc || bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) &&
+ bitstream_size < yuv_size)
+ bitstream_size = (bitstream_size << 1);
+
return ALIGN(bitstream_size, 4096);
}
diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
index 797386cb96ab1d24be6cc1819e2f9202ab4cc224..754a5ad718bc37630bb861012301df7a2e7342a1 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
@@ -7,8 +7,13 @@
#include <media/v4l2-mem2mem.h>
#include "iris_ctrls.h"
+#include "iris_hfi_gen1_defines.h"
+#include "iris_hfi_gen2_defines.h"
#include "iris_instance.h"
+#define CABAC_MAX_BITRATE 160000000
+#define CAVLC_MAX_BITRATE 220000000
+
static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id)
{
return cap_id >= 1 && cap_id < INST_FW_CAP_MAX;
@@ -185,7 +190,7 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)
}
}
-static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+static int iris_op_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct iris_inst *inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler);
enum platform_inst_fw_cap_type cap_id;
@@ -206,11 +211,16 @@ static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
inst->fw_caps[cap_id].value = ctrl->val;
+ if (vb2_is_streaming(q)) {
+ if (cap[cap_id].set)
+ cap[cap_id].set(inst, cap_id);
+ }
+
return 0;
}
static const struct v4l2_ctrl_ops iris_ctrl_ops = {
- .s_ctrl = iris_vdec_op_s_ctrl,
+ .s_ctrl = iris_op_s_ctrl,
};
int iris_ctrls_init(struct iris_inst *inst)
@@ -327,16 +337,24 @@ void iris_session_init_caps(struct iris_core *core)
core->inst_fw_caps_enc[cap_id].value = caps[i].value;
core->inst_fw_caps_enc[cap_id].flags = caps[i].flags;
core->inst_fw_caps_enc[cap_id].hfi_id = caps[i].hfi_id;
+ core->inst_fw_caps_enc[cap_id].set = caps[i].set;
}
}
static u32 iris_get_port_info(struct iris_inst *inst,
enum platform_inst_fw_cap_type cap_id)
{
- if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT)
- return HFI_PORT_BITSTREAM;
- else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT)
- return HFI_PORT_RAW;
+ if (inst->domain == DECODER) {
+ if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT)
+ return HFI_PORT_BITSTREAM;
+ else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT)
+ return HFI_PORT_RAW;
+ } else {
+ if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT)
+ return HFI_PORT_RAW;
+ else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT)
+ return HFI_PORT_BITSTREAM;
+ }
return HFI_PORT_NONE;
}
@@ -376,8 +394,10 @@ int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id
u32 width = inp_f->fmt.pix_mp.width;
u32 work_mode = STAGE_2;
- if (iris_res_is_less_than(width, height, 1280, 720))
- work_mode = STAGE_1;
+ if (inst->domain == DECODER) {
+ if (iris_res_is_less_than(width, height, 1280, 720))
+ work_mode = STAGE_1;
+ }
return hfi_ops->session_set_property(inst, hfi_id,
HFI_HOST_FLAGS_NONE,
@@ -399,6 +419,470 @@ int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
&work_route, sizeof(u32));
}
+int iris_set_profile(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 hfi_id, hfi_value;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ hfi_id = inst->fw_caps[PROFILE_H264].hfi_id;
+ hfi_value = inst->fw_caps[PROFILE_H264].value;
+ } else {
+ hfi_id = inst->fw_caps[PROFILE_HEVC].hfi_id;
+ hfi_value = inst->fw_caps[PROFILE_HEVC].value;
+ }
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32_ENUM,
+ &hfi_value, sizeof(u32));
+}
+
+int iris_set_level(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 hfi_id, hfi_value;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ hfi_id = inst->fw_caps[LEVEL_H264].hfi_id;
+ hfi_value = inst->fw_caps[LEVEL_H264].value;
+ } else {
+ hfi_id = inst->fw_caps[LEVEL_HEVC].hfi_id;
+ hfi_value = inst->fw_caps[LEVEL_HEVC].value;
+ }
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32_ENUM,
+ &hfi_value, sizeof(u32));
+}
+
+int iris_set_profile_level_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ struct hfi_profile_level pl;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ pl.profile = inst->fw_caps[PROFILE_H264].value;
+ pl.level = inst->fw_caps[LEVEL_H264].value;
+ } else {
+ pl.profile = inst->fw_caps[PROFILE_HEVC].value;
+ pl.level = inst->fw_caps[LEVEL_HEVC].value;
+ }
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32_ENUM,
+ &pl, sizeof(u32));
+}
+
+int iris_set_header_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 header_mode = inst->fw_caps[cap_id].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 hfi_val;
+
+ if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)
+ hfi_val = 0;
+ else
+ hfi_val = 1;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32,
+ &hfi_val, sizeof(u32));
+}
+
+int iris_set_header_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 prepend_sps_pps = inst->fw_caps[PREPEND_SPSPPS_TO_IDR].value;
+ u32 header_mode = inst->fw_caps[cap_id].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 hfi_val;
+
+ if (prepend_sps_pps)
+ hfi_val = HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME;
+ else if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME)
+ hfi_val = HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME;
+ else
+ hfi_val = HFI_SEQ_HEADER_SEPERATE_FRAME;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32_ENUM,
+ &hfi_val, sizeof(u32));
+}
+
+int iris_set_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 entropy_mode = inst->fw_caps[ENTROPY_MODE].value;
+ u32 bitrate = inst->fw_caps[cap_id].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 max_bitrate;
+
+ if (inst->codec == V4L2_PIX_FMT_HEVC)
+ max_bitrate = CABAC_MAX_BITRATE;
+
+ if (entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
+ max_bitrate = CABAC_MAX_BITRATE;
+ else
+ max_bitrate = CAVLC_MAX_BITRATE;
+
+ bitrate = min(bitrate, max_bitrate);
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32,
+ &bitrate, sizeof(u32));
+}
+
+int iris_set_peak_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 rc_mode = inst->fw_caps[BITRATE_MODE].value;
+ u32 peak_bitrate = inst->fw_caps[cap_id].value;
+ u32 bitrate = inst->fw_caps[BITRATE].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+
+ if (rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+ return 0;
+
+ if (inst->fw_caps[cap_id].flags & CAP_FLAG_CLIENT_SET) {
+ if (peak_bitrate < bitrate)
+ peak_bitrate = bitrate;
+ } else {
+ peak_bitrate = bitrate;
+ }
+
+ inst->fw_caps[cap_id].value = peak_bitrate;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32,
+ &peak_bitrate, sizeof(u32));
+}
+
+int iris_set_bitrate_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 bitrate_mode = inst->fw_caps[BITRATE_MODE].value;
+ u32 frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value;
+ u32 frame_skip = inst->fw_caps[FRAME_SKIP_MODE].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 rc_mode = 0;
+
+ if (!frame_rc)
+ rc_mode = HFI_RATE_CONTROL_OFF;
+ else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
+ rc_mode = frame_skip ? HFI_RATE_CONTROL_VBR_VFR : HFI_RATE_CONTROL_VBR_CFR;
+ else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+ rc_mode = frame_skip ? HFI_RATE_CONTROL_CBR_VFR : HFI_RATE_CONTROL_CBR_CFR;
+ else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
+ rc_mode = HFI_RATE_CONTROL_CQ;
+
+ inst->hfi_rc_type = rc_mode;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32_ENUM,
+ &rc_mode, sizeof(u32));
+}
+
+int iris_set_bitrate_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 bitrate_mode = inst->fw_caps[BITRATE_MODE].value;
+ u32 frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value;
+ u32 frame_skip = inst->fw_caps[FRAME_SKIP_MODE].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 rc_mode = 0;
+
+ if (!frame_rc)
+ rc_mode = HFI_RC_OFF;
+ else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
+ rc_mode = HFI_RC_VBR_CFR;
+ else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+ rc_mode = frame_skip ? HFI_RC_CBR_VFR : HFI_RC_CBR_CFR;
+ else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
+ rc_mode = HFI_RC_CQ;
+
+ inst->hfi_rc_type = rc_mode;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32_ENUM,
+ &rc_mode, sizeof(u32));
+}
+
+int iris_set_entropy_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 entropy_mode = inst->fw_caps[cap_id].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 hfi_val;
+
+ if (inst->codec != V4L2_PIX_FMT_H264)
+ return 0;
+
+ hfi_val = (entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) ?
+ HFI_H264_ENTROPY_CAVLC : HFI_H264_ENTROPY_CABAC;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32,
+ &hfi_val, sizeof(u32));
+}
+
+int iris_set_entropy_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 entropy_mode = inst->fw_caps[cap_id].value;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 profile;
+
+ if (inst->codec != V4L2_PIX_FMT_H264)
+ return 0;
+
+ profile = inst->fw_caps[PROFILE_H264].value;
+
+ if (profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE ||
+ profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE)
+ entropy_mode = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
+
+ inst->fw_caps[cap_id].value = entropy_mode;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32,
+ &entropy_mode, sizeof(u32));
+}
+
+int iris_set_min_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0;
+ u32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0;
+ u32 min_qp_enable = 0, client_qp_enable = 0;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 hfi_val;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ if (inst->fw_caps[MIN_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET)
+ min_qp_enable = 1;
+ if (min_qp_enable ||
+ (inst->fw_caps[I_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET))
+ i_qp_enable = 1;
+ if (min_qp_enable ||
+ (inst->fw_caps[P_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET))
+ p_qp_enable = 1;
+ if (min_qp_enable ||
+ (inst->fw_caps[B_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET))
+ b_qp_enable = 1;
+ } else {
+ if (inst->fw_caps[MIN_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)
+ min_qp_enable = 1;
+ if (min_qp_enable ||
+ (inst->fw_caps[I_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET))
+ i_qp_enable = 1;
+ if (min_qp_enable ||
+ (inst->fw_caps[P_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET))
+ p_qp_enable = 1;
+ if (min_qp_enable ||
+ (inst->fw_caps[B_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET))
+ b_qp_enable = 1;
+ }
+
+ client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2;
+ if (!client_qp_enable)
+ return 0;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ i_frame_qp = max(inst->fw_caps[I_FRAME_MIN_QP_H264].value,
+ inst->fw_caps[MIN_FRAME_QP_H264].value);
+ p_frame_qp = max(inst->fw_caps[P_FRAME_MIN_QP_H264].value,
+ inst->fw_caps[MIN_FRAME_QP_H264].value);
+ b_frame_qp = max(inst->fw_caps[B_FRAME_MIN_QP_H264].value,
+ inst->fw_caps[MIN_FRAME_QP_H264].value);
+ } else {
+ i_frame_qp = max(inst->fw_caps[I_FRAME_MIN_QP_HEVC].value,
+ inst->fw_caps[MIN_FRAME_QP_HEVC].value);
+ p_frame_qp = max(inst->fw_caps[P_FRAME_MIN_QP_HEVC].value,
+ inst->fw_caps[MIN_FRAME_QP_HEVC].value);
+ b_frame_qp = max(inst->fw_caps[B_FRAME_MIN_QP_HEVC].value,
+ inst->fw_caps[MIN_FRAME_QP_HEVC].value);
+ }
+
+ hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | client_qp_enable << 24;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_32_PACKED,
+ &hfi_val, sizeof(u32));
+}
+
+int iris_set_max_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0;
+ u32 max_qp_enable = 0, client_qp_enable;
+ u32 i_frame_qp, p_frame_qp, b_frame_qp;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ u32 hfi_val;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ if (inst->fw_caps[MAX_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET)
+ max_qp_enable = 1;
+ if (max_qp_enable ||
+ (inst->fw_caps[I_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET))
+ i_qp_enable = 1;
+ if (max_qp_enable ||
+ (inst->fw_caps[P_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET))
+ p_qp_enable = 1;
+ if (max_qp_enable ||
+ (inst->fw_caps[B_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET))
+ b_qp_enable = 1;
+ } else {
+ if (inst->fw_caps[MAX_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)
+ max_qp_enable = 1;
+ if (max_qp_enable ||
+ (inst->fw_caps[I_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET))
+ i_qp_enable = 1;
+ if (max_qp_enable ||
+ (inst->fw_caps[P_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET))
+ p_qp_enable = 1;
+ if (max_qp_enable ||
+ (inst->fw_caps[B_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET))
+ b_qp_enable = 1;
+ }
+
+ client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2;
+ if (!client_qp_enable)
+ return 0;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ i_frame_qp = min(inst->fw_caps[I_FRAME_MAX_QP_H264].value,
+ inst->fw_caps[MAX_FRAME_QP_H264].value);
+ p_frame_qp = min(inst->fw_caps[P_FRAME_MAX_QP_H264].value,
+ inst->fw_caps[MAX_FRAME_QP_H264].value);
+ b_frame_qp = min(inst->fw_caps[B_FRAME_MAX_QP_H264].value,
+ inst->fw_caps[MAX_FRAME_QP_H264].value);
+ } else {
+ i_frame_qp = min(inst->fw_caps[I_FRAME_MAX_QP_HEVC].value,
+ inst->fw_caps[MAX_FRAME_QP_HEVC].value);
+ p_frame_qp = min(inst->fw_caps[P_FRAME_MAX_QP_HEVC].value,
+ inst->fw_caps[MAX_FRAME_QP_HEVC].value);
+ b_frame_qp = min(inst->fw_caps[B_FRAME_MAX_QP_HEVC].value,
+ inst->fw_caps[MAX_FRAME_QP_HEVC].value);
+ }
+
+ hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 |
+ client_qp_enable << 24;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_32_PACKED,
+ &hfi_val, sizeof(u32));
+}
+
+int iris_set_frame_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0, client_qp_enable;
+ u32 i_frame_qp, p_frame_qp, b_frame_qp;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ struct vb2_queue *q;
+ u32 hfi_val;
+
+ q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
+ if (vb2_is_streaming(q)) {
+ if (inst->hfi_rc_type != HFI_RC_OFF)
+ return 0;
+ }
+
+ if (inst->hfi_rc_type == HFI_RC_OFF) {
+ i_qp_enable = 1;
+ p_qp_enable = 1;
+ b_qp_enable = 1;
+ } else {
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ if (inst->fw_caps[I_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET)
+ i_qp_enable = 1;
+ if (inst->fw_caps[P_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET)
+ p_qp_enable = 1;
+ if (inst->fw_caps[B_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET)
+ b_qp_enable = 1;
+ } else {
+ if (inst->fw_caps[I_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)
+ i_qp_enable = 1;
+ if (inst->fw_caps[P_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)
+ p_qp_enable = 1;
+ if (inst->fw_caps[B_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)
+ b_qp_enable = 1;
+ }
+ }
+
+ client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2;
+ if (!client_qp_enable)
+ return 0;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ i_frame_qp = inst->fw_caps[I_FRAME_QP_H264].value;
+ p_frame_qp = inst->fw_caps[P_FRAME_QP_H264].value;
+ b_frame_qp = inst->fw_caps[B_FRAME_QP_H264].value;
+ } else {
+ i_frame_qp = inst->fw_caps[I_FRAME_QP_HEVC].value;
+ p_frame_qp = inst->fw_caps[P_FRAME_QP_HEVC].value;
+ b_frame_qp = inst->fw_caps[B_FRAME_QP_HEVC].value;
+ }
+
+ hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 |
+ client_qp_enable << 24;
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_32_PACKED,
+ &hfi_val, sizeof(u32));
+}
+
+int iris_set_qp_range(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ struct hfi_quantization_range_v2 range;
+ u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+
+ if (inst->codec == V4L2_PIX_FMT_HEVC) {
+ range.min_qp.qp_packed = inst->fw_caps[MIN_FRAME_QP_HEVC].value;
+ range.max_qp.qp_packed = inst->fw_caps[MAX_FRAME_QP_HEVC].value;
+ } else {
+ range.min_qp.qp_packed = inst->fw_caps[MIN_FRAME_QP_H264].value;
+ range.max_qp.qp_packed = inst->fw_caps[MAX_FRAME_QP_H264].value;
+ }
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_32_PACKED,
+ &range, sizeof(range));
+}
+
int iris_set_properties(struct iris_inst *inst, u32 plane)
{
const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h
index 9b5741868933b08dcefd4868ba89f3c43760d31c..30af333cc4941e737eb1ae83a6944b4192896e23 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.h
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.h
@@ -17,6 +17,21 @@ int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap
int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_profile(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_level(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_profile_level_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_header_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_header_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_peak_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_bitrate_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_bitrate_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_entropy_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_entropy_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_min_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_max_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_frame_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_qp_range(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_properties(struct iris_inst *inst, u32 plane);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index fead3318743a09ecdc363eda4cbf252f640eb6e0..39ceab22a9227998c8b402e4b6583ddcd7265cc4 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -539,6 +539,114 @@ iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *p
packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm);
break;
}
+ case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: {
+ struct hfi_profile_level *in = pdata, *pl = prop_data;
+
+ pl->level = in->level;
+ pl->profile = in->profile;
+ if (pl->profile <= 0)
+ /* Profile not supported, falling back to high */
+ pl->profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
+
+ if (!pl->level)
+ /* Level not supported, falling back to 1 */
+ pl->level = 1;
+
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*pl);
+ break;
+ }
+ case HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER: {
+ struct hfi_enable *en = prop_data;
+ u32 *in = pdata;
+
+ en->enable = *in;
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*en);
+ break;
+ }
+ case HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE: {
+ struct hfi_bitrate *brate = prop_data;
+ u32 *in = pdata;
+
+ brate->bitrate = *in;
+ brate->layer_id = 0;
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*brate);
+ break;
+ }
+ case HFI_PROPERTY_PARAM_VENC_RATE_CONTROL: {
+ u32 *in = pdata;
+
+ switch (*in) {
+ case HFI_RATE_CONTROL_OFF:
+ case HFI_RATE_CONTROL_CBR_CFR:
+ case HFI_RATE_CONTROL_CBR_VFR:
+ case HFI_RATE_CONTROL_VBR_CFR:
+ case HFI_RATE_CONTROL_VBR_VFR:
+ case HFI_RATE_CONTROL_CQ:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ packet->data[1] = *in;
+ packet->shdr.hdr.size += sizeof(u32) * 2;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL: {
+ struct hfi_h264_entropy_control *entropy = prop_data;
+ u32 *in = pdata;
+
+ entropy->entropy_mode = *in;
+ if (entropy->entropy_mode == HFI_H264_ENTROPY_CABAC)
+ entropy->cabac_model = HFI_H264_CABAC_MODEL_0;
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*entropy);
+ break;
+ }
+ case HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2: {
+ struct hfi_quantization_range_v2 *range = prop_data;
+ struct hfi_quantization_range_v2 *in = pdata;
+ u32 min_qp, max_qp;
+
+ min_qp = in->min_qp.qp_packed;
+ max_qp = in->max_qp.qp_packed;
+
+ /* We'll be packing in the qp, so make sure we
+ * won't be losing data when masking
+ */
+ if (min_qp > 0xff || max_qp > 0xff)
+ return -ERANGE;
+
+ range->min_qp.layer_id = 0xFF;
+ range->max_qp.layer_id = 0xFF;
+ range->min_qp.qp_packed = (min_qp & 0xFF) | ((min_qp & 0xFF) << 8) |
+ ((min_qp & 0xFF) << 16);
+ range->max_qp.qp_packed = (max_qp & 0xFF) | ((max_qp & 0xFF) << 8) |
+ ((max_qp & 0xFF) << 16);
+ range->min_qp.enable = 7;
+ range->max_qp.enable = 7;
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*range);
+ break;
+ }
+ case HFI_PROPERTY_CONFIG_FRAME_RATE: {
+ struct hfi_framerate *frate = prop_data;
+ struct hfi_framerate *in = pdata;
+
+ frate->buffer_type = in->buffer_type;
+ frate->framerate = in->framerate;
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*frate);
+ break;
+ }
+ case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO: {
+ struct hfi_uncompressed_plane_actual_info *plane_actual_info = prop_data;
+ struct hfi_uncompressed_plane_actual_info *in = pdata;
+
+ plane_actual_info->buffer_type = in->buffer_type;
+ plane_actual_info->num_planes = in->num_planes;
+ plane_actual_info->plane_format[0] = in->plane_format[0];
+ if (in->num_planes > 1)
+ plane_actual_info->plane_format[1] = in->plane_format[1];
+ packet->shdr.hdr.size += sizeof(u32) + sizeof(*plane_actual_info);
+ break;
+ }
default:
return -EINVAL;
}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index 81116420b6a3d86cca7229bdd3a875d95c1a7936..d7bbcfce6941229aedb558d24d4cd6c7a8a1aa32 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -114,15 +114,25 @@
#define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a
#define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c
-#define HFI_PICTURE_I 0x00000001
-#define HFI_PICTURE_P 0x00000002
-#define HFI_PICTURE_B 0x00000004
-#define HFI_PICTURE_IDR 0x00000008
+#define HFI_GEN1_PICTURE_I 0x00000001
+#define HFI_GEN1_PICTURE_P 0x00000002
+#define HFI_GEN1_PICTURE_B 0x00000004
+#define HFI_GEN1_PICTURE_IDR 0x00000008
#define HFI_FRAME_NOTCODED 0x7f002000
#define HFI_FRAME_YUV 0x7f004000
#define HFI_UNUSED_PICT 0x10000000
-#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008
-#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000
+#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008
+#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000
+#define HFI_RATE_CONTROL_OFF 0x1000001
+#define HFI_RATE_CONTROL_VBR_VFR 0x1000002
+#define HFI_RATE_CONTROL_VBR_CFR 0x1000003
+#define HFI_RATE_CONTROL_CBR_VFR 0x1000004
+#define HFI_RATE_CONTROL_CBR_CFR 0x1000005
+#define HFI_RATE_CONTROL_CQ 0x1000008
+
+#define HFI_H264_ENTROPY_CAVLC 0x1
+#define HFI_H264_ENTROPY_CABAC 0x2
+
#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL 0x2005002
#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL 0x2005003
#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL 0x2005004
@@ -388,6 +398,31 @@ struct hfi_buffer_requirements {
u32 alignment;
};
+struct hfi_bitrate {
+ u32 bitrate;
+ u32 layer_id;
+};
+
+#define HFI_H264_CABAC_MODEL_0 0x1
+
+struct hfi_h264_entropy_control {
+ u32 entropy_mode;
+ u32 cabac_model;
+};
+
+struct hfi_quantization_v2 {
+ u32 qp_packed;
+ u32 layer_id;
+ u32 enable;
+ u32 reserved[3];
+};
+
+struct hfi_quantization_range_v2 {
+ struct hfi_quantization_v2 min_qp;
+ struct hfi_quantization_v2 max_qp;
+ u32 reserved[4];
+};
+
struct hfi_framerate {
u32 buffer_type;
u32 framerate;
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index 2a96458833835422d30c9386d15cc1e4fb226e3d..82d3e8de7bff0ac53a971b4763ae848ff8c61ff2 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -469,14 +469,14 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
buf->timestamp = timestamp_us;
switch (pic_type) {
- case HFI_PICTURE_IDR:
- case HFI_PICTURE_I:
+ case HFI_GEN1_PICTURE_IDR:
+ case HFI_GEN1_PICTURE_I:
flags |= V4L2_BUF_FLAG_KEYFRAME;
break;
- case HFI_PICTURE_P:
+ case HFI_GEN1_PICTURE_P:
flags |= V4L2_BUF_FLAG_PFRAME;
break;
- case HFI_PICTURE_B:
+ case HFI_GEN1_PICTURE_B:
flags |= V4L2_BUF_FLAG_BFRAME;
break;
case HFI_FRAME_NOTCODED:
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
index b3d1c966958e516d940a7795e5cbe2f8e8bada57..aa1f795f5626c1f76a32dd650302633877ce67be 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -56,6 +56,16 @@
#define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123
#define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124
#define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128
+
+enum hfi_rate_control {
+ HFI_RC_VBR_CFR = 0x00000000,
+ HFI_RC_CBR_CFR = 0x00000001,
+ HFI_RC_CQ = 0x00000002,
+ HFI_RC_OFF = 0x00000003,
+ HFI_RC_CBR_VFR = 0x00000004,
+ HFI_RC_LOSSLESS = 0x00000005,
+};
+
#define HFI_PROP_RATE_CONTROL 0x0300012a
#define HFI_PROP_QP_PACKED 0x0300012e
#define HFI_PROP_MIN_QP_PACKED 0x0300012f
@@ -64,6 +74,14 @@
#define HFI_PROP_MAX_GOP_FRAMES 0x03000146
#define HFI_PROP_MAX_B_FRAMES 0x03000147
#define HFI_PROP_QUALITY_MODE 0x03000148
+
+enum hfi_seq_header_mode {
+ HFI_SEQ_HEADER_SEPERATE_FRAME = 0x00000001,
+ HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME = 0x00000002,
+ HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME = 0x00000004,
+ HFI_SEQ_HEADER_METADATA = 0x00000008,
+};
+
#define HFI_PROP_SEQ_HEADER_MODE 0x03000149
#define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155
#define HFI_PROP_PICTURE_TYPE 0x03000162
@@ -123,13 +141,13 @@ enum hfi_codec_type {
};
enum hfi_picture_type {
- HFI_PICTURE_IDR = 0x00000001,
- HFI_PICTURE_P = 0x00000002,
- HFI_PICTURE_B = 0x00000004,
- HFI_PICTURE_I = 0x00000008,
- HFI_PICTURE_CRA = 0x00000010,
- HFI_PICTURE_BLA = 0x00000020,
- HFI_PICTURE_NOSHOW = 0x00000040,
+ HFI_GEN2_PICTURE_IDR = 0x00000001,
+ HFI_GEN2_PICTURE_P = 0x00000002,
+ HFI_GEN2_PICTURE_B = 0x00000004,
+ HFI_GEN2_PICTURE_I = 0x00000008,
+ HFI_GEN2_PICTURE_CRA = 0x00000010,
+ HFI_GEN2_PICTURE_BLA = 0x00000020,
+ HFI_GEN2_PICTURE_NOSHOW = 0x00000040,
};
enum hfi_buffer_type {
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
index dda775d463e916f70da0b879702d96df18ea8bf7..4e4fae2359ccf210186397a417049208728b5d53 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -87,17 +87,18 @@ static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type)
static int iris_hfi_gen2_get_driver_buffer_flags(struct iris_inst *inst, u32 hfi_flags)
{
- u32 keyframe = HFI_PICTURE_IDR | HFI_PICTURE_I | HFI_PICTURE_CRA | HFI_PICTURE_BLA;
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+ u32 keyframe = HFI_GEN2_PICTURE_IDR | HFI_GEN2_PICTURE_I |
+ HFI_GEN2_PICTURE_CRA | HFI_GEN2_PICTURE_BLA;
u32 driver_flags = 0;
- if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_NOSHOW)
+ if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_NOSHOW)
driver_flags |= V4L2_BUF_FLAG_ERROR;
else if (inst_hfi_gen2->hfi_frame_info.picture_type & keyframe)
driver_flags |= V4L2_BUF_FLAG_KEYFRAME;
- else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_P)
+ else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_P)
driver_flags |= V4L2_BUF_FLAG_PFRAME;
- else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_B)
+ else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_B)
driver_flags |= V4L2_BUF_FLAG_BFRAME;
if (inst_hfi_gen2->hfi_frame_info.data_corrupt || inst_hfi_gen2->hfi_frame_info.overflow)
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index b75549718df3c87cd85aecfc74c873c60cd4bde5..5982d7adefeab80905478b32cddba7bd4651a691 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -63,7 +63,7 @@ struct iris_fmt {
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
* @frame_rate: frame rate of current instance
* @operating_rate: operating rate of current instance
-
+ * @hfi_rc_type: rate control type
*/
struct iris_inst {
@@ -101,6 +101,7 @@ struct iris_inst {
bool last_buffer_dequeued;
u32 frame_rate;
u32 operating_rate;
+ u32 hfi_rc_type;
};
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index e36c5609507504cb79ef6a16decada062335aaf1..abca7f87f1c20f09f2e62be107c2a66fb80720fb 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -213,6 +213,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
.hfi_id = HFI_PROP_PROFILE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile,
},
{
.cap_id = PROFILE_HEVC,
@@ -224,6 +225,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
.hfi_id = HFI_PROP_PROFILE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile,
},
{
.cap_id = LEVEL_H264,
@@ -250,6 +252,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
.hfi_id = HFI_PROP_LEVEL,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_level,
},
{
.cap_id = LEVEL_HEVC,
@@ -271,6 +274,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
.hfi_id = HFI_PROP_LEVEL,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_level,
},
{
.cap_id = STAGE,
@@ -279,6 +283,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.step_or_mask = 1,
.value = STAGE_2,
.hfi_id = HFI_PROP_STAGE,
+ .set = iris_set_stage,
},
{
.cap_id = HEADER_MODE,
@@ -289,6 +294,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
.hfi_id = HFI_PROP_SEQ_HEADER_MODE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_header_mode_gen2,
},
{
.cap_id = PREPEND_SPSPPS_TO_IDR,
@@ -306,6 +312,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_TOTAL_BITRATE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_bitrate,
},
{
.cap_id = BITRATE_PEAK,
@@ -316,6 +323,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_peak_bitrate,
},
{
.cap_id = BITRATE_MODE,
@@ -326,6 +334,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
.hfi_id = HFI_PROP_RATE_CONTROL,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_bitrate_mode_gen2,
},
{
.cap_id = FRAME_SKIP_MODE,
@@ -353,6 +362,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_MAX_GOP_FRAMES,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_u32,
},
{
.cap_id = ENTROPY_MODE,
@@ -363,6 +373,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
.hfi_id = HFI_PROP_CABAC_SESSION,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_entropy_mode_gen2,
},
{
.cap_id = MIN_FRAME_QP_H264,
@@ -372,6 +383,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = MIN_QP_8BIT,
.hfi_id = HFI_PROP_MIN_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_min_qp,
},
{
.cap_id = MIN_FRAME_QP_HEVC,
@@ -381,6 +393,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = MIN_QP_8BIT,
.hfi_id = HFI_PROP_MIN_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_min_qp,
},
{
.cap_id = MAX_FRAME_QP_H264,
@@ -390,6 +403,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = MAX_QP,
.hfi_id = HFI_PROP_MAX_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_max_qp,
},
{
.cap_id = MAX_FRAME_QP_HEVC,
@@ -399,6 +413,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = MAX_QP,
.hfi_id = HFI_PROP_MAX_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_max_qp,
},
{
.cap_id = I_FRAME_MIN_QP_H264,
@@ -493,6 +508,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
},
{
.cap_id = I_FRAME_QP_HEVC,
@@ -503,6 +519,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
},
{
.cap_id = P_FRAME_QP_H264,
@@ -513,6 +530,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
},
{
.cap_id = P_FRAME_QP_HEVC,
@@ -523,6 +541,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
},
{
.cap_id = B_FRAME_QP_H264,
@@ -533,6 +552,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
},
{
.cap_id = B_FRAME_QP_HEVC,
@@ -543,6 +563,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.hfi_id = HFI_PROP_QP_PACKED,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
},
{
.cap_id = INPUT_BUF_HOST_MAX_COUNT,
@@ -552,6 +573,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = DEFAULT_MAX_HOST_BUF_COUNT,
.hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
.flags = CAP_FLAG_INPUT_PORT,
+ .set = iris_set_u32,
},
{
.cap_id = OUTPUT_BUF_HOST_MAX_COUNT,
@@ -561,6 +583,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.value = DEFAULT_MAX_HOST_BUF_COUNT,
.hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_u32,
},
};
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index 90788b78802a589cbd9a25e95ee7766d3a3bb87f..f71101f6c4b6c3ffd76539e59ee3c5d48d0a8a46 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -45,6 +45,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.step_or_mask = 1,
.value = STAGE_2,
.hfi_id = HFI_PROPERTY_PARAM_WORK_MODE,
+ .set = iris_set_stage,
},
{
.cap_id = PROFILE_H264,
@@ -59,6 +60,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
.hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
},
{
.cap_id = PROFILE_HEVC,
@@ -70,6 +72,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
.hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
},
{
.cap_id = LEVEL_H264,
@@ -94,6 +97,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
.hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
},
{
.cap_id = LEVEL_HEVC,
@@ -115,6 +119,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
.hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
},
{
.cap_id = HEADER_MODE,
@@ -125,6 +130,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
.hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_header_mode_gen1,
},
{
.cap_id = BITRATE,
@@ -135,6 +141,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_bitrate,
},
{
.cap_id = BITRATE_MODE,
@@ -145,6 +152,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
.hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_bitrate_mode_gen1,
},
{
.cap_id = FRAME_SKIP_MODE,
@@ -168,6 +176,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.max = (1 << 16) - 1,
.step_or_mask = 1,
.value = 30,
+ .set = iris_set_u32
},
{
.cap_id = ENTROPY_MODE,
@@ -178,6 +187,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
.hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_entropy_mode_gen1,
},
{
.cap_id = MIN_FRAME_QP_H264,
@@ -187,6 +197,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = MIN_QP_8BIT,
.hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
},
{
.cap_id = MIN_FRAME_QP_HEVC,
@@ -196,6 +207,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = MIN_QP_8BIT,
.hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
},
{
.cap_id = MAX_FRAME_QP_H264,
@@ -205,6 +217,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = MAX_QP,
.hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
},
{
.cap_id = MAX_FRAME_QP_HEVC,
@@ -214,6 +227,7 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
.value = MAX_QP_HEVC,
.hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
.flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
},
};
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 22/24] media: iris: Allocate and queue internal buffers for encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (20 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 21/24] media: iris: Set platform capabilities to firmware " Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 23/24] media: iris: Add support for buffer management ioctls for encoder device Dikshita Agarwal
` (2 subsequent siblings)
24 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for allocating and queuing internal buffers required by the
encoder. The sizes of these buffers are derived from hardware
specifications and are essential to meet the encoder's functional and
performance requirements.
These buffers are not exposed to userspace; they are allocated and
managed internally to ensure correct and efficient hardware operation.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_buffer.c | 114 ++-
drivers/media/platform/qcom/iris/iris_buffer.h | 6 +-
.../platform/qcom/iris/iris_hfi_gen1_command.c | 6 +
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 2 +
.../platform/qcom/iris/iris_hfi_gen2_command.c | 56 +-
.../platform/qcom/iris/iris_hfi_gen2_response.c | 10 +-
.../platform/qcom/iris/iris_platform_common.h | 4 +
.../media/platform/qcom/iris/iris_platform_gen2.c | 17 +
.../platform/qcom/iris/iris_platform_sm8250.c | 9 +
drivers/media/platform/qcom/iris/iris_vdec.c | 2 +-
drivers/media/platform/qcom/iris/iris_venc.c | 36 +
drivers/media/platform/qcom/iris/iris_vidc.c | 10 +-
drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 842 ++++++++++++++++++++-
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 20 +
14 files changed, 1076 insertions(+), 58 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 8811174bfdc0ad5288aa4eb5fab9d9df876c78c9..8891a297d384b018b3cc8313ad6416db6317798b 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -294,16 +294,30 @@ void iris_get_internal_buffers(struct iris_inst *inst, u32 plane)
const u32 *internal_buf_type;
u32 internal_buffer_count, i;
- if (V4L2_TYPE_IS_OUTPUT(plane)) {
- internal_buf_type = platform_data->dec_ip_int_buf_tbl;
- internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
- for (i = 0; i < internal_buffer_count; i++)
- iris_fill_internal_buf_info(inst, internal_buf_type[i]);
+ if (inst->domain == DECODER) {
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->dec_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ for (i = 0; i < internal_buffer_count; i++)
+ iris_fill_internal_buf_info(inst, internal_buf_type[i]);
+ } else {
+ internal_buf_type = platform_data->dec_op_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
+ for (i = 0; i < internal_buffer_count; i++)
+ iris_fill_internal_buf_info(inst, internal_buf_type[i]);
+ }
} else {
- internal_buf_type = platform_data->dec_op_int_buf_tbl;
- internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
- for (i = 0; i < internal_buffer_count; i++)
- iris_fill_internal_buf_info(inst, internal_buf_type[i]);
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->enc_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
+ for (i = 0; i < internal_buffer_count; i++)
+ iris_fill_internal_buf_info(inst, internal_buf_type[i]);
+ } else {
+ internal_buf_type = platform_data->enc_op_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_op_int_buf_tbl_size;
+ for (i = 0; i < internal_buffer_count; i++)
+ iris_fill_internal_buf_info(inst, internal_buf_type[i]);
+ }
}
}
@@ -344,12 +358,22 @@ int iris_create_internal_buffers(struct iris_inst *inst, u32 plane)
const u32 *internal_buf_type;
int ret;
- if (V4L2_TYPE_IS_OUTPUT(plane)) {
- internal_buf_type = platform_data->dec_ip_int_buf_tbl;
- internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ if (inst->domain == DECODER) {
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->dec_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->dec_op_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
+ }
} else {
- internal_buf_type = platform_data->dec_op_int_buf_tbl;
- internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->enc_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->enc_op_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_op_int_buf_tbl_size;
+ }
}
for (i = 0; i < internal_buffer_count; i++) {
@@ -411,12 +435,22 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
u32 internal_buffer_count, i;
int ret;
- if (V4L2_TYPE_IS_OUTPUT(plane)) {
- internal_buf_type = platform_data->dec_ip_int_buf_tbl;
- internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ if (inst->domain == DECODER) {
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->dec_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->dec_op_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
+ }
} else {
- internal_buf_type = platform_data->dec_op_int_buf_tbl;
- internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->enc_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->enc_op_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_op_int_buf_tbl_size;
+ }
}
for (i = 0; i < internal_buffer_count; i++) {
@@ -460,12 +494,22 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool
u32 i, len;
int ret;
- if (V4L2_TYPE_IS_OUTPUT(plane)) {
- internal_buf_type = platform_data->dec_ip_int_buf_tbl;
- len = platform_data->dec_ip_int_buf_tbl_size;
+ if (inst->domain == DECODER) {
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->dec_ip_int_buf_tbl;
+ len = platform_data->dec_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->dec_op_int_buf_tbl;
+ len = platform_data->dec_op_int_buf_tbl_size;
+ }
} else {
- internal_buf_type = platform_data->dec_op_int_buf_tbl;
- len = platform_data->dec_op_int_buf_tbl_size;
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ internal_buf_type = platform_data->enc_ip_int_buf_tbl;
+ len = platform_data->enc_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->enc_op_int_buf_tbl;
+ len = platform_data->enc_op_int_buf_tbl_size;
+ }
}
for (i = 0; i < len; i++) {
@@ -486,7 +530,10 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool
}
if (force) {
- buffers = &inst->buffers[BUF_PERSIST];
+ if (inst->domain == DECODER)
+ buffers = &inst->buffers[BUF_PERSIST];
+ else
+ buffers = &inst->buffers[BUF_ARP];
list_for_each_entry_safe(buf, next, &buffers->list, list) {
ret = iris_destroy_internal_buffer(inst, buf);
@@ -537,8 +584,13 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst)
u32 internal_buffer_count, i;
int ret;
- internal_buf_type = platform_data->dec_ip_int_buf_tbl;
- internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ if (inst->domain == DECODER) {
+ internal_buf_type = platform_data->dec_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+ } else {
+ internal_buf_type = platform_data->enc_ip_int_buf_tbl;
+ internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
+ }
for (i = 0; i < internal_buffer_count; i++) {
ret = iris_release_internal_buffers(inst, internal_buf_type[i]);
@@ -549,9 +601,9 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst)
return 0;
}
-int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst)
+int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buffer_type)
{
- struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST];
+ struct iris_buffers *buffers = &inst->buffers[buffer_type];
struct iris_buffer *buffer, *next;
int ret;
u32 i;
@@ -559,10 +611,10 @@ int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst)
if (!list_empty(&buffers->list))
return 0;
- iris_fill_internal_buf_info(inst, BUF_PERSIST);
+ iris_fill_internal_buf_info(inst, buffer_type);
for (i = 0; i < buffers->min_count; i++) {
- ret = iris_create_internal_buffer(inst, BUF_PERSIST, i);
+ ret = iris_create_internal_buffer(inst, buffer_type, i);
if (ret)
return ret;
}
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h
index b9b011faa13ae72e08545c191cdcc2f1bcaf9e0a..325d30fce5c99185b61ff989fbfd4de9a56762b2 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_buffer.h
@@ -25,6 +25,8 @@ struct iris_inst;
* @BUF_DPB: buffer to store display picture buffers for reference
* @BUF_PERSIST: buffer to store session context data
* @BUF_SCRATCH_1: buffer to store decoding/encoding context data for HW
+ * @BUF_SCRATCH_2: buffer to store encoding context data for HW
+ * @BUF_VPSS: buffer to store VPSS context data for HW
* @BUF_TYPE_MAX: max buffer types
*/
enum iris_buffer_type {
@@ -38,6 +40,8 @@ enum iris_buffer_type {
BUF_DPB,
BUF_PERSIST,
BUF_SCRATCH_1,
+ BUF_SCRATCH_2,
+ BUF_VPSS,
BUF_TYPE_MAX,
};
@@ -109,7 +113,7 @@ int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffe
int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer);
int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane);
int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane);
-int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst);
+int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buf_type);
int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst);
int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf);
int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 39ceab22a9227998c8b402e4b6583ddcd7265cc4..7d73914b30a1b656e06d9f36de563a8713105301 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -21,6 +21,10 @@ static u32 iris_hfi_gen1_buf_type_from_driver(enum iris_buffer_type buffer_type)
return HFI_BUFFER_INTERNAL_SCRATCH;
case BUF_SCRATCH_1:
return HFI_BUFFER_INTERNAL_SCRATCH_1;
+ case BUF_SCRATCH_2:
+ return HFI_BUFFER_INTERNAL_SCRATCH_2;
+ case BUF_ARP:
+ return HFI_BUFFER_INTERNAL_PERSIST;
default:
return -EINVAL;
}
@@ -363,6 +367,8 @@ static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, struct iri
case BUF_PERSIST:
case BUF_BIN:
case BUF_SCRATCH_1:
+ case BUF_SCRATCH_2:
+ case BUF_ARP:
return iris_hfi_gen1_queue_internal_buffer(inst, buf);
default:
return -EINVAL;
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index d7bbcfce6941229aedb558d24d4cd6c7a8a1aa32..21853921483b90604b69001064550a50bb9629ad 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -74,9 +74,11 @@
#define HFI_BUFFER_INPUT 0x1
#define HFI_BUFFER_OUTPUT 0x2
#define HFI_BUFFER_OUTPUT2 0x3
+#define HFI_BUFFER_INTERNAL_PERSIST 0x4
#define HFI_BUFFER_INTERNAL_PERSIST_1 0x5
#define HFI_BUFFER_INTERNAL_SCRATCH 0x6
#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7
+#define HFI_BUFFER_INTERNAL_SCRATCH_2 0x8
#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5
#define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
index 4cdceca3f8a05a6ec9ad76e7cbaa138daba0e958..c71be09211bdc41fdb38551a6c416d1d252bec56 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -111,21 +111,40 @@ static u32 iris_hfi_gen2_get_port(struct iris_inst *inst, u32 plane)
}
}
-static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type)
+static u32 iris_hfi_gen2_get_port_from_buf_type(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type)
{
- switch (buffer_type) {
- case BUF_INPUT:
- case BUF_BIN:
- case BUF_COMV:
- case BUF_NON_COMV:
- case BUF_LINE:
- return HFI_PORT_BITSTREAM;
- case BUF_OUTPUT:
- case BUF_DPB:
- return HFI_PORT_RAW;
- case BUF_PERSIST:
- default:
- return HFI_PORT_NONE;
+ if (inst->domain == DECODER) {
+ switch (buffer_type) {
+ case BUF_INPUT:
+ case BUF_BIN:
+ case BUF_COMV:
+ case BUF_NON_COMV:
+ case BUF_LINE:
+ return HFI_PORT_BITSTREAM;
+ case BUF_OUTPUT:
+ case BUF_DPB:
+ return HFI_PORT_RAW;
+ case BUF_PERSIST:
+ default:
+ return HFI_PORT_NONE;
+ }
+ } else {
+ switch (buffer_type) {
+ case BUF_INPUT:
+ case BUF_VPSS:
+ return HFI_PORT_RAW;
+ case BUF_OUTPUT:
+ case BUF_BIN:
+ case BUF_COMV:
+ case BUF_NON_COMV:
+ case BUF_LINE:
+ case BUF_SCRATCH_2:
+ return HFI_PORT_BITSTREAM;
+ case BUF_ARP:
+ default:
+ return HFI_PORT_NONE;
+ }
}
}
@@ -1040,9 +1059,14 @@ static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
case BUF_LINE:
return HFI_BUFFER_LINE;
case BUF_DPB:
+ case BUF_SCRATCH_2:
return HFI_BUFFER_DPB;
case BUF_PERSIST:
return HFI_BUFFER_PERSIST;
+ case BUF_ARP:
+ return HFI_BUFFER_ARP;
+ case BUF_VPSS:
+ return HFI_BUFFER_VPSS;
default:
return 0;
}
@@ -1098,7 +1122,7 @@ static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iri
return ret;
}
- port = iris_hfi_gen2_get_port_from_buf_type(buffer->type);
+ port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type);
iris_hfi_gen2_packet_session_command(inst,
HFI_CMD_BUFFER,
HFI_HOST_FLAGS_INTR_REQUIRED,
@@ -1120,7 +1144,7 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i
iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE;
- port = iris_hfi_gen2_get_port_from_buf_type(buffer->type);
+ port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type);
iris_hfi_gen2_packet_session_command(inst,
HFI_CMD_BUFFER,
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
index 4e4fae2359ccf210186397a417049208728b5d53..6b8e637ac6d82aee8699db59ee2f04de9e715275 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -29,7 +29,8 @@ struct iris_hfi_gen2_packet_handle {
int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt);
};
-static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type)
+static u32 iris_hfi_gen2_buf_type_to_driver(struct iris_inst *inst,
+ enum hfi_buffer_type buf_type)
{
switch (buf_type) {
case HFI_BUFFER_BITSTREAM:
@@ -47,7 +48,10 @@ static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type)
case HFI_BUFFER_LINE:
return BUF_LINE;
case HFI_BUFFER_DPB:
- return BUF_DPB;
+ if (inst->domain == DECODER)
+ return BUF_DPB;
+ else
+ return BUF_SCRATCH_2;
case HFI_BUFFER_PERSIST:
return BUF_PERSIST;
default:
@@ -421,7 +425,7 @@ static void iris_hfi_gen2_handle_dequeue_buffers(struct iris_inst *inst)
static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
struct iris_hfi_buffer *buffer)
{
- u32 buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type);
+ u32 buf_type = iris_hfi_gen2_buf_type_to_driver(inst, buffer->type);
struct iris_buffers *buffers = &inst->buffers[buf_type];
struct iris_buffer *buf, *iter;
bool found = false;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 0064a90e0e111075341d389fef7adb8f6b46b46f..96fa7b1bb592441e85664da408ea4ba42c9a15b5 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -247,6 +247,10 @@ struct iris_platform_data {
unsigned int dec_ip_int_buf_tbl_size;
const u32 *dec_op_int_buf_tbl;
unsigned int dec_op_int_buf_tbl_size;
+ const u32 *enc_ip_int_buf_tbl;
+ unsigned int enc_ip_int_buf_tbl_size;
+ const u32 *enc_op_int_buf_tbl;
+ unsigned int enc_op_int_buf_tbl_size;
};
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index abca7f87f1c20f09f2e62be107c2a66fb80720fb..8d6dbb18325c289c238eeb44e731a4b15a04789b 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -726,6 +726,14 @@ static const u32 sm8550_dec_op_int_buf_tbl[] = {
BUF_DPB,
};
+static const u32 sm8550_enc_op_int_buf_tbl[] = {
+ BUF_BIN,
+ BUF_COMV,
+ BUF_NON_COMV,
+ BUF_LINE,
+ BUF_SCRATCH_2,
+};
+
struct iris_platform_data sm8550_data = {
.get_instance = iris_hfi_gen2_get_instance,
.init_hfi_command_ops = iris_hfi_gen2_command_ops_init,
@@ -803,6 +811,9 @@ struct iris_platform_data sm8550_data = {
.dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl),
.dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl,
.dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl),
+
+ .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl,
+ .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl),
};
/*
@@ -891,6 +902,9 @@ struct iris_platform_data sm8650_data = {
.dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl),
.dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl,
.dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl),
+
+ .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl,
+ .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl),
};
/*
@@ -975,4 +989,7 @@ struct iris_platform_data qcs8300_data = {
.dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl),
.dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl,
.dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl),
+
+ .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl,
+ .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl),
};
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index f71101f6c4b6c3ffd76539e59ee3c5d48d0a8a46..802376092d87cdb3c127e7f1a74418bc942600d8 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -307,6 +307,12 @@ static const u32 sm8250_dec_op_int_buf_tbl[] = {
BUF_DPB,
};
+static const u32 sm8250_enc_ip_int_buf_tbl[] = {
+ BUF_BIN,
+ BUF_SCRATCH_1,
+ BUF_SCRATCH_2,
+};
+
struct iris_platform_data sm8250_data = {
.get_instance = iris_hfi_gen1_get_instance,
.init_hfi_command_ops = &iris_hfi_gen1_command_ops_init,
@@ -352,4 +358,7 @@ struct iris_platform_data sm8250_data = {
.dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_ip_int_buf_tbl),
.dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl,
.dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl),
+
+ .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl,
+ .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl),
};
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 81ef8254c914c9b0980e3c1537a44f57328e5789..7669301e2ec24f482b449386e3c31f6e155ee3b7 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -321,7 +321,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst)
if (ret)
return ret;
- ret = iris_alloc_and_queue_persist_bufs(inst);
+ ret = iris_alloc_and_queue_persist_bufs(inst, BUF_PERSIST);
if (ret)
return ret;
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 4b0da51e0477ab00019396242be9fd585c11ded3..bd5e8fc2d48882c4fd57607a0ce5183c65272cf9 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -435,6 +435,24 @@ int iris_venc_streamon_input(struct iris_inst *inst)
if (ret)
return ret;
+ ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP);
+ if (ret)
+ return ret;
+
+ iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+ ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
return iris_process_streamon_input(inst);
}
@@ -446,6 +464,24 @@ int iris_venc_streamon_output(struct iris_inst *inst)
if (ret)
goto error;
+ ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP);
+ if (ret)
+ return ret;
+
+ iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+ ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ goto error;
+
+ ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ goto error;
+
+ ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ goto error;
+
ret = iris_process_streamon_output(inst);
if (ret)
goto error;
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index be8688140fd22ffd02e8c286bfc5f62e050ceb5b..03492647429b4f30e907e11d463c36f6b8502116 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -176,6 +176,8 @@ int iris_open(struct file *filp)
INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list);
INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list);
INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list);
+ INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_2].list);
+ INIT_LIST_HEAD(&inst->buffers[BUF_VPSS].list);
init_completion(&inst->completion);
init_completion(&inst->flush_completion);
@@ -266,13 +268,17 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p
count, internal_buf_type[i]);
}
- buffers = &inst->buffers[BUF_PERSIST];
+ if (inst->domain == DECODER)
+ buffers = &inst->buffers[BUF_PERSIST];
+ else
+ buffers = &inst->buffers[BUF_ARP];
count = 0;
list_for_each_entry_safe(buf, next, &buffers->list, list)
count++;
if (count)
- dev_err(inst->core->dev, "%d buffer of type %d not released", count, buf->type);
+ dev_err(inst->core->dev, "%d buffer of type %d not released",
+ count, inst->domain == DECODER ? BUF_PERSIST : BUF_ARP);
}
int iris_close(struct file *filp)
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index 06d5afc3c641f0dfca3967e55273c4fa2614fdff..7337d8d33715810669399d9f86b864d0eb002897 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -5,6 +5,14 @@
#include "iris_instance.h"
#include "iris_vpu_buffer.h"
+#include "iris_hfi_gen1_defines.h"
+#include "iris_hfi_gen2_defines.h"
+
+#define HFI_MAX_COL_FRAME 6
+
+#ifndef SYSTEM_LAL_TILE10
+#define SYSTEM_LAL_TILE10 192
+#endif
static u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
{
@@ -548,6 +556,813 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst)
iris_vpu_dec_line_size(inst);
}
+static inline
+u32 size_enc_single_pipe(u32 rc_type, u32 bitbin_size, u32 num_vpp_pipes,
+ u32 frame_width, u32 frame_height, u32 lcu_size)
+{
+ u32 size_aligned_height = ALIGN((frame_height), lcu_size);
+ u32 size_aligned_width = ALIGN((frame_width), lcu_size);
+ u32 size_single_pipe_eval = 0, sao_bin_buffer_size = 0;
+ u32 padded_bin_sz;
+
+ if ((size_aligned_width * size_aligned_height) > (3840 * 2160))
+ size_single_pipe_eval = (bitbin_size / num_vpp_pipes);
+ else if (num_vpp_pipes > 2)
+ size_single_pipe_eval = bitbin_size / 2;
+ else
+ size_single_pipe_eval = bitbin_size;
+
+ sao_bin_buffer_size = (64 * ((((frame_width) + 32) * ((frame_height) + 32)) >> 10)) + 384;
+ padded_bin_sz = ALIGN(size_single_pipe_eval, 256);
+ size_single_pipe_eval = sao_bin_buffer_size + padded_bin_sz;
+
+ return ALIGN(size_single_pipe_eval, 256);
+}
+
+static inline u32 size_bin_bitstream_enc(u32 width, u32 height,
+ u32 rc_type)
+{
+ u32 aligned_height = ALIGN(height, 32);
+ u32 aligned_width = ALIGN(width, 32);
+ u32 frame_size = width * height * 3;
+ u32 mbs_per_frame;
+
+ /*
+ * Encoder output size calculation: 32 Align width/height
+ * For resolution < 720p : YUVsize * 4
+ * For resolution > 720p & <= 4K : YUVsize / 2
+ * For resolution > 4k : YUVsize / 4
+ * Initially frame_size = YUVsize * 2;
+ */
+
+ mbs_per_frame = (ALIGN(aligned_height, 16) * ALIGN(aligned_width, 16)) / 256;
+
+ if (mbs_per_frame < NUM_MBS_720P)
+ frame_size = frame_size << 1;
+ else if (mbs_per_frame <= NUM_MBS_4K)
+ frame_size = frame_size >> 2;
+ else
+ frame_size = frame_size >> 3;
+
+ if (rc_type == HFI_RATE_CONTROL_OFF || rc_type == HFI_RATE_CONTROL_CQ ||
+ rc_type == HFI_RC_OFF || rc_type == HFI_RC_CQ)
+ frame_size = frame_size << 1;
+
+ /*
+ * In case of opaque color format bitdepth will be known
+ * with first ETB, buffers allocated already with 8 bit
+ * won't be sufficient for 10 bit
+ * calculate size considering 10-bit by default
+ * For 10-bit cases size = size * 1.25
+ */
+ frame_size *= 5;
+ frame_size /= 4;
+
+ return ALIGN(frame_size, SZ_4K);
+}
+
+static inline u32 hfi_buffer_bin_enc(u32 width, u32 height,
+ u32 work_mode, u32 lcu_size,
+ u32 num_vpp_pipes, u32 rc_type)
+{
+ u32 sao_bin_buffer_size, padded_bin_size, bitstream_size;
+ u32 total_bitbin_buffers, size_single_pipe, bitbin_size;
+ u32 aligned_height = ALIGN(height, lcu_size);
+ u32 aligned_width = ALIGN(width, lcu_size);
+
+ bitstream_size = size_bin_bitstream_enc(width, height, rc_type);
+ bitstream_size = ALIGN(bitstream_size, 256);
+
+ if (work_mode == STAGE_2) {
+ total_bitbin_buffers = 3;
+ bitbin_size = bitstream_size * 17 / 10;
+ bitbin_size = ALIGN(bitbin_size, 256);
+ } else {
+ total_bitbin_buffers = 1;
+ bitstream_size = aligned_width * aligned_height * 3;
+ bitbin_size = ALIGN(bitstream_size, 256);
+ }
+
+ if (num_vpp_pipes > 2)
+ size_single_pipe = bitbin_size / 2;
+ else
+ size_single_pipe = bitbin_size;
+
+ size_single_pipe = ALIGN(size_single_pipe, 256);
+ sao_bin_buffer_size = (64 * (((width + 32) * (height + 32)) >> 10)) + 384;
+ padded_bin_size = ALIGN(size_single_pipe, 256);
+ size_single_pipe = sao_bin_buffer_size + padded_bin_size;
+ size_single_pipe = ALIGN(size_single_pipe, 256);
+ bitbin_size = size_single_pipe * num_vpp_pipes;
+
+ return ALIGN(bitbin_size, 256) * total_bitbin_buffers + 512;
+}
+
+static u32 iris_vpu_enc_bin_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ u32 stage = inst->fw_caps[STAGE].value;
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+ u32 lcu_size;
+
+ if (inst->codec == V4L2_PIX_FMT_HEVC)
+ lcu_size = 32;
+ else
+ lcu_size = 16;
+
+ return hfi_buffer_bin_enc(width, height, stage, lcu_size,
+ num_vpp_pipes, inst->hfi_rc_type);
+}
+
+static inline
+u32 hfi_buffer_comv_enc(u32 frame_width, u32 frame_height, u32 lcu_size,
+ u32 num_recon, u32 standard)
+{
+ u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size);
+ u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size);
+ u32 num_lcu_in_frame = width_in_lcus * height_in_lcus;
+ u32 mb_height = ((frame_height) + 15) >> 4;
+ u32 mb_width = ((frame_width) + 15) >> 4;
+ u32 size_colloc_mv, size_colloc_rc;
+
+ size_colloc_mv = (standard == HFI_CODEC_ENCODE_HEVC) ?
+ (16 * ((num_lcu_in_frame << 2) + 32)) :
+ (3 * 16 * (width_in_lcus * height_in_lcus + 32));
+ size_colloc_mv = ALIGN(size_colloc_mv, 256) * num_recon;
+ size_colloc_rc = (((mb_width + 7) >> 3) * 16 * 2 * mb_height);
+ size_colloc_rc = ALIGN(size_colloc_rc, 256) * HFI_MAX_COL_FRAME;
+
+ return size_colloc_mv + size_colloc_rc;
+}
+
+static u32 iris_vpu_enc_comv_size(struct iris_inst *inst)
+{
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+ u32 num_recon = 1;
+ u32 lcu_size = 16;
+
+ if (inst->codec == V4L2_PIX_FMT_HEVC) {
+ lcu_size = 32;
+ return hfi_buffer_comv_enc(width, height, lcu_size,
+ num_recon + 1, HFI_CODEC_ENCODE_HEVC);
+ }
+
+ return hfi_buffer_comv_enc(width, height, lcu_size,
+ num_recon + 1, HFI_CODEC_ENCODE_AVC);
+}
+
+static inline
+u32 size_frame_rc_buf_size(u32 standard, u32 frame_height_coded,
+ u32 num_vpp_pipes_enc)
+{
+ u32 size = 0;
+
+ size = (standard == HFI_CODEC_ENCODE_HEVC) ?
+ (256 + 16 * (14 + ((((frame_height_coded) >> 5) + 7) >> 3))) :
+ (256 + 16 * (14 + ((((frame_height_coded) >> 4) + 7) >> 3)));
+ size *= 11;
+
+ if (num_vpp_pipes_enc > 1)
+ size = ALIGN(size, 256) * num_vpp_pipes_enc;
+
+ return ALIGN(size, 512) * HFI_MAX_COL_FRAME;
+}
+
+static inline
+u32 size_enc_slice_info_buf(u32 num_lcu_in_frame)
+{
+ return ALIGN((256 + (num_lcu_in_frame << 4)), 256);
+}
+
+static inline u32 enc_bitcnt_buf_size(u32 num_lcu_in_frame)
+{
+ return ALIGN((256 + (4 * (num_lcu_in_frame))), 256);
+}
+
+static inline u32 enc_bitmap_buf_size(u32 num_lcu_in_frame)
+{
+ return ALIGN((256 + ((num_lcu_in_frame) >> 3)), 256);
+}
+
+static inline u32 size_override_buf(u32 num_lcumb)
+{
+ return ALIGN(((16 * (((num_lcumb) + 7) >> 3))), 256) * 2;
+}
+
+static inline u32 size_ir_buf(u32 num_lcu_in_frame)
+{
+ return ALIGN((((((num_lcu_in_frame) << 1) + 7) & (~7)) * 3), 256);
+}
+
+static inline
+u32 size_linebuff_data(bool is_ten_bit, u32 frame_width_coded)
+{
+ return is_ten_bit ?
+ (((((10 * (frame_width_coded) + 1024) + (256 - 1)) &
+ (~(256 - 1))) * 1) +
+ (((((10 * (frame_width_coded) + 1024) >> 1) + (256 - 1)) &
+ (~(256 - 1))) * 2)) :
+ (((((8 * (frame_width_coded) + 1024) + (256 - 1)) &
+ (~(256 - 1))) * 1) +
+ (((((8 * (frame_width_coded) + 1024) >> 1) + (256 - 1)) &
+ (~(256 - 1))) * 2));
+}
+
+static inline
+u32 size_left_linebuff_ctrl(u32 standard, u32 frame_height_coded,
+ u32 num_vpp_pipes_enc)
+{
+ u32 size = 0;
+
+ size = standard == HFI_CODEC_ENCODE_HEVC ?
+ (((frame_height_coded) +
+ (32)) / 32 * 4 * 16) :
+ (((frame_height_coded) + 15) / 16 * 5 * 16);
+
+ if ((num_vpp_pipes_enc) > 1) {
+ size += 512;
+ size = ALIGN(size, 512) *
+ num_vpp_pipes_enc;
+ }
+
+ return ALIGN(size, 256);
+}
+
+static inline
+u32 size_left_linebuff_recon_pix(bool is_ten_bit, u32 frame_height_coded,
+ u32 num_vpp_pipes_enc)
+{
+ return (((is_ten_bit + 1) * 2 * (frame_height_coded) + 256) +
+ (256 << (num_vpp_pipes_enc - 1)) - 1) &
+ (~((256 << (num_vpp_pipes_enc - 1)) - 1)) * 1;
+}
+
+static inline
+u32 size_top_linebuff_ctrl_fe(u32 frame_width_coded, u32 standard)
+{
+ return standard == HFI_CODEC_ENCODE_HEVC ?
+ ALIGN((64 * ((frame_width_coded) >> 5)), 256) :
+ ALIGN((256 + 16 * ((frame_width_coded) >> 4)), 256);
+}
+
+static inline
+u32 size_left_linebuff_ctrl_fe(u32 frame_height_coded, u32 num_vpp_pipes_enc)
+{
+ return (((256 + 64 * ((frame_height_coded) >> 4)) +
+ (256 << (num_vpp_pipes_enc - 1)) - 1) &
+ (~((256 << (num_vpp_pipes_enc - 1)) - 1)) * 1) *
+ num_vpp_pipes_enc;
+}
+
+static inline
+u32 size_left_linebuff_metadata_recon_y(u32 frame_height_coded,
+ bool is_ten_bit,
+ u32 num_vpp_pipes_enc)
+{
+ return ALIGN(((256 + 64 * ((frame_height_coded) /
+ (8 * (is_ten_bit ? 4 : 8))))), 256) * num_vpp_pipes_enc;
+}
+
+static inline
+u32 size_left_linebuff_metadata_recon_uv(u32 frame_height_coded,
+ bool is_ten_bit,
+ u32 num_vpp_pipes_enc)
+{
+ return ALIGN(((256 + 64 * ((frame_height_coded) /
+ (4 * (is_ten_bit ? 4 : 8))))), 256) * num_vpp_pipes_enc;
+}
+
+static inline
+u32 size_linebuff_recon_pix(bool is_ten_bit, u32 frame_width_coded)
+{
+ return ALIGN(((is_ten_bit ? 3 : 2) * (frame_width_coded)), 256);
+}
+
+static inline
+u32 size_line_buf_ctrl(u32 frame_width_coded)
+{
+ return ALIGN(frame_width_coded, 256);
+}
+
+static inline
+u32 size_line_buf_ctrl_id2(u32 frame_width_coded)
+{
+ return ALIGN(frame_width_coded, 256);
+}
+
+static inline u32 size_line_buf_sde(u32 frame_width_coded)
+{
+ return ALIGN((256 + (16 * ((frame_width_coded) >> 4))), 256);
+}
+
+static inline
+u32 size_vpss_line_buf(u32 num_vpp_pipes_enc, u32 frame_height_coded,
+ u32 frame_width_coded)
+{
+ return ALIGN(((((((8192) >> 2) << 5) * (num_vpp_pipes_enc)) + 64) +
+ (((((max_t(u32, (frame_width_coded),
+ (frame_height_coded)) + 3) >> 2) << 5) + 256) * 16)), 256);
+}
+
+static inline
+u32 size_top_line_buf_first_stg_sao(u32 frame_width_coded)
+{
+ return ALIGN((16 * ((frame_width_coded) >> 5)), 256);
+}
+
+static inline
+u32 size_enc_ref_buffer(u32 frame_width, u32 frame_height)
+{
+ u32 u_chroma_buffer_height = ALIGN(frame_height >> 1, 32);
+ u32 u_buffer_height = ALIGN(frame_height, 32);
+ u32 u_buffer_width = ALIGN(frame_width, 32);
+
+ return (u_buffer_height + u_chroma_buffer_height) * u_buffer_width;
+}
+
+static inline
+u32 size_enc_ten_bit_ref_buffer(u32 frame_width, u32 frame_height)
+{
+ u32 ref_luma_stride_in_bytes = ((frame_width + SYSTEM_LAL_TILE10 - 1) / SYSTEM_LAL_TILE10) *
+ SYSTEM_LAL_TILE10;
+ u32 ref_buf_height = (frame_height + (32 - 1)) & (~(32 - 1));
+ u32 u_ref_stride, luma_size;
+ u32 ref_chrm_height_in_bytes;
+ u32 chroma_size;
+
+ u_ref_stride = 4 * (ref_luma_stride_in_bytes / 3);
+ u_ref_stride = (u_ref_stride + (128 - 1)) & (~(128 - 1));
+ luma_size = ref_buf_height * u_ref_stride;
+ luma_size = (luma_size + (4096 - 1)) & (~(4096 - 1));
+
+ ref_chrm_height_in_bytes = (((frame_height + 1) >> 1) + (32 - 1)) & (~(32 - 1));
+ chroma_size = u_ref_stride * ref_chrm_height_in_bytes;
+ chroma_size = (chroma_size + (4096 - 1)) & (~(4096 - 1));
+
+ return luma_size + chroma_size;
+}
+
+static inline
+u32 hfi_ubwc_calc_metadata_plane_stride(u32 frame_width,
+ u32 metadata_stride_multiple,
+ u32 tile_width_in_pels)
+{
+ return ALIGN(((frame_width + (tile_width_in_pels - 1)) / tile_width_in_pels),
+ metadata_stride_multiple);
+}
+
+static inline
+u32 hfi_ubwc_metadata_plane_bufheight(u32 frame_height,
+ u32 metadata_height_multiple,
+ u32 tile_height_in_pels)
+{
+ return ALIGN(((frame_height + (tile_height_in_pels - 1)) / tile_height_in_pels),
+ metadata_height_multiple);
+}
+
+static inline
+u32 hfi_ubwc_metadata_plane_buffer_size(u32 _metadata_tride, u32 _metadata_buf_height)
+{
+ return ALIGN(_metadata_tride * _metadata_buf_height, 4096);
+}
+
+static inline
+u32 hfi_buffer_non_comv_enc(u32 frame_width, u32 frame_height,
+ u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard)
+{
+ u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size);
+ u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size);
+ u32 num_lcu_in_frame = width_in_lcus * height_in_lcus;
+ u32 frame_height_coded = height_in_lcus * (lcu_size);
+ u32 frame_width_coded = width_in_lcus * (lcu_size);
+ u32 num_lcumb, frame_rc_buf_size;
+
+ num_lcumb = (frame_height_coded / lcu_size) *
+ ((frame_width_coded + lcu_size * 8) / lcu_size);
+ frame_rc_buf_size = size_frame_rc_buf_size(standard, frame_height_coded,
+ num_vpp_pipes_enc);
+ return size_enc_slice_info_buf(num_lcu_in_frame) +
+ SIZE_SLICE_CMD_BUFFER +
+ SIZE_SPS_PPS_SLICE_HDR +
+ frame_rc_buf_size +
+ enc_bitcnt_buf_size(num_lcu_in_frame) +
+ enc_bitmap_buf_size(num_lcu_in_frame) +
+ SIZE_BSE_SLICE_CMD_BUF +
+ SIZE_LAMBDA_LUT +
+ size_override_buf(num_lcumb) +
+ size_ir_buf(num_lcu_in_frame);
+}
+
+static u32 iris_vpu_enc_non_comv_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+ u32 lcu_size = 16;
+
+ if (inst->codec == V4L2_PIX_FMT_HEVC) {
+ lcu_size = 32;
+ return hfi_buffer_non_comv_enc(width, height, num_vpp_pipes,
+ lcu_size, HFI_CODEC_ENCODE_HEVC);
+ }
+
+ return hfi_buffer_non_comv_enc(width, height, num_vpp_pipes,
+ lcu_size, HFI_CODEC_ENCODE_AVC);
+}
+
+static inline
+u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit,
+ u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard)
+{
+ u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size);
+ u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size);
+ u32 frame_height_coded = height_in_lcus * (lcu_size);
+ u32 frame_width_coded = width_in_lcus * (lcu_size);
+ u32 line_buff_data_size, left_line_buff_ctrl_size;
+ u32 left_line_buff_metadata_recon__uv__size;
+ u32 left_line_buff_metadata_recon__y__size;
+ u32 left_line_buff_recon_pix_size;
+ u32 top_line_buff_ctrl_fe_size;
+ u32 line_buff_recon_pix_size;
+
+ line_buff_data_size = size_linebuff_data(is_ten_bit, frame_width_coded);
+ left_line_buff_ctrl_size =
+ size_left_linebuff_ctrl(standard, frame_height_coded, num_vpp_pipes_enc);
+ left_line_buff_recon_pix_size =
+ size_left_linebuff_recon_pix(is_ten_bit, frame_height_coded,
+ num_vpp_pipes_enc);
+ top_line_buff_ctrl_fe_size =
+ size_top_linebuff_ctrl_fe(frame_width_coded, standard);
+ left_line_buff_metadata_recon__y__size =
+ size_left_linebuff_metadata_recon_y(frame_height_coded, is_ten_bit,
+ num_vpp_pipes_enc);
+ left_line_buff_metadata_recon__uv__size =
+ size_left_linebuff_metadata_recon_uv(frame_height_coded, is_ten_bit,
+ num_vpp_pipes_enc);
+ line_buff_recon_pix_size = size_linebuff_recon_pix(is_ten_bit, frame_width_coded);
+
+ return size_line_buf_ctrl(frame_width_coded) +
+ size_line_buf_ctrl_id2(frame_width_coded) +
+ line_buff_data_size +
+ left_line_buff_ctrl_size +
+ left_line_buff_recon_pix_size +
+ top_line_buff_ctrl_fe_size +
+ left_line_buff_metadata_recon__y__size +
+ left_line_buff_metadata_recon__uv__size +
+ line_buff_recon_pix_size +
+ size_left_linebuff_ctrl_fe(frame_height_coded, num_vpp_pipes_enc) +
+ size_line_buf_sde(frame_width_coded) +
+ size_vpss_line_buf(num_vpp_pipes_enc, frame_height_coded, frame_width_coded) +
+ size_top_line_buf_first_stg_sao(frame_width_coded);
+}
+
+static u32 iris_vpu_enc_line_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+ u32 lcu_size = 16;
+
+ if (inst->codec == V4L2_PIX_FMT_HEVC) {
+ lcu_size = 32;
+ return hfi_buffer_line_enc(width, height, 0, num_vpp_pipes,
+ lcu_size, HFI_CODEC_ENCODE_HEVC);
+ }
+
+ return hfi_buffer_line_enc(width, height, 0, num_vpp_pipes,
+ lcu_size, HFI_CODEC_ENCODE_AVC);
+}
+
+static inline
+u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit)
+{
+ u32 metadata_stride, metadata_buf_height, meta_size_y, meta_size_c;
+ u32 ten_bit_ref_buf_size = 0, ref_buf_size = 0;
+ u32 size;
+
+ if (!is_ten_bit) {
+ ref_buf_size = size_enc_ref_buffer(frame_width, frame_height);
+ metadata_stride =
+ hfi_ubwc_calc_metadata_plane_stride(frame_width, 64,
+ HFI_COL_FMT_NV12C_Y_TILE_WIDTH);
+ metadata_buf_height =
+ hfi_ubwc_metadata_plane_bufheight(frame_height, 16,
+ HFI_COL_FMT_NV12C_Y_TILE_HEIGHT);
+ meta_size_y =
+ hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+ meta_size_c =
+ hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+ size = ref_buf_size + meta_size_y + meta_size_c;
+ } else {
+ ten_bit_ref_buf_size = size_enc_ten_bit_ref_buffer(frame_width, frame_height);
+ metadata_stride =
+ hfi_ubwc_calc_metadata_plane_stride(frame_width,
+ IRIS_METADATA_STRIDE_MULTIPLE,
+ HFI_COL_FMT_TP10C_Y_TILE_WIDTH);
+ metadata_buf_height =
+ hfi_ubwc_metadata_plane_bufheight(frame_height,
+ IRIS_METADATA_HEIGHT_MULTIPLE,
+ HFI_COL_FMT_TP10C_Y_TILE_HEIGHT);
+ meta_size_y =
+ hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+ meta_size_c =
+ hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+ size = ten_bit_ref_buf_size + meta_size_y + meta_size_c;
+ }
+
+ return size;
+}
+
+static u32 iris_vpu_enc_arp_size(struct iris_inst *inst)
+{
+ return HFI_BUFFER_ARP_ENC;
+}
+
+inline bool is_scaling_enabled(struct iris_inst *inst)
+{
+ return inst->crop.left != inst->compose.left ||
+ inst->crop.top != inst->compose.top ||
+ inst->crop.width != inst->compose.width ||
+ inst->crop.height != inst->compose.height;
+}
+
+static inline
+u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable,
+ u32 blur, bool is_ten_bit)
+{
+ if (ds_enable || blur)
+ return hfi_buffer_dpb_enc(dswidth, dsheight, is_ten_bit);
+
+ return 0;
+}
+
+static inline u32 hfi_buffer_scratch1_enc(u32 frame_width, u32 frame_height,
+ u32 lcu_size, u32 num_ref,
+ bool ten_bit, u32 num_vpp_pipes,
+ bool is_h265)
+{
+ u32 line_buf_ctrl_size, line_buf_data_size, leftline_buf_ctrl_size;
+ u32 line_buf_sde_size, sps_pps_slice_hdr, topline_buf_ctrl_size_FE;
+ u32 leftline_buf_ctrl_size_FE, line_buf_recon_pix_size;
+ u32 leftline_buf_recon_pix_size, lambda_lut_size, override_buffer_size;
+ u32 col_mv_buf_size, vpp_reg_buffer_size, ir_buffer_size;
+ u32 vpss_line_buf, leftline_buf_meta_recony, h265e_colrcbuf_size;
+ u32 h265e_framerc_bufsize, h265e_lcubitcnt_bufsize;
+ u32 h265e_lcubitmap_bufsize, se_stats_bufsize;
+ u32 bse_reg_buffer_size, bse_slice_cmd_buffer_size, slice_info_bufsize;
+ u32 line_buf_ctrl_size_buffid2, slice_cmd_buffer_size;
+ u32 width_lcu_num, height_lcu_num, width_coded, height_coded;
+ u32 frame_num_lcu, linebuf_meta_recon_uv, topline_bufsize_fe_1stg_sao;
+ u32 vpss_line_buffer_size_1;
+ u32 bit_depth, num_lcu_mb;
+
+ width_lcu_num = (frame_width + lcu_size - 1) / lcu_size;
+ height_lcu_num = (frame_height + lcu_size - 1) / lcu_size;
+ frame_num_lcu = width_lcu_num * height_lcu_num;
+ width_coded = width_lcu_num * lcu_size;
+ height_coded = height_lcu_num * lcu_size;
+ num_lcu_mb = (height_coded / lcu_size) *
+ ((width_coded + lcu_size * 8) / lcu_size);
+ slice_info_bufsize = 256 + (frame_num_lcu << 4);
+ slice_info_bufsize = ALIGN(slice_info_bufsize, 256);
+ line_buf_ctrl_size = ALIGN(width_coded, 256);
+ line_buf_ctrl_size_buffid2 = ALIGN(width_coded, 256);
+
+ bit_depth = ten_bit ? 10 : 8;
+ line_buf_data_size =
+ (((((bit_depth * width_coded + 1024) + (256 - 1)) &
+ (~(256 - 1))) * 1) +
+ (((((bit_depth * width_coded + 1024) >> 1) + (256 - 1)) &
+ (~(256 - 1))) * 2));
+
+ leftline_buf_ctrl_size = is_h265 ? ((height_coded + 32) / 32 * 4 * 16) :
+ ((height_coded + 15) / 16 * 5 * 16);
+
+ if (num_vpp_pipes > 1) {
+ leftline_buf_ctrl_size += 512;
+ leftline_buf_ctrl_size =
+ ALIGN(leftline_buf_ctrl_size, 512) * num_vpp_pipes;
+ }
+
+ leftline_buf_ctrl_size = ALIGN(leftline_buf_ctrl_size, 256);
+ leftline_buf_recon_pix_size =
+ (((ten_bit + 1) * 2 * (height_coded) + 256) +
+ (256 << (num_vpp_pipes - 1)) - 1) &
+ (~((256 << (num_vpp_pipes - 1)) - 1)) * 1;
+
+ topline_buf_ctrl_size_FE = is_h265 ? (64 * (width_coded >> 5)) :
+ (256 + 16 * (width_coded >> 4));
+ topline_buf_ctrl_size_FE = ALIGN(topline_buf_ctrl_size_FE, 256);
+ leftline_buf_ctrl_size_FE =
+ (((256 + 64 * (height_coded >> 4)) +
+ (256 << (num_vpp_pipes - 1)) - 1) &
+ (~((256 << (num_vpp_pipes - 1)) - 1)) * 1) *
+ num_vpp_pipes;
+ leftline_buf_meta_recony =
+ (256 + 64 * ((height_coded) / (8 * (ten_bit ? 4 : 8))));
+ leftline_buf_meta_recony = ALIGN(leftline_buf_meta_recony, 256);
+ leftline_buf_meta_recony = leftline_buf_meta_recony * num_vpp_pipes;
+ linebuf_meta_recon_uv =
+ (256 + 64 * ((height_coded) / (4 * (ten_bit ? 4 : 8))));
+ linebuf_meta_recon_uv = ALIGN(linebuf_meta_recon_uv, 256);
+ linebuf_meta_recon_uv = linebuf_meta_recon_uv * num_vpp_pipes;
+ line_buf_recon_pix_size = ((ten_bit ? 3 : 2) * width_coded);
+ line_buf_recon_pix_size = ALIGN(line_buf_recon_pix_size, 256);
+ slice_cmd_buffer_size = ALIGN(20480, 256);
+ sps_pps_slice_hdr = 2048 + 4096;
+ col_mv_buf_size =
+ is_h265 ? (16 * ((frame_num_lcu << 2) + 32)) :
+ (3 * 16 * (width_lcu_num * height_lcu_num + 32));
+ col_mv_buf_size = ALIGN(col_mv_buf_size, 256) * (num_ref + 1);
+ h265e_colrcbuf_size =
+ (((width_lcu_num + 7) >> 3) * 16 * 2 * height_lcu_num);
+ if (num_vpp_pipes > 1)
+ h265e_colrcbuf_size =
+ ALIGN(h265e_colrcbuf_size, 256) * num_vpp_pipes;
+
+ h265e_colrcbuf_size =
+ ALIGN(h265e_colrcbuf_size, 256) * HFI_MAX_COL_FRAME;
+ h265e_framerc_bufsize =
+ (is_h265) ?
+ (256 + 16 * (14 + (((height_coded >> 5) + 7) >> 3))) :
+ (256 + 16 * (14 + (((height_coded >> 4) + 7) >> 3)));
+ h265e_framerc_bufsize *= 6;
+ if (num_vpp_pipes > 1)
+ h265e_framerc_bufsize =
+ ALIGN(h265e_framerc_bufsize, 256) * num_vpp_pipes;
+
+ h265e_framerc_bufsize =
+ ALIGN(h265e_framerc_bufsize, 512) * HFI_MAX_COL_FRAME;
+ h265e_lcubitcnt_bufsize = 256 + 4 * frame_num_lcu;
+ h265e_lcubitcnt_bufsize = ALIGN(h265e_lcubitcnt_bufsize, 256);
+ h265e_lcubitmap_bufsize = 256 + (frame_num_lcu >> 3);
+ h265e_lcubitmap_bufsize = ALIGN(h265e_lcubitmap_bufsize, 256);
+ line_buf_sde_size = 256 + 16 * (width_coded >> 4);
+ line_buf_sde_size = ALIGN(line_buf_sde_size, 256);
+ if ((width_coded * height_coded) > (4096 * 2160))
+ se_stats_bufsize = 0;
+ else if ((width_coded * height_coded) > (1920 * 1088))
+ se_stats_bufsize = (40 * 4 * frame_num_lcu + 256 + 256);
+ else
+ se_stats_bufsize = (1024 * frame_num_lcu + 256 + 256);
+
+ se_stats_bufsize = ALIGN(se_stats_bufsize, 256) * 2;
+ bse_slice_cmd_buffer_size = (((8192 << 2) + 7) & (~7)) * 6;
+ bse_reg_buffer_size = (((512 << 3) + 7) & (~7)) * 4;
+ vpp_reg_buffer_size = (((2048 << 3) + 31) & (~31)) * 10;
+ lambda_lut_size = 256 * 11;
+ override_buffer_size = 16 * ((num_lcu_mb + 7) >> 3);
+ override_buffer_size = ALIGN(override_buffer_size, 256) * 2;
+ ir_buffer_size = (((frame_num_lcu << 1) + 7) & (~7)) * 3;
+ vpss_line_buffer_size_1 = (((8192 >> 2) << 5) * num_vpp_pipes) + 64;
+ vpss_line_buf =
+ (((((max(width_coded, height_coded) + 3) >> 2) << 5) + 256) *
+ 16) +
+ vpss_line_buffer_size_1;
+ topline_bufsize_fe_1stg_sao = 16 * (width_coded >> 5);
+ topline_bufsize_fe_1stg_sao = ALIGN(topline_bufsize_fe_1stg_sao, 256);
+
+ return line_buf_ctrl_size + line_buf_data_size +
+ line_buf_ctrl_size_buffid2 + leftline_buf_ctrl_size +
+ vpss_line_buf + col_mv_buf_size + topline_buf_ctrl_size_FE +
+ leftline_buf_ctrl_size_FE + line_buf_recon_pix_size +
+ leftline_buf_recon_pix_size + leftline_buf_meta_recony +
+ linebuf_meta_recon_uv + h265e_colrcbuf_size +
+ h265e_framerc_bufsize + h265e_lcubitcnt_bufsize +
+ h265e_lcubitmap_bufsize + line_buf_sde_size +
+ topline_bufsize_fe_1stg_sao + override_buffer_size +
+ bse_reg_buffer_size + vpp_reg_buffer_size + sps_pps_slice_hdr +
+ slice_cmd_buffer_size + bse_slice_cmd_buffer_size +
+ ir_buffer_size + slice_info_bufsize + lambda_lut_size +
+ se_stats_bufsize + 1024;
+}
+
+static u32 iris_vpu_enc_scratch1_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 frame_height = f->fmt.pix_mp.height;
+ u32 frame_width = f->fmt.pix_mp.width;
+ u32 num_ref = 1;
+ u32 lcu_size;
+ bool is_h265;
+
+ if (inst->codec == V4L2_PIX_FMT_H264) {
+ lcu_size = 16;
+ is_h265 = false;
+ } else if (inst->codec == V4L2_PIX_FMT_HEVC) {
+ lcu_size = 32;
+ is_h265 = true;
+ } else {
+ return 0;
+ }
+
+ return hfi_buffer_scratch1_enc(frame_width, frame_height, lcu_size,
+ num_ref, false, num_vpp_pipes, is_h265);
+}
+
+static inline u32 ubwc_metadata_plane_stride(u32 width,
+ u32 metadata_stride_multi,
+ u32 tile_width_pels)
+{
+ return ALIGN(((width + (tile_width_pels - 1)) / tile_width_pels),
+ metadata_stride_multi);
+}
+
+static inline u32 ubwc_metadata_plane_bufheight(u32 height,
+ u32 metadata_height_multi,
+ u32 tile_height_pels)
+{
+ return ALIGN(((height + (tile_height_pels - 1)) / tile_height_pels),
+ metadata_height_multi);
+}
+
+static inline u32 ubwc_metadata_plane_buffer_size(u32 metadata_stride,
+ u32 metadata_buf_height)
+{
+ return ALIGN(metadata_stride * metadata_buf_height, SZ_4K);
+}
+
+static inline u32 hfi_buffer_scratch2_enc(u32 frame_width, u32 frame_height,
+ u32 num_ref, bool ten_bit)
+{
+ u32 aligned_width, aligned_height, chroma_height, ref_buf_height;
+ u32 metadata_stride, meta_buf_height, meta_size_y, meta_size_c;
+ u32 ref_luma_stride_bytes, ref_chroma_height_bytes;
+ u32 ref_buf_size, ref_stride;
+ u32 luma_size, chroma_size;
+ u32 size;
+
+ if (!ten_bit) {
+ aligned_height = ALIGN(frame_height, 32);
+ chroma_height = frame_height >> 1;
+ chroma_height = ALIGN(chroma_height, 32);
+ aligned_width = ALIGN(frame_width, 128);
+ metadata_stride =
+ ubwc_metadata_plane_stride(frame_width, 64, 32);
+ meta_buf_height =
+ ubwc_metadata_plane_bufheight(frame_height, 16, 8);
+ meta_size_y = ubwc_metadata_plane_buffer_size(metadata_stride,
+ meta_buf_height);
+ meta_size_c = ubwc_metadata_plane_buffer_size(metadata_stride,
+ meta_buf_height);
+ size = (aligned_height + chroma_height) * aligned_width +
+ meta_size_y + meta_size_c;
+ size = (size * (num_ref + 3)) + 4096;
+ } else {
+ ref_buf_height = (frame_height + (32 - 1)) & (~(32 - 1));
+ ref_luma_stride_bytes = ((frame_width + 192 - 1) / 192) * 192;
+ ref_stride = 4 * (ref_luma_stride_bytes / 3);
+ ref_stride = (ref_stride + (128 - 1)) & (~(128 - 1));
+ luma_size = ref_buf_height * ref_stride;
+ ref_chroma_height_bytes =
+ (((frame_height + 1) >> 1) + (32 - 1)) & (~(32 - 1));
+ chroma_size = ref_stride * ref_chroma_height_bytes;
+ luma_size = (luma_size + (SZ_4K - 1)) & (~(SZ_4K - 1));
+ chroma_size = (chroma_size + (SZ_4K - 1)) & (~(SZ_4K - 1));
+ ref_buf_size = luma_size + chroma_size;
+ metadata_stride =
+ ubwc_metadata_plane_stride(frame_width, 64, 48);
+ meta_buf_height =
+ ubwc_metadata_plane_bufheight(frame_height, 16, 4);
+ meta_size_y = ubwc_metadata_plane_buffer_size(metadata_stride,
+ meta_buf_height);
+ meta_size_c = ubwc_metadata_plane_buffer_size(metadata_stride,
+ meta_buf_height);
+ size = ref_buf_size + meta_size_y + meta_size_c;
+ size = (size * (num_ref + 3)) + 4096;
+ }
+
+ return size;
+}
+
+static u32 iris_vpu_enc_scratch2_size(struct iris_inst *inst)
+{
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 frame_width = f->fmt.pix_mp.width;
+ u32 frame_height = f->fmt.pix_mp.height;
+ u32 num_ref = 1;
+
+ return hfi_buffer_scratch2_enc(frame_width, frame_height, num_ref,
+ false);
+}
+
+static u32 iris_vpu_enc_vpss_size(struct iris_inst *inst)
+{
+ u32 ds_enable = is_scaling_enabled(inst);
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+
+ return hfi_buffer_vpss_enc(width, height, ds_enable, 0, 0);
+}
+
static int output_min_count(struct iris_inst *inst)
{
int output_min_count = 4;
@@ -573,8 +1388,8 @@ struct iris_vpu_buf_type_handle {
int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
{
- const struct iris_vpu_buf_type_handle *buf_type_handle_arr;
- u32 size = 0, buf_type_handle_size, i;
+ const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL;
+ u32 size = 0, buf_type_handle_size = 0, i;
static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = {
{BUF_BIN, iris_vpu_dec_bin_size },
@@ -586,8 +1401,24 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
{BUF_SCRATCH_1, iris_vpu_dec_scratch1_size },
};
- buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle);
- buf_type_handle_arr = dec_internal_buf_type_handle;
+ static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = {
+ {BUF_BIN, iris_vpu_enc_bin_size },
+ {BUF_COMV, iris_vpu_enc_comv_size },
+ {BUF_NON_COMV, iris_vpu_enc_non_comv_size },
+ {BUF_LINE, iris_vpu_enc_line_size },
+ {BUF_ARP, iris_vpu_enc_arp_size },
+ {BUF_VPSS, iris_vpu_enc_vpss_size },
+ {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size },
+ {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size },
+ };
+
+ if (inst->domain == DECODER) {
+ buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle);
+ buf_type_handle_arr = dec_internal_buf_type_handle;
+ } else if (inst->domain == ENCODER) {
+ buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle);
+ buf_type_handle_arr = enc_internal_buf_type_handle;
+ }
for (i = 0; i < buf_type_handle_size; i++) {
if (buf_type_handle_arr[i].type == buffer_type) {
@@ -639,6 +1470,9 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type
case BUF_PERSIST:
return internal_buffer_count(inst, buffer_type);
case BUF_SCRATCH_1:
+ case BUF_SCRATCH_2:
+ case BUF_VPSS:
+ case BUF_ARP:
return 1; /* internal buffer count needed by firmware is 1 */
case BUF_DPB:
return iris_vpu_dpb_count(inst);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
index ee95fd20b794c52d0070c93224bd4ee5e4e180d5..1ff1b07ecbaa85345ca948affeb1c4a1c55e36b0 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
@@ -80,6 +80,26 @@ struct iris_inst;
#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384
#define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640
+#define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, 256))
+#define SIZE_SPS_PPS_SLICE_HDR (2048 + 4096)
+#define SIZE_BSE_SLICE_CMD_BUF ((((8192 << 2) + 7) & (~7)) * 3)
+#define SIZE_LAMBDA_LUT (256 * 11)
+
+#define HFI_COL_FMT_NV12C_Y_TILE_HEIGHT (8)
+#define HFI_COL_FMT_NV12C_Y_TILE_WIDTH (32)
+#define HFI_COL_FMT_TP10C_Y_TILE_HEIGHT (4)
+#define HFI_COL_FMT_TP10C_Y_TILE_WIDTH (48)
+
+#define IRIS_METADATA_STRIDE_MULTIPLE 64
+#define IRIS_METADATA_HEIGHT_MULTIPLE 16
+
+#define HFI_BUFFER_ARP_ENC 204800
+
+#define MAX_WIDTH 4096
+#define MAX_HEIGHT 2304
+#define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16))
+#define NUM_MBS_720P (((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4))
+
static inline u32 size_h264d_lb_fe_top_data(u32 frame_width)
{
return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3;
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 23/24] media: iris: Add support for buffer management ioctls for encoder device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (21 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 22/24] media: iris: Allocate and queue internal buffers " Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 24/24] media: iris: Add support for drain sequence in encoder video device Dikshita Agarwal
2025-08-13 15:27 ` [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Neil Armstrong
24 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Implement support for queuing and dequeuing input and output buffers
for the encoder video device using the appropriate V4L2 buffer
management ioctls.
This enables userspace applications to manage streaming buffers
required for encoding operations.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_common.c | 36 +++++++++++++++
drivers/media/platform/qcom/iris/iris_common.h | 2 +
.../platform/qcom/iris/iris_hfi_gen1_command.c | 53 +++++++++++++++-------
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 37 +++++++++++++++
.../platform/qcom/iris/iris_hfi_gen1_response.c | 43 +++++++++++++-----
.../platform/qcom/iris/iris_hfi_gen2_command.c | 23 ++++++----
.../platform/qcom/iris/iris_hfi_gen2_response.c | 22 ++++++---
drivers/media/platform/qcom/iris/iris_vb2.c | 5 +-
drivers/media/platform/qcom/iris/iris_vdec.c | 40 +---------------
drivers/media/platform/qcom/iris/iris_venc.c | 26 +++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 1 +
drivers/media/platform/qcom/iris/iris_vidc.c | 8 ++++
12 files changed, 215 insertions(+), 81 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c
index d6a9271bcec77f142919070bf0566d0cf8a39562..9fc663bdaf3fc989fe1273b4d4280a87f68de85d 100644
--- a/drivers/media/platform/qcom/iris/iris_common.c
+++ b/drivers/media/platform/qcom/iris/iris_common.c
@@ -10,6 +10,42 @@
#include "iris_instance.h"
#include "iris_power.h"
+int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+
+ buf->type = iris_v4l2_type_to_driver(vb2->type);
+ buf->index = vb2->index;
+ buf->fd = vb2->planes[0].m.fd;
+ buf->buffer_size = vb2->planes[0].length;
+ buf->data_offset = vb2->planes[0].data_offset;
+ buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset;
+ buf->flags = vbuf->flags;
+ buf->timestamp = vb2->timestamp;
+ buf->attr = 0;
+
+ return 0;
+}
+
+void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
+{
+ u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ struct vb2_buffer *vb = &vbuf->vb2_buf;
+ u64 ts_us = vb->timestamp;
+
+ if (inst->metadata_idx >= ARRAY_SIZE(inst->tss))
+ inst->metadata_idx = 0;
+
+ do_div(ts_us, NSEC_PER_USEC);
+
+ inst->tss[inst->metadata_idx].flags = vbuf->flags & mask;
+ inst->tss[inst->metadata_idx].tc = vbuf->timecode;
+ inst->tss[inst->metadata_idx].ts_us = ts_us;
+ inst->tss[inst->metadata_idx].ts_ns = vb->timestamp;
+
+ inst->metadata_idx++;
+}
+
int iris_process_streamon_input(struct iris_inst *inst)
{
const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h
index f385eeb53910555f17602f3951e7a6e9636a9ba2..b2a27b781c9aceb60ff43eff855d759ea95e23d9 100644
--- a/drivers/media/platform/qcom/iris/iris_common.h
+++ b/drivers/media/platform/qcom/iris/iris_common.h
@@ -9,6 +9,8 @@
struct iris_inst;
struct iris_buffer;
+int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf);
+void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);
int iris_process_streamon_input(struct iris_inst *inst);
int iris_process_streamon_output(struct iris_inst *inst);
int iris_session_streamoff(struct iris_inst *inst, u32 plane);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 7d73914b30a1b656e06d9f36de563a8713105301..29c8dfa684e3bd5815f7b844ba4d9c6c324c697b 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -278,23 +278,44 @@ static int iris_hfi_gen1_session_continue(struct iris_inst *inst, u32 plane)
static int iris_hfi_gen1_queue_input_buffer(struct iris_inst *inst, struct iris_buffer *buf)
{
- struct hfi_session_empty_buffer_compressed_pkt ip_pkt;
+ struct hfi_session_empty_buffer_compressed_pkt com_ip_pkt;
+ struct hfi_session_empty_buffer_uncompressed_pkt uncom_ip_pkt;
- ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt);
- ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
- ip_pkt.shdr.session_id = inst->session_id;
- ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp);
- ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp);
- ip_pkt.flags = buf->flags;
- ip_pkt.mark_target = 0;
- ip_pkt.mark_data = 0;
- ip_pkt.offset = buf->data_offset;
- ip_pkt.alloc_len = buf->buffer_size;
- ip_pkt.filled_len = buf->data_size;
- ip_pkt.input_tag = buf->index;
- ip_pkt.packet_buffer = buf->device_addr;
-
- return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
+ if (inst->domain == DECODER) {
+ com_ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt);
+ com_ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ com_ip_pkt.shdr.session_id = inst->session_id;
+ com_ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp);
+ com_ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp);
+ com_ip_pkt.flags = buf->flags;
+ com_ip_pkt.mark_target = 0;
+ com_ip_pkt.mark_data = 0;
+ com_ip_pkt.offset = buf->data_offset;
+ com_ip_pkt.alloc_len = buf->buffer_size;
+ com_ip_pkt.filled_len = buf->data_size;
+ com_ip_pkt.input_tag = buf->index;
+ com_ip_pkt.packet_buffer = buf->device_addr;
+ return iris_hfi_queue_cmd_write(inst->core, &com_ip_pkt,
+ com_ip_pkt.shdr.hdr.size);
+ } else {
+ uncom_ip_pkt.shdr.hdr.size =
+ sizeof(struct hfi_session_empty_buffer_uncompressed_pkt);
+ uncom_ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ uncom_ip_pkt.shdr.session_id = inst->session_id;
+ uncom_ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp);
+ uncom_ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp);
+ uncom_ip_pkt.view_id = 0;
+ uncom_ip_pkt.flags = buf->flags;
+ uncom_ip_pkt.mark_target = 0;
+ uncom_ip_pkt.mark_data = 0;
+ uncom_ip_pkt.offset = buf->data_offset;
+ uncom_ip_pkt.alloc_len = buf->buffer_size;
+ uncom_ip_pkt.filled_len = buf->data_size;
+ uncom_ip_pkt.input_tag = buf->index;
+ uncom_ip_pkt.packet_buffer = buf->device_addr;
+ return iris_hfi_queue_cmd_write(inst->core, &uncom_ip_pkt,
+ uncom_ip_pkt.shdr.hdr.size);
+ }
}
static int iris_hfi_gen1_queue_output_buffer(struct iris_inst *inst, struct iris_buffer *buf)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index 21853921483b90604b69001064550a50bb9629ad..42226ccee3d9b9eb5f793c3be127acd8afad2138 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -216,6 +216,23 @@ struct hfi_session_empty_buffer_compressed_pkt {
u32 data;
};
+struct hfi_session_empty_buffer_uncompressed_pkt {
+ struct hfi_session_hdr_pkt shdr;
+ u32 view_id;
+ u32 time_stamp_hi;
+ u32 time_stamp_lo;
+ u32 flags;
+ u32 mark_target;
+ u32 mark_data;
+ u32 alloc_len;
+ u32 filled_len;
+ u32 offset;
+ u32 input_tag;
+ u32 packet_buffer;
+ u32 extradata_buffer;
+ u32 data;
+};
+
struct hfi_session_fill_buffer_pkt {
struct hfi_session_hdr_pkt shdr;
u32 stream_id;
@@ -461,6 +478,26 @@ struct hfi_msg_session_empty_buffer_done_pkt {
u32 data[];
};
+struct hfi_msg_session_fbd_compressed_pkt {
+ struct hfi_session_hdr_pkt shdr;
+ u32 time_stamp_hi;
+ u32 time_stamp_lo;
+ u32 error_type;
+ u32 flags;
+ u32 mark_target;
+ u32 mark_data;
+ u32 stats;
+ u32 offset;
+ u32 alloc_len;
+ u32 filled_len;
+ u32 input_tag;
+ u32 output_tag;
+ u32 picture_type;
+ u32 packet_buffer;
+ u32 extradata_buffer;
+ u32 data[];
+};
+
struct hfi_msg_session_fbd_uncompressed_plane0_pkt {
struct hfi_session_hdr_pkt shdr;
u32 stream_id;
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index 82d3e8de7bff0ac53a971b4763ae848ff8c61ff2..a55d214c84048c6a3ac19a041c0f78f7e58918b8 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -387,24 +387,43 @@ static void iris_hfi_gen1_session_etb_done(struct iris_inst *inst, void *packet)
static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
{
- struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet;
+ struct hfi_msg_session_fbd_uncompressed_plane0_pkt *uncom_pkt = packet;
+ struct hfi_msg_session_fbd_compressed_pkt *com_pkt = packet;
struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
struct v4l2_m2m_buffer *m2m_buffer, *n;
struct hfi_session_flush_pkt flush_pkt;
- u32 timestamp_hi = pkt->time_stamp_hi;
- u32 timestamp_lo = pkt->time_stamp_lo;
+ u32 timestamp_hi;
+ u32 timestamp_lo;
struct iris_core *core = inst->core;
- u32 filled_len = pkt->filled_len;
- u32 pic_type = pkt->picture_type;
- u32 output_tag = pkt->output_tag;
+ u32 filled_len;
+ u32 pic_type;
+ u32 output_tag;
struct iris_buffer *buf, *iter;
struct iris_buffers *buffers;
- u32 hfi_flags = pkt->flags;
- u32 offset = pkt->offset;
+ u32 hfi_flags;
+ u32 offset;
u64 timestamp_us = 0;
bool found = false;
u32 flags = 0;
+ if (inst->domain == DECODER) {
+ timestamp_hi = uncom_pkt->time_stamp_hi;
+ timestamp_lo = uncom_pkt->time_stamp_lo;
+ filled_len = uncom_pkt->filled_len;
+ pic_type = uncom_pkt->picture_type;
+ output_tag = uncom_pkt->output_tag;
+ hfi_flags = uncom_pkt->flags;
+ offset = uncom_pkt->offset;
+ } else {
+ timestamp_hi = com_pkt->time_stamp_hi;
+ timestamp_lo = com_pkt->time_stamp_lo;
+ filled_len = com_pkt->filled_len;
+ pic_type = com_pkt->picture_type;
+ output_tag = com_pkt->output_tag;
+ hfi_flags = com_pkt->flags;
+ offset = com_pkt->offset;
+ }
+
if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) {
reinit_completion(&inst->flush_completion);
@@ -418,7 +437,8 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
iris_inst_sub_state_change_drain_last(inst);
}
- if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) {
+ if (iris_split_mode_enabled(inst) && inst->domain == DECODER &&
+ uncom_pkt->stream_id == 0) {
buffers = &inst->buffers[BUF_DPB];
if (!buffers)
goto error;
@@ -459,7 +479,8 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
timestamp_us = timestamp_hi;
timestamp_us = (timestamp_us << 32) | timestamp_lo;
} else {
- if (pkt->stream_id == 1 && !inst->last_buffer_dequeued) {
+ if (inst->domain == DECODER && uncom_pkt->stream_id == 1 &&
+ !inst->last_buffer_dequeued) {
if (iris_drc_pending(inst) || iris_drain_pending(inst)) {
flags |= V4L2_BUF_FLAG_LAST;
inst->last_buffer_dequeued = true;
@@ -551,7 +572,7 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = {
},
{
.pkt = HFI_MSG_SESSION_FILL_BUFFER,
- .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
+ .pkt_sz = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
},
{
.pkt = HFI_MSG_SESSION_FLUSH,
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
index c71be09211bdc41fdb38551a6c416d1d252bec56..c97e4910e8528df1e18f9a68b956c9fdea03d29a 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -1043,13 +1043,19 @@ static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane)
inst_hfi_gen2->packet->size);
}
-static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
+static u32 iris_hfi_gen2_buf_type_from_driver(u32 domain, enum iris_buffer_type buffer_type)
{
switch (buffer_type) {
case BUF_INPUT:
- return HFI_BUFFER_BITSTREAM;
+ if (domain == DECODER)
+ return HFI_BUFFER_BITSTREAM;
+ else
+ return HFI_BUFFER_RAW;
case BUF_OUTPUT:
- return HFI_BUFFER_RAW;
+ if (domain == DECODER)
+ return HFI_BUFFER_RAW;
+ else
+ return HFI_BUFFER_BITSTREAM;
case BUF_BIN:
return HFI_BUFFER_BIN;
case BUF_COMV:
@@ -1089,16 +1095,17 @@ static int iris_set_num_comv(struct iris_inst *inst)
&num_comv, sizeof(u32));
}
-static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf)
+static void iris_hfi_gen2_get_buffer(u32 domain, struct iris_buffer *buffer,
+ struct iris_hfi_buffer *buf)
{
memset(buf, 0, sizeof(*buf));
- buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type);
+ buf->type = iris_hfi_gen2_buf_type_from_driver(domain, buffer->type);
buf->index = buffer->index;
buf->base_address = buffer->device_addr;
buf->addr_offset = 0;
buf->buffer_size = buffer->buffer_size;
- if (buffer->type == BUF_INPUT)
+ if (domain == DECODER && buffer->type == BUF_INPUT)
buf->buffer_size = ALIGN(buffer->buffer_size, 256);
buf->data_offset = buffer->data_offset;
buf->data_size = buffer->data_size;
@@ -1115,7 +1122,7 @@ static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iri
u32 port;
int ret;
- iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
+ iris_hfi_gen2_get_buffer(inst->domain, buffer, &hfi_buffer);
if (buffer->type == BUF_COMV) {
ret = iris_set_num_comv(inst);
if (ret)
@@ -1142,7 +1149,7 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i
struct iris_hfi_buffer hfi_buffer;
u32 port;
- iris_hfi_gen2_get_buffer(buffer, &hfi_buffer);
+ iris_hfi_gen2_get_buffer(inst->domain, buffer, &hfi_buffer);
hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE;
port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
index 6b8e637ac6d82aee8699db59ee2f04de9e715275..2f1f118eae4f6462ab1aa1d16844b34e6e699f1e 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -480,12 +480,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst,
if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type))
return 0;
- if (buffer->type == HFI_BUFFER_BITSTREAM)
- return iris_hfi_gen2_handle_input_buffer(inst, buffer);
- else if (buffer->type == HFI_BUFFER_RAW)
- return iris_hfi_gen2_handle_output_buffer(inst, buffer);
- else
- return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer);
+ if (inst->domain == DECODER) {
+ if (buffer->type == HFI_BUFFER_BITSTREAM)
+ return iris_hfi_gen2_handle_input_buffer(inst, buffer);
+ else if (buffer->type == HFI_BUFFER_RAW)
+ return iris_hfi_gen2_handle_output_buffer(inst, buffer);
+ else
+ return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer);
+ } else {
+ if (buffer->type == HFI_BUFFER_RAW)
+ return iris_hfi_gen2_handle_input_buffer(inst, buffer);
+ else if (buffer->type == HFI_BUFFER_BITSTREAM)
+ return iris_hfi_gen2_handle_output_buffer(inst, buffer);
+ else
+ return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer);
+ }
+ return 0;
}
static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst,
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index fbf8ebb74193284dc847c54f76f908656b3098c9..139b821f7952feb33b21a7045aef9e8a4782aa3c 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -327,7 +327,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2)
v4l2_m2m_buf_queue(m2m_ctx, vbuf);
- ret = iris_vdec_qbuf(inst, vbuf);
+ if (inst->domain == DECODER)
+ ret = iris_vdec_qbuf(inst, vbuf);
+ else
+ ret = iris_venc_qbuf(inst, vbuf);
exit:
if (ret) {
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 7669301e2ec24f482b449386e3c31f6e155ee3b7..9ec28234fa9140434c01a6b5461f0a83c6dac6d7 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -377,44 +377,6 @@ int iris_vdec_streamon_output(struct iris_inst *inst)
return ret;
}
-static int
-iris_vdec_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
-
- buf->type = iris_v4l2_type_to_driver(vb2->type);
- buf->index = vb2->index;
- buf->fd = vb2->planes[0].m.fd;
- buf->buffer_size = vb2->planes[0].length;
- buf->data_offset = vb2->planes[0].data_offset;
- buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset;
- buf->flags = vbuf->flags;
- buf->timestamp = vb2->timestamp;
- buf->attr = 0;
-
- return 0;
-}
-
-static void
-iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
-{
- u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- struct vb2_buffer *vb = &vbuf->vb2_buf;
- u64 ts_us = vb->timestamp;
-
- if (inst->metadata_idx >= ARRAY_SIZE(inst->tss))
- inst->metadata_idx = 0;
-
- do_div(ts_us, NSEC_PER_USEC);
-
- inst->tss[inst->metadata_idx].flags = vbuf->flags & mask;
- inst->tss[inst->metadata_idx].tc = vbuf->timecode;
- inst->tss[inst->metadata_idx].ts_us = ts_us;
- inst->tss[inst->metadata_idx].ts_ns = vb->timestamp;
-
- inst->metadata_idx++;
-}
-
int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
{
struct iris_buffer *buf = to_iris_buffer(vbuf);
@@ -422,7 +384,7 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
struct vb2_queue *q;
int ret;
- ret = iris_vdec_vb2_buffer_to_driver(vb2, buf);
+ ret = iris_vb2_buffer_to_driver(vb2, buf);
if (ret)
return ret;
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index bd5e8fc2d48882c4fd57607a0ce5183c65272cf9..1dc79e8fbab8d69d95ebe519d736f5f2f65b2886 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -10,6 +10,7 @@
#include "iris_common.h"
#include "iris_ctrls.h"
#include "iris_instance.h"
+#include "iris_power.h"
#include "iris_venc.h"
#include "iris_vpu_buffer.h"
@@ -493,3 +494,28 @@ int iris_venc_streamon_output(struct iris_inst *inst)
return ret;
}
+
+int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
+{
+ struct iris_buffer *buf = to_iris_buffer(vbuf);
+ struct vb2_buffer *vb2 = &vbuf->vb2_buf;
+ struct vb2_queue *q;
+ int ret;
+
+ ret = iris_vb2_buffer_to_driver(vb2, buf);
+ if (ret)
+ return ret;
+
+ if (buf->type == BUF_INPUT)
+ iris_set_ts_metadata(inst, vbuf);
+
+ q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type);
+ if (!vb2_is_streaming(q)) {
+ buf->attr |= BUF_ATTR_DEFERRED;
+ return 0;
+ }
+
+ iris_scale_power(inst);
+
+ return iris_queue_buffer(inst, buf);
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index 941b5c186e4550e3eb6325d5ae3eeac4fcee4675..bbf3b635288dd6cc39719bdde1942918357791aa 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -20,5 +20,6 @@ int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
int iris_venc_streamon_input(struct iris_inst *inst);
int iris_venc_streamon_output(struct iris_inst *inst);
+int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 03492647429b4f30e907e11d463c36f6b8502116..751e6b81a07e1a3a116b3da22f28bee281c5982c 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -666,6 +666,14 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_g_parm = iris_g_parm,
.vidioc_streamon = v4l2_m2m_ioctl_streamon,
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 24/24] media: iris: Add support for drain sequence in encoder video device
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (22 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 23/24] media: iris: Add support for buffer management ioctls for encoder device Dikshita Agarwal
@ 2025-08-13 9:38 ` Dikshita Agarwal
2025-08-13 15:27 ` [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Neil Armstrong
24 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 9:38 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang, Dikshita Agarwal
Add support for handling start and stop commands, including the
end-of-stream (drain) sequence, in the encoder video device.
This enables proper signaling to the firmware and ensures that all
pending frames are processed and flushed before completing the stream.
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
.../platform/qcom/iris/iris_hfi_gen1_command.c | 30 ++++++++---
.../platform/qcom/iris/iris_hfi_gen1_response.c | 5 ++
drivers/media/platform/qcom/iris/iris_state.c | 4 +-
drivers/media/platform/qcom/iris/iris_venc.c | 58 ++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_venc.h | 2 +
drivers/media/platform/qcom/iris/iris_vidc.c | 35 +++++++++++++
6 files changed, 125 insertions(+), 9 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 29c8dfa684e3bd5815f7b844ba4d9c6c324c697b..6d28bb51483ea0e2fad866390d42e1ac22d78566 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -455,15 +455,31 @@ static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct ir
static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane)
{
- struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0};
+ if (inst->domain == DECODER) {
+ struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0};
+
+ ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt);
+ ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ ip_pkt.shdr.session_id = inst->session_id;
+ ip_pkt.flags = HFI_BUFFERFLAG_EOS;
+ ip_pkt.packet_buffer = 0xdeadb000;
+
+ return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
+ }
- ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt);
- ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
- ip_pkt.shdr.session_id = inst->session_id;
- ip_pkt.flags = HFI_BUFFERFLAG_EOS;
- ip_pkt.packet_buffer = 0xdeadb000;
+ if (inst->domain == ENCODER) {
+ struct hfi_session_empty_buffer_uncompressed_pkt ip_pkt = {0};
+
+ ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_uncompressed_pkt);
+ ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ ip_pkt.shdr.session_id = inst->session_id;
+ ip_pkt.flags = HFI_BUFFERFLAG_EOS;
+ ip_pkt.packet_buffer = 0xdeadb000;
+
+ return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
+ }
- return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
+ return -EINVAL;
}
static int
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index a55d214c84048c6a3ac19a041c0f78f7e58918b8..8e864c239e293e004d21e9c3604d3e985c15d9bd 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -485,6 +485,11 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
flags |= V4L2_BUF_FLAG_LAST;
inst->last_buffer_dequeued = true;
}
+ } else if (inst->domain == ENCODER) {
+ if (!inst->last_buffer_dequeued && iris_drain_pending(inst)) {
+ flags |= V4L2_BUF_FLAG_LAST;
+ inst->last_buffer_dequeued = true;
+ }
}
}
buf->timestamp = timestamp_us;
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index d1dc1a863da0b0b1af60974e9ed2ef68ea225cdd..d14472414750dc7edc4834f32a51f2c5adc3762e 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -263,11 +263,11 @@ bool iris_allow_cmd(struct iris_inst *inst, u32 cmd)
struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
- if (cmd == V4L2_DEC_CMD_START) {
+ if (cmd == V4L2_DEC_CMD_START || cmd == V4L2_ENC_CMD_START) {
if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q))
if (iris_drc_pending(inst) || iris_drain_pending(inst))
return true;
- } else if (cmd == V4L2_DEC_CMD_STOP) {
+ } else if (cmd == V4L2_DEC_CMD_STOP || cmd == V4L2_ENC_CMD_STOP) {
if (vb2_is_streaming(src_q))
if (inst->sub_state != IRIS_INST_SUB_DRAIN)
return true;
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 1dc79e8fbab8d69d95ebe519d736f5f2f65b2886..719baa3f82f01fdc10f0eb6c2460186b141ae1e9 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -519,3 +519,61 @@ int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
return iris_queue_buffer(inst, buf);
}
+
+int iris_venc_start_cmd(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ enum iris_inst_sub_state clear_sub_state = 0;
+ struct vb2_queue *dst_vq;
+ int ret;
+
+ dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
+
+ if (inst->sub_state & IRIS_INST_SUB_DRAIN &&
+ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) {
+ vb2_clear_last_buffer_dequeued(dst_vq);
+ clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
+ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+ if (hfi_ops->session_resume_drain) {
+ ret = hfi_ops->session_resume_drain(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ }
+ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
+ }
+ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) {
+ if (hfi_ops->session_resume_drain) {
+ ret = hfi_ops->session_resume_drain(inst,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ return ret;
+ }
+ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
+ }
+ } else {
+ dev_err(inst->core->dev, "start called before receiving last_flag\n");
+ iris_inst_change_state(inst, IRIS_INST_ERROR);
+ return -EBUSY;
+ }
+
+ inst->last_buffer_dequeued = false;
+
+ return iris_inst_change_sub_state(inst, clear_sub_state, 0);
+}
+
+int iris_venc_stop_cmd(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ int ret;
+
+ ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN);
+
+ iris_scale_power(inst);
+
+ return ret;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
index bbf3b635288dd6cc39719bdde1942918357791aa..c4db7433da537578e05d566d53d89a22e1901678 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -21,5 +21,7 @@ int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
int iris_venc_streamon_input(struct iris_inst *inst);
int iris_venc_streamon_output(struct iris_inst *inst);
int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);
+int iris_venc_start_cmd(struct iris_inst *inst);
+int iris_venc_stop_cmd(struct iris_inst *inst);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 751e6b81a07e1a3a116b3da22f28bee281c5982c..db59ddde12037ce62200177728deb55a0e5e23dd 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -599,6 +599,39 @@ static int iris_dec_cmd(struct file *filp, void *fh,
return ret;
}
+static int iris_enc_cmd(struct file *filp, void *fh,
+ struct v4l2_encoder_cmd *enc)
+{
+ struct iris_inst *inst = iris_get_inst(filp, NULL);
+ int ret = 0;
+
+ mutex_lock(&inst->lock);
+
+ ret = v4l2_m2m_ioctl_encoder_cmd(filp, fh, enc);
+ if (ret)
+ goto unlock;
+
+ if (inst->state == IRIS_INST_DEINIT)
+ goto unlock;
+
+ if (!iris_allow_cmd(inst, enc->cmd)) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ if (enc->cmd == V4L2_ENC_CMD_START)
+ ret = iris_venc_start_cmd(inst);
+ else if (enc->cmd == V4L2_ENC_CMD_STOP)
+ ret = iris_venc_stop_cmd(inst);
+ else
+ ret = -EINVAL;
+
+unlock:
+ mutex_unlock(&inst->lock);
+
+ return ret;
+}
+
static struct v4l2_file_operations iris_v4l2_file_ops = {
.owner = THIS_MODULE,
.open = iris_open,
@@ -674,6 +707,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
.vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs,
+ .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
+ .vidioc_encoder_cmd = iris_enc_cmd,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close
2025-08-13 9:37 ` [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close Dikshita Agarwal
@ 2025-08-13 10:53 ` Jorge Ramirez
2025-08-13 12:16 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Jorge Ramirez @ 2025-08-13 10:53 UTC (permalink / raw)
To: Dikshita Agarwal
Cc: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar,
linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/25 15:07:52, Dikshita Agarwal wrote:
> Add error reporting for unreleased PERSIST internal buffers in
> iris_check_num_queued_internal_buffers(). This ensures all buffer types
> are checked and logged if not freed during session close, helping to
> detect memory leaks and improve driver robustness. No change to buffer
> lifecycle or allocation logic.
>
> Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release on close")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_vidc.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 8285bdaf9466d4bea0f89a3b1943ed7d6c014b7d..96313856a026efaff40da97eaaa63e847172cd57 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -247,6 +247,14 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p
> dev_err(inst->core->dev, "%d buffer of type %d not released",
> count, internal_buf_type[i]);
> }
> +
> + buffers = &inst->buffers[BUF_PERSIST];
> +
> + count = 0;
> + list_for_each_entry_safe(buf, next, &buffers->list, list)
> + count++;
I believe at this point is not safe to dereference buf
> + if (count)
> + dev_err(inst->core->dev, "%d buffer of type %d not released", count, buf->type);
> }
>
> int iris_close(struct file *filp)
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close
2025-08-13 10:53 ` Jorge Ramirez
@ 2025-08-13 12:16 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-13 12:16 UTC (permalink / raw)
To: Jorge Ramirez
Cc: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar,
linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 4:23 PM, Jorge Ramirez wrote:
> On 13/08/25 15:07:52, Dikshita Agarwal wrote:
>> Add error reporting for unreleased PERSIST internal buffers in
>> iris_check_num_queued_internal_buffers(). This ensures all buffer types
>> are checked and logged if not freed during session close, helping to
>> detect memory leaks and improve driver robustness. No change to buffer
>> lifecycle or allocation logic.
>>
>> Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release on close")
>> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/iris_vidc.c | 8 ++++++++
>> 1 file changed, 8 insertions(+)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
>> index 8285bdaf9466d4bea0f89a3b1943ed7d6c014b7d..96313856a026efaff40da97eaaa63e847172cd57 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
>> @@ -247,6 +247,14 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p
>> dev_err(inst->core->dev, "%d buffer of type %d not released",
>> count, internal_buf_type[i]);
>> }
>> +
>> + buffers = &inst->buffers[BUF_PERSIST];
>> +
>> + count = 0;
>> + list_for_each_entry_safe(buf, next, &buffers->list, list)
>> + count++;
>
> I believe at this point is not safe to dereference buf
You are right, I fixed it in later patch, but it should be fixed in this
patch instead. Will make the change.
Thanks,
Dikshita
>
>> + if (count)
>> + dev_err(inst->core->dev, "%d buffer of type %d not released", count, buf->type);
>> }
>>
>> int iris_close(struct file *filp)
>>
>> --
>> 2.34.1
>>
>>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
` (23 preceding siblings ...)
2025-08-13 9:38 ` [PATCH v2 24/24] media: iris: Add support for drain sequence in encoder video device Dikshita Agarwal
@ 2025-08-13 15:27 ` Neil Armstrong
2025-08-18 11:47 ` Dikshita Agarwal
24 siblings, 1 reply; 69+ messages in thread
From: Neil Armstrong @ 2025-08-13 15:27 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Bryan O'Donoghue, Mauro Carvalho Chehab, Hans Verkuil,
Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 11:37, Dikshita Agarwal wrote:
> Hi All,
>
> This patch series adds support for H.264 and H.265 encoder in iris
> driver and includes a few fixes and cleanup in the common code that were
> identified during encoder bring-up process.
>
> The changes include:
> - Enabling support for H.264 and H.265 encoding.
> - Fixes and improvements in shared componenets used by both encoder and
> decoder paths.
> - Ensuring compatibility and stability with the existing decoder flow.
>
> Changes in v2:
> - Fixed sparse/coccinnelle issues.
> - Fixed the kernel doc warning.
> - Removed unsupported PEAK_BITRATE property from SM8250.
> - Dropped patch 04/25 to fix quality issue with encoder.
> - Enhanced command handling for encoder to allow start/stop commands.
> - Expanded rate control condition checks to include additional rate
> control types for HFI Gen2.
> - Updated default value to MAX_QP for all caps related to max QP settings.
> - Add support for INPUT/OUTPUT_BUF_HOST_MAX_COUNT caps for encoder.
> - Link to v1: https://lore.kernel.org/r/20250704-iris-video-encoder-v1-0-b6ce24e273cf@quicinc.com
>
> All patches have been tested with v4l2-compliance, v4l2-ctl and
> Gstreamer on SM8250 and SM8550 for encoder, at the same time ensured
> that the existing decoder functionality remains uneffected.
>
> Commands used for V4l2-ctl validation:
>
> v4l2-ctl --verbose --set-fmt-video-out=width=1280,height=720,pixelformat=NV12
> --set-selection-output target=crop,top=0,left=0,width=1280,height=720
> --set-fmt-video=pixelformat=H264 --stream-mmap --stream-out-mmap
> --stream-from=/media/cyclists_1280x720_92frames.yuv
> --stream-to=/tmp/cyclists_1280x720_92frames.h264 -d /dev/video1
>
> v4l2-ctl --verbose --set-fmt-video-out=width=1280,height=720,pixelformat=NV12
> --set-selection-output target=crop,top=0,left=0,width=1280,height=720
> --set-fmt-video=pixelformat=HEVC --stream-mmap --stream-out-mmap
> --stream-from=/media/cyclists_1280x720_92frames.yuv
> --stream-to=/tmp/cyclists_1280x720_92frames.hevc -d /dev/video1
>
> Commands used for GST validation:
>
> gst-launch-1.0 -v filesrc location=/media/cyclists_1280x720_92frames.yuv !
> rawvideoparse format=nv12 width=1280 height=720 framerate=30/1 ! v4l2h264enc
> capture-io-mode=4 output-io-mode=4 ! filesink sync=true
> location=/tmp/gst_cyclists_1280x720_92frames.h264
>
> gst-launch-1.0 -v filesrc location=/media/cyclists_1280x720_92frames.yuv !
> rawvideoparse format=nv12 width=1280 height=720 framerate=30/1 ! v4l2h265enc
> capture-io-mode=4 output-io-mode=4 ! filesink sync=true
> location=/tmp/gst_cyclists_1280x720_92frames.hevc
>
> The result of v4l2-compliance on SM8550:
> v4l2-compliance 1.29.0-5270, 64 bits, 64-bit time_t
> v4l2-compliance SHA: dc947661089e 2024-11-11 10:25:38
>
> Compliance test for iris_driver device /dev/video1:
>
> Driver Info:
> Driver name : iris_driver
> Card type : Iris Encoder
> Bus info : platform:aa00000.video-codec
> Driver version : 6.16.0
> Capabilities : 0x84204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps : 0x04204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
> Detected Stateful Encoder
>
> Required ioctls:
> test VIDIOC_QUERYCAP: OK
> test invalid ioctls: OK
>
> Allow for multiple opens:
> test second /dev/video1 open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
>
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
>
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 0 Audio Inputs: 0 Tuners: 0
>
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
>
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test VIDIOC_G/S_EDID: OK (Not Supported)
>
> Control ioctls:
> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
> test VIDIOC_QUERYCTRL: OK
> test VIDIOC_G/S_CTRL: OK
> test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 37 Private Controls: 0
>
> Format ioctls:
> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> test VIDIOC_G/S_PARM: OK
> test VIDIOC_G_FBUF: OK (Not Supported)
> test VIDIOC_G_FMT: OK
> test VIDIOC_TRY_FMT: OK
> test VIDIOC_S_FMT: OK
> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> test Cropping: OK
> test Composing: OK (Not Supported)
> test Scaling: OK (Not Supported)
>
> Codec ioctls:
> test VIDIOC_(TRY_)ENCODER_CMD: OK
> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>
> Buffer ioctls:
> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> test CREATE_BUFS maximum buffers: OK
> test VIDIOC_REMOVE_BUFS: OK
> test VIDIOC_EXPBUF: OK
> test Requests: OK (Not Supported)
> test blocking wait: OK
>
> Test input 0:
>
> Streaming ioctls:
> test read/write: OK (Not Supported)
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (select, REQBUFS): OK
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (epoll, REQBUFS): OK
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (select, CREATE_BUFS): OK
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (epoll, CREATE_BUFS): OK
> test USERPTR (select): OK (Not Supported)
> test DMABUF: Cannot test, specify --expbuf-device
>
> Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0, Warnings: 0
>
> The result of v4l2-compliance on SM8250:
> v4l2-compliance 1.29.0-5270, 64 bits, 64-bit time_t
> v4l2-compliance SHA: dc947661089e 2024-11-11 10:25:38
>
> Compliance test for iris_driver device /dev/video1:
>
> Driver Info:
> Driver name : iris_driver
> Card type : Iris Encoder
> Bus info : platform:aa00000.video-codec
> Driver version : 6.16.0
> Capabilities : 0x84204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps : 0x04204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
> Detected Stateful Encoder
>
> Required ioctls:
> test VIDIOC_QUERYCAP: OK
> test invalid ioctls: OK
>
> Allow for multiple opens:
> test second /dev/video1 open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
>
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
>
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 0 Audio Inputs: 0 Tuners: 0
>
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
>
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test VIDIOC_G/S_EDID: OK (Not Supported)
>
> Control ioctls:
> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
> test VIDIOC_QUERYCTRL: OK
> test VIDIOC_G/S_CTRL: OK
> test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 19 Private Controls: 0
>
> Format ioctls:
> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> test VIDIOC_G/S_PARM: OK
> test VIDIOC_G_FBUF: OK (Not Supported)
> test VIDIOC_G_FMT: OK
> test VIDIOC_TRY_FMT: OK
> test VIDIOC_S_FMT: OK
> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> test Cropping: OK
> test Composing: OK (Not Supported)
> test Scaling: OK (Not Supported)
>
> Codec ioctls:
> test VIDIOC_(TRY_)ENCODER_CMD: OK
> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>
> Buffer ioctls:
> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> test CREATE_BUFS maximum buffers: OK
> test VIDIOC_REMOVE_BUFS: OK
> test VIDIOC_EXPBUF: OK
> test Requests: OK (Not Supported)
> test blocking wait: OK
>
> Test input 0:
>
> Streaming ioctls:
> test read/write: OK (Not Supported)
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (select, REQBUFS): OK
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (epoll, REQBUFS): OK
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (select, CREATE_BUFS): OK
> Video Capture Multiplanar: Captured 61 buffers
> test MMAP (epoll, CREATE_BUFS): OK
> test USERPTR (select): OK (Not Supported)
> test DMABUF: Cannot test, specify --expbuf-device
>
> Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0, Warnings: 0
>
> Looking forward to your review and feedback.
>
> Thanks,
> Dikshita
>
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> Dikshita Agarwal (24):
> media: iris: Fix buffer count reporting in internal buffer check
> media: iris: Report unreleased PERSIST buffers on session close
> media: iris: Fix memory leak by freeing untracked persist buffer
> media: iris: Fix port streaming handling
> media: iris: Allow substate transition to load resources during output streaming
> media: iris: Always destroy internal buffers on firmware release response
> media: iris: Update vbuf flags before v4l2_m2m_buf_done
> media: iris: Allow stop on firmware only if start was issued.
> media: iris: Send dummy buffer address for all codecs during drain
> media: iris: Fix missing LAST flag handling during drain
> media: iris: Add support for video encoder device
> media: iris: Initialize and deinitialize encoder instance structure
> media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder
> media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder
> media: iris: Add support for VIDIOC_QUERYCAP for encoder video device
> media: iris: Add encoder support for V4L2 event subscription
> media: iris: Add support for G/S_SELECTION for encoder video device
> media: iris: Add support for G/S_PARM for encoder video device
> media: iris: Add platform-specific capabilities for encoder video device
> media: iris: Add V4L2 streaming support for encoder video device
> media: iris: Set platform capabilities to firmware for encoder video device
> media: iris: Allocate and queue internal buffers for encoder video device
> media: iris: Add support for buffer management ioctls for encoder device
> media: iris: Add support for drain sequence in encoder video device
>
> drivers/media/platform/qcom/iris/Makefile | 5 +-
> drivers/media/platform/qcom/iris/iris_buffer.c | 220 ++++--
> drivers/media/platform/qcom/iris/iris_buffer.h | 7 +-
> drivers/media/platform/qcom/iris/iris_common.c | 232 ++++++
> drivers/media/platform/qcom/iris/iris_common.h | 18 +
> drivers/media/platform/qcom/iris/iris_core.h | 20 +-
> drivers/media/platform/qcom/iris/iris_ctrls.c | 675 +++++++++++++++-
> drivers/media/platform/qcom/iris/iris_ctrls.h | 15 +
> drivers/media/platform/qcom/iris/iris_hfi_common.h | 2 +-
> .../platform/qcom/iris/iris_hfi_gen1_command.c | 485 +++++++++---
> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 112 ++-
> .../platform/qcom/iris/iris_hfi_gen1_response.c | 60 +-
> .../platform/qcom/iris/iris_hfi_gen2_command.c | 357 ++++++---
> .../platform/qcom/iris/iris_hfi_gen2_defines.h | 44 +-
> .../platform/qcom/iris/iris_hfi_gen2_response.c | 46 +-
> drivers/media/platform/qcom/iris/iris_instance.h | 24 +
> .../platform/qcom/iris/iris_platform_common.h | 74 +-
> .../media/platform/qcom/iris/iris_platform_gen2.c | 522 ++++++++++++-
> .../platform/qcom/iris/iris_platform_qcs8300.h | 352 ++++++++-
> .../platform/qcom/iris/iris_platform_sm8250.c | 234 +++++-
> drivers/media/platform/qcom/iris/iris_probe.c | 39 +-
> drivers/media/platform/qcom/iris/iris_state.c | 9 +-
> drivers/media/platform/qcom/iris/iris_state.h | 1 +
> drivers/media/platform/qcom/iris/iris_utils.c | 36 +
> drivers/media/platform/qcom/iris/iris_utils.h | 2 +
> drivers/media/platform/qcom/iris/iris_vb2.c | 58 +-
> drivers/media/platform/qcom/iris/iris_vdec.c | 249 +-----
> drivers/media/platform/qcom/iris/iris_vdec.h | 13 +-
> drivers/media/platform/qcom/iris/iris_venc.c | 579 ++++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 27 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 299 +++++++-
> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 847 ++++++++++++++++++++-
> drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 20 +
> 33 files changed, 4970 insertions(+), 713 deletions(-)
> ---
> base-commit: c26e8dcd9d4e86d788c5bf7a5dd0ea70a95ab067
> change-id: 20250704-iris-video-encoder-b193350b487a
>
> Best regards,
I have a successfull encoding on SM8650-HDK with the following commands (ffmpegs segfaults en encoding):
wget https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_30MB.mp4 -O Big_Buck_Bunny_1080_10s_30MB_h264.mp4
ffmpeg -c:v h264_v4l2m2m -i Big_Buck_Bunny_1080_10s_30MB_h264.mp4 -pix_fmt nv12 Big_Buck_Bunny_1080_10s.yuv
v4l2-ctl --verbose --set-fmt-video-out=width=1920,height=1080,pixelformat=NV12 --set-selection-output target=crop,top=0,left=0,width=1920,height=1080 --set-fmt-video=pixelformat=H264 --stream-mmap --stream-out-mmap --stream-from=Big_Buck_Bunny_1080_10s.yuv --stream-to=Big_Buck_Bunny_1080_10s.h264 -d /dev/video1
v4l2-ctl --verbose --set-fmt-video-out=width=1920,height=1080,pixelformat=NV12 --set-selection-output target=crop,top=0,left=0,width=1920,height=1080 --set-fmt-video=pixelformat=HEVC --stream-mmap --stream-out-mmap --stream-from=Big_Buck_Bunny_1080_10s.yuv --stream-to=Big_Buck_Bunny_1080_10s.hevc -d /dev/video1
But the video is 1280x720, if I drop the `--set-selection-output target=crop,top=0,left=0,width=1920,height=1080` I correctly get 1920x1080 but the color keeps moving like if the colors stride is wrong.
Neil
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming
2025-08-13 9:37 ` [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming Dikshita Agarwal
@ 2025-08-13 21:51 ` Bryan O'Donoghue
2025-08-13 21:55 ` Bryan O'Donoghue
2025-08-13 22:55 ` Konrad Dybcio
0 siblings, 2 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-13 21:51 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Bryan O'Donoghue, Mauro Carvalho Chehab, Hans Verkuil,
Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> However, now after removing that restriction, the instance state can be
> OUTPUT_STREAMING when firmware start is triggered and substate needs to
> be moved to LOAD_RESOURCES.
>
> Fixes: 547f7b8c5090 ("media: iris: add check to allow sub states transitions")
If a restriction has been removed, has that restriction been marked as a
Fixes: ?
If not then we can't actually backport this fix as the dependency - the
restriction removal has not been marked for backport.
Please evaluate if the necessary change you have stipulated here has
been marked for backport with Fixes: and if so mention the appropriate
commit SHA in your commit log.
If you are referring to the commit immediately preceding this patch "Fix
buffer count reporting in internal buffer check" then again you should
mention that in the log so _which_ dependency you mean is clear.
If I were trying to follow this series on some kind of -stable kernel, I
don't think this commit log would reasonably tell me which depends I
need as an antecedent.
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming
2025-08-13 21:51 ` Bryan O'Donoghue
@ 2025-08-13 21:55 ` Bryan O'Donoghue
2025-08-13 22:55 ` Konrad Dybcio
1 sibling, 0 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-13 21:55 UTC (permalink / raw)
To: Bryan O'Donoghue, Dikshita Agarwal, Vikash Garodia,
Abhinav Kumar, Mauro Carvalho Chehab, Hans Verkuil,
Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 22:51, Bryan O'Donoghue wrote:
>> Fixes: 547f7b8c5090 ("media: iris: add check to allow sub states transitions")
> If a restriction has been removed, has that restriction been marked as a
> Fixes: ?
Yes it has, never mind my proton mail filters are misdirecting patches...
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming
2025-08-13 21:51 ` Bryan O'Donoghue
2025-08-13 21:55 ` Bryan O'Donoghue
@ 2025-08-13 22:55 ` Konrad Dybcio
2025-08-14 6:13 ` Krzysztof Kozlowski
1 sibling, 1 reply; 69+ messages in thread
From: Konrad Dybcio @ 2025-08-13 22:55 UTC (permalink / raw)
To: Bryan O'Donoghue, Dikshita Agarwal, Vikash Garodia,
Abhinav Kumar, Bryan O'Donoghue, Mauro Carvalho Chehab,
Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/25 11:51 PM, Bryan O'Donoghue wrote:
> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>> However, now after removing that restriction, the instance state can be
>> OUTPUT_STREAMING when firmware start is triggered and substate needs to
>> be moved to LOAD_RESOURCES.
>>
>> Fixes: 547f7b8c5090 ("media: iris: add check to allow sub states transitions")
>
> If a restriction has been removed, has that restriction been marked as a
> Fixes: ?
>
> If not then we can't actually backport this fix as the dependency - the
> restriction removal has not been marked for backport.
Please stop confusing fixes and backports..
If you're really paranoid about this commit getting autoselected, see
'noautosel' under this section:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html#option-1
Konrad
>
> Please evaluate if the necessary change you have stipulated here has
> been marked for backport with Fixes: and if so mention the appropriate
> commit SHA in your commit log.
>
> If you are referring to the commit immediately preceding this patch "Fix
> buffer count reporting in internal buffer check" then again you should
> mention that in the log so _which_ dependency you mean is clear.
>
> If I were trying to follow this series on some kind of -stable kernel, I
> don't think this commit log would reasonably tell me which depends I
> need as an antecedent.
>
> ---
> bod
>
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming
2025-08-13 22:55 ` Konrad Dybcio
@ 2025-08-14 6:13 ` Krzysztof Kozlowski
2025-08-14 7:50 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-14 6:13 UTC (permalink / raw)
To: Konrad Dybcio, Bryan O'Donoghue, Dikshita Agarwal,
Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 14/08/2025 00:55, Konrad Dybcio wrote:
> On 8/13/25 11:51 PM, Bryan O'Donoghue wrote:
>> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>>> However, now after removing that restriction, the instance state can be
>>> OUTPUT_STREAMING when firmware start is triggered and substate needs to
>>> be moved to LOAD_RESOURCES.
>>>
>>> Fixes: 547f7b8c5090 ("media: iris: add check to allow sub states transitions")
>>
>> If a restriction has been removed, has that restriction been marked as a
>> Fixes: ?
>>
>> If not then we can't actually backport this fix as the dependency - the
>> restriction removal has not been marked for backport.
>
> Please stop confusing fixes and backports..
>
> If you're really paranoid about this commit getting autoselected, see
> 'noautosel' under this section:
>
> https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html#option-1
Commit still needs to explain what is the bug, what is observable issue
being fixed here. Lack of feature is not a bug.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming
2025-08-14 6:13 ` Krzysztof Kozlowski
@ 2025-08-14 7:50 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-14 7:50 UTC (permalink / raw)
To: Krzysztof Kozlowski, Konrad Dybcio, Bryan O'Donoghue,
Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/14/2025 11:43 AM, Krzysztof Kozlowski wrote:
> On 14/08/2025 00:55, Konrad Dybcio wrote:
>> On 8/13/25 11:51 PM, Bryan O'Donoghue wrote:
>>> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>>>> However, now after removing that restriction, the instance state can be
>>>> OUTPUT_STREAMING when firmware start is triggered and substate needs to
>>>> be moved to LOAD_RESOURCES.
>>>>
>>>> Fixes: 547f7b8c5090 ("media: iris: add check to allow sub states transitions")
>>>
>>> If a restriction has been removed, has that restriction been marked as a
>>> Fixes: ?
>>>
>>> If not then we can't actually backport this fix as the dependency - the
>>> restriction removal has not been marked for backport.
>>
>> Please stop confusing fixes and backports..
>>
>> If you're really paranoid about this commit getting autoselected, see
>> 'noautosel' under this section:
>>
>> https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html#option-1
>
> Commit still needs to explain what is the bug, what is observable issue
> being fixed here. Lack of feature is not a bug.
Ok, will add more info.
Regards,
Dikshita
>
> Best regards,
> Krzysztof
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 11/24] media: iris: Add support for video encoder device
2025-08-13 9:38 ` [PATCH v2 11/24] media: iris: Add support for video encoder device Dikshita Agarwal
@ 2025-08-14 14:11 ` Vikash Garodia
2025-08-16 11:21 ` Bryan O'Donoghue
1 sibling, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:11 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add support for registering a V4L2 encoder video device to the iris
> driver. The encoder device is registered with the name
> "qcom-iris-encoder".
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_core.h | 7 ++++++
> drivers/media/platform/qcom/iris/iris_probe.c | 36 ++++++++++++++++++++-------
> 2 files changed, 34 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
> index aeeac32a1f6d9a9fa7027e8e3db4d95f021c552e..09e83be4e00efb456b7098a499b6cce850134a06 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.h
> +++ b/drivers/media/platform/qcom/iris/iris_core.h
> @@ -25,6 +25,11 @@ struct icc_info {
> #define IRIS_FW_VERSION_LENGTH 128
> #define IFACEQ_CORE_PKT_SIZE (1024 * 4)
>
> +enum domain_type {
> + ENCODER = BIT(0),
> + DECODER = BIT(1),
> +};
> +
> /**
> * struct iris_core - holds core parameters valid for all instances
> *
> @@ -33,6 +38,7 @@ struct icc_info {
> * @irq: iris irq
> * @v4l2_dev: a holder for v4l2 device structure
> * @vdev_dec: iris video device structure for decoder
> + * @vdev_enc: iris video device structure for encoder
> * @iris_v4l2_file_ops: iris v4l2 file ops
> * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops
> * @iris_vb2_ops: iris vb2 ops
> @@ -73,6 +79,7 @@ struct iris_core {
> int irq;
> struct v4l2_device v4l2_dev;
> struct video_device *vdev_dec;
> + struct video_device *vdev_enc;
> const struct v4l2_file_operations *iris_v4l2_file_ops;
> const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops;
> const struct vb2_ops *iris_vb2_ops;
> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> index 4e6e92357968d7419f114cc0ffa9b571bad19e46..c3be9deb0a57cc2cf25d69784d54be5e4a5fe06c 100644
> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> @@ -146,7 +146,7 @@ static int iris_init_resources(struct iris_core *core)
> return iris_init_resets(core);
> }
>
> -static int iris_register_video_device(struct iris_core *core)
> +static int iris_register_video_device(struct iris_core *core, enum domain_type type)
> {
> struct video_device *vdev;
> int ret;
> @@ -155,7 +155,6 @@ static int iris_register_video_device(struct iris_core *core)
> if (!vdev)
> return -ENOMEM;
>
> - strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
> vdev->release = video_device_release;
> vdev->fops = core->iris_v4l2_file_ops;
> vdev->ioctl_ops = core->iris_v4l2_ioctl_ops;
> @@ -163,11 +162,23 @@ static int iris_register_video_device(struct iris_core *core)
> vdev->v4l2_dev = &core->v4l2_dev;
> vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
>
> - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> - if (ret)
> + if (type == DECODER) {
> + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
> + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> + if (ret)
> + goto err_vdev_release;
> + core->vdev_dec = vdev;
> + } else if (type == ENCODER) {
> + strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
> + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> + if (ret)
> + goto err_vdev_release;
> + core->vdev_enc = vdev;
> + } else {
> + ret = -EINVAL;
> goto err_vdev_release;
> + }
>
> - core->vdev_dec = vdev;
> video_set_drvdata(vdev, core);
>
> return 0;
> @@ -189,6 +200,7 @@ static void iris_remove(struct platform_device *pdev)
> iris_core_deinit(core);
>
> video_unregister_device(core->vdev_dec);
> + video_unregister_device(core->vdev_enc);
>
> v4l2_device_unregister(&core->v4l2_dev);
>
> @@ -258,17 +270,21 @@ static int iris_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> - ret = iris_register_video_device(core);
> + ret = iris_register_video_device(core, DECODER);
> if (ret)
> goto err_v4l2_unreg;
>
> + ret = iris_register_video_device(core, ENCODER);
> + if (ret)
> + goto err_vdev_unreg_dec;
> +
> platform_set_drvdata(pdev, core);
>
> dma_mask = core->iris_platform_data->dma_mask;
>
> ret = dma_set_mask_and_coherent(dev, dma_mask);
> if (ret)
> - goto err_vdev_unreg;
> + goto err_vdev_unreg_enc;
>
> dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
> dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32));
> @@ -277,11 +293,13 @@ static int iris_probe(struct platform_device *pdev)
> pm_runtime_use_autosuspend(core->dev);
> ret = devm_pm_runtime_enable(core->dev);
> if (ret)
> - goto err_vdev_unreg;
> + goto err_vdev_unreg_enc;
>
> return 0;
>
> -err_vdev_unreg:
> +err_vdev_unreg_enc:
> + video_unregister_device(core->vdev_enc);
> +err_vdev_unreg_dec:
> video_unregister_device(core->vdev_dec);
> err_v4l2_unreg:
> v4l2_device_unregister(&core->v4l2_dev);
>
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-13 9:38 ` [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure Dikshita Agarwal
@ 2025-08-14 14:25 ` Vikash Garodia
2025-08-18 3:21 ` Dikshita Agarwal
2025-08-16 9:03 ` Bryan O'Donoghue
1 sibling, 1 reply; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:25 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Introduce initialization and deinitialization for internal encoder
> instance structure with necessary hooks.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/Makefile | 1 +
> drivers/media/platform/qcom/iris/iris_buffer.c | 59 ++++++++++++++++----
> .../platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++-
> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
> drivers/media/platform/qcom/iris/iris_instance.h | 7 +++
> drivers/media/platform/qcom/iris/iris_vdec.c | 2 -
> drivers/media/platform/qcom/iris/iris_venc.c | 65 ++++++++++++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 14 +++++
> drivers/media/platform/qcom/iris/iris_vidc.c | 27 ++++++++-
> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 +-
> 10 files changed, 170 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
> index e86d00ee6f15dda8bae2f25f726feb0d427b7684..ec32145e081b1fc3538dfa7d5113162a76a6068c 100644
> --- a/drivers/media/platform/qcom/iris/Makefile
> +++ b/drivers/media/platform/qcom/iris/Makefile
> @@ -19,6 +19,7 @@ qcom-iris-objs += \
> iris_vidc.o \
> iris_vb2.o \
> iris_vdec.o \
> + iris_venc.o \
> iris_vpu2.o \
> iris_vpu3x.o \
> iris_vpu_buffer.o \
> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
> index 38548ee4749ea7dd1addf2c9d0677cf5217e3546..6bf9b0b35d206d51b927c824d5a5b327596251c6 100644
> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
> @@ -63,7 +63,12 @@
> static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
> {
> u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
> - struct v4l2_format *f = inst->fmt_dst;
> + struct v4l2_format *f;
> +
> + if (inst->domain == DECODER)
> + f = inst->fmt_dst;
> + else
> + f = inst->fmt_src;
>
> y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
> uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
> @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst)
> return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);
> }
>
> -static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
> +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
> {
> struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
> u32 base_res_mbs = NUM_MBS_4K;
> @@ -219,18 +224,50 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
> return ALIGN(frame_size, PIXELS_4K);
> }
>
> +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
> +{
> + u32 aligned_width, aligned_height, bitstream_size, yuv_size;
> + struct v4l2_format *f;
> +
> + f = inst->fmt_dst;
> +
> + aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
> + aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
> + bitstream_size = aligned_width * aligned_height * 3;
> + yuv_size = (aligned_width * aligned_height * 3) >> 1;
> + if (aligned_width * aligned_height > (4096 * 2176))
> + /* bitstream_size = 0.25 * yuv_size; */
> + bitstream_size = (bitstream_size >> 3);
> + else if (aligned_width * aligned_height > (1280 * 720))
> + /* bitstream_size = 0.5 * yuv_size; */
> + bitstream_size = (bitstream_size >> 2);
> +
> + return ALIGN(bitstream_size, 4096);
> +}
> +
> int iris_get_buffer_size(struct iris_inst *inst,
> enum iris_buffer_type buffer_type)
> {
> - switch (buffer_type) {
> - case BUF_INPUT:
> - return iris_bitstream_buffer_size(inst);
> - case BUF_OUTPUT:
> - return iris_yuv_buffer_size_nv12(inst);
> - case BUF_DPB:
> - return iris_yuv_buffer_size_qc08c(inst);
> - default:
> - return 0;
> + if (inst->domain == DECODER) {
> + switch (buffer_type) {
> + case BUF_INPUT:
> + return iris_dec_bitstream_buffer_size(inst);
> + case BUF_OUTPUT:
> + return iris_yuv_buffer_size_nv12(inst);
> + case BUF_DPB:
> + return iris_yuv_buffer_size_qc08c(inst);
> + default:
> + return 0;
> + }
> + } else {
> + switch (buffer_type) {
> + case BUF_INPUT:
> + return iris_yuv_buffer_size_nv12(inst);
> + case BUF_OUTPUT:
> + return iris_enc_bitstream_buffer_size(inst);
> + default:
> + return 0;
> + }
> }
> }
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> index 5097680ee14ebba3a126213c0584161627ca47d7..eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> @@ -109,7 +109,12 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst)
> packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
> packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
> packet.shdr.session_id = inst->session_id;
> - packet.session_domain = HFI_SESSION_TYPE_DEC;
> +
> + if (inst->domain == DECODER)
> + packet.session_domain = HFI_SESSION_TYPE_DEC;
> + else
> + packet.session_domain = HFI_SESSION_TYPE_ENC;
> +
> packet.session_codec = codec;
>
> reinit_completion(&inst->completion);
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> index d4d119ca98b0cb313db351f3794bf278216bd539..5b7c641b727a16c3aa7196a6d49786133653279f 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> @@ -10,6 +10,7 @@
>
> #define HFI_VIDEO_ARCH_OX 0x1
>
> +#define HFI_SESSION_TYPE_ENC 1
> #define HFI_SESSION_TYPE_DEC 2
>
> #define HFI_VIDEO_CODEC_H264 0x00000002
> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
> index 0e1f5799b72d993b25820608969e0011eabdb6bc..ff90f010f1d36690cbadeff0787b1fb7458d7f75 100644
> --- a/drivers/media/platform/qcom/iris/iris_instance.h
> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
> @@ -12,6 +12,9 @@
> #include "iris_core.h"
> #include "iris_utils.h"
>
> +#define DEFAULT_WIDTH 320
> +#define DEFAULT_HEIGHT 240
> +
> /**
> * struct iris_inst - holds per video instance parameters
> *
> @@ -24,7 +27,9 @@
> * @fmt_src: structure of v4l2_format for source
> * @fmt_dst: structure of v4l2_format for destination
> * @ctrl_handler: reference of v4l2 ctrl handler
> + * @domain: domain type: encoder or decoder
> * @crop: structure of crop info
> + * @compose: structure of compose info
> * @completion: structure of signal completions
> * @flush_completion: structure of signal completions for flush cmd
> * @flush_responses_pending: counter to track number of pending flush responses
> @@ -57,7 +62,9 @@ struct iris_inst {
> struct v4l2_format *fmt_src;
> struct v4l2_format *fmt_dst;
> struct v4l2_ctrl_handler ctrl_handler;
> + enum domain_type domain;
> struct iris_hfi_rect_desc crop;
> + struct iris_hfi_rect_desc compose;
> struct completion completion;
> struct completion flush_completion;
> u32 flush_responses_pending;
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
> index d670b51c5839d1fad54d34f373cf71d5f3973a96..3482ff3f18d2bcd592b7eb7d803bf98e29276ebb 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
> @@ -13,8 +13,6 @@
> #include "iris_vdec.h"
> #include "iris_vpu_buffer.h"
>
> -#define DEFAULT_WIDTH 320
> -#define DEFAULT_HEIGHT 240
> #define DEFAULT_CODEC_ALIGNMENT 16
>
> int iris_vdec_inst_init(struct iris_inst *inst)
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "iris_buffer.h"
> +#include "iris_instance.h"
> +#include "iris_venc.h"
> +#include "iris_vpu_buffer.h"
> +
> +int iris_venc_inst_init(struct iris_inst *inst)
> +{
> + struct v4l2_format *f;
> +
> + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
> + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
> + if (!inst->fmt_src || !inst->fmt_dst)
> + return -ENOMEM;
What if inst->fmt_src succeeds while inst->fmt_dst fails, does it frees up
inst->fmt_src ?
> +
> + f = inst->fmt_dst;
> + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> + f->fmt.pix_mp.width = DEFAULT_WIDTH;
> + f->fmt.pix_mp.height = DEFAULT_HEIGHT;
> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
> + inst->codec = f->fmt.pix_mp.pixelformat;
> + f->fmt.pix_mp.num_planes = 1;
> + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
> + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
> + inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
> +
> + f = inst->fmt_src;
> + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
> + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
> + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
> + f->fmt.pix_mp.num_planes = 1;
> + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
> + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
> + inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
> +
> + inst->crop.left = 0;
> + inst->crop.top = 0;
> + inst->crop.width = f->fmt.pix_mp.width;
> + inst->crop.height = f->fmt.pix_mp.height;
> +
> + return 0;
> +}
> +
> +void iris_venc_inst_deinit(struct iris_inst *inst)
> +{
> + kfree(inst->fmt_dst);
> + kfree(inst->fmt_src);
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..8a4cbddd0114b6d0e4ea895362b01c302250c78b
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _IRIS_VENC_H_
> +#define _IRIS_VENC_H_
> +
> +struct iris_inst;
> +
> +int iris_venc_inst_init(struct iris_inst *inst);
> +void iris_venc_inst_deinit(struct iris_inst *inst);
> +
> +#endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 96313856a026efaff40da97eaaa63e847172cd57..11f27fc867dc610c18022b0942e65aa175a8567e 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -12,6 +12,7 @@
> #include "iris_vidc.h"
> #include "iris_instance.h"
> #include "iris_vdec.h"
> +#include "iris_venc.h"
> #include "iris_vb2.h"
> #include "iris_vpu_buffer.h"
> #include "iris_platform_common.h"
> @@ -23,7 +24,10 @@
>
> static void iris_v4l2_fh_init(struct iris_inst *inst)
> {
> - v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
> + if (inst->domain == ENCODER)
> + v4l2_fh_init(&inst->fh, inst->core->vdev_enc);
> + else if (inst->domain == DECODER)
> + v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
> inst->fh.ctrl_handler = &inst->ctrl_handler;
> v4l2_fh_add(&inst->fh);
> }
> @@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_
> int iris_open(struct file *filp)
> {
> struct iris_core *core = video_drvdata(filp);
> + struct video_device *vdev;
> struct iris_inst *inst;
> + u32 session_type;
> int ret;
>
> + vdev = video_devdata(filp);
> + if (strcmp(vdev->name, "qcom-iris-decoder") == 0)
> + session_type = DECODER;
> + else if (strcmp(vdev->name, "qcom-iris-encoder") == 0)
> + session_type = ENCODER;
> + else
> + return -EINVAL;
> +
> ret = pm_runtime_resume_and_get(core->dev);
> if (ret < 0)
> return ret;
> @@ -147,6 +161,7 @@ int iris_open(struct file *filp)
> return -ENOMEM;
>
> inst->core = core;
> + inst->domain = session_type;
> inst->session_id = hash32_ptr(inst);
> inst->state = IRIS_INST_DEINIT;
>
> @@ -178,7 +193,10 @@ int iris_open(struct file *filp)
> goto fail_m2m_release;
> }
>
> - ret = iris_vdec_inst_init(inst);
> + if (inst->domain == DECODER)
> + ret = iris_vdec_inst_init(inst);
> + else if (inst->domain == ENCODER)
> + ret = iris_venc_inst_init(inst);
> if (ret)
> goto fail_m2m_ctx_release;
>
> @@ -265,7 +283,10 @@ int iris_close(struct file *filp)
> v4l2_m2m_ctx_release(inst->m2m_ctx);
> v4l2_m2m_release(inst->m2m_dev);
> mutex_lock(&inst->lock);
> - iris_vdec_inst_deinit(inst);
> + if (inst->domain == DECODER)
> + iris_vdec_inst_deinit(inst);
> + else if (inst->domain == ENCODER)
> + iris_venc_inst_deinit(inst);
> iris_session_close(inst);
> iris_inst_change_state(inst, IRIS_INST_DEINIT);
> iris_v4l2_fh_deinit(inst);
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> index f92fd39fe310b9661f892dcf1ff036ebbc102270..06d5afc3c641f0dfca3967e55273c4fa2614fdff 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> @@ -628,7 +628,10 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type
> case BUF_INPUT:
> return MIN_BUFFERS;
> case BUF_OUTPUT:
> - return output_min_count(inst);
> + if (inst->domain == ENCODER)
> + return MIN_BUFFERS;
> + else
> + return output_min_count(inst);
> case BUF_BIN:
> case BUF_COMV:
> case BUF_NON_COMV:
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 13/24] media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder
2025-08-13 9:38 ` [PATCH v2 13/24] media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder Dikshita Agarwal
@ 2025-08-14 14:32 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:32 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add V4L2 format handling support for the encoder by adding
> implementation of ENUM/S/G/TRY_FMT with necessary hooks.
>
> This ensures that the encoder supports format negotiation consistent
> with V4L2 expectation, enabling userspace applications to configure
> resolution, pixel format and buffer layout properly.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_core.h | 6 +-
> drivers/media/platform/qcom/iris/iris_instance.h | 11 ++
> drivers/media/platform/qcom/iris/iris_probe.c | 3 +-
> drivers/media/platform/qcom/iris/iris_vdec.h | 11 --
> drivers/media/platform/qcom/iris/iris_venc.c | 207 +++++++++++++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 3 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 41 ++++-
> 7 files changed, 261 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
> index 09e83be4e00efb456b7098a499b6cce850134a06..827aee8dcec3ee17af5a90f5594b9315f663c0b3 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.h
> +++ b/drivers/media/platform/qcom/iris/iris_core.h
> @@ -40,7 +40,8 @@ enum domain_type {
> * @vdev_dec: iris video device structure for decoder
> * @vdev_enc: iris video device structure for encoder
> * @iris_v4l2_file_ops: iris v4l2 file ops
> - * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops
> + * @iris_v4l2_ioctl_ops_dec: iris v4l2 ioctl ops for decoder
> + * @iris_v4l2_ioctl_ops_enc: iris v4l2 ioctl ops for encoder
> * @iris_vb2_ops: iris vb2 ops
> * @icc_tbl: table of iris interconnects
> * @icc_count: count of iris interconnects
> @@ -81,7 +82,8 @@ struct iris_core {
> struct video_device *vdev_dec;
> struct video_device *vdev_enc;
> const struct v4l2_file_operations *iris_v4l2_file_ops;
> - const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops;
> + const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec;
> + const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc;
> const struct vb2_ops *iris_vb2_ops;
> struct icc_bulk_data *icc_tbl;
> u32 icc_count;
> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
> index ff90f010f1d36690cbadeff0787b1fb7458d7f75..55cf9702111829ef24189986ba5245c7684bfe11 100644
> --- a/drivers/media/platform/qcom/iris/iris_instance.h
> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
> @@ -15,6 +15,17 @@
> #define DEFAULT_WIDTH 320
> #define DEFAULT_HEIGHT 240
>
> +enum iris_fmt_type {
> + IRIS_FMT_H264,
> + IRIS_FMT_HEVC,
> + IRIS_FMT_VP9,
> +};
> +
> +struct iris_fmt {
> + u32 pixfmt;
> + u32 type;
> +};
> +
> /**
> * struct iris_inst - holds per video instance parameters
> *
> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> index c3be9deb0a57cc2cf25d69784d54be5e4a5fe06c..0f2596427a773e5c9105b97cb234c8f0a3483226 100644
> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> @@ -157,19 +157,20 @@ static int iris_register_video_device(struct iris_core *core, enum domain_type t
>
> vdev->release = video_device_release;
> vdev->fops = core->iris_v4l2_file_ops;
> - vdev->ioctl_ops = core->iris_v4l2_ioctl_ops;
> vdev->vfl_dir = VFL_DIR_M2M;
> vdev->v4l2_dev = &core->v4l2_dev;
> vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
>
> if (type == DECODER) {
> strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
> + vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec;
> ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> if (ret)
> goto err_vdev_release;
> core->vdev_dec = vdev;
> } else if (type == ENCODER) {
> strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
> + vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc;
> ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> if (ret)
> goto err_vdev_release;
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
> index cd7aab66dc7c82dc50acef9e654a3d6c1ddb088f..b24932dc511a65017b1cadbcb984544475bd0723 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.h
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.h
> @@ -8,17 +8,6 @@
>
> struct iris_inst;
>
> -enum iris_fmt_type {
> - IRIS_FMT_H264,
> - IRIS_FMT_HEVC,
> - IRIS_FMT_VP9,
> -};
> -
> -struct iris_fmt {
> - u32 pixfmt;
> - u32 type;
> -};
> -
> int iris_vdec_inst_init(struct iris_inst *inst);
> void iris_vdec_inst_deinit(struct iris_inst *inst);
> int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index e418d347ac111c1bc48304adafa259d697e49fed..6bb59ce4fc565d3dcc6185233ef25d2e4d85cb3e 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -3,6 +3,8 @@
> * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> +#include <media/v4l2-mem2mem.h>
> +
> #include "iris_buffer.h"
> #include "iris_instance.h"
> #include "iris_venc.h"
> @@ -63,3 +65,208 @@ void iris_venc_inst_deinit(struct iris_inst *inst)
> kfree(inst->fmt_dst);
> kfree(inst->fmt_src);
> }
> +
> +static const struct iris_fmt iris_venc_formats[] = {
> + [IRIS_FMT_H264] = {
> + .pixfmt = V4L2_PIX_FMT_H264,
> + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
> + },
> + [IRIS_FMT_HEVC] = {
> + .pixfmt = V4L2_PIX_FMT_HEVC,
> + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
> + },
> +};
> +
> +static const struct iris_fmt *
> +find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
> +{
> + const struct iris_fmt *fmt = iris_venc_formats;
> + unsigned int size = ARRAY_SIZE(iris_venc_formats);
> + unsigned int i;
> +
> + for (i = 0; i < size; i++) {
> + if (fmt[i].pixfmt == pixfmt)
> + break;
> + }
> +
> + if (i == size || fmt[i].type != type)
> + return NULL;
> +
> + return &fmt[i];
> +}
> +
> +static const struct iris_fmt *
> +find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
> +{
> + const struct iris_fmt *fmt = iris_venc_formats;
> + unsigned int size = ARRAY_SIZE(iris_venc_formats);
> +
> + if (index >= size || fmt[index].type != type)
> + return NULL;
> +
> + return &fmt[index];
> +}
> +
> +int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
> +{
> + const struct iris_fmt *fmt;
> +
> + switch (f->type) {
> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> + if (f->index)
> + return -EINVAL;
> + f->pixelformat = V4L2_PIX_FMT_NV12;
> + break;
> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> + fmt = find_format_by_index(inst, f->index, f->type);
> + if (!fmt)
> + return -EINVAL;
> +
> + f->pixelformat = fmt->pixfmt;
> + f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
> +{
> + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
> + const struct iris_fmt *fmt;
> + struct v4l2_format *f_inst;
> +
> + memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
> + fmt = find_format(inst, pixmp->pixelformat, f->type);
> + switch (f->type) {
> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) {
> + f_inst = inst->fmt_src;
> + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
> + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
> + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
> + }
> + break;
> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> + if (!fmt) {
> + f_inst = inst->fmt_dst;
> + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
> + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
> + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
> + }
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + if (pixmp->field == V4L2_FIELD_ANY)
> + pixmp->field = V4L2_FIELD_NONE;
> +
> + pixmp->num_planes = 1;
> +
> + return 0;
> +}
> +
> +static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f)
> +{
> + struct v4l2_format *fmt;
> +
> + iris_venc_try_fmt(inst, f);
> +
> + if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
> + return -EINVAL;
> +
> + fmt = inst->fmt_dst;
> + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> + fmt->fmt.pix_mp.num_planes = 1;
> + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
> + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
> +
> + if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT &&
> + f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709)
> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
> + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
> + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
> + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
> + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
> +
> + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
> + inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
> + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
> + inst->codec = f->fmt.pix_mp.pixelformat;
> + memcpy(f, fmt, sizeof(struct v4l2_format));
> +
> + return 0;
> +}
> +
> +static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f)
> +{
> + struct v4l2_format *fmt, *output_fmt;
> +
> + iris_venc_try_fmt(inst, f);
> +
> + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12)
> + return -EINVAL;
> +
> + fmt = inst->fmt_src;
> + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> + fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
> + fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
> + fmt->fmt.pix_mp.num_planes = 1;
> + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
> + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128);
> + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
> +
> + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
> + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
> + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
> + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
> +
> + output_fmt = inst->fmt_dst;
> + output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width;
> + output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height;
> + output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace;
> + output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func;
> + output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc;
> + output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization;
> +
> + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
> + inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
> +
> + if (f->fmt.pix_mp.width != inst->crop.width ||
> + f->fmt.pix_mp.height != inst->crop.height) {
> + inst->crop.top = 0;
> + inst->crop.left = 0;
> + inst->crop.width = fmt->fmt.pix_mp.width;
> + inst->crop.height = fmt->fmt.pix_mp.height;
> +
> + iris_venc_s_fmt_output(inst, output_fmt);
> + }
> +
> + memcpy(f, fmt, sizeof(struct v4l2_format));
> +
> + return 0;
> +}
> +
> +int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
> +{
> + struct vb2_queue *q;
> +
> + q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
> + if (!q)
> + return -EINVAL;
> +
> + if (vb2_is_busy(q))
> + return -EBUSY;
> +
> + switch (f->type) {
> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> + return iris_venc_s_fmt_input(inst, f);
> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> + return iris_venc_s_fmt_output(inst, f);
> + default:
> + return -EINVAL;
> + }
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> index 8a4cbddd0114b6d0e4ea895362b01c302250c78b..eb26a3ecbd98b3f02dfdea0dfc41bcd3a90904b6 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.h
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -10,5 +10,8 @@ struct iris_inst;
>
> int iris_venc_inst_init(struct iris_inst *inst);
> void iris_venc_inst_deinit(struct iris_inst *inst);
> +int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
> +int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
> +int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 11f27fc867dc610c18022b0942e65aa175a8567e..06b2737c5892ebbcf43b4cff66062d85cf805c20 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -308,16 +308,26 @@ static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f)
> {
> struct iris_inst *inst = iris_get_inst(filp, NULL);
>
> - return iris_vdec_enum_fmt(inst, f);
> + if (inst->domain == DECODER)
> + return iris_vdec_enum_fmt(inst, f);
> + else if (inst->domain == ENCODER)
> + return iris_venc_enum_fmt(inst, f);
> + else
> + return -EINVAL;
> }
>
> static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
> {
> struct iris_inst *inst = iris_get_inst(filp, NULL);
> - int ret;
> + int ret = 0;
>
> mutex_lock(&inst->lock);
> - ret = iris_vdec_try_fmt(inst, f);
> +
> + if (inst->domain == DECODER)
> + ret = iris_vdec_try_fmt(inst, f);
> + else if (inst->domain == ENCODER)
> + ret = iris_venc_try_fmt(inst, f);
> +
> mutex_unlock(&inst->lock);
>
> return ret;
> @@ -326,10 +336,15 @@ static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_form
> static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
> {
> struct iris_inst *inst = iris_get_inst(filp, NULL);
> - int ret;
> + int ret = 0;
>
> mutex_lock(&inst->lock);
> - ret = iris_vdec_s_fmt(inst, f);
> +
> + if (inst->domain == DECODER)
> + ret = iris_vdec_s_fmt(inst, f);
> + else if (inst->domain == ENCODER)
> + ret = iris_venc_s_fmt(inst, f);
> +
> mutex_unlock(&inst->lock);
>
> return ret;
> @@ -473,7 +488,7 @@ static const struct vb2_ops iris_vb2_ops = {
> .buf_queue = iris_vb2_buf_queue,
> };
>
> -static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
> +static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_dec = {
> .vidioc_enum_fmt_vid_cap = iris_enum_fmt,
> .vidioc_enum_fmt_vid_out = iris_enum_fmt,
> .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane,
> @@ -501,9 +516,21 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
> .vidioc_decoder_cmd = iris_dec_cmd,
> };
>
> +static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
> + .vidioc_enum_fmt_vid_cap = iris_enum_fmt,
> + .vidioc_enum_fmt_vid_out = iris_enum_fmt,
> + .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane,
> + .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane,
> + .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane,
> + .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane,
> + .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane,
> + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
> +};
> +
> void iris_init_ops(struct iris_core *core)
> {
> core->iris_v4l2_file_ops = &iris_v4l2_file_ops;
> core->iris_vb2_ops = &iris_vb2_ops;
> - core->iris_v4l2_ioctl_ops = &iris_v4l2_ioctl_ops;
> + core->iris_v4l2_ioctl_ops_dec = &iris_v4l2_ioctl_ops_dec;
> + core->iris_v4l2_ioctl_ops_enc = &iris_v4l2_ioctl_ops_enc;
> }
>
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder
2025-08-13 9:38 ` [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder Dikshita Agarwal
@ 2025-08-14 14:43 ` Vikash Garodia
2025-08-18 3:21 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:43 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add support for frame size and frame interval enumeration by
> implementing ENUM_FRAMESIZES/FRAMEINTERVALS V4L2 ioctls for encoder
> video device with necessary hooks.
>
> This allows userspace application to query encoder capabilities and
> adapt encoding configurations accordingly.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> .../platform/qcom/iris/iris_platform_common.h | 5 +-
> .../media/platform/qcom/iris/iris_platform_gen2.c | 3 ++
> .../platform/qcom/iris/iris_platform_sm8250.c | 1 +
> drivers/media/platform/qcom/iris/iris_vdec.c | 13 +++++
> drivers/media/platform/qcom/iris/iris_vdec.h | 1 +
> drivers/media/platform/qcom/iris/iris_venc.c | 13 +++++
> drivers/media/platform/qcom/iris/iris_venc.h | 1 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 58 ++++++++++++++++++++--
> 8 files changed, 91 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
> index adafdce8a856f9c661aabc5ca28f0faceaa93551..792f46e2e34fd564a1ed61523f72826fc8f74582 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h
> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
> @@ -21,7 +21,8 @@ struct iris_inst;
> #define DEFAULT_MAX_HOST_BUF_COUNT 64
> #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256
> #define DEFAULT_FPS 30
> -#define NUM_MBS_8K ((8192 * 4352) / 256)
> +#define MAXIMUM_FPS 480
> +#define NUM_MBS_8K ((8192 * 4352) / 256)
>
> enum stage_type {
> STAGE_1 = 1,
> @@ -179,6 +180,8 @@ struct iris_platform_data {
> u32 max_session_count;
> /* max number of macroblocks per frame supported */
> u32 max_core_mbpf;
> + /* max number of macroblocks per second supported */
> + u32 max_core_mbps;
> const u32 *input_config_params_default;
> unsigned int input_config_params_default_size;
> const u32 *input_config_params_hevc;
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> index d3026b2bcb708c7ec31f134f628df7e57b54af4f..1e2fadfe17672029b46e07ce00a8e31e0711fd58 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> @@ -354,6 +354,7 @@ struct iris_platform_data sm8550_data = {
> .num_vpp_pipe = 4,
> .max_session_count = 16,
> .max_core_mbpf = NUM_MBS_8K * 2,
> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
> .input_config_params_default =
> sm8550_vdec_input_config_params_default,
> .input_config_params_default_size =
> @@ -429,6 +430,7 @@ struct iris_platform_data sm8650_data = {
> .num_vpp_pipe = 4,
> .max_session_count = 16,
> .max_core_mbpf = NUM_MBS_8K * 2,
> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
> .input_config_params_default =
> sm8550_vdec_input_config_params_default,
> .input_config_params_default_size =
> @@ -500,6 +502,7 @@ struct iris_platform_data qcs8300_data = {
> .num_vpp_pipe = 2,
> .max_session_count = 16,
> .max_core_mbpf = ((4096 * 2176) / 256) * 4,
> + .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
TODO ? 4k@60 is supported mbps for qcs8300
> .input_config_params_default =
> sm8550_vdec_input_config_params_default,
> .input_config_params_default_size =
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> index 8d0816a67ae0b6886204ce93fa5ccafaac10392a..2a3cbe1f2d4b27d3cce9e9cdad1525801d71a041 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> @@ -128,6 +128,7 @@ struct iris_platform_data sm8250_data = {
> .num_vpp_pipe = 4,
> .max_session_count = 16,
> .max_core_mbpf = NUM_MBS_8K,
> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
> .input_config_params_default =
> sm8250_vdec_input_config_param_default,
> .input_config_params_default_size =
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
> index 3482ff3f18d2bcd592b7eb7d803bf98e29276ebb..6afbd2f89260a233d75d7a0cdf3647236216c9ec 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
> @@ -263,6 +263,19 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
> return 0;
> }
>
> +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat)
> +{
> + const struct iris_fmt *fmt = NULL;
> +
> + if (pixelformat != V4L2_PIX_FMT_NV12) {
> + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
> + if (!fmt)
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub)
> {
> int ret = 0;
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
> index b24932dc511a65017b1cadbcb984544475bd0723..097e02bfa72b5ac4e46e66c61842df1d9dd4565b 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.h
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.h
> @@ -13,6 +13,7 @@ void iris_vdec_inst_deinit(struct iris_inst *inst);
> int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
> int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
> +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat);
> int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
> void iris_vdec_src_change(struct iris_inst *inst);
> int iris_vdec_streamon_input(struct iris_inst *inst);
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index 6bb59ce4fc565d3dcc6185233ef25d2e4d85cb3e..301206253090962abbb4e4eac8ee88e7b359c98d 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -270,3 +270,16 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
> return -EINVAL;
> }
> }
> +
> +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat)
> +{
> + const struct iris_fmt *fmt = NULL;
> +
> + if (pixelformat != V4L2_PIX_FMT_NV12) {
> + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> + if (!fmt)
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> index eb26a3ecbd98b3f02dfdea0dfc41bcd3a90904b6..04fd41275547c40c359c6ea04dfe4ee31d2d0df6 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.h
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -13,5 +13,6 @@ void iris_venc_inst_deinit(struct iris_inst *inst);
> int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
> int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
> +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 06b2737c5892ebbcf43b4cff66062d85cf805c20..cb1280c0c6c82187243f0bda4d98e42370ee787c 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -373,13 +373,18 @@ static int iris_enum_framesizes(struct file *filp, void *fh,
> {
> struct iris_inst *inst = iris_get_inst(filp, NULL);
> struct platform_inst_caps *caps;
> + int ret = 0;
>
> if (fsize->index)
> return -EINVAL;
>
> - if (fsize->pixel_format != V4L2_PIX_FMT_H264 &&
> - fsize->pixel_format != V4L2_PIX_FMT_NV12)
> - return -EINVAL;
> + if (inst->domain == DECODER)
> + ret = iris_vdec_validate_format(inst, fsize->pixel_format);
> + else
> + ret = iris_venc_validate_format(inst, fsize->pixel_format);
> +
> + if (ret)
> + return ret;
>
> caps = inst->core->iris_platform_data->inst_caps;
>
> @@ -391,6 +396,51 @@ static int iris_enum_framesizes(struct file *filp, void *fh,
> fsize->stepwise.max_height = caps->max_frame_height;
> fsize->stepwise.step_height = STEP_HEIGHT;
>
> + return ret;
> +}
> +
> +static int iris_enum_frameintervals(struct file *filp, void *fh,
> + struct v4l2_frmivalenum *fival)
> +
> +{
> + struct iris_inst *inst = iris_get_inst(filp, NULL);
> + struct platform_inst_caps *caps;
> + struct iris_core *core = inst->core;
> + u32 fps, mbpf;
> + int ret = 0;
> +
> + if (inst->domain == DECODER)
> + return -ENOTTY;
> +
> + if (fival->index)
> + return -EINVAL;
> +
> + ret = iris_venc_validate_format(inst, fival->pixel_format);
> + if (ret)
> + return ret;
> +
> + if (!fival->width || !fival->height)
> + return -EINVAL;
> +
> + caps = inst->core->iris_platform_data->inst_caps;
> + if (fival->width > caps->max_frame_width ||
> + fival->width < caps->min_frame_width ||
> + fival->height > caps->max_frame_height ||
> + fival->height < caps->min_frame_height)
> + return -EINVAL;
> +
> + mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width);
> + fps = DIV_ROUND_UP(core->iris_platform_data->max_core_mbps, mbpf);
> +
> + fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
> + fival->stepwise.min.numerator = 1;
> + fival->stepwise.min.denominator =
> + min_t(u32, fps, MAXIMUM_FPS);
> + fival->stepwise.max.numerator = 1;
> + fival->stepwise.max.denominator = 1;
> + fival->stepwise.step.numerator = 1;
> + fival->stepwise.step.denominator = MAXIMUM_FPS;
> +
> return 0;
> }
>
> @@ -525,6 +575,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
> .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane,
> .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane,
> .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
> + .vidioc_enum_framesizes = iris_enum_framesizes,
> + .vidioc_enum_frameintervals = iris_enum_frameintervals,
> };
>
> void iris_init_ops(struct iris_core *core)
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 15/24] media: iris: Add support for VIDIOC_QUERYCAP for encoder video device
2025-08-13 9:38 ` [PATCH v2 15/24] media: iris: Add support for VIDIOC_QUERYCAP for encoder video device Dikshita Agarwal
@ 2025-08-14 14:46 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:46 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add support for the VIDIOC_QUERYCAP V4L2 iocts for the encoder video
> device to report core driver capabilities.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_vidc.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index cb1280c0c6c82187243f0bda4d98e42370ee787c..458773a2ed7f5e16d5bd5e79dba2f5c029036505 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -446,8 +446,14 @@ static int iris_enum_frameintervals(struct file *filp, void *fh,
>
> static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap)
> {
> + struct iris_inst *inst = iris_get_inst(filp, NULL);
> +
> strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver));
> - strscpy(cap->card, "Iris Decoder", sizeof(cap->card));
> +
> + if (inst->domain == DECODER)
> + strscpy(cap->card, "Iris Decoder", sizeof(cap->card));
> + else
> + strscpy(cap->card, "Iris Encoder", sizeof(cap->card));
>
> return 0;
> }
> @@ -577,6 +583,7 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
> .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
> .vidioc_enum_framesizes = iris_enum_framesizes,
> .vidioc_enum_frameintervals = iris_enum_frameintervals,
> + .vidioc_querycap = iris_querycap,
> };
>
> void iris_init_ops(struct iris_core *core)
>
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 16/24] media: iris: Add encoder support for V4L2 event subscription
2025-08-13 9:38 ` [PATCH v2 16/24] media: iris: Add encoder support for V4L2 event subscription Dikshita Agarwal
@ 2025-08-14 14:48 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:48 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Implement support for V4L2 event subscription on the encoder device by
> handling the SUBSCRIBE_EVENT and UNSUBSCRIBE_EVENT ioctls with the
> necessary hooks.
>
> This enables userspace applications to subscribe to V4L2 events,
> allowing asynchronous notification mechanisms.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_venc.c | 14 ++++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 1 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 9 ++++++++-
> 3 files changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index 301206253090962abbb4e4eac8ee88e7b359c98d..3dbcce23cbe94cf0edc4421694a3ba11faa5eb96 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -3,6 +3,7 @@
> * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> +#include <media/v4l2-event.h>
> #include <media/v4l2-mem2mem.h>
>
> #include "iris_buffer.h"
> @@ -283,3 +284,16 @@ int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat)
>
> return 0;
> }
> +
> +int iris_venc_subscribe_event(struct iris_inst *inst,
> + const struct v4l2_event_subscription *sub)
> +{
> + switch (sub->type) {
> + case V4L2_EVENT_EOS:
> + return v4l2_event_subscribe(&inst->fh, sub, 0, NULL);
> + case V4L2_EVENT_CTRL:
> + return v4l2_ctrl_subscribe_event(&inst->fh, sub);
> + default:
> + return -EINVAL;
> + }
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> index 04fd41275547c40c359c6ea04dfe4ee31d2d0df6..2d9614ae18e8a2318df6673fbeae5ee33c99b596 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.h
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -14,5 +14,6 @@ int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
> int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
> +int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 458773a2ed7f5e16d5bd5e79dba2f5c029036505..d8c94074153e9b1ceac4f911210ddbf89bbe3533 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -489,7 +489,12 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
> {
> struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
>
> - return iris_vdec_subscribe_event(inst, sub);
> + if (inst->domain == DECODER)
> + return iris_vdec_subscribe_event(inst, sub);
> + else if (inst->domain == ENCODER)
> + return iris_venc_subscribe_event(inst, sub);
> +
> + return -EINVAL;
> }
>
> static int iris_dec_cmd(struct file *filp, void *fh,
> @@ -584,6 +589,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
> .vidioc_enum_framesizes = iris_enum_framesizes,
> .vidioc_enum_frameintervals = iris_enum_frameintervals,
> .vidioc_querycap = iris_querycap,
> + .vidioc_subscribe_event = iris_subscribe_event,
> + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> };
>
> void iris_init_ops(struct iris_core *core)
>
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device
2025-08-13 9:38 ` [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device Dikshita Agarwal
@ 2025-08-14 14:54 ` Vikash Garodia
2025-08-18 3:25 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 14:54 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add support for G/S_SELECTION V4L2 ioctls for the encoder video
> device with necessary hooks. This allows userspace to query and
> configure rectangular selection areas such as crop.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_venc.c | 28 ++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 1 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 65 ++++++++++++++++++++++------
> 3 files changed, 80 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index 3dbcce23cbe94cf0edc4421694a3ba11faa5eb96..930f5afe9489d01be193f1dbe429d33f5401b468 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -297,3 +297,31 @@ int iris_venc_subscribe_event(struct iris_inst *inst,
> return -EINVAL;
> }
> }
> +
> +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
> +{
> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
> + return -EINVAL;
> +
> + switch (s->target) {
> + case V4L2_SEL_TGT_CROP:
> + s->r.left = 0;
> + s->r.top = 0;
> +
> + if (s->r.width > inst->fmt_src->fmt.pix_mp.width ||
> + s->r.height > inst->fmt_src->fmt.pix_mp.height)
> + return -EINVAL;
> +
> + inst->crop.left = s->r.left;
> + inst->crop.top = s->r.top;
> + inst->crop.width = s->r.width;
> + inst->crop.height = s->r.height;
> + inst->fmt_dst->fmt.pix_mp.width = inst->crop.width;
> + inst->fmt_dst->fmt.pix_mp.height = inst->crop.height;
> + return iris_venc_s_fmt_output(inst, inst->fmt_dst);
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
Why do you need a return here ?
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> index 2d9614ae18e8a2318df6673fbeae5ee33c99b596..72c6e25d87113baa6d2219ae478b7d7df1aed7bf 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.h
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -15,5 +15,6 @@ int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
> int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
> +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index d8c94074153e9b1ceac4f911210ddbf89bbe3533..2074682a35fd1c4c9f5d29fdaee3392d98bf8923 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -462,29 +462,64 @@ static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *
> {
> struct iris_inst *inst = iris_get_inst(filp, NULL);
>
> - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
> + inst->domain == DECODER)
> return -EINVAL;
>
> - switch (s->target) {
> - case V4L2_SEL_TGT_CROP_BOUNDS:
> - case V4L2_SEL_TGT_CROP_DEFAULT:
> - case V4L2_SEL_TGT_CROP:
> - case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> - case V4L2_SEL_TGT_COMPOSE_PADDED:
> - case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> - case V4L2_SEL_TGT_COMPOSE:
> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
> + inst->domain == ENCODER)
> + return -EINVAL;
> +
> + if (inst->domain == DECODER) {
> + switch (s->target) {
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + case V4L2_SEL_TGT_CROP_DEFAULT:
> + case V4L2_SEL_TGT_CROP:
> + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> + case V4L2_SEL_TGT_COMPOSE_PADDED:
> + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> + case V4L2_SEL_TGT_COMPOSE:
> + s->r.left = inst->crop.left;
> + s->r.top = inst->crop.top;
> + s->r.width = inst->crop.width;
> + s->r.height = inst->crop.height;
> + break;
> + default:
> + return -EINVAL;
> + }
> + } else if (inst->domain == ENCODER) {
> + switch (s->target) {
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + case V4L2_SEL_TGT_CROP_DEFAULT:
> + s->r.width = inst->fmt_src->fmt.pix_mp.width;
> + s->r.height = inst->fmt_src->fmt.pix_mp.height;
> + break;
> + case V4L2_SEL_TGT_CROP:
> + s->r.width = inst->crop.width;
> + s->r.height = inst->crop.height;
> + break;
> + default:
> + return -EINVAL;
> + }
> s->r.left = inst->crop.left;
> s->r.top = inst->crop.top;
> - s->r.width = inst->crop.width;
> - s->r.height = inst->crop.height;
> - break;
> - default:
> - return -EINVAL;
> }
>
> return 0;
> }
>
> +static int iris_s_selection(struct file *filp, void *fh, struct v4l2_selection *s)
> +{
> + struct iris_inst *inst = iris_get_inst(filp, NULL);
s->r.left and s->r.top are signed and can be negative. Need to range bound
within 0 to src dimension ?
> +
> + if (inst->domain == DECODER)
> + return -EINVAL;
> + else if (inst->domain == ENCODER)
> + return iris_venc_s_selection(inst, s);
> +
> + return -EINVAL;
> +}
> +
> static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
> {
> struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
> @@ -591,6 +626,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
> .vidioc_querycap = iris_querycap,
> .vidioc_subscribe_event = iris_subscribe_event,
> .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> + .vidioc_g_selection = iris_g_selection,
> + .vidioc_s_selection = iris_s_selection,
> };
>
> void iris_init_ops(struct iris_core *core)
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 18/24] media: iris: Add support for G/S_PARM for encoder video device
2025-08-13 9:38 ` [PATCH v2 18/24] media: iris: Add support for G/S_PARM " Dikshita Agarwal
@ 2025-08-14 15:01 ` Vikash Garodia
2025-08-18 7:29 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 15:01 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add supports for the G/S_PARM V4L2 ioctls for encoder video device with
> necessary hooks. This allows userspace to query the current streaming
> parameters such as frame intervals and set desired streaming parameters
> primarily the frame rate.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_instance.h | 5 ++
> .../platform/qcom/iris/iris_platform_common.h | 2 +
> .../media/platform/qcom/iris/iris_platform_gen2.c | 4 +-
> .../platform/qcom/iris/iris_platform_qcs8300.h | 2 +
> .../platform/qcom/iris/iris_platform_sm8250.c | 2 +
> drivers/media/platform/qcom/iris/iris_utils.c | 36 ++++++++
> drivers/media/platform/qcom/iris/iris_utils.h | 2 +
> drivers/media/platform/qcom/iris/iris_vb2.c | 17 ----
> drivers/media/platform/qcom/iris/iris_venc.c | 95 ++++++++++++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 2 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 30 +++++++
> 11 files changed, 179 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
> index 55cf9702111829ef24189986ba5245c7684bfe11..b75549718df3c87cd85aecfc74c873c60cd4bde5 100644
> --- a/drivers/media/platform/qcom/iris/iris_instance.h
> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
> @@ -61,6 +61,9 @@ struct iris_fmt {
> * @metadata_idx: index for metadata buffer
> * @codec: codec type
> * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
> + * @frame_rate: frame rate of current instance
> + * @operating_rate: operating rate of current instance
> +
> */
>
> struct iris_inst {
> @@ -96,6 +99,8 @@ struct iris_inst {
> u32 metadata_idx;
> u32 codec;
> bool last_buffer_dequeued;
> + u32 frame_rate;
> + u32 operating_rate;
> };
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
> index 792f46e2e34fd564a1ed61523f72826fc8f74582..d0b84c93aef409b51a767ba11f91c6ce2533f27f 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h
> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
> @@ -79,6 +79,8 @@ struct platform_inst_caps {
> u32 mb_cycles_fw;
> u32 mb_cycles_fw_vpp;
> u32 num_comv;
> + u32 max_frame_rate;
> + u32 max_operating_rate;
> };
>
> enum platform_inst_fw_cap_type {
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> index 1e2fadfe17672029b46e07ce00a8e31e0711fd58..e047fb75a99a6372dac4ad029baea16034cac633 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> @@ -209,6 +209,8 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = {
> .mb_cycles_fw = 489583,
> .mb_cycles_fw_vpp = 66234,
> .num_comv = 0,
> + .max_frame_rate = MAXIMUM_FPS << 16,
> + .max_operating_rate = MAXIMUM_FPS << 16,
> };
>
> static void iris_set_sm8550_preset_registers(struct iris_core *core)
> @@ -502,7 +504,7 @@ struct iris_platform_data qcs8300_data = {
> .num_vpp_pipe = 2,
> .max_session_count = 16,
> .max_core_mbpf = ((4096 * 2176) / 256) * 4,
> - .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
> + .max_core_mbps = (((3840 * 2176) / 256) * 120),
> .input_config_params_default =
> sm8550_vdec_input_config_params_default,
> .input_config_params_default_size =
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
> index a8d66ed388a34e6bb45d4a089d981bb7d135fb50..22e485b0b2ae8f110d2f3b817e202d1aa7d227fd 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
> +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
> @@ -197,4 +197,6 @@ static struct platform_inst_caps platform_inst_cap_qcs8300 = {
> .mb_cycles_fw = 326389,
> .mb_cycles_fw_vpp = 44156,
> .num_comv = 0,
> + .max_frame_rate = MAXIMUM_FPS << 16,
> + .max_operating_rate = MAXIMUM_FPS << 16,
> };
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> index 2a3cbe1f2d4b27d3cce9e9cdad1525801d71a041..5d59a5a3172a510b3a38f7c9c29dffd919fafce7 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> @@ -40,6 +40,8 @@ static struct platform_inst_caps platform_inst_cap_sm8250 = {
> .max_mbpf = 138240,
> .mb_cycles_vsp = 25,
> .mb_cycles_vpp = 200,
> + .max_frame_rate = MAXIMUM_FPS << 16,
> + .max_operating_rate = MAXIMUM_FPS << 16,
> };
>
> static void iris_set_sm8250_preset_registers(struct iris_core *core)
> diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c
> index 83c70d6a2d9092615dcf1b7d0fc85110f0df1aa0..f0af926879d5d90c56222aa8d48998a34be1c636 100644
> --- a/drivers/media/platform/qcom/iris/iris_utils.c
> +++ b/drivers/media/platform/qcom/iris/iris_utils.c
> @@ -88,3 +88,39 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id)
> mutex_unlock(&core->lock);
> return NULL;
> }
> +
> +int iris_check_core_mbpf(struct iris_inst *inst)
> +{
> + struct iris_core *core = inst->core;
> + struct iris_inst *instance;
> + u32 total_mbpf = 0;
> +
> + mutex_lock(&core->lock);
> + list_for_each_entry(instance, &core->instances, list)
> + total_mbpf += iris_get_mbpf(instance);
> + mutex_unlock(&core->lock);
> +
> + if (total_mbpf > core->iris_platform_data->max_core_mbpf)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +int iris_check_core_mbps(struct iris_inst *inst)
> +{
> + struct iris_core *core = inst->core;
> + struct iris_inst *instance;
> + u32 total_mbps = 0, fps = 0;
> +
> + mutex_lock(&core->lock);
> + list_for_each_entry(instance, &core->instances, list) {
> + fps = max(instance->frame_rate >> 16, instance->operating_rate >> 16);
> + total_mbps += iris_get_mbpf(instance) * fps;
> + }
> + mutex_unlock(&core->lock);
> +
> + if (total_mbps > core->iris_platform_data->max_core_mbps)
> + return -ENOMEM;
> +
> + return 0;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h
> index 49869cf7a376880a026f44ff3883a6b13c6fcfbb..75740181122f5bdf93d64d3f43b3a26a9fe97919 100644
> --- a/drivers/media/platform/qcom/iris/iris_utils.h
> +++ b/drivers/media/platform/qcom/iris/iris_utils.h
> @@ -49,5 +49,7 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id);
> void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type,
> enum vb2_buffer_state state);
> int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush);
> +int iris_check_core_mbpf(struct iris_inst *inst);
> +int iris_check_core_mbps(struct iris_inst *inst);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
> index e62ed7a57df2debf0a930ad8307e6d945f589922..e32f7e1f007228a3b2b51cd76cd193d852f16080 100644
> --- a/drivers/media/platform/qcom/iris/iris_vb2.c
> +++ b/drivers/media/platform/qcom/iris/iris_vb2.c
> @@ -12,23 +12,6 @@
> #include "iris_vdec.h"
> #include "iris_power.h"
>
> -static int iris_check_core_mbpf(struct iris_inst *inst)
> -{
> - struct iris_core *core = inst->core;
> - struct iris_inst *instance;
> - u32 total_mbpf = 0;
> -
> - mutex_lock(&core->lock);
> - list_for_each_entry(instance, &core->instances, list)
> - total_mbpf += iris_get_mbpf(instance);
> - mutex_unlock(&core->lock);
> -
> - if (total_mbpf > core->iris_platform_data->max_core_mbpf)
> - return -ENOMEM;
> -
> - return 0;
> -}
> -
> static int iris_check_inst_mbpf(struct iris_inst *inst)
> {
> struct platform_inst_caps *caps;
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index 930f5afe9489d01be193f1dbe429d33f5401b468..11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -58,6 +58,9 @@ int iris_venc_inst_init(struct iris_inst *inst)
> inst->crop.width = f->fmt.pix_mp.width;
> inst->crop.height = f->fmt.pix_mp.height;
>
> + inst->operating_rate = DEFAULT_FPS << 16;
> + inst->frame_rate = DEFAULT_FPS << 16;
I understand that firmware expects the rate in Q16 format, but does driver needs
to keep it in that format ? I see most of the time in calculations, it is right
shifted to bring it back to normal one and then back n forth.
> +
> return 0;
> }
>
> @@ -325,3 +328,95 @@ int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
>
> return 0;
> }
> +
> +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
> +{
> + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
> + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
> + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
> + struct v4l2_fract *timeperframe = NULL;
> + u32 default_rate = DEFAULT_FPS;
> + bool is_frame_rate = false;
> + u32 q16_rate, max_rate;
> + u64 us_per_frame, fps;
> + int ret = 0;
> +
> + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> + timeperframe = &s_parm->parm.output.timeperframe;
> + max_rate = caps->max_operating_rate >> 16;
> + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
> + } else {
> + timeperframe = &s_parm->parm.capture.timeperframe;
> + is_frame_rate = true;
> + max_rate = caps->max_frame_rate >> 16;
> + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
> + }
> +
> + if (!timeperframe->denominator || !timeperframe->numerator) {
> + if (!timeperframe->numerator)
> + timeperframe->numerator = 1;
> + if (!timeperframe->denominator)
> + timeperframe->denominator = default_rate;
> + }
> +
> + us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
> + do_div(us_per_frame, timeperframe->denominator);
> +
> + if (!us_per_frame)
> + return -EINVAL;
> +
> + fps = (u64)USEC_PER_SEC;
> + do_div(fps, us_per_frame);
> + ret = fps > max_rate;
> + if (ret) {
if (fps > max_rate)
> + ret = -ENOMEM;
> + goto reset_rate;
> + }
> +
> + q16_rate = (u32)fps << 16;
> + if (is_frame_rate)
> + inst->frame_rate = q16_rate;
> + else
> + inst->operating_rate = q16_rate;
> +
> + if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) ||
> + (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) {
> + ret = iris_check_core_mbpf(inst);
> + if (ret)
> + goto reset_rate;
> + ret = iris_check_core_mbps(inst);
> + if (ret)
> + goto reset_rate;
> + }
> +
> + return 0;
> +
> +reset_rate:
> + if (ret) {
> + if (is_frame_rate)
> + inst->frame_rate = default_rate << 16;
> + else
> + inst->operating_rate = default_rate << 16;
> + }
> +
> + return ret;
> +}
> +
> +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
> +{
> + struct v4l2_fract *timeperframe = NULL;
> +
> + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> + timeperframe = &s_parm->parm.output.timeperframe;
> + timeperframe->numerator = 1;
> + timeperframe->denominator = inst->operating_rate >> 16;
> + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
> + } else {
> + timeperframe = &s_parm->parm.capture.timeperframe;
> + timeperframe->numerator = 1;
> + timeperframe->denominator = inst->frame_rate >> 16;
> + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> index 72c6e25d87113baa6d2219ae478b7d7df1aed7bf..0d566b7fc89b96b8fbc62a35b2ba795ca0bcf460 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.h
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -16,5 +16,7 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
> int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
> int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
> int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
> +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
> +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 2074682a35fd1c4c9f5d29fdaee3392d98bf8923..4c11cdac19f97d08a9e6242eea74649aad0242cf 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -532,6 +532,34 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
> return -EINVAL;
> }
>
> +static int iris_s_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
> +{
> + struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
> +
> + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
> + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
> + return -EINVAL;
> +
> + if (inst->domain == ENCODER)
> + return iris_venc_s_param(inst, a);
> + else
> + return -EINVAL;
> +}
> +
> +static int iris_g_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
> +{
> + struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
> +
> + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
> + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
> + return -EINVAL;
> +
> + if (inst->domain == ENCODER)
> + return iris_venc_g_param(inst, a);
> + else
> + return -EINVAL;
> +}
> +
> static int iris_dec_cmd(struct file *filp, void *fh,
> struct v4l2_decoder_cmd *dec)
> {
> @@ -628,6 +656,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
> .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> .vidioc_g_selection = iris_g_selection,
> .vidioc_s_selection = iris_s_selection,
> + .vidioc_s_parm = iris_s_parm,
> + .vidioc_g_parm = iris_g_parm,
> };
>
> void iris_init_ops(struct iris_core *core)
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 19/24] media: iris: Add platform-specific capabilities for encoder video device
2025-08-13 9:38 ` [PATCH v2 19/24] media: iris: Add platform-specific capabilities " Dikshita Agarwal
@ 2025-08-14 15:05 ` Vikash Garodia
2025-08-18 7:25 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Vikash Garodia @ 2025-08-14 15:05 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
> Add platform-specific capabilities for the encoder video device and
> initialize the corresponding controls in the control handler.
>
> This enables proper configuration and handling of encoder-specific
> features based on platform requirements.
>
> Co-developed-by: Wangao Wang <quic_wangaow@quicinc.com>
> Signed-off-by: Wangao Wang <quic_wangaow@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_core.h | 7 +-
> drivers/media/platform/qcom/iris/iris_ctrls.c | 175 +++++++++-
> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 7 +
> .../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 +
> .../platform/qcom/iris/iris_platform_common.h | 43 ++-
> .../media/platform/qcom/iris/iris_platform_gen2.c | 385 ++++++++++++++++++++-
> .../platform/qcom/iris/iris_platform_qcs8300.h | 350 ++++++++++++++++++-
> .../platform/qcom/iris/iris_platform_sm8250.c | 185 +++++++++-
> drivers/media/platform/qcom/iris/iris_vdec.c | 2 +-
> drivers/media/platform/qcom/iris/iris_venc.c | 7 +-
> 10 files changed, 1140 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
> index 827aee8dcec3ee17af5a90f5594b9315f663c0b3..fb194c967ad4f9b5e00cd74f0d41e0b827ef14db 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.h
> +++ b/drivers/media/platform/qcom/iris/iris_core.h
> @@ -71,7 +71,8 @@ enum domain_type {
> * @intr_status: interrupt status
> * @sys_error_handler: a delayed work for handling system fatal error
> * @instances: a list_head of all instances
> - * @inst_fw_caps: an array of supported instance capabilities
> + * @inst_fw_caps_dec: an array of supported instance capabilities by decoder
> + * @inst_fw_caps_enc: an array of supported instance capabilities by encoder
> */
>
> struct iris_core {
> @@ -113,7 +114,9 @@ struct iris_core {
> u32 intr_status;
> struct delayed_work sys_error_handler;
> struct list_head instances;
> - struct platform_inst_fw_cap inst_fw_caps[INST_FW_CAP_MAX];
> + /* encoder and decoder have overlapping caps, so two different arrays are required */
> + struct platform_inst_fw_cap inst_fw_caps_dec[INST_FW_CAP_MAX];
> + struct platform_inst_fw_cap inst_fw_caps_enc[INST_FW_CAP_MAX];
> };
>
> int iris_core_init(struct iris_core *core);
> diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
> index 9136b723c0f2a3d5833af32ae2735ccdb244f60f..797386cb96ab1d24be6cc1819e2f9202ab4cc224 100644
> --- a/drivers/media/platform/qcom/iris/iris_ctrls.c
> +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
> @@ -31,6 +31,68 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id)
> return LEVEL_VP9;
> case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
> return TIER;
> + case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
> + return HEADER_MODE;
> + case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
> + return PREPEND_SPSPPS_TO_IDR;
> + case V4L2_CID_MPEG_VIDEO_BITRATE:
> + return BITRATE;
> + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
> + return BITRATE_PEAK;
> + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
> + return BITRATE_MODE;
> + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
> + return FRAME_SKIP_MODE;
> + case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
> + return FRAME_RC_ENABLE;
> + case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
> + return GOP_SIZE;
> + case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
> + return ENTROPY_MODE;
> + case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
> + return MIN_FRAME_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
> + return MIN_FRAME_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
> + return MAX_FRAME_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
> + return MAX_FRAME_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP:
> + return I_FRAME_MIN_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP:
> + return I_FRAME_MIN_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP:
> + return P_FRAME_MIN_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP:
> + return P_FRAME_MIN_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP:
> + return B_FRAME_MIN_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP:
> + return B_FRAME_MIN_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP:
> + return I_FRAME_MAX_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP:
> + return I_FRAME_MAX_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP:
> + return P_FRAME_MAX_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP:
> + return P_FRAME_MAX_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP:
> + return B_FRAME_MAX_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP:
> + return B_FRAME_MAX_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
> + return I_FRAME_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
> + return I_FRAME_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
> + return P_FRAME_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
> + return P_FRAME_QP_HEVC;
> + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
> + return B_FRAME_QP_H264;
> + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
> + return B_FRAME_QP_HEVC;
> default:
> return INST_FW_CAP_MAX;
> }
> @@ -56,6 +118,68 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)
> return V4L2_CID_MPEG_VIDEO_VP9_LEVEL;
> case TIER:
> return V4L2_CID_MPEG_VIDEO_HEVC_TIER;
> + case HEADER_MODE:
> + return V4L2_CID_MPEG_VIDEO_HEADER_MODE;
> + case PREPEND_SPSPPS_TO_IDR:
> + return V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR;
> + case BITRATE:
> + return V4L2_CID_MPEG_VIDEO_BITRATE;
> + case BITRATE_PEAK:
> + return V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
> + case BITRATE_MODE:
> + return V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
> + case FRAME_SKIP_MODE:
> + return V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE;
> + case FRAME_RC_ENABLE:
> + return V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
> + case GOP_SIZE:
> + return V4L2_CID_MPEG_VIDEO_GOP_SIZE;
> + case ENTROPY_MODE:
> + return V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
> + case MIN_FRAME_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_MIN_QP;
> + case MIN_FRAME_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP;
> + case MAX_FRAME_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_MAX_QP;
> + case MAX_FRAME_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP;
> + case I_FRAME_MIN_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP;
> + case I_FRAME_MIN_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP;
> + case P_FRAME_MIN_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP;
> + case P_FRAME_MIN_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP;
> + case B_FRAME_MIN_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP;
> + case B_FRAME_MIN_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP;
> + case I_FRAME_MAX_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP;
> + case I_FRAME_MAX_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP;
> + case P_FRAME_MAX_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP;
> + case P_FRAME_MAX_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP;
> + case B_FRAME_MAX_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP;
> + case B_FRAME_MAX_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP;
> + case I_FRAME_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP;
> + case I_FRAME_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP;
> + case P_FRAME_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP;
> + case P_FRAME_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP;
> + case B_FRAME_QP_H264:
> + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP;
> + case B_FRAME_QP_HEVC:
> + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP;
> default:
> return 0;
> }
> @@ -101,7 +225,10 @@ int iris_ctrls_init(struct iris_inst *inst)
> num_ctrls++;
> }
>
> - /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */
> + /* Adding 1 to num_ctrls to include
> + * V4L2_CID_MIN_BUFFERS_FOR_CAPTURE for decoder and
> + * V4L2_CID_MIN_BUFFERS_FOR_OUTPUT for encoder
> + */
>
> ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1);
> if (ret)
> @@ -143,8 +270,13 @@ int iris_ctrls_init(struct iris_inst *inst)
> ctrl_idx++;
> }
>
> - v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
> - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
> + if (inst->domain == DECODER) {
> + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
> + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
> + } else {
> + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
> + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 4);
> + }
>
> ret = inst->ctrl_handler.error;
> if (ret)
> @@ -162,22 +294,39 @@ void iris_session_init_caps(struct iris_core *core)
> struct platform_inst_fw_cap *caps;
> u32 i, num_cap, cap_id;
>
> - caps = core->iris_platform_data->inst_fw_caps;
> - num_cap = core->iris_platform_data->inst_fw_caps_size;
> + caps = core->iris_platform_data->inst_fw_caps_dec;
> + num_cap = core->iris_platform_data->inst_fw_caps_dec_size;
> +
> + for (i = 0; i < num_cap; i++) {
> + cap_id = caps[i].cap_id;
> + if (!iris_valid_cap_id(cap_id))
> + continue;
> +
> + core->inst_fw_caps_dec[cap_id].cap_id = caps[i].cap_id;
> + core->inst_fw_caps_dec[cap_id].min = caps[i].min;
> + core->inst_fw_caps_dec[cap_id].max = caps[i].max;
> + core->inst_fw_caps_dec[cap_id].step_or_mask = caps[i].step_or_mask;
> + core->inst_fw_caps_dec[cap_id].value = caps[i].value;
> + core->inst_fw_caps_dec[cap_id].flags = caps[i].flags;
> + core->inst_fw_caps_dec[cap_id].hfi_id = caps[i].hfi_id;
> + core->inst_fw_caps_dec[cap_id].set = caps[i].set;
> + }
> +
> + caps = core->iris_platform_data->inst_fw_caps_enc;
> + num_cap = core->iris_platform_data->inst_fw_caps_enc_size;
>
> for (i = 0; i < num_cap; i++) {
> cap_id = caps[i].cap_id;
> if (!iris_valid_cap_id(cap_id))
> continue;
>
> - core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id;
> - core->inst_fw_caps[cap_id].min = caps[i].min;
> - core->inst_fw_caps[cap_id].max = caps[i].max;
> - core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask;
> - core->inst_fw_caps[cap_id].value = caps[i].value;
> - core->inst_fw_caps[cap_id].flags = caps[i].flags;
> - core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id;
> - core->inst_fw_caps[cap_id].set = caps[i].set;
> + core->inst_fw_caps_enc[cap_id].cap_id = caps[i].cap_id;
> + core->inst_fw_caps_enc[cap_id].min = caps[i].min;
> + core->inst_fw_caps_enc[cap_id].max = caps[i].max;
> + core->inst_fw_caps_enc[cap_id].step_or_mask = caps[i].step_or_mask;
> + core->inst_fw_caps_enc[cap_id].value = caps[i].value;
> + core->inst_fw_caps_enc[cap_id].flags = caps[i].flags;
> + core->inst_fw_caps_enc[cap_id].hfi_id = caps[i].hfi_id;
> }
> }
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> index 5b7c641b727a16c3aa7196a6d49786133653279f..a7f4379c5973fdc4366969139bef25472e8f11a5 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> @@ -121,6 +121,13 @@
> #define HFI_UNUSED_PICT 0x10000000
> #define HFI_BUFFERFLAG_DATACORRUPT 0x00000008
> #define HFI_BUFFERFLAG_DROP_FRAME 0x20000000
> +#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL 0x2005002
> +#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL 0x2005003
> +#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL 0x2005004
> +#define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2 0x2005009
> +#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020
> +#define HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE 0x2006001
> +#define HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER 0x2006008
>
> struct hfi_pkt_hdr {
> u32 size;
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
> index 5f13dc11bea532600cc9b15db57e8981a1f3eb93..fb6724d7f95ff8858aa9ba093fefb642e89de279 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
> @@ -55,12 +55,21 @@
> #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123
> #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124
> #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128
> +#define HFI_PROP_RATE_CONTROL 0x0300012a
> +#define HFI_PROP_QP_PACKED 0x0300012e
> +#define HFI_PROP_MIN_QP_PACKED 0x0300012f
> +#define HFI_PROP_MAX_QP_PACKED 0x03000130
> +#define HFI_PROP_TOTAL_BITRATE 0x0300013b
> +#define HFI_PROP_MAX_GOP_FRAMES 0x03000146
> +#define HFI_PROP_MAX_B_FRAMES 0x03000147
> #define HFI_PROP_QUALITY_MODE 0x03000148
> +#define HFI_PROP_SEQ_HEADER_MODE 0x03000149
> #define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155
> #define HFI_PROP_PICTURE_TYPE 0x03000162
> #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168
> #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169
> #define HFI_PROP_NO_OUTPUT 0x0300016a
> +#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C
> #define HFI_PROP_COMV_BUFFER_COUNT 0x03000193
> #define HFI_PROP_END 0x03FFFFFF
>
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
> index d0b84c93aef409b51a767ba11f91c6ce2533f27f..6d6a8f3b38271d928d753dd180e6e9a991991d24 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h
> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
> @@ -23,6 +23,11 @@ struct iris_inst;
> #define DEFAULT_FPS 30
> #define MAXIMUM_FPS 480
> #define NUM_MBS_8K ((8192 * 4352) / 256)
> +#define MIN_QP_8BIT 1
> +#define MAX_QP 51
> +#define MAX_QP_HEVC 63
> +#define DEFAULT_QP 20
> +#define BITRATE_DEFAULT 20000000
>
> enum stage_type {
> STAGE_1 = 1,
> @@ -91,6 +96,7 @@ enum platform_inst_fw_cap_type {
> LEVEL_HEVC,
> LEVEL_VP9,
> INPUT_BUF_HOST_MAX_COUNT,
> + OUTPUT_BUF_HOST_MAX_COUNT,
> STAGE,
> PIPE,
> POC,
> @@ -98,6 +104,37 @@ enum platform_inst_fw_cap_type {
> BIT_DEPTH,
> RAP_FRAME,
> TIER,
> + HEADER_MODE,
> + PREPEND_SPSPPS_TO_IDR,
> + BITRATE,
> + BITRATE_PEAK,
> + BITRATE_MODE,
> + FRAME_SKIP_MODE,
> + FRAME_RC_ENABLE,
> + GOP_SIZE,
> + ENTROPY_MODE,
> + MIN_FRAME_QP_H264,
> + MIN_FRAME_QP_HEVC,
> + MAX_FRAME_QP_H264,
> + MAX_FRAME_QP_HEVC,
> + I_FRAME_MIN_QP_H264,
> + I_FRAME_MIN_QP_HEVC,
> + P_FRAME_MIN_QP_H264,
> + P_FRAME_MIN_QP_HEVC,
> + B_FRAME_MIN_QP_H264,
> + B_FRAME_MIN_QP_HEVC,
> + I_FRAME_MAX_QP_H264,
> + I_FRAME_MAX_QP_HEVC,
> + P_FRAME_MAX_QP_H264,
> + P_FRAME_MAX_QP_HEVC,
> + B_FRAME_MAX_QP_H264,
> + B_FRAME_MAX_QP_HEVC,
> + I_FRAME_QP_H264,
> + I_FRAME_QP_HEVC,
> + P_FRAME_QP_H264,
> + P_FRAME_QP_HEVC,
> + B_FRAME_QP_H264,
> + B_FRAME_QP_HEVC,
> INST_FW_CAP_MAX,
> };
>
> @@ -172,8 +209,10 @@ struct iris_platform_data {
> const char *fwname;
> u32 pas_id;
> struct platform_inst_caps *inst_caps;
> - struct platform_inst_fw_cap *inst_fw_caps;
> - u32 inst_fw_caps_size;
> + struct platform_inst_fw_cap *inst_fw_caps_dec;
> + u32 inst_fw_caps_dec_size;
> + struct platform_inst_fw_cap *inst_fw_caps_enc;
> + u32 inst_fw_caps_enc_size;
> struct tz_cp_config *tz_cp_config_data;
> u32 core_arch;
> u32 hw_response_timeout;
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> index e047fb75a99a6372dac4ad029baea16034cac633..1bf289d322c86a8f8c03c80697c08af5d9067769 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
> @@ -14,8 +14,9 @@
> #include "iris_platform_sm8650.h"
>
> #define VIDEO_ARCH_LX 1
> +#define BITRATE_MAX 245000000
>
> -static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = {
> +static struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = {
> {
> .cap_id = PROFILE_H264,
> .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> @@ -199,6 +200,370 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = {
> },
> };
>
> +static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
> + {
> + .cap_id = PROFILE_H264,
> + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
> + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
> + .hfi_id = HFI_PROP_PROFILE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = PROFILE_HEVC,
> + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
> + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> + .hfi_id = HFI_PROP_PROFILE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = LEVEL_H264,
> + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
> + .hfi_id = HFI_PROP_LEVEL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = LEVEL_HEVC,
> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
> + .hfi_id = HFI_PROP_LEVEL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = STAGE,
> + .min = STAGE_1,
> + .max = STAGE_2,
> + .step_or_mask = 1,
> + .value = STAGE_2,
> + .hfi_id = HFI_PROP_STAGE,
> + },
> + {
> + .cap_id = HEADER_MODE,
> + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
> + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
> + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> + .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = PREPEND_SPSPPS_TO_IDR,
> + .min = 0,
> + .max = 1,
> + .step_or_mask = 1,
> + .value = 0,
> + },
> + {
> + .cap_id = BITRATE,
> + .min = 1,
> + .max = BITRATE_MAX,
> + .step_or_mask = 1,
> + .value = BITRATE_DEFAULT,
> + .hfi_id = HFI_PROP_TOTAL_BITRATE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = BITRATE_PEAK,
> + .min = 1,
> + .max = BITRATE_MAX,
> + .step_or_mask = 1,
> + .value = BITRATE_DEFAULT,
> + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = BITRATE_MODE,
> + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
> + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> + .hfi_id = HFI_PROP_RATE_CONTROL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = FRAME_SKIP_MODE,
> + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
> + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = FRAME_RC_ENABLE,
> + .min = 0,
> + .max = 1,
> + .step_or_mask = 1,
> + .value = 1,
> + },
> + {
> + .cap_id = GOP_SIZE,
> + .min = 0,
> + .max = INT_MAX,
> + .step_or_mask = 1,
> + .value = 2 * DEFAULT_FPS - 1,
> + .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = ENTROPY_MODE,
> + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> + .hfi_id = HFI_PROP_CABAC_SESSION,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = MIN_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MIN_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MAX_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MAX_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = I_FRAME_MIN_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = I_FRAME_MIN_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = P_FRAME_MIN_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = P_FRAME_MIN_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = B_FRAME_MIN_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = B_FRAME_MIN_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = I_FRAME_MAX_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = I_FRAME_MAX_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = P_FRAME_MAX_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = P_FRAME_MAX_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = B_FRAME_MAX_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = B_FRAME_MAX_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = I_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = I_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = P_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = P_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = B_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = B_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = INPUT_BUF_HOST_MAX_COUNT,
> + .min = DEFAULT_MAX_HOST_BUF_COUNT,
> + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
> + .step_or_mask = 1,
> + .value = DEFAULT_MAX_HOST_BUF_COUNT,
> + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
> + .flags = CAP_FLAG_INPUT_PORT,
> + },
> + {
> + .cap_id = OUTPUT_BUF_HOST_MAX_COUNT,
> + .min = DEFAULT_MAX_HOST_BUF_COUNT,
> + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
> + .step_or_mask = 1,
> + .value = DEFAULT_MAX_HOST_BUF_COUNT,
> + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> +};
> +
> static struct platform_inst_caps platform_inst_cap_sm8550 = {
> .min_frame_width = 96,
> .max_frame_width = 8192,
> @@ -347,8 +712,10 @@ struct iris_platform_data sm8550_data = {
> .fwname = "qcom/vpu/vpu30_p4.mbn",
> .pas_id = IRIS_PAS_ID,
> .inst_caps = &platform_inst_cap_sm8550,
> - .inst_fw_caps = inst_fw_cap_sm8550,
> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550),
> + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
> + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
> .tz_cp_config_data = &tz_cp_config_sm8550,
> .core_arch = VIDEO_ARCH_LX,
> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
> @@ -423,8 +790,10 @@ struct iris_platform_data sm8650_data = {
> .fwname = "qcom/vpu/vpu33_p4.mbn",
> .pas_id = IRIS_PAS_ID,
> .inst_caps = &platform_inst_cap_sm8550,
> - .inst_fw_caps = inst_fw_cap_sm8550,
> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550),
> + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
> + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
> .tz_cp_config_data = &tz_cp_config_sm8550,
> .core_arch = VIDEO_ARCH_LX,
> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
> @@ -495,8 +864,10 @@ struct iris_platform_data qcs8300_data = {
> .fwname = "qcom/vpu/vpu30_p4_s6.mbn",
> .pas_id = IRIS_PAS_ID,
> .inst_caps = &platform_inst_cap_qcs8300,
> - .inst_fw_caps = inst_fw_cap_qcs8300,
> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_qcs8300),
> + .inst_fw_caps_dec = inst_fw_cap_qcs8300_dec,
> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_qcs8300_dec),
> + .inst_fw_caps_enc = inst_fw_cap_qcs8300_enc,
> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_qcs8300_enc),
> .tz_cp_config_data = &tz_cp_config_sm8550,
> .core_arch = VIDEO_ARCH_LX,
> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
> index 22e485b0b2ae8f110d2f3b817e202d1aa7d227fd..624e3a442b06aabf3241d0b364b1d12fe937d6be 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
> +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
> @@ -3,7 +3,9 @@
> * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> */
>
> -static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = {
> +#define BITRATE_MAX 245000000
> +
> +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_dec[] = {
> {
> .cap_id = PROFILE_H264,
> .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> @@ -187,6 +189,352 @@ static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = {
> },
> };
>
> +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_enc[] = {
> + {
> + .cap_id = PROFILE_H264,
> + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
> + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
> + .hfi_id = HFI_PROP_PROFILE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = PROFILE_HEVC,
> + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
> + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> + .hfi_id = HFI_PROP_PROFILE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = LEVEL_H264,
> + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
> + .hfi_id = HFI_PROP_LEVEL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = LEVEL_HEVC,
> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
> + .hfi_id = HFI_PROP_LEVEL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = STAGE,
> + .min = STAGE_1,
> + .max = STAGE_2,
> + .step_or_mask = 1,
> + .value = STAGE_2,
> + .hfi_id = HFI_PROP_STAGE,
> + },
> + {
> + .cap_id = HEADER_MODE,
> + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
> + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
> + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> + .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = PREPEND_SPSPPS_TO_IDR,
> + .min = 0,
> + .max = 1,
> + .step_or_mask = 1,
> + .value = 0,
> + },
> + {
> + .cap_id = BITRATE,
> + .min = 1,
> + .max = BITRATE_MAX,
> + .step_or_mask = 1,
> + .value = BITRATE_DEFAULT,
> + .hfi_id = HFI_PROP_TOTAL_BITRATE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = BITRATE_PEAK,
> + .min = 1,
> + .max = BITRATE_MAX,
> + .step_or_mask = 1,
> + .value = BITRATE_DEFAULT,
> + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = BITRATE_MODE,
> + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
> + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> + .hfi_id = HFI_PROP_RATE_CONTROL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = FRAME_SKIP_MODE,
> + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
> + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = FRAME_RC_ENABLE,
> + .min = 0,
> + .max = 1,
> + .step_or_mask = 1,
> + .value = 1,
> + },
> + {
> + .cap_id = GOP_SIZE,
> + .min = 0,
> + .max = INT_MAX,
> + .step_or_mask = 1,
> + .value = 2 * DEFAULT_FPS - 1,
> + .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = ENTROPY_MODE,
> + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> + .hfi_id = HFI_PROP_CABAC_SESSION,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = MIN_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MIN_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MAX_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MAX_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = I_FRAME_MIN_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = I_FRAME_MIN_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = P_FRAME_MIN_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = P_FRAME_MIN_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = B_FRAME_MIN_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = B_FRAME_MIN_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + },
> + {
> + .cap_id = I_FRAME_MAX_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = I_FRAME_MAX_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = P_FRAME_MAX_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = P_FRAME_MAX_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = B_FRAME_MAX_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = B_FRAME_MAX_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + },
> + {
> + .cap_id = I_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = I_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = P_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = P_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = B_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = B_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = DEFAULT_QP,
> + .hfi_id = HFI_PROP_QP_PACKED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> +};
> +
> static struct platform_inst_caps platform_inst_cap_qcs8300 = {
> .min_frame_width = 96,
> .max_frame_width = 4096,
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> index 5d59a5a3172a510b3a38f7c9c29dffd919fafce7..b1ed6a140980ab6ca27f372f6f5851569a93ceed 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
> @@ -11,7 +11,12 @@
> #include "iris_hfi_gen1_defines.h"
> #include "iris_vpu_common.h"
>
> -static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = {
> +#define BITRATE_MIN 32000
> +#define BITRATE_MAX 160000000
> +#define BITRATE_PEAK_DEFAULT (BITRATE_DEFAULT * 2)
> +#define BITRATE_STEP 100
> +
> +static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = {
> {
> .cap_id = PIPE,
> .min = PIPE_1,
> @@ -32,6 +37,178 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = {
> },
> };
>
> +static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
> + {
> + .cap_id = PROFILE_H264,
> + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> + .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH),
> + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = PROFILE_HEVC,
> + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
> + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = LEVEL_H264,
> + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> + .max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1),
> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = LEVEL_HEVC,
> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
Fix the default value to V4L2_MPEG_VIDEO_HEVC_LEVEL_1
> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = HEADER_MODE,
> + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
> + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
> + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
> + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
> + .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = BITRATE,
> + .min = BITRATE_MIN,
> + .max = BITRATE_MAX,
> + .step_or_mask = BITRATE_STEP,
> + .value = BITRATE_DEFAULT,
> + .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
> + CAP_FLAG_DYNAMIC_ALLOWED,
> + },
> + {
> + .cap_id = BITRATE_MODE,
> + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
> + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
> + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
> + .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = FRAME_SKIP_MODE,
> + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
> + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = FRAME_RC_ENABLE,
> + .min = 0,
> + .max = 1,
> + .step_or_mask = 1,
> + .value = 1,
> + },
> + {
> + .cap_id = GOP_SIZE,
> + .min = 0,
> + .max = (1 << 16) - 1,
> + .step_or_mask = 1,
> + .value = 30,
> + },
> + {
> + .cap_id = ENTROPY_MODE,
> + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
> + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
> + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
> + .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL,
> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
> + },
> + {
> + .cap_id = MIN_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MIN_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP_HEVC,
> + .step_or_mask = 1,
> + .value = MIN_QP_8BIT,
> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MAX_FRAME_QP_H264,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP,
> + .step_or_mask = 1,
> + .value = MAX_QP,
> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> + {
> + .cap_id = MAX_FRAME_QP_HEVC,
> + .min = MIN_QP_8BIT,
> + .max = MAX_QP_HEVC,
> + .step_or_mask = 1,
> + .value = MAX_QP_HEVC,
> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
> + .flags = CAP_FLAG_OUTPUT_PORT,
> + },
> +};
> +
> static struct platform_inst_caps platform_inst_cap_sm8250 = {
> .min_frame_width = 128,
> .max_frame_width = 8192,
> @@ -123,8 +300,10 @@ struct iris_platform_data sm8250_data = {
> .fwname = "qcom/vpu-1.0/venus.mbn",
> .pas_id = IRIS_PAS_ID,
> .inst_caps = &platform_inst_cap_sm8250,
> - .inst_fw_caps = inst_fw_cap_sm8250,
> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8250),
> + .inst_fw_caps_dec = inst_fw_cap_sm8250_dec,
> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8250_dec),
> + .inst_fw_caps_enc = inst_fw_cap_sm8250_enc,
> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8250_enc),
> .tz_cp_config_data = &tz_cp_config_sm8250,
> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
> .num_vpp_pipe = 4,
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
> index 6afbd2f89260a233d75d7a0cdf3647236216c9ec..fcefd7c36335efd4154159d8a7fab31fae33a2fe 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
> @@ -54,7 +54,7 @@ int iris_vdec_inst_init(struct iris_inst *inst)
> inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
> inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
>
> - memcpy(&inst->fw_caps[0], &core->inst_fw_caps[0],
> + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_dec[0],
> INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
>
> return iris_ctrls_init(inst);
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index 11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67..4630ba12349a62a37515e93ed5efa2df197bce17 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -7,12 +7,14 @@
> #include <media/v4l2-mem2mem.h>
>
> #include "iris_buffer.h"
> +#include "iris_ctrls.h"
> #include "iris_instance.h"
> #include "iris_venc.h"
> #include "iris_vpu_buffer.h"
>
> int iris_venc_inst_init(struct iris_inst *inst)
> {
> + struct iris_core *core = inst->core;
> struct v4l2_format *f;
>
> inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
> @@ -61,7 +63,10 @@ int iris_venc_inst_init(struct iris_inst *inst)
> inst->operating_rate = DEFAULT_FPS << 16;
> inst->frame_rate = DEFAULT_FPS << 16;
>
> - return 0;
> + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0],
> + INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
> +
> + return iris_ctrls_init(inst);
> }
>
> void iris_venc_inst_deinit(struct iris_inst *inst)
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-13 9:38 ` [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure Dikshita Agarwal
2025-08-14 14:25 ` Vikash Garodia
@ 2025-08-16 9:03 ` Bryan O'Donoghue
2025-08-16 11:23 ` Bryan O'Donoghue
1 sibling, 1 reply; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 9:03 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:38, Dikshita Agarwal wrote:
> Introduce initialization and deinitialization for internal encoder
> instance structure with necessary hooks.
>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/Makefile | 1 +
> drivers/media/platform/qcom/iris/iris_buffer.c | 59 ++++++++++++++++----
> .../platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++-
> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
> drivers/media/platform/qcom/iris/iris_instance.h | 7 +++
> drivers/media/platform/qcom/iris/iris_vdec.c | 2 -
> drivers/media/platform/qcom/iris/iris_venc.c | 65 ++++++++++++++++++++++
> drivers/media/platform/qcom/iris/iris_venc.h | 14 +++++
> drivers/media/platform/qcom/iris/iris_vidc.c | 27 ++++++++-
> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 +-
> 10 files changed, 170 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
> index e86d00ee6f15dda8bae2f25f726feb0d427b7684..ec32145e081b1fc3538dfa7d5113162a76a6068c 100644
> --- a/drivers/media/platform/qcom/iris/Makefile
> +++ b/drivers/media/platform/qcom/iris/Makefile
> @@ -19,6 +19,7 @@ qcom-iris-objs += \
> iris_vidc.o \
> iris_vb2.o \
> iris_vdec.o \
> + iris_venc.o \
> iris_vpu2.o \
> iris_vpu3x.o \
> iris_vpu_buffer.o \
> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
> index 38548ee4749ea7dd1addf2c9d0677cf5217e3546..6bf9b0b35d206d51b927c824d5a5b327596251c6 100644
> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
> @@ -63,7 +63,12 @@
> static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
> {
> u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
> - struct v4l2_format *f = inst->fmt_dst;
> + struct v4l2_format *f;
> +
> + if (inst->domain == DECODER)
> + f = inst->fmt_dst;
> + else
> + f = inst->fmt_src;
>
> y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
> uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
> @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst)
> return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);
> }
>
> -static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
> +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
> {
> struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
> u32 base_res_mbs = NUM_MBS_4K;
> @@ -219,18 +224,50 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
> return ALIGN(frame_size, PIXELS_4K);
> }
>
> +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
> +{
> + u32 aligned_width, aligned_height, bitstream_size, yuv_size;
> + struct v4l2_format *f;
> +
> + f = inst->fmt_dst;
> +
> + aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
> + aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
> + bitstream_size = aligned_width * aligned_height * 3;
> + yuv_size = (aligned_width * aligned_height * 3) >> 1;
> + if (aligned_width * aligned_height > (4096 * 2176))
> + /* bitstream_size = 0.25 * yuv_size; */
> + bitstream_size = (bitstream_size >> 3);
> + else if (aligned_width * aligned_height > (1280 * 720))
> + /* bitstream_size = 0.5 * yuv_size; */
> + bitstream_size = (bitstream_size >> 2);
> +
> + return ALIGN(bitstream_size, 4096);
> +}
> +
> int iris_get_buffer_size(struct iris_inst *inst,
> enum iris_buffer_type buffer_type)
> {
> - switch (buffer_type) {
> - case BUF_INPUT:
> - return iris_bitstream_buffer_size(inst);
> - case BUF_OUTPUT:
> - return iris_yuv_buffer_size_nv12(inst);
> - case BUF_DPB:
> - return iris_yuv_buffer_size_qc08c(inst);
> - default:
> - return 0;
> + if (inst->domain == DECODER) {
> + switch (buffer_type) {
> + case BUF_INPUT:
> + return iris_dec_bitstream_buffer_size(inst);
> + case BUF_OUTPUT:
> + return iris_yuv_buffer_size_nv12(inst);
> + case BUF_DPB:
> + return iris_yuv_buffer_size_qc08c(inst);
> + default:
> + return 0;
> + }
> + } else {
> + switch (buffer_type) {
> + case BUF_INPUT:
> + return iris_yuv_buffer_size_nv12(inst);
> + case BUF_OUTPUT:
> + return iris_enc_bitstream_buffer_size(inst);
> + default:
> + return 0;
> + }
> }
> }
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> index 5097680ee14ebba3a126213c0584161627ca47d7..eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> @@ -109,7 +109,12 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst)
> packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
> packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
> packet.shdr.session_id = inst->session_id;
> - packet.session_domain = HFI_SESSION_TYPE_DEC;
> +
> + if (inst->domain == DECODER)
> + packet.session_domain = HFI_SESSION_TYPE_DEC;
> + else
> + packet.session_domain = HFI_SESSION_TYPE_ENC;
> +
> packet.session_codec = codec;
>
> reinit_completion(&inst->completion);
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> index d4d119ca98b0cb313db351f3794bf278216bd539..5b7c641b727a16c3aa7196a6d49786133653279f 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> @@ -10,6 +10,7 @@
>
> #define HFI_VIDEO_ARCH_OX 0x1
>
> +#define HFI_SESSION_TYPE_ENC 1
> #define HFI_SESSION_TYPE_DEC 2
>
> #define HFI_VIDEO_CODEC_H264 0x00000002
> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
> index 0e1f5799b72d993b25820608969e0011eabdb6bc..ff90f010f1d36690cbadeff0787b1fb7458d7f75 100644
> --- a/drivers/media/platform/qcom/iris/iris_instance.h
> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
> @@ -12,6 +12,9 @@
> #include "iris_core.h"
> #include "iris_utils.h"
>
> +#define DEFAULT_WIDTH 320
> +#define DEFAULT_HEIGHT 240
> +
> /**
> * struct iris_inst - holds per video instance parameters
> *
> @@ -24,7 +27,9 @@
> * @fmt_src: structure of v4l2_format for source
> * @fmt_dst: structure of v4l2_format for destination
> * @ctrl_handler: reference of v4l2 ctrl handler
> + * @domain: domain type: encoder or decoder
> * @crop: structure of crop info
> + * @compose: structure of compose info
> * @completion: structure of signal completions
> * @flush_completion: structure of signal completions for flush cmd
> * @flush_responses_pending: counter to track number of pending flush responses
> @@ -57,7 +62,9 @@ struct iris_inst {
> struct v4l2_format *fmt_src;
> struct v4l2_format *fmt_dst;
> struct v4l2_ctrl_handler ctrl_handler;
> + enum domain_type domain;
> struct iris_hfi_rect_desc crop;
> + struct iris_hfi_rect_desc compose;
> struct completion completion;
> struct completion flush_completion;
> u32 flush_responses_pending;
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
> index d670b51c5839d1fad54d34f373cf71d5f3973a96..3482ff3f18d2bcd592b7eb7d803bf98e29276ebb 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
> @@ -13,8 +13,6 @@
> #include "iris_vdec.h"
> #include "iris_vpu_buffer.h"
>
> -#define DEFAULT_WIDTH 320
> -#define DEFAULT_HEIGHT 240
> #define DEFAULT_CODEC_ALIGNMENT 16
>
> int iris_vdec_inst_init(struct iris_inst *inst)
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "iris_buffer.h"
> +#include "iris_instance.h"
> +#include "iris_venc.h"
> +#include "iris_vpu_buffer.h"
> +
> +int iris_venc_inst_init(struct iris_inst *inst)
> +{
> + struct v4l2_format *f;
> +
> + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
> + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
> + if (!inst->fmt_src || !inst->fmt_dst)
> + return -ENOMEM;
> +
> + f = inst->fmt_dst;
> + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> + f->fmt.pix_mp.width = DEFAULT_WIDTH;
> + f->fmt.pix_mp.height = DEFAULT_HEIGHT;
> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
> + inst->codec = f->fmt.pix_mp.pixelformat;
> + f->fmt.pix_mp.num_planes = 1;
> + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
> + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
> + inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
> +
> + f = inst->fmt_src;
> + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
> + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
> + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
> + f->fmt.pix_mp.num_planes = 1;
> + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
> + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
> + inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
> +
> + inst->crop.left = 0;
> + inst->crop.top = 0;
> + inst->crop.width = f->fmt.pix_mp.width;
> + inst->crop.height = f->fmt.pix_mp.height;
> +
> + return 0;
> +}
> +
> +void iris_venc_inst_deinit(struct iris_inst *inst)
> +{
> + kfree(inst->fmt_dst);
> + kfree(inst->fmt_src);
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..8a4cbddd0114b6d0e4ea895362b01c302250c78b
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _IRIS_VENC_H_
> +#define _IRIS_VENC_H_
> +
> +struct iris_inst;
> +
> +int iris_venc_inst_init(struct iris_inst *inst);
> +void iris_venc_inst_deinit(struct iris_inst *inst);
> +
> +#endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 96313856a026efaff40da97eaaa63e847172cd57..11f27fc867dc610c18022b0942e65aa175a8567e 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -12,6 +12,7 @@
> #include "iris_vidc.h"
> #include "iris_instance.h"
> #include "iris_vdec.h"
> +#include "iris_venc.h"
> #include "iris_vb2.h"
> #include "iris_vpu_buffer.h"
> #include "iris_platform_common.h"
> @@ -23,7 +24,10 @@
>
> static void iris_v4l2_fh_init(struct iris_inst *inst)
> {
> - v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
> + if (inst->domain == ENCODER)
> + v4l2_fh_init(&inst->fh, inst->core->vdev_enc);
> + else if (inst->domain == DECODER)
> + v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
> inst->fh.ctrl_handler = &inst->ctrl_handler;
> v4l2_fh_add(&inst->fh);
> }
> @@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_
> int iris_open(struct file *filp)
> {
> struct iris_core *core = video_drvdata(filp);
> + struct video_device *vdev;
> struct iris_inst *inst;
> + u32 session_type;
> int ret;
>
> + vdev = video_devdata(filp);
> + if (strcmp(vdev->name, "qcom-iris-decoder") == 0)
> + session_type = DECODER;
> + else if (strcmp(vdev->name, "qcom-iris-encoder") == 0)
> + session_type = ENCODER;
> + else
> + return -EINVAL;
> +
> ret = pm_runtime_resume_and_get(core->dev);
> if (ret < 0)
> return ret;
> @@ -147,6 +161,7 @@ int iris_open(struct file *filp)
> return -ENOMEM;
>
> inst->core = core;
> + inst->domain = session_type;
> inst->session_id = hash32_ptr(inst);
> inst->state = IRIS_INST_DEINIT;
>
> @@ -178,7 +193,10 @@ int iris_open(struct file *filp)
> goto fail_m2m_release;
> }
>
> - ret = iris_vdec_inst_init(inst);
> + if (inst->domain == DECODER)
> + ret = iris_vdec_inst_init(inst);
> + else if (inst->domain == ENCODER)
> + ret = iris_venc_inst_init(inst);
> if (ret)
> goto fail_m2m_ctx_release;
>
> @@ -265,7 +283,10 @@ int iris_close(struct file *filp)
> v4l2_m2m_ctx_release(inst->m2m_ctx);
> v4l2_m2m_release(inst->m2m_dev);
> mutex_lock(&inst->lock);
> - iris_vdec_inst_deinit(inst);
> + if (inst->domain == DECODER)
> + iris_vdec_inst_deinit(inst);
> + else if (inst->domain == ENCODER)
> + iris_venc_inst_deinit(inst);
> iris_session_close(inst);
> iris_inst_change_state(inst, IRIS_INST_DEINIT);
> iris_v4l2_fh_deinit(inst);
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> index f92fd39fe310b9661f892dcf1ff036ebbc102270..06d5afc3c641f0dfca3967e55273c4fa2614fdff 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> @@ -628,7 +628,10 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type
> case BUF_INPUT:
> return MIN_BUFFERS;
> case BUF_OUTPUT:
> - return output_min_count(inst);
> + if (inst->domain == ENCODER)
> + return MIN_BUFFERS;
> + else
> + return output_min_count(inst);
> case BUF_BIN:
> case BUF_COMV:
> case BUF_NON_COMV:
>
Patch failed at 0012 media: iris: Initialize and deinitialize encoder
instance structure
error: patch failed: drivers/media/platform/qcom/iris/iris_vidc.c:23
error: drivers/media/platform/qcom/iris/iris_vidc.c: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
git log drivers/media/platform/qcom/iris/iris_vidc.c
commit 095ac6efdcaaa0169c5e0b4471f7835d39cd82d7
Author: Dikshita Agarwal <quic_dikshita@quicinc.com>
Date: Wed Aug 13 15:07:52 2025 +0530
media: iris: Report unreleased PERSIST buffers on session close
Add error reporting for unreleased PERSIST internal buffers in
iris_check_num_queued_internal_buffers(). This ensures all buffer types
are checked and logged if not freed during session close, helping to
detect memory leaks and improve driver robustness. No change to buffer
lifecycle or allocation logic.
Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release
on close")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
commit 7c6719080cbcc1d3376385c66d456b25f85abcdc
Author: Dikshita Agarwal <quic_dikshita@quicinc.com>
Date: Wed Aug 13 15:07:51 2025 +0530
media: iris: Fix buffer count reporting in internal buffer check
Initialize the count variable to zero before counting unreleased
internal buffers in iris_check_num_queued_internal_buffers().
This prevents stale values from previous iterations and ensures
accurate
error reporting for each buffer type. Without this initialization, the
count could accumulate across types, leading to incorrect log messages.
Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release
on close")
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
commit 277966749f46bc6292c4052b4e66a554f193a78a
Author: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Sun Aug 10 04:30:09 2025 +0300
media: Reset file->private_data to NULL in v4l2_fh_del()
https://gitlab.freedesktop.org/linux-media/users/bodonoghue/-/commits/b4/bod-media-committers-next-platform-qcom-6.17-rc1
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer
2025-08-13 9:37 ` [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer Dikshita Agarwal
@ 2025-08-16 10:15 ` Bryan O'Donoghue
2025-08-18 3:10 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 10:15 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> One internal buffer which is allocated only once per session was not
> being freed during session close because it was not being tracked as
> part of internal buffer list which resulted in a memory leak.
>
> Add the necessary logic to explicitly free the untracked internal buffer
> during session close to ensure all allocated memory is released
> properly.
>
> Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_buffer.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
> index 6425e4919e3b0b849ba801ca9e01921c114144cd..9f664c241149362d44d3a8fa65e2266f9c2e80e0 100644
> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
> @@ -413,6 +413,16 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool
> }
> }
>
> + if (force) {
> + buffers = &inst->buffers[BUF_PERSIST];
> +
> + list_for_each_entry_safe(buf, next, &buffers->list, list) {
> + ret = iris_destroy_internal_buffer(inst, buf);
> + if (ret)
> + return ret;
> + }
> + }
> +
> return 0;
> }
>
>
Why is the logic here not to simply release every index of the enum
iris_buffer_type ?
If I'm reading the code right here, len indicates the list of linked
lists to free, adding BUF_PERSIST appends to the list that may be freed
if force is true but, then what about the remaining entries BUF_SCRATCH_1 ?
Is it valid to leave this routine with force = true but BUF_SCRATCH_1
not specifically indexed, if so why ?
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 04/24] media: iris: Fix port streaming handling
2025-08-13 9:37 ` [PATCH v2 04/24] media: iris: Fix port streaming handling Dikshita Agarwal
@ 2025-08-16 10:40 ` Bryan O'Donoghue
2025-08-18 9:45 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 10:40 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> + if (!ret)
I think you should have a consistent error pattern
if (ret)
goto error;
Once amended
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 06/24] media: iris: Always destroy internal buffers on firmware release response
2025-08-13 9:37 ` [PATCH v2 06/24] media: iris: Always destroy internal buffers on firmware release response Dikshita Agarwal
@ 2025-08-16 10:44 ` Bryan O'Donoghue
0 siblings, 0 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 10:44 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> Currently, internal buffers are destroyed only if 'PENDING_RELEASE' flag
> is set when a release response is received from the firmware, which is
> incorrect. Internal buffers should always be destroyed when the firmware
> explicitly releases it, regardless of whether the 'PENDING_RELEASE' flag
> was set by the driver. This is specially important during force-stop
> scenarios, where the firmware may release buffers without driver marking
> them for release.
> Fix this by removing the incorrect check and ensuring all buffers are
> properly cleaned up.
>
> Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 5 +----
> 1 file changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> index a8c30fc5c0d0668cc9980f2fcfcf21072cf9ef0a..dda775d463e916f70da0b879702d96df18ea8bf7 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> @@ -424,7 +424,6 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
> struct iris_buffers *buffers = &inst->buffers[buf_type];
> struct iris_buffer *buf, *iter;
> bool found = false;
> - int ret = 0;
>
> list_for_each_entry(iter, &buffers->list, list) {
> if (iter->device_addr == buffer->base_address) {
> @@ -437,10 +436,8 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
> return -EINVAL;
>
> buf->attr &= ~BUF_ATTR_QUEUED;
> - if (buf->attr & BUF_ATTR_PENDING_RELEASE)
> - ret = iris_destroy_internal_buffer(inst, buf);
>
> - return ret;
> + return iris_destroy_internal_buffer(inst, buf);
> }
>
> static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst,
>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 07/24] media: iris: Update vbuf flags before v4l2_m2m_buf_done
2025-08-13 9:37 ` [PATCH v2 07/24] media: iris: Update vbuf flags before v4l2_m2m_buf_done Dikshita Agarwal
@ 2025-08-16 10:49 ` Bryan O'Donoghue
0 siblings, 0 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 10:49 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> Update the vbuf flags appropriately in error cases before calling
> v4l2_m2m_buf_done(). Previously, the flag update was skippied in error
> scenario, which could result in incorrect state reporting for buffers.
>
> Fixes: 17f2a485ca67 ("media: iris: implement vb2 ops for buf_queue and firmware response")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_buffer.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
> index 23cac5d1312913b8dac44347ae66cb80a6a15deb..38548ee4749ea7dd1addf2c9d0677cf5217e3546 100644
> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
> @@ -651,6 +651,8 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
>
> vb2 = &vbuf->vb2_buf;
>
> + vbuf->flags |= buf->flags;
> +
> if (buf->flags & V4L2_BUF_FLAG_ERROR) {
> state = VB2_BUF_STATE_ERROR;
> vb2_set_plane_payload(vb2, 0, 0);
> @@ -659,8 +661,6 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
> return 0;
> }
>
> - vbuf->flags |= buf->flags;
> -
> if (V4L2_TYPE_IS_CAPTURE(type)) {
> vb2_set_plane_payload(vb2, 0, buf->data_size);
> vbuf->sequence = inst->sequence_cap++;
>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued.
2025-08-13 9:37 ` [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued Dikshita Agarwal
@ 2025-08-16 11:07 ` Bryan O'Donoghue
2025-08-19 7:29 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 11:07 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> For HFI Gen1, the instances substate is changed to LOAD_RESOURCES only
> when a START command is issues to the firmware. If STOP is called
> without a prior START, the firmware may reject the command and throw
> some erros.
> Handle this by adding a substate check before issuing STOP command to
> the firmware.
>
> Fixes: 11712ce70f8e ("media: iris: implement vb2 streaming ops")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> index 5fc30d54af4dc34616cfd08813940aa0b7044a20..5f1748ab80f88393215fc2d82c5c6b4af1266090 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> @@ -184,11 +184,12 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane)
> u32 flush_type = 0;
> int ret = 0;
>
> - if ((V4L2_TYPE_IS_OUTPUT(plane) &&
> - inst->state == IRIS_INST_INPUT_STREAMING) ||
> + if (((V4L2_TYPE_IS_OUTPUT(plane) &&
> + inst->state == IRIS_INST_INPUT_STREAMING) ||
this is becoming a highly complex clause
if (((V4L2_TYPE_IS_OUTPUT(plane) &&
inst->state == IRIS_INST_INPUT_STREAMING) ||
(V4L2_TYPE_IS_CAPTURE(plane) &&
inst->state == IRIS_INST_OUTPUT_STREAMING) ||
inst->state == IRIS_INST_ERROR) &&
inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
can we not reduce down the number of conjunctions and dis-junctions here ?
Its getting hard to follow.
For example pivot on if (inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES)
or make it into a switch for inst->state... no that wouldn't work
Either way the complexity of this clause is indicating to me we need to
do some decomposition.
Please consider if you can rationalise the logic here and make the code
more readable.
> (V4L2_TYPE_IS_CAPTURE(plane) &&
> inst->state == IRIS_INST_OUTPUT_STREAMING) ||
> - inst->state == IRIS_INST_ERROR) {
> + inst->state == IRIS_INST_ERROR) &&
> + inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
> reinit_completion(&inst->completion);
> iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP);
> ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
>
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 09/24] media: iris: Send dummy buffer address for all codecs during drain
2025-08-13 9:37 ` [PATCH v2 09/24] media: iris: Send dummy buffer address for all codecs during drain Dikshita Agarwal
@ 2025-08-16 11:11 ` Bryan O'Donoghue
0 siblings, 0 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 11:11 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:37, Dikshita Agarwal wrote:
> Firmware can handle a dummy address for buffers with the EOS flag. To
> ensure consistent behavior across all codecs, update the drain
> command to always send a dummy buffer address.
>
> This makes the drain handling uniform and avoids any codec specific
> assumptions.
>
> Fixes: 478c4478610d ("media: iris: Add codec specific check for VP9 decoder drain handling")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> index 5f1748ab80f88393215fc2d82c5c6b4af1266090..5097680ee14ebba3a126213c0584161627ca47d7 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> @@ -402,8 +402,7 @@ static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane)
> ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
> ip_pkt.shdr.session_id = inst->session_id;
> ip_pkt.flags = HFI_BUFFERFLAG_EOS;
> - if (inst->codec == V4L2_PIX_FMT_VP9)
> - ip_pkt.packet_buffer = 0xdeadb000;
> + ip_pkt.packet_buffer = 0xdeadb000;
>
> return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
> }
>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 10/24] media: iris: Fix missing LAST flag handling during drain
2025-08-13 9:38 ` [PATCH v2 10/24] media: iris: Fix missing LAST flag handling " Dikshita Agarwal
@ 2025-08-16 11:17 ` Bryan O'Donoghue
0 siblings, 0 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 11:17 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:38, Dikshita Agarwal wrote:
> Improve drain handling by ensuring the LAST flag is attached to final
> capture buffer when drain response is received from the firmware.
>
> Previously, the driver failed to attach the V4L2_BUF_FLAG_LAST flag when
> a drain response was received from the firmware, relying on userspace to
> mark the next queued buffer as LAST. This update fixes the issue by
> checking the pending drain status, attaching the LAST flag to the
> capture buffer received from the firmware (with EOS attached), and
> returning it to the V4L2 layer correctly.
>
> Fixes: d09100763bed ("media: iris: add support for drain sequence")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
> drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 4 +---
> drivers/media/platform/qcom/iris/iris_state.c | 2 +-
> drivers/media/platform/qcom/iris/iris_state.h | 1 +
> 3 files changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> index 8d1ce8a19a45ebb2b29457e0fef7d72c1c0d9785..2a96458833835422d30c9386d15cc1e4fb226e3d 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> @@ -416,8 +416,6 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
> inst->flush_responses_pending++;
>
> iris_inst_sub_state_change_drain_last(inst);
> -
> - return;
> }
>
> if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) {
> @@ -462,7 +460,7 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
> timestamp_us = (timestamp_us << 32) | timestamp_lo;
> } else {
> if (pkt->stream_id == 1 && !inst->last_buffer_dequeued) {
> - if (iris_drc_pending(inst)) {
> + if (iris_drc_pending(inst) || iris_drain_pending(inst)) {
> flags |= V4L2_BUF_FLAG_LAST;
> inst->last_buffer_dequeued = true;
> }
> diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
> index a21238d2818f9606871953bd0bee25382cca0474..d1dc1a863da0b0b1af60974e9ed2ef68ea225cdd 100644
> --- a/drivers/media/platform/qcom/iris/iris_state.c
> +++ b/drivers/media/platform/qcom/iris/iris_state.c
> @@ -252,7 +252,7 @@ bool iris_drc_pending(struct iris_inst *inst)
> inst->sub_state & IRIS_INST_SUB_DRC_LAST;
> }
>
> -static inline bool iris_drain_pending(struct iris_inst *inst)
> +bool iris_drain_pending(struct iris_inst *inst)
> {
> return inst->sub_state & IRIS_INST_SUB_DRAIN &&
> inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
> diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h
> index e718386dbe0402417f408d8fc696a33e5c7f23b3..b09fa54cf17eeee0c9ae254588964ad959c82c80 100644
> --- a/drivers/media/platform/qcom/iris/iris_state.h
> +++ b/drivers/media/platform/qcom/iris/iris_state.h
> @@ -141,5 +141,6 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst);
> int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane);
> bool iris_allow_cmd(struct iris_inst *inst, u32 cmd);
> bool iris_drc_pending(struct iris_inst *inst);
> +bool iris_drain_pending(struct iris_inst *inst);
>
> #endif
>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 11/24] media: iris: Add support for video encoder device
2025-08-13 9:38 ` [PATCH v2 11/24] media: iris: Add support for video encoder device Dikshita Agarwal
2025-08-14 14:11 ` Vikash Garodia
@ 2025-08-16 11:21 ` Bryan O'Donoghue
2025-08-18 3:28 ` Dikshita Agarwal
1 sibling, 1 reply; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 11:21 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 13/08/2025 10:38, Dikshita Agarwal wrote:
> + if (type == DECODER) {
> + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
> + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> + if (ret)
> + goto err_vdev_release;
> + core->vdev_dec = vdev;
> + } else if (type == ENCODER) {
> + strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
> + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> + if (ret)
> + goto err_vdev_release;
> + core->vdev_enc = vdev;
> + } else {
A bit of duplicate reduction.
if (type == DECODER) {
strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
core->vdev_dec = vdev;
} else if (type == ENCODER) {
strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
core->vdev_enc = vdev;
} else {
ret = -EINVAL;
goto err_vdev_release;
}
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret)
goto err_vdev_release;
once done
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-16 9:03 ` Bryan O'Donoghue
@ 2025-08-16 11:23 ` Bryan O'Donoghue
2025-08-18 3:27 ` Dikshita Agarwal
0 siblings, 1 reply; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-16 11:23 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 16/08/2025 10:03, Bryan O'Donoghue wrote:
> On 13/08/2025 10:38, Dikshita Agarwal wrote:
>> Introduce initialization and deinitialization for internal encoder
>> instance structure with necessary hooks.
>>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/Makefile | 1 +
>> drivers/media/platform/qcom/iris/iris_buffer.c | 59 ++++++++++++
>> ++++----
>> .../platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++-
>> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
>> drivers/media/platform/qcom/iris/iris_instance.h | 7 +++
>> drivers/media/platform/qcom/iris/iris_vdec.c | 2 -
>> drivers/media/platform/qcom/iris/iris_venc.c | 65 ++++++++++++
>> ++++++++++
>> drivers/media/platform/qcom/iris/iris_venc.h | 14 +++++
>> drivers/media/platform/qcom/iris/iris_vidc.c | 27 ++++++++-
>> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 +-
>> 10 files changed, 170 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/
>> media/platform/qcom/iris/Makefile
>> index
>> e86d00ee6f15dda8bae2f25f726feb0d427b7684..ec32145e081b1fc3538dfa7d5113162a76a6068c 100644
>> --- a/drivers/media/platform/qcom/iris/Makefile
>> +++ b/drivers/media/platform/qcom/iris/Makefile
>> @@ -19,6 +19,7 @@ qcom-iris-objs += \
>> iris_vidc.o \
>> iris_vb2.o \
>> iris_vdec.o \
>> + iris_venc.o \
>> iris_vpu2.o \
>> iris_vpu3x.o \
>> iris_vpu_buffer.o \
>> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/
>> media/platform/qcom/iris/iris_buffer.c
>> index
>> 38548ee4749ea7dd1addf2c9d0677cf5217e3546..6bf9b0b35d206d51b927c824d5a5b327596251c6 100644
>> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
>> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
>> @@ -63,7 +63,12 @@
>> static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
>> {
>> u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines,
>> uv_scanlines;
>> - struct v4l2_format *f = inst->fmt_dst;
>> + struct v4l2_format *f;
>> +
>> + if (inst->domain == DECODER)
>> + f = inst->fmt_dst;
>> + else
>> + f = inst->fmt_src;
>> y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
>> uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
>> @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct
>> iris_inst *inst)
>> return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane,
>> PIXELS_4K);
>> }
>> -static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
>> +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
>> {
>> struct platform_inst_caps *caps = inst->core-
>> >iris_platform_data->inst_caps;
>> u32 base_res_mbs = NUM_MBS_4K;
>> @@ -219,18 +224,50 @@ static u32 iris_bitstream_buffer_size(struct
>> iris_inst *inst)
>> return ALIGN(frame_size, PIXELS_4K);
>> }
>> +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
>> +{
>> + u32 aligned_width, aligned_height, bitstream_size, yuv_size;
>> + struct v4l2_format *f;
>> +
>> + f = inst->fmt_dst;
>> +
>> + aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
>> + aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
>> + bitstream_size = aligned_width * aligned_height * 3;
>> + yuv_size = (aligned_width * aligned_height * 3) >> 1;
>> + if (aligned_width * aligned_height > (4096 * 2176))
>> + /* bitstream_size = 0.25 * yuv_size; */
>> + bitstream_size = (bitstream_size >> 3);
>> + else if (aligned_width * aligned_height > (1280 * 720))
>> + /* bitstream_size = 0.5 * yuv_size; */
>> + bitstream_size = (bitstream_size >> 2);
>> +
>> + return ALIGN(bitstream_size, 4096);
>> +}
>> +
>> int iris_get_buffer_size(struct iris_inst *inst,
>> enum iris_buffer_type buffer_type)
>> {
>> - switch (buffer_type) {
>> - case BUF_INPUT:
>> - return iris_bitstream_buffer_size(inst);
>> - case BUF_OUTPUT:
>> - return iris_yuv_buffer_size_nv12(inst);
>> - case BUF_DPB:
>> - return iris_yuv_buffer_size_qc08c(inst);
>> - default:
>> - return 0;
>> + if (inst->domain == DECODER) {
>> + switch (buffer_type) {
>> + case BUF_INPUT:
>> + return iris_dec_bitstream_buffer_size(inst);
>> + case BUF_OUTPUT:
>> + return iris_yuv_buffer_size_nv12(inst);
>> + case BUF_DPB:
>> + return iris_yuv_buffer_size_qc08c(inst);
>> + default:
>> + return 0;
>> + }
>> + } else {
>> + switch (buffer_type) {
>> + case BUF_INPUT:
>> + return iris_yuv_buffer_size_nv12(inst);
>> + case BUF_OUTPUT:
>> + return iris_enc_bitstream_buffer_size(inst);
>> + default:
>> + return 0;
>> + }
>> }
>> }
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> index
>> 5097680ee14ebba3a126213c0584161627ca47d7..eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> @@ -109,7 +109,12 @@ static int iris_hfi_gen1_session_open(struct
>> iris_inst *inst)
>> packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
>> packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
>> packet.shdr.session_id = inst->session_id;
>> - packet.session_domain = HFI_SESSION_TYPE_DEC;
>> +
>> + if (inst->domain == DECODER)
>> + packet.session_domain = HFI_SESSION_TYPE_DEC;
>> + else
>> + packet.session_domain = HFI_SESSION_TYPE_ENC;
>> +
>> packet.session_codec = codec;
>> reinit_completion(&inst->completion);
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> index
>> d4d119ca98b0cb313db351f3794bf278216bd539..5b7c641b727a16c3aa7196a6d49786133653279f 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> @@ -10,6 +10,7 @@
>> #define HFI_VIDEO_ARCH_OX 0x1
>> +#define HFI_SESSION_TYPE_ENC 1
>> #define HFI_SESSION_TYPE_DEC 2
>> #define HFI_VIDEO_CODEC_H264 0x00000002
>> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/
>> drivers/media/platform/qcom/iris/iris_instance.h
>> index
>> 0e1f5799b72d993b25820608969e0011eabdb6bc..ff90f010f1d36690cbadeff0787b1fb7458d7f75 100644
>> --- a/drivers/media/platform/qcom/iris/iris_instance.h
>> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
>> @@ -12,6 +12,9 @@
>> #include "iris_core.h"
>> #include "iris_utils.h"
>> +#define DEFAULT_WIDTH 320
>> +#define DEFAULT_HEIGHT 240
>> +
>> /**
>> * struct iris_inst - holds per video instance parameters
>> *
>> @@ -24,7 +27,9 @@
>> * @fmt_src: structure of v4l2_format for source
>> * @fmt_dst: structure of v4l2_format for destination
>> * @ctrl_handler: reference of v4l2 ctrl handler
>> + * @domain: domain type: encoder or decoder
>> * @crop: structure of crop info
>> + * @compose: structure of compose info
>> * @completion: structure of signal completions
>> * @flush_completion: structure of signal completions for flush cmd
>> * @flush_responses_pending: counter to track number of pending
>> flush responses
>> @@ -57,7 +62,9 @@ struct iris_inst {
>> struct v4l2_format *fmt_src;
>> struct v4l2_format *fmt_dst;
>> struct v4l2_ctrl_handler ctrl_handler;
>> + enum domain_type domain;
>> struct iris_hfi_rect_desc crop;
>> + struct iris_hfi_rect_desc compose;
>> struct completion completion;
>> struct completion flush_completion;
>> u32 flush_responses_pending;
>> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/
>> media/platform/qcom/iris/iris_vdec.c
>> index
>> d670b51c5839d1fad54d34f373cf71d5f3973a96..3482ff3f18d2bcd592b7eb7d803bf98e29276ebb 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
>> @@ -13,8 +13,6 @@
>> #include "iris_vdec.h"
>> #include "iris_vpu_buffer.h"
>> -#define DEFAULT_WIDTH 320
>> -#define DEFAULT_HEIGHT 240
>> #define DEFAULT_CODEC_ALIGNMENT 16
>> int iris_vdec_inst_init(struct iris_inst *inst)
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/
>> media/platform/qcom/iris/iris_venc.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>> @@ -0,0 +1,65 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All
>> rights reserved.
>> + */
>> +
>> +#include "iris_buffer.h"
>> +#include "iris_instance.h"
>> +#include "iris_venc.h"
>> +#include "iris_vpu_buffer.h"
>> +
>> +int iris_venc_inst_init(struct iris_inst *inst)
>> +{
>> + struct v4l2_format *f;
>> +
>> + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
>> + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
>> + if (!inst->fmt_src || !inst->fmt_dst)
>> + return -ENOMEM;
>> +
>> + f = inst->fmt_dst;
>> + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>> + f->fmt.pix_mp.width = DEFAULT_WIDTH;
>> + f->fmt.pix_mp.height = DEFAULT_HEIGHT;
>> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
>> + inst->codec = f->fmt.pix_mp.pixelformat;
>> + f->fmt.pix_mp.num_planes = 1;
>> + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
>> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst,
>> BUF_OUTPUT);
>> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
>> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
>> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
>> + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst,
>> BUF_OUTPUT);
>> + inst->buffers[BUF_OUTPUT].size = f-
>> >fmt.pix_mp.plane_fmt[0].sizeimage;
>> +
>> + f = inst->fmt_src;
>> + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
>> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
>> + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
>> + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
>> + f->fmt.pix_mp.num_planes = 1;
>> + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
>> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst,
>> BUF_INPUT);
>> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
>> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
>> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
>> + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst,
>> BUF_INPUT);
>> + inst->buffers[BUF_INPUT].size = f-
>> >fmt.pix_mp.plane_fmt[0].sizeimage;
>> +
>> + inst->crop.left = 0;
>> + inst->crop.top = 0;
>> + inst->crop.width = f->fmt.pix_mp.width;
>> + inst->crop.height = f->fmt.pix_mp.height;
>> +
>> + return 0;
>> +}
>> +
>> +void iris_venc_inst_deinit(struct iris_inst *inst)
>> +{
>> + kfree(inst->fmt_dst);
>> + kfree(inst->fmt_src);
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/
>> media/platform/qcom/iris/iris_venc.h
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..8a4cbddd0114b6d0e4ea895362b01c302250c78b
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
>> @@ -0,0 +1,14 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All
>> rights reserved.
>> + */
>> +
>> +#ifndef _IRIS_VENC_H_
>> +#define _IRIS_VENC_H_
>> +
>> +struct iris_inst;
>> +
>> +int iris_venc_inst_init(struct iris_inst *inst);
>> +void iris_venc_inst_deinit(struct iris_inst *inst);
>> +
>> +#endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/
>> media/platform/qcom/iris/iris_vidc.c
>> index
>> 96313856a026efaff40da97eaaa63e847172cd57..11f27fc867dc610c18022b0942e65aa175a8567e 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
>> @@ -12,6 +12,7 @@
>> #include "iris_vidc.h"
>> #include "iris_instance.h"
>> #include "iris_vdec.h"
>> +#include "iris_venc.h"
>> #include "iris_vb2.h"
>> #include "iris_vpu_buffer.h"
>> #include "iris_platform_common.h"
>> @@ -23,7 +24,10 @@
>> static void iris_v4l2_fh_init(struct iris_inst *inst)
>> {
>> - v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
>> + if (inst->domain == ENCODER)
>> + v4l2_fh_init(&inst->fh, inst->core->vdev_enc);
>> + else if (inst->domain == DECODER)
>> + v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
>> inst->fh.ctrl_handler = &inst->ctrl_handler;
>> v4l2_fh_add(&inst->fh);
>> }
>> @@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue
>> *src_vq, struct vb2_queue *dst_
>> int iris_open(struct file *filp)
>> {
>> struct iris_core *core = video_drvdata(filp);
>> + struct video_device *vdev;
>> struct iris_inst *inst;
>> + u32 session_type;
>> int ret;
>> + vdev = video_devdata(filp);
>> + if (strcmp(vdev->name, "qcom-iris-decoder") == 0)
>> + session_type = DECODER;
>> + else if (strcmp(vdev->name, "qcom-iris-encoder") == 0)
>> + session_type = ENCODER;
>> + else
>> + return -EINVAL;
>> +
>> ret = pm_runtime_resume_and_get(core->dev);
>> if (ret < 0)
>> return ret;
>> @@ -147,6 +161,7 @@ int iris_open(struct file *filp)
>> return -ENOMEM;
>> inst->core = core;
>> + inst->domain = session_type;
>> inst->session_id = hash32_ptr(inst);
>> inst->state = IRIS_INST_DEINIT;
>> @@ -178,7 +193,10 @@ int iris_open(struct file *filp)
>> goto fail_m2m_release;
>> }
>> - ret = iris_vdec_inst_init(inst);
>> + if (inst->domain == DECODER)
>> + ret = iris_vdec_inst_init(inst);
>> + else if (inst->domain == ENCODER)
>> + ret = iris_venc_inst_init(inst);
>> if (ret)
>> goto fail_m2m_ctx_release;
>> @@ -265,7 +283,10 @@ int iris_close(struct file *filp)
>> v4l2_m2m_ctx_release(inst->m2m_ctx);
>> v4l2_m2m_release(inst->m2m_dev);
>> mutex_lock(&inst->lock);
>> - iris_vdec_inst_deinit(inst);
>> + if (inst->domain == DECODER)
>> + iris_vdec_inst_deinit(inst);
>> + else if (inst->domain == ENCODER)
>> + iris_venc_inst_deinit(inst);
>> iris_session_close(inst);
>> iris_inst_change_state(inst, IRIS_INST_DEINIT);
>> iris_v4l2_fh_deinit(inst);
>> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/
>> drivers/media/platform/qcom/iris/iris_vpu_buffer.c
>> index
>> f92fd39fe310b9661f892dcf1ff036ebbc102270..06d5afc3c641f0dfca3967e55273c4fa2614fdff 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
>> @@ -628,7 +628,10 @@ int iris_vpu_buf_count(struct iris_inst *inst,
>> enum iris_buffer_type buffer_type
>> case BUF_INPUT:
>> return MIN_BUFFERS;
>> case BUF_OUTPUT:
>> - return output_min_count(inst);
>> + if (inst->domain == ENCODER)
>> + return MIN_BUFFERS;
>> + else
>> + return output_min_count(inst);
>> case BUF_BIN:
>> case BUF_COMV:
>> case BUF_NON_COMV:
>>
>
> Patch failed at 0012 media: iris: Initialize and deinitialize encoder
> instance structure
> error: patch failed: drivers/media/platform/qcom/iris/iris_vidc.c:23
> error: drivers/media/platform/qcom/iris/iris_vidc.c: patch does not apply
> hint: Use 'git am --show-current-patch=diff' to see the failed patch
>
> git log drivers/media/platform/qcom/iris/iris_vidc.c
> commit 095ac6efdcaaa0169c5e0b4471f7835d39cd82d7
> Author: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Date: Wed Aug 13 15:07:52 2025 +0530
>
> media: iris: Report unreleased PERSIST buffers on session close
>
> Add error reporting for unreleased PERSIST internal buffers in
> iris_check_num_queued_internal_buffers(). This ensures all buffer
> types
> are checked and logged if not freed during session close, helping to
> detect memory leaks and improve driver robustness. No change to buffer
> lifecycle or allocation logic.
>
> Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release
> on close")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>
> commit 7c6719080cbcc1d3376385c66d456b25f85abcdc
> Author: Dikshita Agarwal <quic_dikshita@quicinc.com>
> Date: Wed Aug 13 15:07:51 2025 +0530
>
> media: iris: Fix buffer count reporting in internal buffer check
>
> Initialize the count variable to zero before counting unreleased
> internal buffers in iris_check_num_queued_internal_buffers().
> This prevents stale values from previous iterations and ensures
> accurate
> error reporting for each buffer type. Without this initialization, the
> count could accumulate across types, leading to incorrect log
> messages.
>
> Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release
> on close")
> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>
> commit 277966749f46bc6292c4052b4e66a554f193a78a
> Author: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Date: Sun Aug 10 04:30:09 2025 +0300
>
> media: Reset file->private_data to NULL in v4l2_fh_del()
>
>
> https://gitlab.freedesktop.org/linux-media/users/bodonoghue/-/commits/
> b4/bod-media-committers-next-platform-qcom-6.17-rc1
>
> ---
> bod
BTW the majority of the patches remaining in this series won't apply
after this failure.
Please rebase to resolve.
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer
2025-08-16 10:15 ` Bryan O'Donoghue
@ 2025-08-18 3:10 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 3:10 UTC (permalink / raw)
To: Bryan O'Donoghue, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/16/2025 3:45 PM, Bryan O'Donoghue wrote:
> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>> One internal buffer which is allocated only once per session was not
>> being freed during session close because it was not being tracked as
>> part of internal buffer list which resulted in a memory leak.
>>
>> Add the necessary logic to explicitly free the untracked internal buffer
>> during session close to ensure all allocated memory is released
>> properly.
>>
>> Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue
>> internal buffers")
>> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/iris_buffer.c | 10 ++++++++++
>> 1 file changed, 10 insertions(+)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c
>> b/drivers/media/platform/qcom/iris/iris_buffer.c
>> index
>> 6425e4919e3b0b849ba801ca9e01921c114144cd..9f664c241149362d44d3a8fa65e2266f9c2e80e0 100644
>> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
>> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
>> @@ -413,6 +413,16 @@ static int iris_destroy_internal_buffers(struct
>> iris_inst *inst, u32 plane, bool
>> }
>> }
>> + if (force) {
>> + buffers = &inst->buffers[BUF_PERSIST];
>> +
>> + list_for_each_entry_safe(buf, next, &buffers->list, list) {
>> + ret = iris_destroy_internal_buffer(inst, buf);
>> + if (ret)
>> + return ret;
>> + }
>> + }
>> +
>> return 0;
>> }
>>
>
> Why is the logic here not to simply release every index of the enum
> iris_buffer_type ?
All buffers indicated with enum iris_buffer_type are not related to both
encoder and decoder, some are specific for encoder and some are for
decoder. Hence while freeing we read the internal buffer list maintained in
platform data to get the exact buffer list applicable.
>
> If I'm reading the code right here, len indicates the list of linked lists
> to free, adding BUF_PERSIST appends to the list that may be freed if force
> is true but, then what about the remaining entries BUF_SCRATCH_1 ?
>
the buffer list here is the list of buffers of a specific kind eg: BUF_PERSIST.
BUF_PERSIST is not part of list maintained in platform data because it has
a different lifecycle than other internal buffers. that's why this specific
routine is needed to free BUF_PERSIST when destroying all buffers.
> Is it valid to leave this routine with force = true but BUF_SCRATCH_1 not
> specifically indexed, if so why ?
Other internal buffers are freed in another routine in the same API which
is not part of this particular code snippet.
Thanks,
Dikshita
>
> ---
> bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-14 14:25 ` Vikash Garodia
@ 2025-08-18 3:21 ` Dikshita Agarwal
2025-08-18 6:08 ` Vikash Garodia
0 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 3:21 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/14/2025 7:55 PM, Vikash Garodia wrote:
>
> On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
>> Introduce initialization and deinitialization for internal encoder
>> instance structure with necessary hooks.
>>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/Makefile | 1 +
>> drivers/media/platform/qcom/iris/iris_buffer.c | 59 ++++++++++++++++----
>> .../platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++-
>> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
>> drivers/media/platform/qcom/iris/iris_instance.h | 7 +++
>> drivers/media/platform/qcom/iris/iris_vdec.c | 2 -
>> drivers/media/platform/qcom/iris/iris_venc.c | 65 ++++++++++++++++++++++
>> drivers/media/platform/qcom/iris/iris_venc.h | 14 +++++
>> drivers/media/platform/qcom/iris/iris_vidc.c | 27 ++++++++-
>> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 +-
>> 10 files changed, 170 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
>> index e86d00ee6f15dda8bae2f25f726feb0d427b7684..ec32145e081b1fc3538dfa7d5113162a76a6068c 100644
>> --- a/drivers/media/platform/qcom/iris/Makefile
>> +++ b/drivers/media/platform/qcom/iris/Makefile
>> @@ -19,6 +19,7 @@ qcom-iris-objs += \
>> iris_vidc.o \
>> iris_vb2.o \
>> iris_vdec.o \
>> + iris_venc.o \
>> iris_vpu2.o \
>> iris_vpu3x.o \
>> iris_vpu_buffer.o \
>> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
>> index 38548ee4749ea7dd1addf2c9d0677cf5217e3546..6bf9b0b35d206d51b927c824d5a5b327596251c6 100644
>> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
>> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
>> @@ -63,7 +63,12 @@
>> static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
>> {
>> u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
>> - struct v4l2_format *f = inst->fmt_dst;
>> + struct v4l2_format *f;
>> +
>> + if (inst->domain == DECODER)
>> + f = inst->fmt_dst;
>> + else
>> + f = inst->fmt_src;
>>
>> y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
>> uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
>> @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst)
>> return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);
>> }
>>
>> -static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
>> +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
>> {
>> struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
>> u32 base_res_mbs = NUM_MBS_4K;
>> @@ -219,18 +224,50 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
>> return ALIGN(frame_size, PIXELS_4K);
>> }
>>
>> +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
>> +{
>> + u32 aligned_width, aligned_height, bitstream_size, yuv_size;
>> + struct v4l2_format *f;
>> +
>> + f = inst->fmt_dst;
>> +
>> + aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
>> + aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
>> + bitstream_size = aligned_width * aligned_height * 3;
>> + yuv_size = (aligned_width * aligned_height * 3) >> 1;
>> + if (aligned_width * aligned_height > (4096 * 2176))
>> + /* bitstream_size = 0.25 * yuv_size; */
>> + bitstream_size = (bitstream_size >> 3);
>> + else if (aligned_width * aligned_height > (1280 * 720))
>> + /* bitstream_size = 0.5 * yuv_size; */
>> + bitstream_size = (bitstream_size >> 2);
>> +
>> + return ALIGN(bitstream_size, 4096);
>> +}
>> +
>> int iris_get_buffer_size(struct iris_inst *inst,
>> enum iris_buffer_type buffer_type)
>> {
>> - switch (buffer_type) {
>> - case BUF_INPUT:
>> - return iris_bitstream_buffer_size(inst);
>> - case BUF_OUTPUT:
>> - return iris_yuv_buffer_size_nv12(inst);
>> - case BUF_DPB:
>> - return iris_yuv_buffer_size_qc08c(inst);
>> - default:
>> - return 0;
>> + if (inst->domain == DECODER) {
>> + switch (buffer_type) {
>> + case BUF_INPUT:
>> + return iris_dec_bitstream_buffer_size(inst);
>> + case BUF_OUTPUT:
>> + return iris_yuv_buffer_size_nv12(inst);
>> + case BUF_DPB:
>> + return iris_yuv_buffer_size_qc08c(inst);
>> + default:
>> + return 0;
>> + }
>> + } else {
>> + switch (buffer_type) {
>> + case BUF_INPUT:
>> + return iris_yuv_buffer_size_nv12(inst);
>> + case BUF_OUTPUT:
>> + return iris_enc_bitstream_buffer_size(inst);
>> + default:
>> + return 0;
>> + }
>> }
>> }
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> index 5097680ee14ebba3a126213c0584161627ca47d7..eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> @@ -109,7 +109,12 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst)
>> packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
>> packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
>> packet.shdr.session_id = inst->session_id;
>> - packet.session_domain = HFI_SESSION_TYPE_DEC;
>> +
>> + if (inst->domain == DECODER)
>> + packet.session_domain = HFI_SESSION_TYPE_DEC;
>> + else
>> + packet.session_domain = HFI_SESSION_TYPE_ENC;
>> +
>> packet.session_codec = codec;
>>
>> reinit_completion(&inst->completion);
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> index d4d119ca98b0cb313db351f3794bf278216bd539..5b7c641b727a16c3aa7196a6d49786133653279f 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> @@ -10,6 +10,7 @@
>>
>> #define HFI_VIDEO_ARCH_OX 0x1
>>
>> +#define HFI_SESSION_TYPE_ENC 1
>> #define HFI_SESSION_TYPE_DEC 2
>>
>> #define HFI_VIDEO_CODEC_H264 0x00000002
>> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
>> index 0e1f5799b72d993b25820608969e0011eabdb6bc..ff90f010f1d36690cbadeff0787b1fb7458d7f75 100644
>> --- a/drivers/media/platform/qcom/iris/iris_instance.h
>> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
>> @@ -12,6 +12,9 @@
>> #include "iris_core.h"
>> #include "iris_utils.h"
>>
>> +#define DEFAULT_WIDTH 320
>> +#define DEFAULT_HEIGHT 240
>> +
>> /**
>> * struct iris_inst - holds per video instance parameters
>> *
>> @@ -24,7 +27,9 @@
>> * @fmt_src: structure of v4l2_format for source
>> * @fmt_dst: structure of v4l2_format for destination
>> * @ctrl_handler: reference of v4l2 ctrl handler
>> + * @domain: domain type: encoder or decoder
>> * @crop: structure of crop info
>> + * @compose: structure of compose info
>> * @completion: structure of signal completions
>> * @flush_completion: structure of signal completions for flush cmd
>> * @flush_responses_pending: counter to track number of pending flush responses
>> @@ -57,7 +62,9 @@ struct iris_inst {
>> struct v4l2_format *fmt_src;
>> struct v4l2_format *fmt_dst;
>> struct v4l2_ctrl_handler ctrl_handler;
>> + enum domain_type domain;
>> struct iris_hfi_rect_desc crop;
>> + struct iris_hfi_rect_desc compose;
>> struct completion completion;
>> struct completion flush_completion;
>> u32 flush_responses_pending;
>> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
>> index d670b51c5839d1fad54d34f373cf71d5f3973a96..3482ff3f18d2bcd592b7eb7d803bf98e29276ebb 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
>> @@ -13,8 +13,6 @@
>> #include "iris_vdec.h"
>> #include "iris_vpu_buffer.h"
>>
>> -#define DEFAULT_WIDTH 320
>> -#define DEFAULT_HEIGHT 240
>> #define DEFAULT_CODEC_ALIGNMENT 16
>>
>> int iris_vdec_inst_init(struct iris_inst *inst)
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>> @@ -0,0 +1,65 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include "iris_buffer.h"
>> +#include "iris_instance.h"
>> +#include "iris_venc.h"
>> +#include "iris_vpu_buffer.h"
>> +
>> +int iris_venc_inst_init(struct iris_inst *inst)
>> +{
>> + struct v4l2_format *f;
>> +
>> + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
>> + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
>> + if (!inst->fmt_src || !inst->fmt_dst)
>> + return -ENOMEM;
>
> What if inst->fmt_src succeeds while inst->fmt_dst fails, does it frees up
> inst->fmt_src ?
>
would you prefer below?
if (!inst->fmt_src || !inst->fmt_dst) {
kfree(inst->fmt_src);
kfree(inst->fmt_dst);
return -ENOMEM;
}
Thanks,
Dikshita
>> +
>> + f = inst->fmt_dst;
>> + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>> + f->fmt.pix_mp.width = DEFAULT_WIDTH;
>> + f->fmt.pix_mp.height = DEFAULT_HEIGHT;
>> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
>> + inst->codec = f->fmt.pix_mp.pixelformat;
>> + f->fmt.pix_mp.num_planes = 1;
>> + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
>> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
>> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
>> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
>> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
>> + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
>> + inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
>> +
>> + f = inst->fmt_src;
>> + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
>> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
>> + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
>> + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
>> + f->fmt.pix_mp.num_planes = 1;
>> + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
>> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
>> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
>> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
>> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
>> + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
>> + inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
>> +
>> + inst->crop.left = 0;
>> + inst->crop.top = 0;
>> + inst->crop.width = f->fmt.pix_mp.width;
>> + inst->crop.height = f->fmt.pix_mp.height;
>> +
>> + return 0;
>> +}
>> +
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder
2025-08-14 14:43 ` Vikash Garodia
@ 2025-08-18 3:21 ` Dikshita Agarwal
2025-08-18 6:10 ` Vikash Garodia
0 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 3:21 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/14/2025 8:13 PM, Vikash Garodia wrote:
>
> On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
>> Add support for frame size and frame interval enumeration by
>> implementing ENUM_FRAMESIZES/FRAMEINTERVALS V4L2 ioctls for encoder
>> video device with necessary hooks.
>>
>> This allows userspace application to query encoder capabilities and
>> adapt encoding configurations accordingly.
>>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> .../platform/qcom/iris/iris_platform_common.h | 5 +-
>> .../media/platform/qcom/iris/iris_platform_gen2.c | 3 ++
>> .../platform/qcom/iris/iris_platform_sm8250.c | 1 +
>> drivers/media/platform/qcom/iris/iris_vdec.c | 13 +++++
>> drivers/media/platform/qcom/iris/iris_vdec.h | 1 +
>> drivers/media/platform/qcom/iris/iris_venc.c | 13 +++++
>> drivers/media/platform/qcom/iris/iris_venc.h | 1 +
>> drivers/media/platform/qcom/iris/iris_vidc.c | 58 ++++++++++++++++++++--
>> 8 files changed, 91 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
>> index adafdce8a856f9c661aabc5ca28f0faceaa93551..792f46e2e34fd564a1ed61523f72826fc8f74582 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
>> @@ -21,7 +21,8 @@ struct iris_inst;
>> #define DEFAULT_MAX_HOST_BUF_COUNT 64
>> #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256
>> #define DEFAULT_FPS 30
>> -#define NUM_MBS_8K ((8192 * 4352) / 256)
>> +#define MAXIMUM_FPS 480
>> +#define NUM_MBS_8K ((8192 * 4352) / 256)
>>
>> enum stage_type {
>> STAGE_1 = 1,
>> @@ -179,6 +180,8 @@ struct iris_platform_data {
>> u32 max_session_count;
>> /* max number of macroblocks per frame supported */
>> u32 max_core_mbpf;
>> + /* max number of macroblocks per second supported */
>> + u32 max_core_mbps;
>> const u32 *input_config_params_default;
>> unsigned int input_config_params_default_size;
>> const u32 *input_config_params_hevc;
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> index d3026b2bcb708c7ec31f134f628df7e57b54af4f..1e2fadfe17672029b46e07ce00a8e31e0711fd58 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> @@ -354,6 +354,7 @@ struct iris_platform_data sm8550_data = {
>> .num_vpp_pipe = 4,
>> .max_session_count = 16,
>> .max_core_mbpf = NUM_MBS_8K * 2,
>> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
>> .input_config_params_default =
>> sm8550_vdec_input_config_params_default,
>> .input_config_params_default_size =
>> @@ -429,6 +430,7 @@ struct iris_platform_data sm8650_data = {
>> .num_vpp_pipe = 4,
>> .max_session_count = 16,
>> .max_core_mbpf = NUM_MBS_8K * 2,
>> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
>> .input_config_params_default =
>> sm8550_vdec_input_config_params_default,
>> .input_config_params_default_size =
>> @@ -500,6 +502,7 @@ struct iris_platform_data qcs8300_data = {
>> .num_vpp_pipe = 2,
>> .max_session_count = 16,
>> .max_core_mbpf = ((4096 * 2176) / 256) * 4,
>> + .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
>
> TODO ? 4k@60 is supported mbps for qcs8300
It was a miss, will remove the TODO.
Thanks,
Dikshita
>
>> .input_config_params_default =
>> sm8550_vdec_input_config_params_default,
>> .input_config_params_default_size =
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> index 8d0816a67ae0b6886204ce93fa5ccafaac10392a..2a3cbe1f2d4b27d3cce9e9cdad1525801d71a041 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> @@ -128,6 +128,7 @@ struct iris_platform_data sm8250_data = {
>> .num_vpp_pipe = 4,
>> .max_session_count = 16,
>> .max_core_mbpf = NUM_MBS_8K,
>> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
>> .input_config_params_default =
>> sm8250_vdec_input_config_param_default,
>> .input_config_params_default_size =
>> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
>> index 3482ff3f18d2bcd592b7eb7d803bf98e29276ebb..6afbd2f89260a233d75d7a0cdf3647236216c9ec 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
>> @@ -263,6 +263,19 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
>> return 0;
>> }
>>
>> +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat)
>> +{
>> + const struct iris_fmt *fmt = NULL;
>> +
>> + if (pixelformat != V4L2_PIX_FMT_NV12) {
>> + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
>> + if (!fmt)
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub)
>> {
>> int ret = 0;
>> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
>> index b24932dc511a65017b1cadbcb984544475bd0723..097e02bfa72b5ac4e46e66c61842df1d9dd4565b 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vdec.h
>> +++ b/drivers/media/platform/qcom/iris/iris_vdec.h
>> @@ -13,6 +13,7 @@ void iris_vdec_inst_deinit(struct iris_inst *inst);
>> int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
>> int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat);
>> int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
>> void iris_vdec_src_change(struct iris_inst *inst);
>> int iris_vdec_streamon_input(struct iris_inst *inst);
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>> index 6bb59ce4fc565d3dcc6185233ef25d2e4d85cb3e..301206253090962abbb4e4eac8ee88e7b359c98d 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>> @@ -270,3 +270,16 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
>> return -EINVAL;
>> }
>> }
>> +
>> +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat)
>> +{
>> + const struct iris_fmt *fmt = NULL;
>> +
>> + if (pixelformat != V4L2_PIX_FMT_NV12) {
>> + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
>> + if (!fmt)
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
>> index eb26a3ecbd98b3f02dfdea0dfc41bcd3a90904b6..04fd41275547c40c359c6ea04dfe4ee31d2d0df6 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.h
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
>> @@ -13,5 +13,6 @@ void iris_venc_inst_deinit(struct iris_inst *inst);
>> int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
>> int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
>>
>> #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
>> index 06b2737c5892ebbcf43b4cff66062d85cf805c20..cb1280c0c6c82187243f0bda4d98e42370ee787c 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
>> @@ -373,13 +373,18 @@ static int iris_enum_framesizes(struct file *filp, void *fh,
>> {
>> struct iris_inst *inst = iris_get_inst(filp, NULL);
>> struct platform_inst_caps *caps;
>> + int ret = 0;
>>
>> if (fsize->index)
>> return -EINVAL;
>>
>> - if (fsize->pixel_format != V4L2_PIX_FMT_H264 &&
>> - fsize->pixel_format != V4L2_PIX_FMT_NV12)
>> - return -EINVAL;
>> + if (inst->domain == DECODER)
>> + ret = iris_vdec_validate_format(inst, fsize->pixel_format);
>> + else
>> + ret = iris_venc_validate_format(inst, fsize->pixel_format);
>> +
>> + if (ret)
>> + return ret;
>>
>> caps = inst->core->iris_platform_data->inst_caps;
>>
>> @@ -391,6 +396,51 @@ static int iris_enum_framesizes(struct file *filp, void *fh,
>> fsize->stepwise.max_height = caps->max_frame_height;
>> fsize->stepwise.step_height = STEP_HEIGHT;
>>
>> + return ret;
>> +}
>> +
>> +static int iris_enum_frameintervals(struct file *filp, void *fh,
>> + struct v4l2_frmivalenum *fival)
>> +
>> +{
>> + struct iris_inst *inst = iris_get_inst(filp, NULL);
>> + struct platform_inst_caps *caps;
>> + struct iris_core *core = inst->core;
>> + u32 fps, mbpf;
>> + int ret = 0;
>> +
>> + if (inst->domain == DECODER)
>> + return -ENOTTY;
>> +
>> + if (fival->index)
>> + return -EINVAL;
>> +
>> + ret = iris_venc_validate_format(inst, fival->pixel_format);
>> + if (ret)
>> + return ret;
>> +
>> + if (!fival->width || !fival->height)
>> + return -EINVAL;
>> +
>> + caps = inst->core->iris_platform_data->inst_caps;
>> + if (fival->width > caps->max_frame_width ||
>> + fival->width < caps->min_frame_width ||
>> + fival->height > caps->max_frame_height ||
>> + fival->height < caps->min_frame_height)
>> + return -EINVAL;
>> +
>> + mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width);
>> + fps = DIV_ROUND_UP(core->iris_platform_data->max_core_mbps, mbpf);
>> +
>> + fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
>> + fival->stepwise.min.numerator = 1;
>> + fival->stepwise.min.denominator =
>> + min_t(u32, fps, MAXIMUM_FPS);
>> + fival->stepwise.max.numerator = 1;
>> + fival->stepwise.max.denominator = 1;
>> + fival->stepwise.step.numerator = 1;
>> + fival->stepwise.step.denominator = MAXIMUM_FPS;
>> +
>> return 0;
>> }
>>
>> @@ -525,6 +575,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
>> .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane,
>> .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane,
>> .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane,
>> + .vidioc_enum_framesizes = iris_enum_framesizes,
>> + .vidioc_enum_frameintervals = iris_enum_frameintervals,
>> };
>>
>> void iris_init_ops(struct iris_core *core)
>>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device
2025-08-14 14:54 ` Vikash Garodia
@ 2025-08-18 3:25 ` Dikshita Agarwal
2025-08-18 6:11 ` Vikash Garodia
0 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 3:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/14/2025 8:24 PM, Vikash Garodia wrote:
>
>
> On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
>> Add support for G/S_SELECTION V4L2 ioctls for the encoder video
>> device with necessary hooks. This allows userspace to query and
>> configure rectangular selection areas such as crop.
>>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/iris_venc.c | 28 ++++++++++++
>> drivers/media/platform/qcom/iris/iris_venc.h | 1 +
>> drivers/media/platform/qcom/iris/iris_vidc.c | 65 ++++++++++++++++++++++------
>> 3 files changed, 80 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>> index 3dbcce23cbe94cf0edc4421694a3ba11faa5eb96..930f5afe9489d01be193f1dbe429d33f5401b468 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>> @@ -297,3 +297,31 @@ int iris_venc_subscribe_event(struct iris_inst *inst,
>> return -EINVAL;
>> }
>> }
>> +
>> +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
>> +{
>> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
>> + return -EINVAL;
>> +
>> + switch (s->target) {
>> + case V4L2_SEL_TGT_CROP:
>> + s->r.left = 0;
>> + s->r.top = 0;
>> +
>> + if (s->r.width > inst->fmt_src->fmt.pix_mp.width ||
>> + s->r.height > inst->fmt_src->fmt.pix_mp.height)
>> + return -EINVAL;
>> +
>> + inst->crop.left = s->r.left;
>> + inst->crop.top = s->r.top;
>> + inst->crop.width = s->r.width;
>> + inst->crop.height = s->r.height;
>> + inst->fmt_dst->fmt.pix_mp.width = inst->crop.width;
>> + inst->fmt_dst->fmt.pix_mp.height = inst->crop.height;
>> + return iris_venc_s_fmt_output(inst, inst->fmt_dst);
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>
> Why do you need a return here ?
We actually don't, it should be safe to remove this, will fix.
Thanks,
Dikshita
>
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
>> index 2d9614ae18e8a2318df6673fbeae5ee33c99b596..72c6e25d87113baa6d2219ae478b7d7df1aed7bf 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.h
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
>> @@ -15,5 +15,6 @@ int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
>> int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
>> +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
>>
>> #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
>> index d8c94074153e9b1ceac4f911210ddbf89bbe3533..2074682a35fd1c4c9f5d29fdaee3392d98bf8923 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
>> @@ -462,29 +462,64 @@ static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *
>> {
>> struct iris_inst *inst = iris_get_inst(filp, NULL);
>>
>> - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
>> + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
>> + inst->domain == DECODER)
>> return -EINVAL;
>>
>> - switch (s->target) {
>> - case V4L2_SEL_TGT_CROP_BOUNDS:
>> - case V4L2_SEL_TGT_CROP_DEFAULT:
>> - case V4L2_SEL_TGT_CROP:
>> - case V4L2_SEL_TGT_COMPOSE_BOUNDS:
>> - case V4L2_SEL_TGT_COMPOSE_PADDED:
>> - case V4L2_SEL_TGT_COMPOSE_DEFAULT:
>> - case V4L2_SEL_TGT_COMPOSE:
>> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
>> + inst->domain == ENCODER)
>> + return -EINVAL;
>> +
>> + if (inst->domain == DECODER) {
>> + switch (s->target) {
>> + case V4L2_SEL_TGT_CROP_BOUNDS:
>> + case V4L2_SEL_TGT_CROP_DEFAULT:
>> + case V4L2_SEL_TGT_CROP:
>> + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
>> + case V4L2_SEL_TGT_COMPOSE_PADDED:
>> + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
>> + case V4L2_SEL_TGT_COMPOSE:
>> + s->r.left = inst->crop.left;
>> + s->r.top = inst->crop.top;
>> + s->r.width = inst->crop.width;
>> + s->r.height = inst->crop.height;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> + } else if (inst->domain == ENCODER) {
>> + switch (s->target) {
>> + case V4L2_SEL_TGT_CROP_BOUNDS:
>> + case V4L2_SEL_TGT_CROP_DEFAULT:
>> + s->r.width = inst->fmt_src->fmt.pix_mp.width;
>> + s->r.height = inst->fmt_src->fmt.pix_mp.height;
>> + break;
>> + case V4L2_SEL_TGT_CROP:
>> + s->r.width = inst->crop.width;
>> + s->r.height = inst->crop.height;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> s->r.left = inst->crop.left;
>> s->r.top = inst->crop.top;
>> - s->r.width = inst->crop.width;
>> - s->r.height = inst->crop.height;
>> - break;
>> - default:
>> - return -EINVAL;
>> }
>>
>> return 0;
>> }
>>
>> +static int iris_s_selection(struct file *filp, void *fh, struct v4l2_selection *s)
>> +{
>> + struct iris_inst *inst = iris_get_inst(filp, NULL);
>
> s->r.left and s->r.top are signed and can be negative. Need to range bound
> within 0 to src dimension ?
>
>> +
>> + if (inst->domain == DECODER)
>> + return -EINVAL;
>> + else if (inst->domain == ENCODER)
>> + return iris_venc_s_selection(inst, s);
>> +
>> + return -EINVAL;
>> +}
>> +
>> static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
>> {
>> struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
>> @@ -591,6 +626,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
>> .vidioc_querycap = iris_querycap,
>> .vidioc_subscribe_event = iris_subscribe_event,
>> .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>> + .vidioc_g_selection = iris_g_selection,
>> + .vidioc_s_selection = iris_s_selection,
>> };
>>
>> void iris_init_ops(struct iris_core *core)
>>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-16 11:23 ` Bryan O'Donoghue
@ 2025-08-18 3:27 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 3:27 UTC (permalink / raw)
To: Bryan O'Donoghue, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/16/2025 4:53 PM, Bryan O'Donoghue wrote:
> On 16/08/2025 10:03, Bryan O'Donoghue wrote:
>> On 13/08/2025 10:38, Dikshita Agarwal wrote:
>>> Introduce initialization and deinitialization for internal encoder
>>> instance structure with necessary hooks.
>>>
>>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>> ---
>>> drivers/media/platform/qcom/iris/Makefile | 1 +
>>> drivers/media/platform/qcom/iris/iris_buffer.c | 59 ++++++++++++
>>> ++++----
>>> .../platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++-
>>> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
>>> drivers/media/platform/qcom/iris/iris_instance.h | 7 +++
>>> drivers/media/platform/qcom/iris/iris_vdec.c | 2 -
>>> drivers/media/platform/qcom/iris/iris_venc.c | 65 ++++++++++++
>>> ++++++++++
>>> drivers/media/platform/qcom/iris/iris_venc.h | 14 +++++
>>> drivers/media/platform/qcom/iris/iris_vidc.c | 27 ++++++++-
>>> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 +-
>>> 10 files changed, 170 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/
>>> media/platform/qcom/iris/Makefile
>>> index
>>> e86d00ee6f15dda8bae2f25f726feb0d427b7684..ec32145e081b1fc3538dfa7d5113162a76a6068c 100644
>>> --- a/drivers/media/platform/qcom/iris/Makefile
>>> +++ b/drivers/media/platform/qcom/iris/Makefile
>>> @@ -19,6 +19,7 @@ qcom-iris-objs += \
>>> iris_vidc.o \
>>> iris_vb2.o \
>>> iris_vdec.o \
>>> + iris_venc.o \
>>> iris_vpu2.o \
>>> iris_vpu3x.o \
>>> iris_vpu_buffer.o \
>>> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/
>>> media/platform/qcom/iris/iris_buffer.c
>>> index
>>> 38548ee4749ea7dd1addf2c9d0677cf5217e3546..6bf9b0b35d206d51b927c824d5a5b327596251c6 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
>>> @@ -63,7 +63,12 @@
>>> static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
>>> {
>>> u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines,
>>> uv_scanlines;
>>> - struct v4l2_format *f = inst->fmt_dst;
>>> + struct v4l2_format *f;
>>> +
>>> + if (inst->domain == DECODER)
>>> + f = inst->fmt_dst;
>>> + else
>>> + f = inst->fmt_src;
>>> y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
>>> uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
>>> @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct
>>> iris_inst *inst)
>>> return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane,
>>> PIXELS_4K);
>>> }
>>> -static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
>>> +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
>>> {
>>> struct platform_inst_caps *caps = inst->core-
>>> >iris_platform_data->inst_caps;
>>> u32 base_res_mbs = NUM_MBS_4K;
>>> @@ -219,18 +224,50 @@ static u32 iris_bitstream_buffer_size(struct
>>> iris_inst *inst)
>>> return ALIGN(frame_size, PIXELS_4K);
>>> }
>>> +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
>>> +{
>>> + u32 aligned_width, aligned_height, bitstream_size, yuv_size;
>>> + struct v4l2_format *f;
>>> +
>>> + f = inst->fmt_dst;
>>> +
>>> + aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
>>> + aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
>>> + bitstream_size = aligned_width * aligned_height * 3;
>>> + yuv_size = (aligned_width * aligned_height * 3) >> 1;
>>> + if (aligned_width * aligned_height > (4096 * 2176))
>>> + /* bitstream_size = 0.25 * yuv_size; */
>>> + bitstream_size = (bitstream_size >> 3);
>>> + else if (aligned_width * aligned_height > (1280 * 720))
>>> + /* bitstream_size = 0.5 * yuv_size; */
>>> + bitstream_size = (bitstream_size >> 2);
>>> +
>>> + return ALIGN(bitstream_size, 4096);
>>> +}
>>> +
>>> int iris_get_buffer_size(struct iris_inst *inst,
>>> enum iris_buffer_type buffer_type)
>>> {
>>> - switch (buffer_type) {
>>> - case BUF_INPUT:
>>> - return iris_bitstream_buffer_size(inst);
>>> - case BUF_OUTPUT:
>>> - return iris_yuv_buffer_size_nv12(inst);
>>> - case BUF_DPB:
>>> - return iris_yuv_buffer_size_qc08c(inst);
>>> - default:
>>> - return 0;
>>> + if (inst->domain == DECODER) {
>>> + switch (buffer_type) {
>>> + case BUF_INPUT:
>>> + return iris_dec_bitstream_buffer_size(inst);
>>> + case BUF_OUTPUT:
>>> + return iris_yuv_buffer_size_nv12(inst);
>>> + case BUF_DPB:
>>> + return iris_yuv_buffer_size_qc08c(inst);
>>> + default:
>>> + return 0;
>>> + }
>>> + } else {
>>> + switch (buffer_type) {
>>> + case BUF_INPUT:
>>> + return iris_yuv_buffer_size_nv12(inst);
>>> + case BUF_OUTPUT:
>>> + return iris_enc_bitstream_buffer_size(inst);
>>> + default:
>>> + return 0;
>>> + }
>>> }
>>> }
>>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>>> index
>>> 5097680ee14ebba3a126213c0584161627ca47d7..eae3dc5c596d1eb6090126ac391b8e0e2c9f09eb 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>>> @@ -109,7 +109,12 @@ static int iris_hfi_gen1_session_open(struct
>>> iris_inst *inst)
>>> packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
>>> packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
>>> packet.shdr.session_id = inst->session_id;
>>> - packet.session_domain = HFI_SESSION_TYPE_DEC;
>>> +
>>> + if (inst->domain == DECODER)
>>> + packet.session_domain = HFI_SESSION_TYPE_DEC;
>>> + else
>>> + packet.session_domain = HFI_SESSION_TYPE_ENC;
>>> +
>>> packet.session_codec = codec;
>>> reinit_completion(&inst->completion);
>>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>>> index
>>> d4d119ca98b0cb313db351f3794bf278216bd539..5b7c641b727a16c3aa7196a6d49786133653279f 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>>> @@ -10,6 +10,7 @@
>>> #define HFI_VIDEO_ARCH_OX 0x1
>>> +#define HFI_SESSION_TYPE_ENC 1
>>> #define HFI_SESSION_TYPE_DEC 2
>>> #define HFI_VIDEO_CODEC_H264 0x00000002
>>> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/
>>> drivers/media/platform/qcom/iris/iris_instance.h
>>> index
>>> 0e1f5799b72d993b25820608969e0011eabdb6bc..ff90f010f1d36690cbadeff0787b1fb7458d7f75 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_instance.h
>>> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
>>> @@ -12,6 +12,9 @@
>>> #include "iris_core.h"
>>> #include "iris_utils.h"
>>> +#define DEFAULT_WIDTH 320
>>> +#define DEFAULT_HEIGHT 240
>>> +
>>> /**
>>> * struct iris_inst - holds per video instance parameters
>>> *
>>> @@ -24,7 +27,9 @@
>>> * @fmt_src: structure of v4l2_format for source
>>> * @fmt_dst: structure of v4l2_format for destination
>>> * @ctrl_handler: reference of v4l2 ctrl handler
>>> + * @domain: domain type: encoder or decoder
>>> * @crop: structure of crop info
>>> + * @compose: structure of compose info
>>> * @completion: structure of signal completions
>>> * @flush_completion: structure of signal completions for flush cmd
>>> * @flush_responses_pending: counter to track number of pending flush
>>> responses
>>> @@ -57,7 +62,9 @@ struct iris_inst {
>>> struct v4l2_format *fmt_src;
>>> struct v4l2_format *fmt_dst;
>>> struct v4l2_ctrl_handler ctrl_handler;
>>> + enum domain_type domain;
>>> struct iris_hfi_rect_desc crop;
>>> + struct iris_hfi_rect_desc compose;
>>> struct completion completion;
>>> struct completion flush_completion;
>>> u32 flush_responses_pending;
>>> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/
>>> media/platform/qcom/iris/iris_vdec.c
>>> index
>>> d670b51c5839d1fad54d34f373cf71d5f3973a96..3482ff3f18d2bcd592b7eb7d803bf98e29276ebb 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
>>> @@ -13,8 +13,6 @@
>>> #include "iris_vdec.h"
>>> #include "iris_vpu_buffer.h"
>>> -#define DEFAULT_WIDTH 320
>>> -#define DEFAULT_HEIGHT 240
>>> #define DEFAULT_CODEC_ALIGNMENT 16
>>> int iris_vdec_inst_init(struct iris_inst *inst)
>>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/
>>> media/platform/qcom/iris/iris_venc.c
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
>>> --- /dev/null
>>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>>> @@ -0,0 +1,65 @@
>>> +// SPDX-License-Identifier: GPL-2.0-only
>>> +/*
>>> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights
>>> reserved.
>>> + */
>>> +
>>> +#include "iris_buffer.h"
>>> +#include "iris_instance.h"
>>> +#include "iris_venc.h"
>>> +#include "iris_vpu_buffer.h"
>>> +
>>> +int iris_venc_inst_init(struct iris_inst *inst)
>>> +{
>>> + struct v4l2_format *f;
>>> +
>>> + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
>>> + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
>>> + if (!inst->fmt_src || !inst->fmt_dst)
>>> + return -ENOMEM;
>>> +
>>> + f = inst->fmt_dst;
>>> + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>>> + f->fmt.pix_mp.width = DEFAULT_WIDTH;
>>> + f->fmt.pix_mp.height = DEFAULT_HEIGHT;
>>> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
>>> + inst->codec = f->fmt.pix_mp.pixelformat;
>>> + f->fmt.pix_mp.num_planes = 1;
>>> + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
>>> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst,
>>> BUF_OUTPUT);
>>> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
>>> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
>>> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>>> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>>> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
>>> + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst,
>>> BUF_OUTPUT);
>>> + inst->buffers[BUF_OUTPUT].size = f-
>>> >fmt.pix_mp.plane_fmt[0].sizeimage;
>>> +
>>> + f = inst->fmt_src;
>>> + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
>>> + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
>>> + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128);
>>> + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
>>> + f->fmt.pix_mp.num_planes = 1;
>>> + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
>>> + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst,
>>> BUF_INPUT);
>>> + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
>>> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
>>> + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>>> + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>>> + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
>>> + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst,
>>> BUF_INPUT);
>>> + inst->buffers[BUF_INPUT].size = f- >fmt.pix_mp.plane_fmt[0].sizeimage;
>>> +
>>> + inst->crop.left = 0;
>>> + inst->crop.top = 0;
>>> + inst->crop.width = f->fmt.pix_mp.width;
>>> + inst->crop.height = f->fmt.pix_mp.height;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +void iris_venc_inst_deinit(struct iris_inst *inst)
>>> +{
>>> + kfree(inst->fmt_dst);
>>> + kfree(inst->fmt_src);
>>> +}
>>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/
>>> media/platform/qcom/iris/iris_venc.h
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..8a4cbddd0114b6d0e4ea895362b01c302250c78b
>>> --- /dev/null
>>> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
>>> @@ -0,0 +1,14 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +/*
>>> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights
>>> reserved.
>>> + */
>>> +
>>> +#ifndef _IRIS_VENC_H_
>>> +#define _IRIS_VENC_H_
>>> +
>>> +struct iris_inst;
>>> +
>>> +int iris_venc_inst_init(struct iris_inst *inst);
>>> +void iris_venc_inst_deinit(struct iris_inst *inst);
>>> +
>>> +#endif
>>> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/
>>> media/platform/qcom/iris/iris_vidc.c
>>> index
>>> 96313856a026efaff40da97eaaa63e847172cd57..11f27fc867dc610c18022b0942e65aa175a8567e 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
>>> @@ -12,6 +12,7 @@
>>> #include "iris_vidc.h"
>>> #include "iris_instance.h"
>>> #include "iris_vdec.h"
>>> +#include "iris_venc.h"
>>> #include "iris_vb2.h"
>>> #include "iris_vpu_buffer.h"
>>> #include "iris_platform_common.h"
>>> @@ -23,7 +24,10 @@
>>> static void iris_v4l2_fh_init(struct iris_inst *inst)
>>> {
>>> - v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
>>> + if (inst->domain == ENCODER)
>>> + v4l2_fh_init(&inst->fh, inst->core->vdev_enc);
>>> + else if (inst->domain == DECODER)
>>> + v4l2_fh_init(&inst->fh, inst->core->vdev_dec);
>>> inst->fh.ctrl_handler = &inst->ctrl_handler;
>>> v4l2_fh_add(&inst->fh);
>>> }
>>> @@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue
>>> *src_vq, struct vb2_queue *dst_
>>> int iris_open(struct file *filp)
>>> {
>>> struct iris_core *core = video_drvdata(filp);
>>> + struct video_device *vdev;
>>> struct iris_inst *inst;
>>> + u32 session_type;
>>> int ret;
>>> + vdev = video_devdata(filp);
>>> + if (strcmp(vdev->name, "qcom-iris-decoder") == 0)
>>> + session_type = DECODER;
>>> + else if (strcmp(vdev->name, "qcom-iris-encoder") == 0)
>>> + session_type = ENCODER;
>>> + else
>>> + return -EINVAL;
>>> +
>>> ret = pm_runtime_resume_and_get(core->dev);
>>> if (ret < 0)
>>> return ret;
>>> @@ -147,6 +161,7 @@ int iris_open(struct file *filp)
>>> return -ENOMEM;
>>> inst->core = core;
>>> + inst->domain = session_type;
>>> inst->session_id = hash32_ptr(inst);
>>> inst->state = IRIS_INST_DEINIT;
>>> @@ -178,7 +193,10 @@ int iris_open(struct file *filp)
>>> goto fail_m2m_release;
>>> }
>>> - ret = iris_vdec_inst_init(inst);
>>> + if (inst->domain == DECODER)
>>> + ret = iris_vdec_inst_init(inst);
>>> + else if (inst->domain == ENCODER)
>>> + ret = iris_venc_inst_init(inst);
>>> if (ret)
>>> goto fail_m2m_ctx_release;
>>> @@ -265,7 +283,10 @@ int iris_close(struct file *filp)
>>> v4l2_m2m_ctx_release(inst->m2m_ctx);
>>> v4l2_m2m_release(inst->m2m_dev);
>>> mutex_lock(&inst->lock);
>>> - iris_vdec_inst_deinit(inst);
>>> + if (inst->domain == DECODER)
>>> + iris_vdec_inst_deinit(inst);
>>> + else if (inst->domain == ENCODER)
>>> + iris_venc_inst_deinit(inst);
>>> iris_session_close(inst);
>>> iris_inst_change_state(inst, IRIS_INST_DEINIT);
>>> iris_v4l2_fh_deinit(inst);
>>> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/
>>> drivers/media/platform/qcom/iris/iris_vpu_buffer.c
>>> index
>>> f92fd39fe310b9661f892dcf1ff036ebbc102270..06d5afc3c641f0dfca3967e55273c4fa2614fdff 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
>>> @@ -628,7 +628,10 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum
>>> iris_buffer_type buffer_type
>>> case BUF_INPUT:
>>> return MIN_BUFFERS;
>>> case BUF_OUTPUT:
>>> - return output_min_count(inst);
>>> + if (inst->domain == ENCODER)
>>> + return MIN_BUFFERS;
>>> + else
>>> + return output_min_count(inst);
>>> case BUF_BIN:
>>> case BUF_COMV:
>>> case BUF_NON_COMV:
>>>
>>
>> Patch failed at 0012 media: iris: Initialize and deinitialize encoder
>> instance structure
>> error: patch failed: drivers/media/platform/qcom/iris/iris_vidc.c:23
>> error: drivers/media/platform/qcom/iris/iris_vidc.c: patch does not apply
>> hint: Use 'git am --show-current-patch=diff' to see the failed patch
>>
>> git log drivers/media/platform/qcom/iris/iris_vidc.c
>> commit 095ac6efdcaaa0169c5e0b4471f7835d39cd82d7
>> Author: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Date: Wed Aug 13 15:07:52 2025 +0530
>>
>> media: iris: Report unreleased PERSIST buffers on session close
>>
>> Add error reporting for unreleased PERSIST internal buffers in
>> iris_check_num_queued_internal_buffers(). This ensures all buffer types
>> are checked and logged if not freed during session close, helping to
>> detect memory leaks and improve driver robustness. No change to buffer
>> lifecycle or allocation logic.
>>
>> Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release on
>> close")
>> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> commit 7c6719080cbcc1d3376385c66d456b25f85abcdc
>> Author: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> Date: Wed Aug 13 15:07:51 2025 +0530
>>
>> media: iris: Fix buffer count reporting in internal buffer check
>>
>> Initialize the count variable to zero before counting unreleased
>> internal buffers in iris_check_num_queued_internal_buffers().
>> This prevents stale values from previous iterations and ensures
>> accurate
>> error reporting for each buffer type. Without this initialization, the
>> count could accumulate across types, leading to incorrect log messages.
>>
>> Fixes: d2abb1ff5a3c ("media: iris: Verify internal buffer release on
>> close")
>> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> commit 277966749f46bc6292c4052b4e66a554f193a78a
>> Author: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>> Date: Sun Aug 10 04:30:09 2025 +0300
>>
>> media: Reset file->private_data to NULL in v4l2_fh_del()
>>
>>
>> https://gitlab.freedesktop.org/linux-media/users/bodonoghue/-/commits/
>> b4/bod-media-committers-next-platform-qcom-6.17-rc1
>>
>> ---
>> bod
>
> BTW the majority of the patches remaining in this series won't apply after
> this failure.
>
> Please rebase to resolve.
Sure, will rebase the next revision on latest linux-media.
>
> ---
> bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 11/24] media: iris: Add support for video encoder device
2025-08-16 11:21 ` Bryan O'Donoghue
@ 2025-08-18 3:28 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 3:28 UTC (permalink / raw)
To: Bryan O'Donoghue, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/16/2025 4:51 PM, Bryan O'Donoghue wrote:
> On 13/08/2025 10:38, Dikshita Agarwal wrote:
>> + if (type == DECODER) {
>> + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
>> + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
>> + if (ret)
>> + goto err_vdev_release;
>> + core->vdev_dec = vdev;
>> + } else if (type == ENCODER) {
>> + strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
>> + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
>> + if (ret)
>> + goto err_vdev_release;
>> + core->vdev_enc = vdev;
>> + } else {
>
> A bit of duplicate reduction.
>
> if (type == DECODER) {
> strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
> core->vdev_dec = vdev;
> } else if (type == ENCODER) {
> strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
> core->vdev_enc = vdev;
> } else {
> ret = -EINVAL;
> goto err_vdev_release;
> }
>
> ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> if (ret)
> goto err_vdev_release;
>
> once done
Sure, will fix.
>
> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>
> ---
> bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure
2025-08-18 3:21 ` Dikshita Agarwal
@ 2025-08-18 6:08 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-18 6:08 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/18/2025 8:51 AM, Dikshita Agarwal wrote:
>>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>>> new file mode 100644
>>> index 0000000000000000000000000000000000000000..e418d347ac111c1bc48304adafa259d697e49fed
>>> --- /dev/null
>>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>>> @@ -0,0 +1,65 @@
>>> +// SPDX-License-Identifier: GPL-2.0-only
>>> +/*
>>> + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
>>> + */
>>> +
>>> +#include "iris_buffer.h"
>>> +#include "iris_instance.h"
>>> +#include "iris_venc.h"
>>> +#include "iris_vpu_buffer.h"
>>> +
>>> +int iris_venc_inst_init(struct iris_inst *inst)
>>> +{
>>> + struct v4l2_format *f;
>>> +
>>> + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
>>> + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL);
>>> + if (!inst->fmt_src || !inst->fmt_dst)
>>> + return -ENOMEM;
>> What if inst->fmt_src succeeds while inst->fmt_dst fails, does it frees up
>> inst->fmt_src ?
>>
> would you prefer below?
>
> if (!inst->fmt_src || !inst->fmt_dst) {
> kfree(inst->fmt_src);
> kfree(inst->fmt_dst);
> return -ENOMEM;
> }
>
Looks ok..
with that addressed,
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
> Thanks,
> Dikshita
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder
2025-08-18 3:21 ` Dikshita Agarwal
@ 2025-08-18 6:10 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-18 6:10 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/18/2025 8:51 AM, Dikshita Agarwal wrote:
>>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>>> index d3026b2bcb708c7ec31f134f628df7e57b54af4f..1e2fadfe17672029b46e07ce00a8e31e0711fd58 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>>> @@ -354,6 +354,7 @@ struct iris_platform_data sm8550_data = {
>>> .num_vpp_pipe = 4,
>>> .max_session_count = 16,
>>> .max_core_mbpf = NUM_MBS_8K * 2,
>>> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
>>> .input_config_params_default =
>>> sm8550_vdec_input_config_params_default,
>>> .input_config_params_default_size =
>>> @@ -429,6 +430,7 @@ struct iris_platform_data sm8650_data = {
>>> .num_vpp_pipe = 4,
>>> .max_session_count = 16,
>>> .max_core_mbpf = NUM_MBS_8K * 2,
>>> + .max_core_mbps = ((7680 * 4320) / 256) * 60,
>>> .input_config_params_default =
>>> sm8550_vdec_input_config_params_default,
>>> .input_config_params_default_size =
>>> @@ -500,6 +502,7 @@ struct iris_platform_data qcs8300_data = {
>>> .num_vpp_pipe = 2,
>>> .max_session_count = 16,
>>> .max_core_mbpf = ((4096 * 2176) / 256) * 4,
>>> + .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
>> TODO ? 4k@60 is supported mbps for qcs8300
> It was a miss, will remove the TODO.
>
With that fixed..
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device
2025-08-18 3:25 ` Dikshita Agarwal
@ 2025-08-18 6:11 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-18 6:11 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/18/2025 8:55 AM, Dikshita Agarwal wrote:
>>> +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
>>> +{
>>> + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
>>> + return -EINVAL;
>>> +
>>> + switch (s->target) {
>>> + case V4L2_SEL_TGT_CROP:
>>> + s->r.left = 0;
>>> + s->r.top = 0;
>>> +
>>> + if (s->r.width > inst->fmt_src->fmt.pix_mp.width ||
>>> + s->r.height > inst->fmt_src->fmt.pix_mp.height)
>>> + return -EINVAL;
>>> +
>>> + inst->crop.left = s->r.left;
>>> + inst->crop.top = s->r.top;
>>> + inst->crop.width = s->r.width;
>>> + inst->crop.height = s->r.height;
>>> + inst->fmt_dst->fmt.pix_mp.width = inst->crop.width;
>>> + inst->fmt_dst->fmt.pix_mp.height = inst->crop.height;
>>> + return iris_venc_s_fmt_output(inst, inst->fmt_dst);
>>> + default:
>>> + return -EINVAL;
>>> + }
>>> +
>>> + return 0;
>> Why do you need a return here ?
> We actually don't, it should be safe to remove this, will fix.
With that fixed,
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 19/24] media: iris: Add platform-specific capabilities for encoder video device
2025-08-14 15:05 ` Vikash Garodia
@ 2025-08-18 7:25 ` Dikshita Agarwal
2025-08-18 7:27 ` Vikash Garodia
0 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 7:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/14/2025 8:35 PM, Vikash Garodia wrote:
>
> On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
>> Add platform-specific capabilities for the encoder video device and
>> initialize the corresponding controls in the control handler.
>>
>> This enables proper configuration and handling of encoder-specific
>> features based on platform requirements.
>>
>> Co-developed-by: Wangao Wang <quic_wangaow@quicinc.com>
>> Signed-off-by: Wangao Wang <quic_wangaow@quicinc.com>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/iris_core.h | 7 +-
>> drivers/media/platform/qcom/iris/iris_ctrls.c | 175 +++++++++-
>> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 7 +
>> .../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 +
>> .../platform/qcom/iris/iris_platform_common.h | 43 ++-
>> .../media/platform/qcom/iris/iris_platform_gen2.c | 385 ++++++++++++++++++++-
>> .../platform/qcom/iris/iris_platform_qcs8300.h | 350 ++++++++++++++++++-
>> .../platform/qcom/iris/iris_platform_sm8250.c | 185 +++++++++-
>> drivers/media/platform/qcom/iris/iris_vdec.c | 2 +-
>> drivers/media/platform/qcom/iris/iris_venc.c | 7 +-
>> 10 files changed, 1140 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
>> index 827aee8dcec3ee17af5a90f5594b9315f663c0b3..fb194c967ad4f9b5e00cd74f0d41e0b827ef14db 100644
>> --- a/drivers/media/platform/qcom/iris/iris_core.h
>> +++ b/drivers/media/platform/qcom/iris/iris_core.h
>> @@ -71,7 +71,8 @@ enum domain_type {
>> * @intr_status: interrupt status
>> * @sys_error_handler: a delayed work for handling system fatal error
>> * @instances: a list_head of all instances
>> - * @inst_fw_caps: an array of supported instance capabilities
>> + * @inst_fw_caps_dec: an array of supported instance capabilities by decoder
>> + * @inst_fw_caps_enc: an array of supported instance capabilities by encoder
>> */
>>
>> struct iris_core {
>> @@ -113,7 +114,9 @@ struct iris_core {
>> u32 intr_status;
>> struct delayed_work sys_error_handler;
>> struct list_head instances;
>> - struct platform_inst_fw_cap inst_fw_caps[INST_FW_CAP_MAX];
>> + /* encoder and decoder have overlapping caps, so two different arrays are required */
>> + struct platform_inst_fw_cap inst_fw_caps_dec[INST_FW_CAP_MAX];
>> + struct platform_inst_fw_cap inst_fw_caps_enc[INST_FW_CAP_MAX];
>> };
>>
>> int iris_core_init(struct iris_core *core);
>> diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
>> index 9136b723c0f2a3d5833af32ae2735ccdb244f60f..797386cb96ab1d24be6cc1819e2f9202ab4cc224 100644
>> --- a/drivers/media/platform/qcom/iris/iris_ctrls.c
>> +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
>> @@ -31,6 +31,68 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id)
>> return LEVEL_VP9;
>> case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
>> return TIER;
>> + case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
>> + return HEADER_MODE;
>> + case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
>> + return PREPEND_SPSPPS_TO_IDR;
>> + case V4L2_CID_MPEG_VIDEO_BITRATE:
>> + return BITRATE;
>> + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
>> + return BITRATE_PEAK;
>> + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
>> + return BITRATE_MODE;
>> + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
>> + return FRAME_SKIP_MODE;
>> + case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
>> + return FRAME_RC_ENABLE;
>> + case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
>> + return GOP_SIZE;
>> + case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
>> + return ENTROPY_MODE;
>> + case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
>> + return MIN_FRAME_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
>> + return MIN_FRAME_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
>> + return MAX_FRAME_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
>> + return MAX_FRAME_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP:
>> + return I_FRAME_MIN_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP:
>> + return I_FRAME_MIN_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP:
>> + return P_FRAME_MIN_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP:
>> + return P_FRAME_MIN_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP:
>> + return B_FRAME_MIN_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP:
>> + return B_FRAME_MIN_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP:
>> + return I_FRAME_MAX_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP:
>> + return I_FRAME_MAX_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP:
>> + return P_FRAME_MAX_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP:
>> + return P_FRAME_MAX_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP:
>> + return B_FRAME_MAX_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP:
>> + return B_FRAME_MAX_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
>> + return I_FRAME_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
>> + return I_FRAME_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
>> + return P_FRAME_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
>> + return P_FRAME_QP_HEVC;
>> + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
>> + return B_FRAME_QP_H264;
>> + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
>> + return B_FRAME_QP_HEVC;
>> default:
>> return INST_FW_CAP_MAX;
>> }
>> @@ -56,6 +118,68 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)
>> return V4L2_CID_MPEG_VIDEO_VP9_LEVEL;
>> case TIER:
>> return V4L2_CID_MPEG_VIDEO_HEVC_TIER;
>> + case HEADER_MODE:
>> + return V4L2_CID_MPEG_VIDEO_HEADER_MODE;
>> + case PREPEND_SPSPPS_TO_IDR:
>> + return V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR;
>> + case BITRATE:
>> + return V4L2_CID_MPEG_VIDEO_BITRATE;
>> + case BITRATE_PEAK:
>> + return V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
>> + case BITRATE_MODE:
>> + return V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
>> + case FRAME_SKIP_MODE:
>> + return V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE;
>> + case FRAME_RC_ENABLE:
>> + return V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
>> + case GOP_SIZE:
>> + return V4L2_CID_MPEG_VIDEO_GOP_SIZE;
>> + case ENTROPY_MODE:
>> + return V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
>> + case MIN_FRAME_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_MIN_QP;
>> + case MIN_FRAME_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP;
>> + case MAX_FRAME_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_MAX_QP;
>> + case MAX_FRAME_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP;
>> + case I_FRAME_MIN_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP;
>> + case I_FRAME_MIN_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP;
>> + case P_FRAME_MIN_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP;
>> + case P_FRAME_MIN_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP;
>> + case B_FRAME_MIN_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP;
>> + case B_FRAME_MIN_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP;
>> + case I_FRAME_MAX_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP;
>> + case I_FRAME_MAX_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP;
>> + case P_FRAME_MAX_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP;
>> + case P_FRAME_MAX_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP;
>> + case B_FRAME_MAX_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP;
>> + case B_FRAME_MAX_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP;
>> + case I_FRAME_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP;
>> + case I_FRAME_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP;
>> + case P_FRAME_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP;
>> + case P_FRAME_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP;
>> + case B_FRAME_QP_H264:
>> + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP;
>> + case B_FRAME_QP_HEVC:
>> + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP;
>> default:
>> return 0;
>> }
>> @@ -101,7 +225,10 @@ int iris_ctrls_init(struct iris_inst *inst)
>> num_ctrls++;
>> }
>>
>> - /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */
>> + /* Adding 1 to num_ctrls to include
>> + * V4L2_CID_MIN_BUFFERS_FOR_CAPTURE for decoder and
>> + * V4L2_CID_MIN_BUFFERS_FOR_OUTPUT for encoder
>> + */
>>
>> ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1);
>> if (ret)
>> @@ -143,8 +270,13 @@ int iris_ctrls_init(struct iris_inst *inst)
>> ctrl_idx++;
>> }
>>
>> - v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
>> - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
>> + if (inst->domain == DECODER) {
>> + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
>> + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
>> + } else {
>> + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
>> + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 4);
>> + }
>>
>> ret = inst->ctrl_handler.error;
>> if (ret)
>> @@ -162,22 +294,39 @@ void iris_session_init_caps(struct iris_core *core)
>> struct platform_inst_fw_cap *caps;
>> u32 i, num_cap, cap_id;
>>
>> - caps = core->iris_platform_data->inst_fw_caps;
>> - num_cap = core->iris_platform_data->inst_fw_caps_size;
>> + caps = core->iris_platform_data->inst_fw_caps_dec;
>> + num_cap = core->iris_platform_data->inst_fw_caps_dec_size;
>> +
>> + for (i = 0; i < num_cap; i++) {
>> + cap_id = caps[i].cap_id;
>> + if (!iris_valid_cap_id(cap_id))
>> + continue;
>> +
>> + core->inst_fw_caps_dec[cap_id].cap_id = caps[i].cap_id;
>> + core->inst_fw_caps_dec[cap_id].min = caps[i].min;
>> + core->inst_fw_caps_dec[cap_id].max = caps[i].max;
>> + core->inst_fw_caps_dec[cap_id].step_or_mask = caps[i].step_or_mask;
>> + core->inst_fw_caps_dec[cap_id].value = caps[i].value;
>> + core->inst_fw_caps_dec[cap_id].flags = caps[i].flags;
>> + core->inst_fw_caps_dec[cap_id].hfi_id = caps[i].hfi_id;
>> + core->inst_fw_caps_dec[cap_id].set = caps[i].set;
>> + }
>> +
>> + caps = core->iris_platform_data->inst_fw_caps_enc;
>> + num_cap = core->iris_platform_data->inst_fw_caps_enc_size;
>>
>> for (i = 0; i < num_cap; i++) {
>> cap_id = caps[i].cap_id;
>> if (!iris_valid_cap_id(cap_id))
>> continue;
>>
>> - core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id;
>> - core->inst_fw_caps[cap_id].min = caps[i].min;
>> - core->inst_fw_caps[cap_id].max = caps[i].max;
>> - core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask;
>> - core->inst_fw_caps[cap_id].value = caps[i].value;
>> - core->inst_fw_caps[cap_id].flags = caps[i].flags;
>> - core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id;
>> - core->inst_fw_caps[cap_id].set = caps[i].set;
>> + core->inst_fw_caps_enc[cap_id].cap_id = caps[i].cap_id;
>> + core->inst_fw_caps_enc[cap_id].min = caps[i].min;
>> + core->inst_fw_caps_enc[cap_id].max = caps[i].max;
>> + core->inst_fw_caps_enc[cap_id].step_or_mask = caps[i].step_or_mask;
>> + core->inst_fw_caps_enc[cap_id].value = caps[i].value;
>> + core->inst_fw_caps_enc[cap_id].flags = caps[i].flags;
>> + core->inst_fw_caps_enc[cap_id].hfi_id = caps[i].hfi_id;
>> }
>> }
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> index 5b7c641b727a16c3aa7196a6d49786133653279f..a7f4379c5973fdc4366969139bef25472e8f11a5 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> @@ -121,6 +121,13 @@
>> #define HFI_UNUSED_PICT 0x10000000
>> #define HFI_BUFFERFLAG_DATACORRUPT 0x00000008
>> #define HFI_BUFFERFLAG_DROP_FRAME 0x20000000
>> +#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL 0x2005002
>> +#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL 0x2005003
>> +#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL 0x2005004
>> +#define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2 0x2005009
>> +#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020
>> +#define HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE 0x2006001
>> +#define HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER 0x2006008
>>
>> struct hfi_pkt_hdr {
>> u32 size;
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
>> index 5f13dc11bea532600cc9b15db57e8981a1f3eb93..fb6724d7f95ff8858aa9ba093fefb642e89de279 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
>> @@ -55,12 +55,21 @@
>> #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123
>> #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124
>> #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128
>> +#define HFI_PROP_RATE_CONTROL 0x0300012a
>> +#define HFI_PROP_QP_PACKED 0x0300012e
>> +#define HFI_PROP_MIN_QP_PACKED 0x0300012f
>> +#define HFI_PROP_MAX_QP_PACKED 0x03000130
>> +#define HFI_PROP_TOTAL_BITRATE 0x0300013b
>> +#define HFI_PROP_MAX_GOP_FRAMES 0x03000146
>> +#define HFI_PROP_MAX_B_FRAMES 0x03000147
>> #define HFI_PROP_QUALITY_MODE 0x03000148
>> +#define HFI_PROP_SEQ_HEADER_MODE 0x03000149
>> #define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155
>> #define HFI_PROP_PICTURE_TYPE 0x03000162
>> #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168
>> #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169
>> #define HFI_PROP_NO_OUTPUT 0x0300016a
>> +#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C
>> #define HFI_PROP_COMV_BUFFER_COUNT 0x03000193
>> #define HFI_PROP_END 0x03FFFFFF
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
>> index d0b84c93aef409b51a767ba11f91c6ce2533f27f..6d6a8f3b38271d928d753dd180e6e9a991991d24 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
>> @@ -23,6 +23,11 @@ struct iris_inst;
>> #define DEFAULT_FPS 30
>> #define MAXIMUM_FPS 480
>> #define NUM_MBS_8K ((8192 * 4352) / 256)
>> +#define MIN_QP_8BIT 1
>> +#define MAX_QP 51
>> +#define MAX_QP_HEVC 63
>> +#define DEFAULT_QP 20
>> +#define BITRATE_DEFAULT 20000000
>>
>> enum stage_type {
>> STAGE_1 = 1,
>> @@ -91,6 +96,7 @@ enum platform_inst_fw_cap_type {
>> LEVEL_HEVC,
>> LEVEL_VP9,
>> INPUT_BUF_HOST_MAX_COUNT,
>> + OUTPUT_BUF_HOST_MAX_COUNT,
>> STAGE,
>> PIPE,
>> POC,
>> @@ -98,6 +104,37 @@ enum platform_inst_fw_cap_type {
>> BIT_DEPTH,
>> RAP_FRAME,
>> TIER,
>> + HEADER_MODE,
>> + PREPEND_SPSPPS_TO_IDR,
>> + BITRATE,
>> + BITRATE_PEAK,
>> + BITRATE_MODE,
>> + FRAME_SKIP_MODE,
>> + FRAME_RC_ENABLE,
>> + GOP_SIZE,
>> + ENTROPY_MODE,
>> + MIN_FRAME_QP_H264,
>> + MIN_FRAME_QP_HEVC,
>> + MAX_FRAME_QP_H264,
>> + MAX_FRAME_QP_HEVC,
>> + I_FRAME_MIN_QP_H264,
>> + I_FRAME_MIN_QP_HEVC,
>> + P_FRAME_MIN_QP_H264,
>> + P_FRAME_MIN_QP_HEVC,
>> + B_FRAME_MIN_QP_H264,
>> + B_FRAME_MIN_QP_HEVC,
>> + I_FRAME_MAX_QP_H264,
>> + I_FRAME_MAX_QP_HEVC,
>> + P_FRAME_MAX_QP_H264,
>> + P_FRAME_MAX_QP_HEVC,
>> + B_FRAME_MAX_QP_H264,
>> + B_FRAME_MAX_QP_HEVC,
>> + I_FRAME_QP_H264,
>> + I_FRAME_QP_HEVC,
>> + P_FRAME_QP_H264,
>> + P_FRAME_QP_HEVC,
>> + B_FRAME_QP_H264,
>> + B_FRAME_QP_HEVC,
>> INST_FW_CAP_MAX,
>> };
>>
>> @@ -172,8 +209,10 @@ struct iris_platform_data {
>> const char *fwname;
>> u32 pas_id;
>> struct platform_inst_caps *inst_caps;
>> - struct platform_inst_fw_cap *inst_fw_caps;
>> - u32 inst_fw_caps_size;
>> + struct platform_inst_fw_cap *inst_fw_caps_dec;
>> + u32 inst_fw_caps_dec_size;
>> + struct platform_inst_fw_cap *inst_fw_caps_enc;
>> + u32 inst_fw_caps_enc_size;
>> struct tz_cp_config *tz_cp_config_data;
>> u32 core_arch;
>> u32 hw_response_timeout;
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> index e047fb75a99a6372dac4ad029baea16034cac633..1bf289d322c86a8f8c03c80697c08af5d9067769 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> @@ -14,8 +14,9 @@
>> #include "iris_platform_sm8650.h"
>>
>> #define VIDEO_ARCH_LX 1
>> +#define BITRATE_MAX 245000000
>>
>> -static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = {
>> +static struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = {
>> {
>> .cap_id = PROFILE_H264,
>> .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> @@ -199,6 +200,370 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = {
>> },
>> };
>>
>> +static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
>> + {
>> + .cap_id = PROFILE_H264,
>> + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
>> + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
>> + .hfi_id = HFI_PROP_PROFILE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = PROFILE_HEVC,
>> + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
>> + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> + .hfi_id = HFI_PROP_PROFILE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = LEVEL_H264,
>> + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
>> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
>> + .hfi_id = HFI_PROP_LEVEL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = LEVEL_HEVC,
>> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
>> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
>> + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
>> + .hfi_id = HFI_PROP_LEVEL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = STAGE,
>> + .min = STAGE_1,
>> + .max = STAGE_2,
>> + .step_or_mask = 1,
>> + .value = STAGE_2,
>> + .hfi_id = HFI_PROP_STAGE,
>> + },
>> + {
>> + .cap_id = HEADER_MODE,
>> + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
>> + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
>> + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
>> + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> + .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = PREPEND_SPSPPS_TO_IDR,
>> + .min = 0,
>> + .max = 1,
>> + .step_or_mask = 1,
>> + .value = 0,
>> + },
>> + {
>> + .cap_id = BITRATE,
>> + .min = 1,
>> + .max = BITRATE_MAX,
>> + .step_or_mask = 1,
>> + .value = BITRATE_DEFAULT,
>> + .hfi_id = HFI_PROP_TOTAL_BITRATE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = BITRATE_PEAK,
>> + .min = 1,
>> + .max = BITRATE_MAX,
>> + .step_or_mask = 1,
>> + .value = BITRATE_DEFAULT,
>> + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = BITRATE_MODE,
>> + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
>> + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
>> + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> + .hfi_id = HFI_PROP_RATE_CONTROL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = FRAME_SKIP_MODE,
>> + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
>> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
>> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
>> + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = FRAME_RC_ENABLE,
>> + .min = 0,
>> + .max = 1,
>> + .step_or_mask = 1,
>> + .value = 1,
>> + },
>> + {
>> + .cap_id = GOP_SIZE,
>> + .min = 0,
>> + .max = INT_MAX,
>> + .step_or_mask = 1,
>> + .value = 2 * DEFAULT_FPS - 1,
>> + .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = ENTROPY_MODE,
>> + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
>> + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
>> + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
>> + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> + .hfi_id = HFI_PROP_CABAC_SESSION,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = MIN_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MIN_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MAX_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MAX_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = I_FRAME_MIN_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = I_FRAME_MIN_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = P_FRAME_MIN_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = P_FRAME_MIN_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = B_FRAME_MIN_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = B_FRAME_MIN_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = I_FRAME_MAX_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = I_FRAME_MAX_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = P_FRAME_MAX_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = P_FRAME_MAX_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = B_FRAME_MAX_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = B_FRAME_MAX_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = I_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = I_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = P_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = P_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = B_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = B_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = INPUT_BUF_HOST_MAX_COUNT,
>> + .min = DEFAULT_MAX_HOST_BUF_COUNT,
>> + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_MAX_HOST_BUF_COUNT,
>> + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
>> + .flags = CAP_FLAG_INPUT_PORT,
>> + },
>> + {
>> + .cap_id = OUTPUT_BUF_HOST_MAX_COUNT,
>> + .min = DEFAULT_MAX_HOST_BUF_COUNT,
>> + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_MAX_HOST_BUF_COUNT,
>> + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> +};
>> +
>> static struct platform_inst_caps platform_inst_cap_sm8550 = {
>> .min_frame_width = 96,
>> .max_frame_width = 8192,
>> @@ -347,8 +712,10 @@ struct iris_platform_data sm8550_data = {
>> .fwname = "qcom/vpu/vpu30_p4.mbn",
>> .pas_id = IRIS_PAS_ID,
>> .inst_caps = &platform_inst_cap_sm8550,
>> - .inst_fw_caps = inst_fw_cap_sm8550,
>> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550),
>> + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
>> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
>> + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
>> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
>> .tz_cp_config_data = &tz_cp_config_sm8550,
>> .core_arch = VIDEO_ARCH_LX,
>> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
>> @@ -423,8 +790,10 @@ struct iris_platform_data sm8650_data = {
>> .fwname = "qcom/vpu/vpu33_p4.mbn",
>> .pas_id = IRIS_PAS_ID,
>> .inst_caps = &platform_inst_cap_sm8550,
>> - .inst_fw_caps = inst_fw_cap_sm8550,
>> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550),
>> + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
>> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
>> + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
>> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
>> .tz_cp_config_data = &tz_cp_config_sm8550,
>> .core_arch = VIDEO_ARCH_LX,
>> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
>> @@ -495,8 +864,10 @@ struct iris_platform_data qcs8300_data = {
>> .fwname = "qcom/vpu/vpu30_p4_s6.mbn",
>> .pas_id = IRIS_PAS_ID,
>> .inst_caps = &platform_inst_cap_qcs8300,
>> - .inst_fw_caps = inst_fw_cap_qcs8300,
>> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_qcs8300),
>> + .inst_fw_caps_dec = inst_fw_cap_qcs8300_dec,
>> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_qcs8300_dec),
>> + .inst_fw_caps_enc = inst_fw_cap_qcs8300_enc,
>> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_qcs8300_enc),
>> .tz_cp_config_data = &tz_cp_config_sm8550,
>> .core_arch = VIDEO_ARCH_LX,
>> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
>> index 22e485b0b2ae8f110d2f3b817e202d1aa7d227fd..624e3a442b06aabf3241d0b364b1d12fe937d6be 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
>> @@ -3,7 +3,9 @@
>> * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
>> */
>>
>> -static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = {
>> +#define BITRATE_MAX 245000000
>> +
>> +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_dec[] = {
>> {
>> .cap_id = PROFILE_H264,
>> .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> @@ -187,6 +189,352 @@ static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = {
>> },
>> };
>>
>> +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_enc[] = {
>> + {
>> + .cap_id = PROFILE_H264,
>> + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
>> + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
>> + .hfi_id = HFI_PROP_PROFILE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = PROFILE_HEVC,
>> + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
>> + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> + .hfi_id = HFI_PROP_PROFILE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = LEVEL_H264,
>> + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0),
>> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0,
>> + .hfi_id = HFI_PROP_LEVEL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = LEVEL_HEVC,
>> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
>> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
>> + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5,
>> + .hfi_id = HFI_PROP_LEVEL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = STAGE,
>> + .min = STAGE_1,
>> + .max = STAGE_2,
>> + .step_or_mask = 1,
>> + .value = STAGE_2,
>> + .hfi_id = HFI_PROP_STAGE,
>> + },
>> + {
>> + .cap_id = HEADER_MODE,
>> + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
>> + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
>> + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
>> + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> + .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = PREPEND_SPSPPS_TO_IDR,
>> + .min = 0,
>> + .max = 1,
>> + .step_or_mask = 1,
>> + .value = 0,
>> + },
>> + {
>> + .cap_id = BITRATE,
>> + .min = 1,
>> + .max = BITRATE_MAX,
>> + .step_or_mask = 1,
>> + .value = BITRATE_DEFAULT,
>> + .hfi_id = HFI_PROP_TOTAL_BITRATE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = BITRATE_PEAK,
>> + .min = 1,
>> + .max = BITRATE_MAX,
>> + .step_or_mask = 1,
>> + .value = BITRATE_DEFAULT,
>> + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = BITRATE_MODE,
>> + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
>> + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
>> + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> + .hfi_id = HFI_PROP_RATE_CONTROL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = FRAME_SKIP_MODE,
>> + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
>> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
>> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
>> + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = FRAME_RC_ENABLE,
>> + .min = 0,
>> + .max = 1,
>> + .step_or_mask = 1,
>> + .value = 1,
>> + },
>> + {
>> + .cap_id = GOP_SIZE,
>> + .min = 0,
>> + .max = INT_MAX,
>> + .step_or_mask = 1,
>> + .value = 2 * DEFAULT_FPS - 1,
>> + .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = ENTROPY_MODE,
>> + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
>> + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
>> + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
>> + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> + .hfi_id = HFI_PROP_CABAC_SESSION,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = MIN_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MIN_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + .hfi_id = HFI_PROP_MIN_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MAX_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MAX_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + .hfi_id = HFI_PROP_MAX_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = I_FRAME_MIN_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = I_FRAME_MIN_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = P_FRAME_MIN_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = P_FRAME_MIN_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = B_FRAME_MIN_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = B_FRAME_MIN_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + },
>> + {
>> + .cap_id = I_FRAME_MAX_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = I_FRAME_MAX_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = P_FRAME_MAX_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = P_FRAME_MAX_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = B_FRAME_MAX_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = B_FRAME_MAX_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + },
>> + {
>> + .cap_id = I_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = I_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = P_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = P_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = B_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = B_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = DEFAULT_QP,
>> + .hfi_id = HFI_PROP_QP_PACKED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> +};
>> +
>> static struct platform_inst_caps platform_inst_cap_qcs8300 = {
>> .min_frame_width = 96,
>> .max_frame_width = 4096,
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> index 5d59a5a3172a510b3a38f7c9c29dffd919fafce7..b1ed6a140980ab6ca27f372f6f5851569a93ceed 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> @@ -11,7 +11,12 @@
>> #include "iris_hfi_gen1_defines.h"
>> #include "iris_vpu_common.h"
>>
>> -static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = {
>> +#define BITRATE_MIN 32000
>> +#define BITRATE_MAX 160000000
>> +#define BITRATE_PEAK_DEFAULT (BITRATE_DEFAULT * 2)
>> +#define BITRATE_STEP 100
>> +
>> +static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = {
>> {
>> .cap_id = PIPE,
>> .min = PIPE_1,
>> @@ -32,6 +37,178 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = {
>> },
>> };
>>
>> +static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = {
>> + {
>> + .cap_id = PROFILE_H264,
>> + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> + .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
>> + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH),
>> + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
>> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = PROFILE_HEVC,
>> + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
>> + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
>> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = LEVEL_H264,
>> + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> + .max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
>> + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1),
>> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = LEVEL_HEVC,
>> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
>> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
>> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>
> Fix the default value to V4L2_MPEG_VIDEO_HEVC_LEVEL_1
Seems like a typo, thanks for pointing out, will fix.
>
>> + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = HEADER_MODE,
>> + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
>> + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
>> + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
>> + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
>> + .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = BITRATE,
>> + .min = BITRATE_MIN,
>> + .max = BITRATE_MAX,
>> + .step_or_mask = BITRATE_STEP,
>> + .value = BITRATE_DEFAULT,
>> + .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
>> + CAP_FLAG_DYNAMIC_ALLOWED,
>> + },
>> + {
>> + .cap_id = BITRATE_MODE,
>> + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
>> + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
>> + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
>> + .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = FRAME_SKIP_MODE,
>> + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
>> + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
>> + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = FRAME_RC_ENABLE,
>> + .min = 0,
>> + .max = 1,
>> + .step_or_mask = 1,
>> + .value = 1,
>> + },
>> + {
>> + .cap_id = GOP_SIZE,
>> + .min = 0,
>> + .max = (1 << 16) - 1,
>> + .step_or_mask = 1,
>> + .value = 30,
>> + },
>> + {
>> + .cap_id = ENTROPY_MODE,
>> + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
>> + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
>> + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
>> + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
>> + .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL,
>> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
>> + },
>> + {
>> + .cap_id = MIN_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MIN_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP_HEVC,
>> + .step_or_mask = 1,
>> + .value = MIN_QP_8BIT,
>> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MAX_FRAME_QP_H264,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP,
>> + .step_or_mask = 1,
>> + .value = MAX_QP,
>> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> + {
>> + .cap_id = MAX_FRAME_QP_HEVC,
>> + .min = MIN_QP_8BIT,
>> + .max = MAX_QP_HEVC,
>> + .step_or_mask = 1,
>> + .value = MAX_QP_HEVC,
>> + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
>> + .flags = CAP_FLAG_OUTPUT_PORT,
>> + },
>> +};
>> +
>> static struct platform_inst_caps platform_inst_cap_sm8250 = {
>> .min_frame_width = 128,
>> .max_frame_width = 8192,
>> @@ -123,8 +300,10 @@ struct iris_platform_data sm8250_data = {
>> .fwname = "qcom/vpu-1.0/venus.mbn",
>> .pas_id = IRIS_PAS_ID,
>> .inst_caps = &platform_inst_cap_sm8250,
>> - .inst_fw_caps = inst_fw_cap_sm8250,
>> - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8250),
>> + .inst_fw_caps_dec = inst_fw_cap_sm8250_dec,
>> + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8250_dec),
>> + .inst_fw_caps_enc = inst_fw_cap_sm8250_enc,
>> + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8250_enc),
>> .tz_cp_config_data = &tz_cp_config_sm8250,
>> .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
>> .num_vpp_pipe = 4,
>> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
>> index 6afbd2f89260a233d75d7a0cdf3647236216c9ec..fcefd7c36335efd4154159d8a7fab31fae33a2fe 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
>> @@ -54,7 +54,7 @@ int iris_vdec_inst_init(struct iris_inst *inst)
>> inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
>> inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
>>
>> - memcpy(&inst->fw_caps[0], &core->inst_fw_caps[0],
>> + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_dec[0],
>> INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
>>
>> return iris_ctrls_init(inst);
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>> index 11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67..4630ba12349a62a37515e93ed5efa2df197bce17 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>> @@ -7,12 +7,14 @@
>> #include <media/v4l2-mem2mem.h>
>>
>> #include "iris_buffer.h"
>> +#include "iris_ctrls.h"
>> #include "iris_instance.h"
>> #include "iris_venc.h"
>> #include "iris_vpu_buffer.h"
>>
>> int iris_venc_inst_init(struct iris_inst *inst)
>> {
>> + struct iris_core *core = inst->core;
>> struct v4l2_format *f;
>>
>> inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL);
>> @@ -61,7 +63,10 @@ int iris_venc_inst_init(struct iris_inst *inst)
>> inst->operating_rate = DEFAULT_FPS << 16;
>> inst->frame_rate = DEFAULT_FPS << 16;
>>
>> - return 0;
>> + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0],
>> + INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
>> +
>> + return iris_ctrls_init(inst);
>> }
>>
>> void iris_venc_inst_deinit(struct iris_inst *inst)
>>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 19/24] media: iris: Add platform-specific capabilities for encoder video device
2025-08-18 7:25 ` Dikshita Agarwal
@ 2025-08-18 7:27 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-18 7:27 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/18/2025 12:55 PM, Dikshita Agarwal wrote:
>>> + {
>>> + .cap_id = LEVEL_HEVC,
>>> + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
>>> + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
>>> + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
>>> + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2),
>>> + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
>> Fix the default value to V4L2_MPEG_VIDEO_HEVC_LEVEL_1
> Seems like a typo, thanks for pointing out, will fix.
With that fixed,
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 18/24] media: iris: Add support for G/S_PARM for encoder video device
2025-08-14 15:01 ` Vikash Garodia
@ 2025-08-18 7:29 ` Dikshita Agarwal
2025-08-18 7:34 ` Vikash Garodia
0 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 7:29 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/14/2025 8:31 PM, Vikash Garodia wrote:
>
>
> On 8/13/2025 3:08 PM, Dikshita Agarwal wrote:
>> Add supports for the G/S_PARM V4L2 ioctls for encoder video device with
>> necessary hooks. This allows userspace to query the current streaming
>> parameters such as frame intervals and set desired streaming parameters
>> primarily the frame rate.
>>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/iris_instance.h | 5 ++
>> .../platform/qcom/iris/iris_platform_common.h | 2 +
>> .../media/platform/qcom/iris/iris_platform_gen2.c | 4 +-
>> .../platform/qcom/iris/iris_platform_qcs8300.h | 2 +
>> .../platform/qcom/iris/iris_platform_sm8250.c | 2 +
>> drivers/media/platform/qcom/iris/iris_utils.c | 36 ++++++++
>> drivers/media/platform/qcom/iris/iris_utils.h | 2 +
>> drivers/media/platform/qcom/iris/iris_vb2.c | 17 ----
>> drivers/media/platform/qcom/iris/iris_venc.c | 95 ++++++++++++++++++++++
>> drivers/media/platform/qcom/iris/iris_venc.h | 2 +
>> drivers/media/platform/qcom/iris/iris_vidc.c | 30 +++++++
>> 11 files changed, 179 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
>> index 55cf9702111829ef24189986ba5245c7684bfe11..b75549718df3c87cd85aecfc74c873c60cd4bde5 100644
>> --- a/drivers/media/platform/qcom/iris/iris_instance.h
>> +++ b/drivers/media/platform/qcom/iris/iris_instance.h
>> @@ -61,6 +61,9 @@ struct iris_fmt {
>> * @metadata_idx: index for metadata buffer
>> * @codec: codec type
>> * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
>> + * @frame_rate: frame rate of current instance
>> + * @operating_rate: operating rate of current instance
>> +
>> */
>>
>> struct iris_inst {
>> @@ -96,6 +99,8 @@ struct iris_inst {
>> u32 metadata_idx;
>> u32 codec;
>> bool last_buffer_dequeued;
>> + u32 frame_rate;
>> + u32 operating_rate;
>> };
>>
>> #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
>> index 792f46e2e34fd564a1ed61523f72826fc8f74582..d0b84c93aef409b51a767ba11f91c6ce2533f27f 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
>> @@ -79,6 +79,8 @@ struct platform_inst_caps {
>> u32 mb_cycles_fw;
>> u32 mb_cycles_fw_vpp;
>> u32 num_comv;
>> + u32 max_frame_rate;
>> + u32 max_operating_rate;
>> };
>>
>> enum platform_inst_fw_cap_type {
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> index 1e2fadfe17672029b46e07ce00a8e31e0711fd58..e047fb75a99a6372dac4ad029baea16034cac633 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
>> @@ -209,6 +209,8 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = {
>> .mb_cycles_fw = 489583,
>> .mb_cycles_fw_vpp = 66234,
>> .num_comv = 0,
>> + .max_frame_rate = MAXIMUM_FPS << 16,
>> + .max_operating_rate = MAXIMUM_FPS << 16,
>> };
>>
>> static void iris_set_sm8550_preset_registers(struct iris_core *core)
>> @@ -502,7 +504,7 @@ struct iris_platform_data qcs8300_data = {
>> .num_vpp_pipe = 2,
>> .max_session_count = 16,
>> .max_core_mbpf = ((4096 * 2176) / 256) * 4,
>> - .max_core_mbps = ((7680 * 4320) / 256) * 60, //TODO confirm!!
>> + .max_core_mbps = (((3840 * 2176) / 256) * 120),
>> .input_config_params_default =
>> sm8550_vdec_input_config_params_default,
>> .input_config_params_default_size =
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
>> index a8d66ed388a34e6bb45d4a089d981bb7d135fb50..22e485b0b2ae8f110d2f3b817e202d1aa7d227fd 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h
>> @@ -197,4 +197,6 @@ static struct platform_inst_caps platform_inst_cap_qcs8300 = {
>> .mb_cycles_fw = 326389,
>> .mb_cycles_fw_vpp = 44156,
>> .num_comv = 0,
>> + .max_frame_rate = MAXIMUM_FPS << 16,
>> + .max_operating_rate = MAXIMUM_FPS << 16,
>> };
>> diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> index 2a3cbe1f2d4b27d3cce9e9cdad1525801d71a041..5d59a5a3172a510b3a38f7c9c29dffd919fafce7 100644
>> --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
>> @@ -40,6 +40,8 @@ static struct platform_inst_caps platform_inst_cap_sm8250 = {
>> .max_mbpf = 138240,
>> .mb_cycles_vsp = 25,
>> .mb_cycles_vpp = 200,
>> + .max_frame_rate = MAXIMUM_FPS << 16,
>> + .max_operating_rate = MAXIMUM_FPS << 16,
>> };
>>
>> static void iris_set_sm8250_preset_registers(struct iris_core *core)
>> diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c
>> index 83c70d6a2d9092615dcf1b7d0fc85110f0df1aa0..f0af926879d5d90c56222aa8d48998a34be1c636 100644
>> --- a/drivers/media/platform/qcom/iris/iris_utils.c
>> +++ b/drivers/media/platform/qcom/iris/iris_utils.c
>> @@ -88,3 +88,39 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id)
>> mutex_unlock(&core->lock);
>> return NULL;
>> }
>> +
>> +int iris_check_core_mbpf(struct iris_inst *inst)
>> +{
>> + struct iris_core *core = inst->core;
>> + struct iris_inst *instance;
>> + u32 total_mbpf = 0;
>> +
>> + mutex_lock(&core->lock);
>> + list_for_each_entry(instance, &core->instances, list)
>> + total_mbpf += iris_get_mbpf(instance);
>> + mutex_unlock(&core->lock);
>> +
>> + if (total_mbpf > core->iris_platform_data->max_core_mbpf)
>> + return -ENOMEM;
>> +
>> + return 0;
>> +}
>> +
>> +int iris_check_core_mbps(struct iris_inst *inst)
>> +{
>> + struct iris_core *core = inst->core;
>> + struct iris_inst *instance;
>> + u32 total_mbps = 0, fps = 0;
>> +
>> + mutex_lock(&core->lock);
>> + list_for_each_entry(instance, &core->instances, list) {
>> + fps = max(instance->frame_rate >> 16, instance->operating_rate >> 16);
>> + total_mbps += iris_get_mbpf(instance) * fps;
>> + }
>> + mutex_unlock(&core->lock);
>> +
>> + if (total_mbps > core->iris_platform_data->max_core_mbps)
>> + return -ENOMEM;
>> +
>> + return 0;
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h
>> index 49869cf7a376880a026f44ff3883a6b13c6fcfbb..75740181122f5bdf93d64d3f43b3a26a9fe97919 100644
>> --- a/drivers/media/platform/qcom/iris/iris_utils.h
>> +++ b/drivers/media/platform/qcom/iris/iris_utils.h
>> @@ -49,5 +49,7 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id);
>> void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type,
>> enum vb2_buffer_state state);
>> int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush);
>> +int iris_check_core_mbpf(struct iris_inst *inst);
>> +int iris_check_core_mbps(struct iris_inst *inst);
>>
>> #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
>> index e62ed7a57df2debf0a930ad8307e6d945f589922..e32f7e1f007228a3b2b51cd76cd193d852f16080 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vb2.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vb2.c
>> @@ -12,23 +12,6 @@
>> #include "iris_vdec.h"
>> #include "iris_power.h"
>>
>> -static int iris_check_core_mbpf(struct iris_inst *inst)
>> -{
>> - struct iris_core *core = inst->core;
>> - struct iris_inst *instance;
>> - u32 total_mbpf = 0;
>> -
>> - mutex_lock(&core->lock);
>> - list_for_each_entry(instance, &core->instances, list)
>> - total_mbpf += iris_get_mbpf(instance);
>> - mutex_unlock(&core->lock);
>> -
>> - if (total_mbpf > core->iris_platform_data->max_core_mbpf)
>> - return -ENOMEM;
>> -
>> - return 0;
>> -}
>> -
>> static int iris_check_inst_mbpf(struct iris_inst *inst)
>> {
>> struct platform_inst_caps *caps;
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>> index 930f5afe9489d01be193f1dbe429d33f5401b468..11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>> @@ -58,6 +58,9 @@ int iris_venc_inst_init(struct iris_inst *inst)
>> inst->crop.width = f->fmt.pix_mp.width;
>> inst->crop.height = f->fmt.pix_mp.height;
>>
>> + inst->operating_rate = DEFAULT_FPS << 16;
>> + inst->frame_rate = DEFAULT_FPS << 16;
>
> I understand that firmware expects the rate in Q16 format, but does driver needs
> to keep it in that format ? I see most of the time in calculations, it is right
> shifted to bring it back to normal one and then back n forth.
>
Currently in driver inst->frame_rate is in Q16 format everywhere, no
inconsistency.
do you prefer to keep it in non Q16 format and convert to Q16 when setting
to firmware?
>> +
>> return 0;
>> }
>>
>> @@ -325,3 +328,95 @@ int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
>>
>> return 0;
>> }
>> +
>> +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
>> +{
>> + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
>> + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
>> + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
>> + struct v4l2_fract *timeperframe = NULL;
>> + u32 default_rate = DEFAULT_FPS;
>> + bool is_frame_rate = false;
>> + u32 q16_rate, max_rate;
>> + u64 us_per_frame, fps;
>> + int ret = 0;
>> +
>> + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>> + timeperframe = &s_parm->parm.output.timeperframe;
>> + max_rate = caps->max_operating_rate >> 16;
>> + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
>> + } else {
>> + timeperframe = &s_parm->parm.capture.timeperframe;
>> + is_frame_rate = true;
>> + max_rate = caps->max_frame_rate >> 16;
>> + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
>> + }
>> +
>> + if (!timeperframe->denominator || !timeperframe->numerator) {
>> + if (!timeperframe->numerator)
>> + timeperframe->numerator = 1;
>> + if (!timeperframe->denominator)
>> + timeperframe->denominator = default_rate;
>> + }
>> +
>> + us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
>> + do_div(us_per_frame, timeperframe->denominator);
>> +
>> + if (!us_per_frame)
>> + return -EINVAL;
>> +
>> + fps = (u64)USEC_PER_SEC;
>> + do_div(fps, us_per_frame);
>> + ret = fps > max_rate;
>> + if (ret) {
>
> if (fps > max_rate)
Sure.
>
>> + ret = -ENOMEM;
>> + goto reset_rate;
>> + }
>> +
>> + q16_rate = (u32)fps << 16;
>> + if (is_frame_rate)
>> + inst->frame_rate = q16_rate;
>> + else
>> + inst->operating_rate = q16_rate;
>> +
>> + if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) ||
>> + (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) {
>> + ret = iris_check_core_mbpf(inst);
>> + if (ret)
>> + goto reset_rate;
>> + ret = iris_check_core_mbps(inst);
>> + if (ret)
>> + goto reset_rate;
>> + }
>> +
>> + return 0;
>> +
>> +reset_rate:
>> + if (ret) {
>> + if (is_frame_rate)
>> + inst->frame_rate = default_rate << 16;
>> + else
>> + inst->operating_rate = default_rate << 16;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
>> +{
>> + struct v4l2_fract *timeperframe = NULL;
>> +
>> + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>> + timeperframe = &s_parm->parm.output.timeperframe;
>> + timeperframe->numerator = 1;
>> + timeperframe->denominator = inst->operating_rate >> 16;
>> + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
>> + } else {
>> + timeperframe = &s_parm->parm.capture.timeperframe;
>> + timeperframe->numerator = 1;
>> + timeperframe->denominator = inst->frame_rate >> 16;
>> + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
>> + }
>> +
>> + return 0;
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h
>> index 72c6e25d87113baa6d2219ae478b7d7df1aed7bf..0d566b7fc89b96b8fbc62a35b2ba795ca0bcf460 100644
>> --- a/drivers/media/platform/qcom/iris/iris_venc.h
>> +++ b/drivers/media/platform/qcom/iris/iris_venc.h
>> @@ -16,5 +16,7 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
>> int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
>> int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
>> int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
>> +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
>> +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
>>
>> #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
>> index 2074682a35fd1c4c9f5d29fdaee3392d98bf8923..4c11cdac19f97d08a9e6242eea74649aad0242cf 100644
>> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
>> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
>> @@ -532,6 +532,34 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
>> return -EINVAL;
>> }
>>
>> +static int iris_s_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
>> +{
>> + struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
>> +
>> + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
>> + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
>> + return -EINVAL;
>> +
>> + if (inst->domain == ENCODER)
>> + return iris_venc_s_param(inst, a);
>> + else
>> + return -EINVAL;
>> +}
>> +
>> +static int iris_g_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
>> +{
>> + struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
>> +
>> + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
>> + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
>> + return -EINVAL;
>> +
>> + if (inst->domain == ENCODER)
>> + return iris_venc_g_param(inst, a);
>> + else
>> + return -EINVAL;
>> +}
>> +
>> static int iris_dec_cmd(struct file *filp, void *fh,
>> struct v4l2_decoder_cmd *dec)
>> {
>> @@ -628,6 +656,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
>> .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>> .vidioc_g_selection = iris_g_selection,
>> .vidioc_s_selection = iris_s_selection,
>> + .vidioc_s_parm = iris_s_parm,
>> + .vidioc_g_parm = iris_g_parm,
>> };
>>
>> void iris_init_ops(struct iris_core *core)
>>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 18/24] media: iris: Add support for G/S_PARM for encoder video device
2025-08-18 7:29 ` Dikshita Agarwal
@ 2025-08-18 7:34 ` Vikash Garodia
0 siblings, 0 replies; 69+ messages in thread
From: Vikash Garodia @ 2025-08-18 7:34 UTC (permalink / raw)
To: Dikshita Agarwal, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/18/2025 12:59 PM, Dikshita Agarwal wrote:
>>> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
>>> index 930f5afe9489d01be193f1dbe429d33f5401b468..11666f40a4d1c34e1b6eca0b5e40e0f09eeb2b67 100644
>>> --- a/drivers/media/platform/qcom/iris/iris_venc.c
>>> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
>>> @@ -58,6 +58,9 @@ int iris_venc_inst_init(struct iris_inst *inst)
>>> inst->crop.width = f->fmt.pix_mp.width;
>>> inst->crop.height = f->fmt.pix_mp.height;
>>>
>>> + inst->operating_rate = DEFAULT_FPS << 16;
>>> + inst->frame_rate = DEFAULT_FPS << 16;
>> I understand that firmware expects the rate in Q16 format, but does driver needs
>> to keep it in that format ? I see most of the time in calculations, it is right
>> shifted to bring it back to normal one and then back n forth.
>>
> Currently in driver inst->frame_rate is in Q16 format everywhere, no
> inconsistency.
>
> do you prefer to keep it in non Q16 format and convert to Q16 when setting
> to firmware?
>
Given that it simplifies the handling in driver, by avoiding doing the
adjustment everytime before using that value, yes please.
Regards,
Vikash
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 04/24] media: iris: Fix port streaming handling
2025-08-16 10:40 ` Bryan O'Donoghue
@ 2025-08-18 9:45 ` Dikshita Agarwal
2025-08-19 13:34 ` Bryan O'Donoghue
0 siblings, 1 reply; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 9:45 UTC (permalink / raw)
To: Bryan O'Donoghue, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/16/2025 4:10 PM, Bryan O'Donoghue wrote:
> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>> + if (!ret)
>
> I think you should have a consistent error pattern
>
> if (ret)
> goto error;
>
Its done to avoid duplication of code, otherwise it would look like
if (inst->state == IRIS_INST_STREAMING)
ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB);
if (ret)
goto error;
ret = iris_queue_deferred_buffers(inst, buf_type);
if (ret)
goto error;
and more duplication when encoder is added.
Thanks,
Dikshita
> Once amended
>
> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>
> ---
> bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code
2025-08-13 15:27 ` [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Neil Armstrong
@ 2025-08-18 11:47 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-18 11:47 UTC (permalink / raw)
To: Neil Armstrong, Vikash Garodia, Abhinav Kumar,
Bryan O'Donoghue, Mauro Carvalho Chehab, Hans Verkuil,
Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/13/2025 8:57 PM, Neil Armstrong wrote:
> On 13/08/2025 11:37, Dikshita Agarwal wrote:
>> Hi All,
>>
>> This patch series adds support for H.264 and H.265 encoder in iris
>> driver and includes a few fixes and cleanup in the common code that were
>> identified during encoder bring-up process.
>>
>> The changes include:
>> - Enabling support for H.264 and H.265 encoding.
>> - Fixes and improvements in shared componenets used by both encoder and
>> decoder paths.
>> - Ensuring compatibility and stability with the existing decoder flow.
>>
>> Changes in v2:
>> - Fixed sparse/coccinnelle issues.
>> - Fixed the kernel doc warning.
>> - Removed unsupported PEAK_BITRATE property from SM8250.
>> - Dropped patch 04/25 to fix quality issue with encoder.
>> - Enhanced command handling for encoder to allow start/stop commands.
>> - Expanded rate control condition checks to include additional rate
>> control types for HFI Gen2.
>> - Updated default value to MAX_QP for all caps related to max QP settings.
>> - Add support for INPUT/OUTPUT_BUF_HOST_MAX_COUNT caps for encoder.
>> - Link to v1:
>> https://lore.kernel.org/r/20250704-iris-video-encoder-v1-0-b6ce24e273cf@quicinc.com
>>
>> All patches have been tested with v4l2-compliance, v4l2-ctl and
>> Gstreamer on SM8250 and SM8550 for encoder, at the same time ensured
>> that the existing decoder functionality remains uneffected.
>>
>> Commands used for V4l2-ctl validation:
>>
>> v4l2-ctl --verbose
>> --set-fmt-video-out=width=1280,height=720,pixelformat=NV12
>> --set-selection-output target=crop,top=0,left=0,width=1280,height=720
>> --set-fmt-video=pixelformat=H264 --stream-mmap --stream-out-mmap
>> --stream-from=/media/cyclists_1280x720_92frames.yuv
>> --stream-to=/tmp/cyclists_1280x720_92frames.h264 -d /dev/video1
>>
>> v4l2-ctl --verbose
>> --set-fmt-video-out=width=1280,height=720,pixelformat=NV12
>> --set-selection-output target=crop,top=0,left=0,width=1280,height=720
>> --set-fmt-video=pixelformat=HEVC --stream-mmap --stream-out-mmap
>> --stream-from=/media/cyclists_1280x720_92frames.yuv
>> --stream-to=/tmp/cyclists_1280x720_92frames.hevc -d /dev/video1
>>
>> Commands used for GST validation:
>>
>> gst-launch-1.0 -v filesrc location=/media/cyclists_1280x720_92frames.yuv !
>> rawvideoparse format=nv12 width=1280 height=720 framerate=30/1 ! v4l2h264enc
>> capture-io-mode=4 output-io-mode=4 ! filesink sync=true
>> location=/tmp/gst_cyclists_1280x720_92frames.h264
>>
>> gst-launch-1.0 -v filesrc location=/media/cyclists_1280x720_92frames.yuv !
>> rawvideoparse format=nv12 width=1280 height=720 framerate=30/1 ! v4l2h265enc
>> capture-io-mode=4 output-io-mode=4 ! filesink sync=true
>> location=/tmp/gst_cyclists_1280x720_92frames.hevc
>>
>> The result of v4l2-compliance on SM8550:
>> v4l2-compliance 1.29.0-5270, 64 bits, 64-bit time_t
>> v4l2-compliance SHA: dc947661089e 2024-11-11 10:25:38
>>
>> Compliance test for iris_driver device /dev/video1:
>>
>> Driver Info:
>> Driver name : iris_driver
>> Card type : Iris Encoder
>> Bus info : platform:aa00000.video-codec
>> Driver version : 6.16.0
>> Capabilities : 0x84204000
>> Video Memory-to-Memory Multiplanar
>> Streaming
>> Extended Pix Format
>> Device Capabilities
>> Device Caps : 0x04204000
>> Video Memory-to-Memory Multiplanar
>> Streaming
>> Extended Pix Format
>> Detected Stateful Encoder
>>
>> Required ioctls:
>> test VIDIOC_QUERYCAP: OK
>> test invalid ioctls: OK
>>
>> Allow for multiple opens:
>> test second /dev/video1 open: OK
>> test VIDIOC_QUERYCAP: OK
>> test VIDIOC_G/S_PRIORITY: OK
>> test for unlimited opens: OK
>>
>> Debug ioctls:
>> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>> test VIDIOC_LOG_STATUS: OK (Not Supported)
>>
>> Input ioctls:
>> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>> test VIDIOC_ENUMAUDIO: OK (Not Supported)
>> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>> test VIDIOC_G/S_AUDIO: OK (Not Supported)
>> Inputs: 0 Audio Inputs: 0 Tuners: 0
>>
>> Output ioctls:
>> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>> Outputs: 0 Audio Outputs: 0 Modulators: 0
>>
>> Input/Output configuration ioctls:
>> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>> test VIDIOC_G/S_EDID: OK (Not Supported)
>>
>> Control ioctls:
>> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>> test VIDIOC_QUERYCTRL: OK
>> test VIDIOC_G/S_CTRL: OK
>> test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>> Standard Controls: 37 Private Controls: 0
>>
>> Format ioctls:
>> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>> test VIDIOC_G/S_PARM: OK
>> test VIDIOC_G_FBUF: OK (Not Supported)
>> test VIDIOC_G_FMT: OK
>> test VIDIOC_TRY_FMT: OK
>> test VIDIOC_S_FMT: OK
>> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>> test Cropping: OK
>> test Composing: OK (Not Supported)
>> test Scaling: OK (Not Supported)
>>
>> Codec ioctls:
>> test VIDIOC_(TRY_)ENCODER_CMD: OK
>> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>>
>> Buffer ioctls:
>> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>> test CREATE_BUFS maximum buffers: OK
>> test VIDIOC_REMOVE_BUFS: OK
>> test VIDIOC_EXPBUF: OK
>> test Requests: OK (Not Supported)
>> test blocking wait: OK
>>
>> Test input 0:
>>
>> Streaming ioctls:
>> test read/write: OK (Not Supported)
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (select, REQBUFS): OK
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (epoll, REQBUFS): OK
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (select, CREATE_BUFS): OK
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (epoll, CREATE_BUFS): OK
>> test USERPTR (select): OK (Not Supported)
>> test DMABUF: Cannot test, specify --expbuf-device
>>
>> Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0,
>> Warnings: 0
>>
>> The result of v4l2-compliance on SM8250:
>> v4l2-compliance 1.29.0-5270, 64 bits, 64-bit time_t
>> v4l2-compliance SHA: dc947661089e 2024-11-11 10:25:38
>>
>> Compliance test for iris_driver device /dev/video1:
>>
>> Driver Info:
>> Driver name : iris_driver
>> Card type : Iris Encoder
>> Bus info : platform:aa00000.video-codec
>> Driver version : 6.16.0
>> Capabilities : 0x84204000
>> Video Memory-to-Memory Multiplanar
>> Streaming
>> Extended Pix Format
>> Device Capabilities
>> Device Caps : 0x04204000
>> Video Memory-to-Memory Multiplanar
>> Streaming
>> Extended Pix Format
>> Detected Stateful Encoder
>>
>> Required ioctls:
>> test VIDIOC_QUERYCAP: OK
>> test invalid ioctls: OK
>>
>> Allow for multiple opens:
>> test second /dev/video1 open: OK
>> test VIDIOC_QUERYCAP: OK
>> test VIDIOC_G/S_PRIORITY: OK
>> test for unlimited opens: OK
>>
>> Debug ioctls:
>> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>> test VIDIOC_LOG_STATUS: OK (Not Supported)
>>
>> Input ioctls:
>> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>> test VIDIOC_ENUMAUDIO: OK (Not Supported)
>> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>> test VIDIOC_G/S_AUDIO: OK (Not Supported)
>> Inputs: 0 Audio Inputs: 0 Tuners: 0
>>
>> Output ioctls:
>> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>> Outputs: 0 Audio Outputs: 0 Modulators: 0
>>
>> Input/Output configuration ioctls:
>> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>> test VIDIOC_G/S_EDID: OK (Not Supported)
>>
>> Control ioctls:
>> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>> test VIDIOC_QUERYCTRL: OK
>> test VIDIOC_G/S_CTRL: OK
>> test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>> Standard Controls: 19 Private Controls: 0
>>
>> Format ioctls:
>> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>> test VIDIOC_G/S_PARM: OK
>> test VIDIOC_G_FBUF: OK (Not Supported)
>> test VIDIOC_G_FMT: OK
>> test VIDIOC_TRY_FMT: OK
>> test VIDIOC_S_FMT: OK
>> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>> test Cropping: OK
>> test Composing: OK (Not Supported)
>> test Scaling: OK (Not Supported)
>>
>> Codec ioctls:
>> test VIDIOC_(TRY_)ENCODER_CMD: OK
>> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>>
>> Buffer ioctls:
>> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>> test CREATE_BUFS maximum buffers: OK
>> test VIDIOC_REMOVE_BUFS: OK
>> test VIDIOC_EXPBUF: OK
>> test Requests: OK (Not Supported)
>> test blocking wait: OK
>>
>> Test input 0:
>>
>> Streaming ioctls:
>> test read/write: OK (Not Supported)
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (select, REQBUFS): OK
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (epoll, REQBUFS): OK
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (select, CREATE_BUFS): OK
>> Video Capture Multiplanar: Captured 61 buffers
>> test MMAP (epoll, CREATE_BUFS): OK
>> test USERPTR (select): OK (Not Supported)
>> test DMABUF: Cannot test, specify --expbuf-device
>>
>> Total for iris_driver device /dev/video1: 54, Succeeded: 54, Failed: 0,
>> Warnings: 0
>>
>> Looking forward to your review and feedback.
>>
>> Thanks,
>> Dikshita
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> Dikshita Agarwal (24):
>> media: iris: Fix buffer count reporting in internal buffer check
>> media: iris: Report unreleased PERSIST buffers on session close
>> media: iris: Fix memory leak by freeing untracked persist buffer
>> media: iris: Fix port streaming handling
>> media: iris: Allow substate transition to load resources during
>> output streaming
>> media: iris: Always destroy internal buffers on firmware release
>> response
>> media: iris: Update vbuf flags before v4l2_m2m_buf_done
>> media: iris: Allow stop on firmware only if start was issued.
>> media: iris: Send dummy buffer address for all codecs during drain
>> media: iris: Fix missing LAST flag handling during drain
>> media: iris: Add support for video encoder device
>> media: iris: Initialize and deinitialize encoder instance structure
>> media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder
>> media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for
>> encoder
>> media: iris: Add support for VIDIOC_QUERYCAP for encoder video device
>> media: iris: Add encoder support for V4L2 event subscription
>> media: iris: Add support for G/S_SELECTION for encoder video device
>> media: iris: Add support for G/S_PARM for encoder video device
>> media: iris: Add platform-specific capabilities for encoder video
>> device
>> media: iris: Add V4L2 streaming support for encoder video device
>> media: iris: Set platform capabilities to firmware for encoder
>> video device
>> media: iris: Allocate and queue internal buffers for encoder video
>> device
>> media: iris: Add support for buffer management ioctls for encoder
>> device
>> media: iris: Add support for drain sequence in encoder video device
>>
>> drivers/media/platform/qcom/iris/Makefile | 5 +-
>> drivers/media/platform/qcom/iris/iris_buffer.c | 220 ++++--
>> drivers/media/platform/qcom/iris/iris_buffer.h | 7 +-
>> drivers/media/platform/qcom/iris/iris_common.c | 232 ++++++
>> drivers/media/platform/qcom/iris/iris_common.h | 18 +
>> drivers/media/platform/qcom/iris/iris_core.h | 20 +-
>> drivers/media/platform/qcom/iris/iris_ctrls.c | 675 +++++++++++++++-
>> drivers/media/platform/qcom/iris/iris_ctrls.h | 15 +
>> drivers/media/platform/qcom/iris/iris_hfi_common.h | 2 +-
>> .../platform/qcom/iris/iris_hfi_gen1_command.c | 485 +++++++++---
>> .../platform/qcom/iris/iris_hfi_gen1_defines.h | 112 ++-
>> .../platform/qcom/iris/iris_hfi_gen1_response.c | 60 +-
>> .../platform/qcom/iris/iris_hfi_gen2_command.c | 357 ++++++---
>> .../platform/qcom/iris/iris_hfi_gen2_defines.h | 44 +-
>> .../platform/qcom/iris/iris_hfi_gen2_response.c | 46 +-
>> drivers/media/platform/qcom/iris/iris_instance.h | 24 +
>> .../platform/qcom/iris/iris_platform_common.h | 74 +-
>> .../media/platform/qcom/iris/iris_platform_gen2.c | 522 ++++++++++++-
>> .../platform/qcom/iris/iris_platform_qcs8300.h | 352 ++++++++-
>> .../platform/qcom/iris/iris_platform_sm8250.c | 234 +++++-
>> drivers/media/platform/qcom/iris/iris_probe.c | 39 +-
>> drivers/media/platform/qcom/iris/iris_state.c | 9 +-
>> drivers/media/platform/qcom/iris/iris_state.h | 1 +
>> drivers/media/platform/qcom/iris/iris_utils.c | 36 +
>> drivers/media/platform/qcom/iris/iris_utils.h | 2 +
>> drivers/media/platform/qcom/iris/iris_vb2.c | 58 +-
>> drivers/media/platform/qcom/iris/iris_vdec.c | 249 +-----
>> drivers/media/platform/qcom/iris/iris_vdec.h | 13 +-
>> drivers/media/platform/qcom/iris/iris_venc.c | 579 ++++++++++++++
>> drivers/media/platform/qcom/iris/iris_venc.h | 27 +
>> drivers/media/platform/qcom/iris/iris_vidc.c | 299 +++++++-
>> drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 847
>> ++++++++++++++++++++-
>> drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 20 +
>> 33 files changed, 4970 insertions(+), 713 deletions(-)
>> ---
>> base-commit: c26e8dcd9d4e86d788c5bf7a5dd0ea70a95ab067
>> change-id: 20250704-iris-video-encoder-b193350b487a
>>
>> Best regards,
>
> I have a successfull encoding on SM8650-HDK with the following commands
> (ffmpegs segfaults en encoding):
>
> wget
> https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_30MB.mp4 -O Big_Buck_Bunny_1080_10s_30MB_h264.mp4
> ffmpeg -c:v h264_v4l2m2m -i Big_Buck_Bunny_1080_10s_30MB_h264.mp4 -pix_fmt
> nv12 Big_Buck_Bunny_1080_10s.yuv
> v4l2-ctl --verbose
> --set-fmt-video-out=width=1920,height=1080,pixelformat=NV12
> --set-selection-output target=crop,top=0,left=0,width=1920,height=1080
> --set-fmt-video=pixelformat=H264 --stream-mmap --stream-out-mmap
> --stream-from=Big_Buck_Bunny_1080_10s.yuv
> --stream-to=Big_Buck_Bunny_1080_10s.h264 -d /dev/video1
> v4l2-ctl --verbose
> --set-fmt-video-out=width=1920,height=1080,pixelformat=NV12
> --set-selection-output target=crop,top=0,left=0,width=1920,height=1080
> --set-fmt-video=pixelformat=HEVC --stream-mmap --stream-out-mmap
> --stream-from=Big_Buck_Bunny_1080_10s.yuv
> --stream-to=Big_Buck_Bunny_1080_10s.hevc -d /dev/video1
>
> But the video is 1280x720, if I drop the `--set-selection-output
Seems like a bug, checking and will fix in next revision
> target=crop,top=0,left=0,width=1920,height=1080` I correctly get 1920x1080
> but the color keeps moving like if the colors stride is wrong.
For input resolutions that are not 16x16 aligned, require the client to set
the crop rectangle using the s_selection API as per v4l2 specification.
Pls see
https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-encoder.html
4.5.2.5.6
Thanks,
Dikshita
>
> Neil
>
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued.
2025-08-16 11:07 ` Bryan O'Donoghue
@ 2025-08-19 7:29 ` Dikshita Agarwal
0 siblings, 0 replies; 69+ messages in thread
From: Dikshita Agarwal @ 2025-08-19 7:29 UTC (permalink / raw)
To: Bryan O'Donoghue, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 8/16/2025 4:37 PM, Bryan O'Donoghue wrote:
> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>> For HFI Gen1, the instances substate is changed to LOAD_RESOURCES only
>> when a START command is issues to the firmware. If STOP is called
>> without a prior START, the firmware may reject the command and throw
>> some erros.
>> Handle this by adding a substate check before issuing STOP command to
>> the firmware.
>>
>> Fixes: 11712ce70f8e ("media: iris: implement vb2 streaming ops")
>> Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
>> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>> drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 7 ++++---
>> 1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> index
>> 5fc30d54af4dc34616cfd08813940aa0b7044a20..5f1748ab80f88393215fc2d82c5c6b4af1266090 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> @@ -184,11 +184,12 @@ static int iris_hfi_gen1_session_stop(struct
>> iris_inst *inst, u32 plane)
>> u32 flush_type = 0;
>> int ret = 0;
>> - if ((V4L2_TYPE_IS_OUTPUT(plane) &&
>> - inst->state == IRIS_INST_INPUT_STREAMING) ||
>> + if (((V4L2_TYPE_IS_OUTPUT(plane) &&
>> + inst->state == IRIS_INST_INPUT_STREAMING) ||
>
> this is becoming a highly complex clause
>
> if (((V4L2_TYPE_IS_OUTPUT(plane) &&
> inst->state == IRIS_INST_INPUT_STREAMING) ||
> (V4L2_TYPE_IS_CAPTURE(plane) &&
> inst->state == IRIS_INST_OUTPUT_STREAMING) ||
> inst->state == IRIS_INST_ERROR) &&
> inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
>
> can we not reduce down the number of conjunctions and dis-junctions here ?
>
> Its getting hard to follow.
>
> For example pivot on if (inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES)
>
> or make it into a switch for inst->state... no that wouldn't work
>
> Either way the complexity of this clause is indicating to me we need to do
> some decomposition.
>
> Please consider if you can rationalise the logic here and make the code
> more readable.
Sure, I will see if some of these conditions can be absorbed in caller or
if handled by vb2 framework itself.
Thanks,
Dikshita
>> (V4L2_TYPE_IS_CAPTURE(plane) &&
>> inst->state == IRIS_INST_OUTPUT_STREAMING) ||
>> - inst->state == IRIS_INST_ERROR) {
>> + inst->state == IRIS_INST_ERROR) &&
>> + inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) {
>> reinit_completion(&inst->completion);
>> iris_hfi_gen1_packet_session_cmd(inst, &pkt,
>> HFI_CMD_SESSION_STOP);
>> ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
>>
>
> ---
> bod
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 04/24] media: iris: Fix port streaming handling
2025-08-18 9:45 ` Dikshita Agarwal
@ 2025-08-19 13:34 ` Bryan O'Donoghue
0 siblings, 0 replies; 69+ messages in thread
From: Bryan O'Donoghue @ 2025-08-19 13:34 UTC (permalink / raw)
To: Dikshita Agarwal, Vikash Garodia, Abhinav Kumar,
Mauro Carvalho Chehab, Hans Verkuil, Stefan Schmidt, Vedang Nagar
Cc: linux-media, linux-arm-msm, linux-kernel, Renjiang Han,
Wangao Wang
On 18/08/2025 10:45, Dikshita Agarwal wrote:
>
>
> On 8/16/2025 4:10 PM, Bryan O'Donoghue wrote:
>> On 13/08/2025 10:37, Dikshita Agarwal wrote:
>>> + if (!ret)
>>
>> I think you should have a consistent error pattern
>>
>> if (ret)
>> goto error;
>>
> Its done to avoid duplication of code, otherwise it would look like
>
> if (inst->state == IRIS_INST_STREAMING)
> ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB);
> if (ret)
> goto error;
>
> ret = iris_queue_deferred_buffers(inst, buf_type);
> if (ret)
> goto error;
>
> and more duplication when encoder is added.
Understood, IMO the pattern above is clearer and easier to read.
Up to you if you want to change it though.
---
bod
^ permalink raw reply [flat|nested] 69+ messages in thread
end of thread, other threads:[~2025-08-19 13:34 UTC | newest]
Thread overview: 69+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-13 9:37 [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 01/24] media: iris: Fix buffer count reporting in internal buffer check Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 02/24] media: iris: Report unreleased PERSIST buffers on session close Dikshita Agarwal
2025-08-13 10:53 ` Jorge Ramirez
2025-08-13 12:16 ` Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 03/24] media: iris: Fix memory leak by freeing untracked persist buffer Dikshita Agarwal
2025-08-16 10:15 ` Bryan O'Donoghue
2025-08-18 3:10 ` Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 04/24] media: iris: Fix port streaming handling Dikshita Agarwal
2025-08-16 10:40 ` Bryan O'Donoghue
2025-08-18 9:45 ` Dikshita Agarwal
2025-08-19 13:34 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 05/24] media: iris: Allow substate transition to load resources during output streaming Dikshita Agarwal
2025-08-13 21:51 ` Bryan O'Donoghue
2025-08-13 21:55 ` Bryan O'Donoghue
2025-08-13 22:55 ` Konrad Dybcio
2025-08-14 6:13 ` Krzysztof Kozlowski
2025-08-14 7:50 ` Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 06/24] media: iris: Always destroy internal buffers on firmware release response Dikshita Agarwal
2025-08-16 10:44 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 07/24] media: iris: Update vbuf flags before v4l2_m2m_buf_done Dikshita Agarwal
2025-08-16 10:49 ` Bryan O'Donoghue
2025-08-13 9:37 ` [PATCH v2 08/24] media: iris: Allow stop on firmware only if start was issued Dikshita Agarwal
2025-08-16 11:07 ` Bryan O'Donoghue
2025-08-19 7:29 ` Dikshita Agarwal
2025-08-13 9:37 ` [PATCH v2 09/24] media: iris: Send dummy buffer address for all codecs during drain Dikshita Agarwal
2025-08-16 11:11 ` Bryan O'Donoghue
2025-08-13 9:38 ` [PATCH v2 10/24] media: iris: Fix missing LAST flag handling " Dikshita Agarwal
2025-08-16 11:17 ` Bryan O'Donoghue
2025-08-13 9:38 ` [PATCH v2 11/24] media: iris: Add support for video encoder device Dikshita Agarwal
2025-08-14 14:11 ` Vikash Garodia
2025-08-16 11:21 ` Bryan O'Donoghue
2025-08-18 3:28 ` Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 12/24] media: iris: Initialize and deinitialize encoder instance structure Dikshita Agarwal
2025-08-14 14:25 ` Vikash Garodia
2025-08-18 3:21 ` Dikshita Agarwal
2025-08-18 6:08 ` Vikash Garodia
2025-08-16 9:03 ` Bryan O'Donoghue
2025-08-16 11:23 ` Bryan O'Donoghue
2025-08-18 3:27 ` Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 13/24] media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder Dikshita Agarwal
2025-08-14 14:32 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 14/24] media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder Dikshita Agarwal
2025-08-14 14:43 ` Vikash Garodia
2025-08-18 3:21 ` Dikshita Agarwal
2025-08-18 6:10 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 15/24] media: iris: Add support for VIDIOC_QUERYCAP for encoder video device Dikshita Agarwal
2025-08-14 14:46 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 16/24] media: iris: Add encoder support for V4L2 event subscription Dikshita Agarwal
2025-08-14 14:48 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 17/24] media: iris: Add support for G/S_SELECTION for encoder video device Dikshita Agarwal
2025-08-14 14:54 ` Vikash Garodia
2025-08-18 3:25 ` Dikshita Agarwal
2025-08-18 6:11 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 18/24] media: iris: Add support for G/S_PARM " Dikshita Agarwal
2025-08-14 15:01 ` Vikash Garodia
2025-08-18 7:29 ` Dikshita Agarwal
2025-08-18 7:34 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 19/24] media: iris: Add platform-specific capabilities " Dikshita Agarwal
2025-08-14 15:05 ` Vikash Garodia
2025-08-18 7:25 ` Dikshita Agarwal
2025-08-18 7:27 ` Vikash Garodia
2025-08-13 9:38 ` [PATCH v2 20/24] media: iris: Add V4L2 streaming support " Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 21/24] media: iris: Set platform capabilities to firmware " Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 22/24] media: iris: Allocate and queue internal buffers " Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 23/24] media: iris: Add support for buffer management ioctls for encoder device Dikshita Agarwal
2025-08-13 9:38 ` [PATCH v2 24/24] media: iris: Add support for drain sequence in encoder video device Dikshita Agarwal
2025-08-13 15:27 ` [PATCH v2 00/24] Enable H.264/H.265 encoder support and fixes in common code Neil Armstrong
2025-08-18 11:47 ` Dikshita Agarwal
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).