On Fri Nov 14 11:09:01 2025 +0800, Wangao Wang wrote:
> Add rotation control for encoder, enabling V4L2_CID_ROTATE and handling
>  90/180/270 degree rotation.
> 
> Reviewed-by: Dikshita Agarwal <[email protected]>
> Co-developed-by: Neil Armstrong <[email protected]>
> Signed-off-by: Neil Armstrong <[email protected]>
> Tested-by: Neil Armstrong <[email protected]> # on SM8650-HDK
> Signed-off-by: Wangao Wang <[email protected]>
> Signed-off-by: Bryan O'Donoghue <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/platform/qcom/iris/iris_ctrls.c      | 34 +++++++++++++++
 drivers/media/platform/qcom/iris/iris_ctrls.h      |  1 +
 .../platform/qcom/iris/iris_hfi_gen2_command.c     | 41 ++++++++++++-----
 .../platform/qcom/iris/iris_hfi_gen2_defines.h     |  9 ++++
 .../platform/qcom/iris/iris_platform_common.h      |  1 +
 .../media/platform/qcom/iris/iris_platform_gen2.c  | 10 +++++
 drivers/media/platform/qcom/iris/iris_utils.c      |  6 +++
 drivers/media/platform/qcom/iris/iris_utils.h      |  1 +
 drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 51 +++++++++++++---------
 9 files changed, 123 insertions(+), 31 deletions(-)

---

diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c 
b/drivers/media/platform/qcom/iris/iris_ctrls.c
index 87f929442ec6..faa0f75abfea 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
@@ -102,6 +102,8 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 
id)
                return PROFILE_AV1;
        case V4L2_CID_MPEG_VIDEO_AV1_LEVEL:
                return LEVEL_AV1;
+       case V4L2_CID_ROTATE:
+               return ROTATION;
        default:
                return INST_FW_CAP_MAX;
        }
@@ -193,6 +195,8 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type 
cap_id)
                return V4L2_CID_MPEG_VIDEO_AV1_PROFILE;
        case LEVEL_AV1:
                return V4L2_CID_MPEG_VIDEO_AV1_LEVEL;
+       case ROTATION:
+               return V4L2_CID_ROTATE;
        default:
                return 0;
        }
@@ -901,6 +905,36 @@ int iris_set_qp_range(struct iris_inst *inst, enum 
platform_inst_fw_cap_type cap
                                     &range, sizeof(range));
 }
 
+int iris_set_rotation(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;
+       u32 hfi_val;
+
+       switch (inst->fw_caps[cap_id].value) {
+       case 0:
+               hfi_val = HFI_ROTATION_NONE;
+               return 0;
+       case 90:
+               hfi_val = HFI_ROTATION_90;
+               break;
+       case 180:
+               hfi_val = HFI_ROTATION_180;
+               break;
+       case 270:
+               hfi_val = HFI_ROTATION_270;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       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_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 30af333cc494..3ea0a00c7587 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.h
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.h
@@ -32,6 +32,7 @@ int iris_set_min_qp(struct iris_inst *inst, enum 
platform_inst_fw_cap_type cap_i
 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_rotation(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_gen2_command.c 
b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
index 16df96dbb594..715ec9575b90 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -182,22 +182,36 @@ static int iris_hfi_gen2_set_raw_resolution(struct 
iris_inst *inst, u32 plane)
                                                  sizeof(u32));
 }
 
+static inline u32 iris_hfi_get_aligned_resolution(struct iris_inst *inst, u32 
width, u32 height)
+{
+       u32 codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16;
+
+       return (ALIGN(width, codec_align) << 16 | ALIGN(height, codec_align));
+}
+
 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, codec_align;
+       u32 width, height;
+       u32 resolution;
 
        if (inst->domain == DECODER) {
-               resolution = inst->fmt_src->fmt.pix_mp.width << 16 |
-                       inst->fmt_src->fmt.pix_mp.height;
+               width = inst->fmt_src->fmt.pix_mp.width;
+               height = inst->fmt_src->fmt.pix_mp.height;
+               resolution = iris_hfi_get_aligned_resolution(inst, width, 
height);
                inst_hfi_gen2->src_subcr_params.bitstream_resolution = 
resolution;
                payload_type = HFI_PAYLOAD_U32;
        } else {
-               codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16;
-               resolution = ALIGN(inst->enc_scale_width, codec_align) << 16 |
-                       ALIGN(inst->enc_scale_height, codec_align);
+               if (is_rotation_90_or_270(inst)) {
+                       width = inst->enc_scale_height;
+                       height = inst->enc_scale_width;
+               } else {
+                       width = inst->enc_scale_width;
+                       height = inst->enc_scale_height;
+               }
+               resolution = iris_hfi_get_aligned_resolution(inst, width, 
height);
                inst_hfi_gen2->dst_subcr_params.bitstream_resolution = 
resolution;
                payload_type = HFI_PAYLOAD_32_PACKED;
        }
@@ -239,10 +253,17 @@ static int iris_hfi_gen2_set_crop_offsets(struct 
iris_inst *inst, u32 plane)
                        left_offset = inst->crop.left;
                        top_offset = inst->crop.top;
                } else {
-                       bottom_offset = (ALIGN(inst->enc_scale_height, 
codec_align) -
-                                       inst->enc_scale_height);
-                       right_offset = (ALIGN(inst->enc_scale_width, 
codec_align) -
-                                      inst->enc_scale_width);
+                       if (is_rotation_90_or_270(inst)) {
+                               bottom_offset = (ALIGN(inst->enc_scale_width, 
codec_align) -
+                                               inst->enc_scale_width);
+                               right_offset = (ALIGN(inst->enc_scale_height, 
codec_align) -
+                                              inst->enc_scale_height);
+                       } else {
+                               bottom_offset = (ALIGN(inst->enc_scale_height, 
codec_align) -
+                                               inst->enc_scale_height);
+                               right_offset = (ALIGN(inst->enc_scale_width, 
codec_align) -
+                                              inst->enc_scale_width);
+                       }
                        left_offset = 0;
                        top_offset = 0;
                }
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 5f1f1a7eb91f..c3508514014c 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -83,6 +83,15 @@ enum hfi_seq_header_mode {
 };
 
 #define HFI_PROP_SEQ_HEADER_MODE               0x03000149
+
+enum hfi_rotation {
+       HFI_ROTATION_NONE = 0x00000000,
+       HFI_ROTATION_90   = 0x00000001,
+       HFI_ROTATION_180  = 0x00000002,
+       HFI_ROTATION_270  = 0x00000003,
+};
+
+#define HFI_PROP_ROTATION                      0x0300014b
 #define HFI_PROP_SIGNAL_COLOR_INFO             0x03000155
 #define HFI_PROP_PICTURE_TYPE                  0x03000162
 #define HFI_PROP_DEC_DEFAULT_HEADER            0x03000168
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h 
b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 14a2f4dbe38a..e8fe8b9bd21e 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -150,6 +150,7 @@ enum platform_inst_fw_cap_type {
        P_FRAME_QP_HEVC,
        B_FRAME_QP_H264,
        B_FRAME_QP_HEVC,
+       ROTATION,
        INST_FW_CAP_MAX,
 };
 
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c 
b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index 39ab973aebce..3412a77a2c08 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -689,6 +689,16 @@ static const struct platform_inst_fw_cap 
inst_fw_cap_sm8550_enc[] = {
                .flags = CAP_FLAG_OUTPUT_PORT,
                .set = iris_set_u32,
        },
+       {
+               .cap_id = ROTATION,
+               .min = 0,
+               .max = 270,
+               .step_or_mask = 90,
+               .value = 0,
+               .hfi_id = HFI_PROP_ROTATION,
+               .flags = CAP_FLAG_OUTPUT_PORT,
+               .set = iris_set_rotation,
+       },
 };
 
 static struct platform_inst_caps platform_inst_cap_sm8550 = {
diff --git a/drivers/media/platform/qcom/iris/iris_utils.c 
b/drivers/media/platform/qcom/iris/iris_utils.c
index e2f1131de431..cfc5b576ec56 100644
--- a/drivers/media/platform/qcom/iris/iris_utils.c
+++ b/drivers/media/platform/qcom/iris/iris_utils.c
@@ -125,3 +125,9 @@ int iris_check_core_mbps(struct iris_inst *inst)
 
        return 0;
 }
+
+bool is_rotation_90_or_270(struct iris_inst *inst)
+{
+       return inst->fw_caps[ROTATION].value == 90 ||
+               inst->fw_caps[ROTATION].value == 270;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_utils.h 
b/drivers/media/platform/qcom/iris/iris_utils.h
index 75740181122f..b5705d156431 100644
--- a/drivers/media/platform/qcom/iris/iris_utils.h
+++ b/drivers/media/platform/qcom/iris/iris_utils.h
@@ -51,5 +51,6 @@ void iris_helper_buffers_done(struct iris_inst *inst, 
unsigned int type,
 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);
+bool is_rotation_90_or_270(struct iris_inst *inst);
 
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c 
b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index e110b139f003..aced49495bb8 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -822,6 +822,22 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst 
*inst)
                iris_vpu_dec_line_size(inst);
 }
 
+static inline u32 iris_vpu_enc_get_bitstream_width(struct iris_inst *inst)
+{
+       if (is_rotation_90_or_270(inst))
+               return inst->fmt_dst->fmt.pix_mp.height;
+       else
+               return inst->fmt_dst->fmt.pix_mp.width;
+}
+
+static inline u32 iris_vpu_enc_get_bitstream_height(struct iris_inst *inst)
+{
+       if (is_rotation_90_or_270(inst))
+               return inst->fmt_dst->fmt.pix_mp.width;
+       else
+               return inst->fmt_dst->fmt.pix_mp.height;
+}
+
 static inline u32 size_bin_bitstream_enc(u32 width, u32 height,
                                         u32 rc_type)
 {
@@ -904,10 +920,9 @@ static inline u32 hfi_buffer_bin_enc(u32 width, u32 height,
 static u32 iris_vpu_enc_bin_size(struct iris_inst *inst)
 {
        u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+       u32 height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 width = iris_vpu_enc_get_bitstream_width(inst);
        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)
@@ -951,9 +966,8 @@ u32 hfi_buffer_comv_enc(u32 frame_width, u32 frame_height, 
u32 lcu_size,
 
 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 height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 width = iris_vpu_enc_get_bitstream_width(inst);
        u32 num_recon = 1;
        u32 lcu_size = 16;
 
@@ -1233,9 +1247,8 @@ u32 hfi_buffer_non_comv_enc(u32 frame_width, u32 
frame_height,
 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 height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 width = iris_vpu_enc_get_bitstream_width(inst);
        u32 lcu_size = 16;
 
        if (inst->codec == V4L2_PIX_FMT_HEVC) {
@@ -1326,9 +1339,8 @@ u32 hfi_buffer_line_enc_vpu33(u32 frame_width, u32 
frame_height, bool is_ten_bit
 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 height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 width = iris_vpu_enc_get_bitstream_width(inst);
        u32 lcu_size = 16;
 
        if (inst->codec == V4L2_PIX_FMT_HEVC) {
@@ -1344,9 +1356,8 @@ static u32 iris_vpu_enc_line_size(struct iris_inst *inst)
 static u32 iris_vpu33_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 height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 width = iris_vpu_enc_get_bitstream_width(inst);
        u32 lcu_size = 16;
 
        if (inst->codec == V4L2_PIX_FMT_HEVC) {
@@ -1567,9 +1578,8 @@ static inline u32 hfi_buffer_scratch1_enc(u32 
frame_width, u32 frame_height,
 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 frame_height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 frame_width = iris_vpu_enc_get_bitstream_width(inst);
        u32 num_ref = 1;
        u32 lcu_size;
        bool is_h265;
@@ -1665,9 +1675,8 @@ static inline u32 hfi_buffer_scratch2_enc(u32 
frame_width, u32 frame_height,
 
 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 frame_height = iris_vpu_enc_get_bitstream_height(inst);
+       u32 frame_width = iris_vpu_enc_get_bitstream_width(inst);
        u32 num_ref = 1;
 
        return hfi_buffer_scratch2_enc(frame_width, frame_height, num_ref,
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to