[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250902-rfc_split-v1-4-47307a70c061@oss.qualcomm.com>
Date: Tue, 02 Sep 2025 16:00:06 -0700
From: DEEPA GUTHYAPPA MADIVALARA <deepa.madivalara@....qualcomm.com>
To: Mauro Carvalho Chehab <mchehab@...nel.org>,
Vikash Garodia <quic_vgarodia@...cinc.com>,
Dikshita Agarwal <quic_dikshita@...cinc.com>,
Abhinav Kumar <abhinav.kumar@...ux.dev>,
Bryan O'Donoghue <bryan.odonoghue@...aro.org>
Cc: linux-media@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-arm-msm@...r.kernel.org,
Deepa Guthyappa Madivalara <deepa.madivalara@....qualcomm.com>
Subject: [PATCH RFC 4/5] media: iris: Add internal buffer calculation for
AV1 decoder
Implement internal buffer count and size calculations for AV1 decoder.
Signed-off-by: DEEPA GUTHYAPPA MADIVALARA <deepa.madivalara@....qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_buffer.h | 2 +
.../platform/qcom/iris/iris_hfi_gen2_command.c | 109 ++++++++-
.../platform/qcom/iris/iris_hfi_gen2_response.c | 3 +
.../media/platform/qcom/iris/iris_platform_gen2.c | 1 +
drivers/media/platform/qcom/iris/iris_vidc.c | 1 +
drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 255 ++++++++++++++++++++-
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 105 +++++++++
7 files changed, 468 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h
index 325d30fce5c99185b61ff989fbfd4de9a56762b2..75bb767761824c4c02e0df9b765896cc093be333 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_buffer.h
@@ -27,6 +27,7 @@ struct iris_inst;
* @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_PARTIAL: buffer for AV1 IBC data
* @BUF_TYPE_MAX: max buffer types
*/
enum iris_buffer_type {
@@ -42,6 +43,7 @@ enum iris_buffer_type {
BUF_SCRATCH_1,
BUF_SCRATCH_2,
BUF_VPSS,
+ BUF_PARTIAL,
BUF_TYPE_MAX,
};
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 4ce71a14250832440099e4cf3835b4aedfb749e8..e3a8b031b3f191a6d18e1084db34804a8172439c 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -10,6 +10,7 @@
#define UNSPECIFIED_COLOR_FORMAT 5
#define NUM_SYS_INIT_PACKETS 8
+#define NUM_COMV_AV1 18
#define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \
NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32)))
@@ -121,6 +122,7 @@ static u32 iris_hfi_gen2_get_port_from_buf_type(struct iris_inst *inst,
case BUF_COMV:
case BUF_NON_COMV:
case BUF_LINE:
+ case BUF_PARTIAL:
return HFI_PORT_BITSTREAM;
case BUF_OUTPUT:
case BUF_DPB:
@@ -380,6 +382,9 @@ static int iris_hfi_gen2_set_profile(struct iris_inst *inst, u32 plane)
case V4L2_PIX_FMT_H264:
profile = inst->fw_caps[PROFILE_H264].value;
break;
+ case V4L2_PIX_FMT_AV1:
+ profile = inst->fw_caps[PROFILE_AV1].value;
+ break;
}
inst_hfi_gen2->src_subcr_params.profile = profile;
@@ -409,6 +414,9 @@ static int iris_hfi_gen2_set_level(struct iris_inst *inst, u32 plane)
case V4L2_PIX_FMT_H264:
level = inst->fw_caps[LEVEL_H264].value;
break;
+ case V4L2_PIX_FMT_AV1:
+ level = inst->fw_caps[LEVEL_AV1].value;
+ break;
}
inst_hfi_gen2->src_subcr_params.level = level;
@@ -484,7 +492,8 @@ static int iris_hfi_gen2_set_tier(struct iris_inst *inst, u32 plane)
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;
+ tier = (inst->codec == V4L2_PIX_FMT_AV1) ? inst->fw_caps[TIER_AV1].value :
+ inst->fw_caps[TIER].value;
return iris_hfi_gen2_session_set_property(inst,
HFI_PROP_TIER,
@@ -509,6 +518,56 @@ static int iris_hfi_gen2_set_frame_rate(struct iris_inst *inst, u32 plane)
sizeof(u32));
}
+static int iris_hfi_gen2_set_film_grain(struct iris_inst *inst, u32 plane)
+{
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+ u32 film_grain;
+
+ film_grain = inst->fw_caps[FILM_GRAIN].value;
+ inst_hfi_gen2->src_subcr_params.film_grain = film_grain;
+
+ return iris_hfi_gen2_session_set_property(inst,
+ HFI_PROP_AV1_FILM_GRAIN_PRESENT,
+ HFI_HOST_FLAGS_NONE,
+ port,
+ HFI_PAYLOAD_U32_ENUM,
+ &film_grain,
+ sizeof(u32));
+}
+
+static int iris_hfi_gen2_set_super_block(struct iris_inst *inst, u32 plane)
+{
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+ u32 super_block;
+
+ super_block = inst->fw_caps[SUPER_BLOCK].value;
+ inst_hfi_gen2->src_subcr_params.super_block = super_block;
+
+ return iris_hfi_gen2_session_set_property(inst,
+ HFI_PROP_AV1_SUPER_BLOCK_ENABLED,
+ HFI_HOST_FLAGS_NONE,
+ port,
+ HFI_PAYLOAD_U32_ENUM,
+ &super_block,
+ sizeof(u32));
+}
+
+static int iris_hfi_gen2_set_opb_enable(struct iris_inst *inst, u32 plane)
+{
+ u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ u32 opb_enable = iris_split_mode_enabled(inst);
+
+ return iris_hfi_gen2_session_set_property(inst,
+ HFI_PROP_OPB_ENABLE,
+ HFI_HOST_FLAGS_NONE,
+ port,
+ HFI_PAYLOAD_U32,
+ &opb_enable,
+ sizeof(u32));
+}
+
static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane)
{
const struct iris_platform_data *pdata = inst->core->iris_platform_data;
@@ -531,6 +590,9 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p
{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 },
+ {HFI_PROP_AV1_FILM_GRAIN_PRESENT, iris_hfi_gen2_set_film_grain },
+ {HFI_PROP_AV1_SUPER_BLOCK_ENABLED, iris_hfi_gen2_set_super_block },
+ {HFI_PROP_OPB_ENABLE, iris_hfi_gen2_set_opb_enable },
};
if (inst->domain == DECODER) {
@@ -544,12 +606,20 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p
} 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 if (inst->codec == V4L2_PIX_FMT_AV1) {
+ config_params = pdata->dec_input_config_params_av1;
+ config_params_size = pdata->dec_input_config_params_av1_size;
} else {
return -EINVAL;
}
} else {
- config_params = pdata->dec_output_config_params;
- config_params_size = pdata->dec_output_config_params_size;
+ if (inst->codec == V4L2_PIX_FMT_AV1) {
+ config_params = pdata->dec_output_config_params_av1;
+ config_params_size = pdata->dec_output_config_params_av1_size;
+ } else {
+ config_params = pdata->dec_output_config_params;
+ config_params_size = pdata->dec_output_config_params_size;
+ }
}
} else {
if (V4L2_TYPE_IS_OUTPUT(plane)) {
@@ -598,6 +668,9 @@ static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
break;
case V4L2_PIX_FMT_VP9:
codec = HFI_CODEC_DECODE_VP9;
+ break;
+ case V4L2_PIX_FMT_AV1:
+ codec = HFI_CODEC_DECODE_AV1;
}
iris_hfi_gen2_packet_session_property(inst,
@@ -763,6 +836,11 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan
change_param_size =
core->iris_platform_data->dec_input_config_params_vp9_size;
break;
+ case V4L2_PIX_FMT_AV1:
+ change_param = core->iris_platform_data->dec_input_config_params_av1;
+ change_param_size =
+ core->iris_platform_data->dec_input_config_params_av1_size;
+ break;
}
payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;
@@ -845,6 +923,16 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan
payload_size = sizeof(u32);
payload_type = HFI_PAYLOAD_U32;
break;
+ case HFI_PROP_AV1_FILM_GRAIN_PRESENT:
+ payload[0] = subsc_params.film_grain;
+ payload_size = sizeof(u32);
+ payload_type = HFI_PAYLOAD_U32;
+ break;
+ case HFI_PROP_AV1_SUPER_BLOCK_ENABLED:
+ payload[0] = subsc_params.super_block;
+ payload_size = sizeof(u32);
+ payload_type = HFI_PAYLOAD_U32;
+ break;
default:
prop_type = 0;
ret = -EINVAL;
@@ -900,6 +988,11 @@ static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane)
subscribe_prop_size =
core->iris_platform_data->dec_output_prop_vp9_size;
break;
+ case V4L2_PIX_FMT_AV1:
+ subcribe_prop = core->iris_platform_data->dec_output_prop_av1;
+ subscribe_prop_size =
+ core->iris_platform_data->dec_output_prop_av1_size;
+ break;
}
}
@@ -1075,6 +1168,8 @@ static u32 iris_hfi_gen2_buf_type_from_driver(u32 domain, enum iris_buffer_type
return HFI_BUFFER_ARP;
case BUF_VPSS:
return HFI_BUFFER_VPSS;
+ case BUF_PARTIAL:
+ return HFI_BUFFER_PARTIAL_DATA;
default:
return 0;
}
@@ -1087,7 +1182,13 @@ static int iris_set_num_comv(struct iris_inst *inst)
u32 num_comv;
caps = core->iris_platform_data->inst_caps;
- num_comv = caps->num_comv;
+
+ /*
+ * If Host allocates less comv count for AV1 then
+ * FW can raise SESSION_ERROR
+ */
+ num_comv = (inst->codec == V4L2_PIX_FMT_AV1) ?
+ NUM_COMV_AV1 : caps->num_comv;
return core->hfi_ops->session_set_property(inst,
HFI_PROP_COMV_BUFFER_COUNT,
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 2f1f118eae4f6462ab1aa1d16844b34e6e699f1e..943d3884248fafccc3b8e944e455c96124914353 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -54,6 +54,8 @@ static u32 iris_hfi_gen2_buf_type_to_driver(struct iris_inst *inst,
return BUF_SCRATCH_2;
case HFI_BUFFER_PERSIST:
return BUF_PERSIST;
+ case HFI_BUFFER_PARTIAL_DATA:
+ return BUF_PARTIAL;
default:
return 0;
}
@@ -72,6 +74,7 @@ static bool iris_hfi_gen2_is_valid_hfi_buffer_type(u32 buffer_type)
case HFI_BUFFER_DPB:
case HFI_BUFFER_PERSIST:
case HFI_BUFFER_VPSS:
+ case HFI_BUFFER_PARTIAL_DATA:
return true;
default:
return false;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index fecf2e06f19723f30777c04bc4b155954c2b746d..c0a03c03bb9349a0e551ce6dc72b6f8b23ff696d 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -739,6 +739,7 @@ static const u32 sm8550_dec_ip_int_buf_tbl[] = {
BUF_COMV,
BUF_NON_COMV,
BUF_LINE,
+ BUF_PARTIAL,
};
static const u32 sm8550_dec_op_int_buf_tbl[] = {
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 798c3613e57eac1742633d61c1482229dbc32562..43a77687a668423a5547c7f159622249634264e0 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -178,6 +178,7 @@ int iris_open(struct file *filp)
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_LIST_HEAD(&inst->buffers[BUF_PARTIAL].list);
init_completion(&inst->completion);
init_completion(&inst->flush_completion);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index 7337d8d33715810669399d9f86b864d0eb002897..cfdd28f005986d5b14b18a97215933b171355f7a 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -9,6 +9,14 @@
#include "iris_hfi_gen2_defines.h"
#define HFI_MAX_COL_FRAME 6
+#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT (8)
+#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH (32)
+#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_HEIGHT (8)
+#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_WIDTH (16)
+#define HFI_COLOR_FORMAT_YUV420_TP10_UBWC_Y_TILE_HEIGHT (4)
+#define HFI_COLOR_FORMAT_YUV420_TP10_UBWC_Y_TILE_WIDTH (48)
+#define HFI_COLOR_FORMAT_YUV420_TP10_UBWC_UV_TILE_HEIGHT (4)
+#define HFI_COLOR_FORMAT_YUV420_TP10_UBWC_UV_TILE_WIDTH (24)
#ifndef SYSTEM_LAL_TILE10
#define SYSTEM_LAL_TILE10 192
@@ -39,6 +47,31 @@ static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_p
return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes);
}
+static u32 size_av1d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 size_yuv, size_bin_hdr, size_bin_res;
+
+ size_yuv = ((frame_width * frame_height) <= BIN_BUFFER_THRESHOLD) ?
+ ((BIN_BUFFER_THRESHOLD * 3) >> 1) :
+ ((frame_width * frame_height * 3) >> 1);
+ size_bin_hdr = size_yuv * AV1_CABAC_HDR_RATIO_HD_TOT;
+ size_bin_res = size_yuv * AV1_CABAC_RES_RATIO_HD_TOT;
+ size_bin_hdr = ALIGN(size_bin_hdr / num_vpp_pipes,
+ DMA_ALIGNMENT) * num_vpp_pipes;
+ size_bin_res = ALIGN(size_bin_res / num_vpp_pipes,
+ DMA_ALIGNMENT) * num_vpp_pipes;
+
+ return size_bin_hdr + size_bin_res;
+}
+
+static u32 hfi_buffer_bin_av1d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 n_aligned_h = ALIGN(frame_height, 16);
+ u32 n_aligned_w = ALIGN(frame_width, 16);
+
+ return size_av1d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes);
+}
+
static u32 size_h265d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
{
u32 product = frame_width * frame_height;
@@ -110,6 +143,20 @@ static u32 hfi_buffer_comv_h265d(u32 frame_width, u32 frame_height, u32 _comv_bu
return (_size * (_comv_bufcount)) + 512;
}
+static u32 hfi_buffer_comv_av1d(u32 frame_width, u32 frame_height, u32 comv_bufcount)
+{
+ u32 size;
+
+ size = 2 * ALIGN(MAX(((frame_width + 63) / 64) *
+ ((frame_height + 63) / 64) * 512,
+ ((frame_width + 127) / 128) *
+ ((frame_height + 127) / 128) * 2816),
+ DMA_ALIGNMENT);
+ size *= comv_bufcount;
+
+ return size;
+}
+
static u32 size_h264d_bse_cmd_buf(u32 frame_height)
{
u32 height = ALIGN(frame_height, 32);
@@ -174,6 +221,20 @@ static u32 hfi_buffer_persist_h264d(void)
DMA_ALIGNMENT);
}
+static u32 hfi_buffer_persist_av1d(u32 max_width, u32 max_height, u32 total_ref_count)
+{
+ u32 comv_size, size;
+
+ comv_size = hfi_buffer_comv_av1d(max_width, max_height, total_ref_count);
+ size = ALIGN((SIZE_AV1D_SEQUENCE_HEADER * 2 + SIZE_AV1D_METADATA +
+ AV1D_NUM_HW_PIC_BUF * (SIZE_AV1D_TILE_OFFSET + SIZE_AV1D_QM) +
+ AV1D_NUM_FRAME_HEADERS * (SIZE_AV1D_FRAME_HEADER +
+ 2 * SIZE_AV1D_PROB_TABLE) + comv_size + HDR10_HIST_EXTRADATA_SIZE +
+ SIZE_AV1D_METADATA * AV1D_NUM_HW_PIC_BUF), DMA_ALIGNMENT);
+
+ return ALIGN(size, DMA_ALIGNMENT);
+}
+
static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
{
u32 size_bse = size_h264d_bse_cmd_buf(frame_height);
@@ -459,6 +520,148 @@ static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height,
return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT);
}
+static u32 size_av1d_lb_opb_wr1_nv12_ubwc(u32 frame_width, u32 frame_height)
+{
+ u32 y_width, y_width_a = 128;
+
+ y_width = ALIGN(frame_width, y_width_a);
+
+ return (256 * ((y_width + 31) / 32 + (AV1D_MAX_TILE_COLS - 1)));
+}
+
+static u32 size_av1d_lb_opb_wr1_tp10_ubwc(u32 frame_width, u32 frame_height)
+{
+ u32 y_width, y_width_a = 256;
+
+ y_width = ALIGN(frame_width, 192);
+ y_width = ALIGN(y_width * 4 / 3, y_width_a);
+
+ return (256 * ((y_width + 47) / 48 + (AV1D_MAX_TILE_COLS - 1)));
+}
+
+static u32 hfi_buffer_line_av1d(u32 frame_width, u32 frame_height,
+ bool is_opb, u32 num_vpp_pipes)
+{
+ u32 size, vpss_lb_size, opbwrbufsize, opbwr8, opbwr10;
+
+ size = ALIGN(size_av1d_lb_fe_top_data(frame_width, frame_height),
+ DMA_ALIGNMENT) +
+ ALIGN(size_av1d_lb_fe_top_ctrl(frame_width, frame_height),
+ DMA_ALIGNMENT) +
+ ALIGN(size_av1d_lb_fe_left_data(frame_width, frame_height),
+ DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_av1d_lb_fe_left_ctrl(frame_width, frame_height),
+ DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_av1d_lb_se_left_ctrl(frame_width, frame_height),
+ DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_av1d_lb_se_top_ctrl(frame_width, frame_height),
+ DMA_ALIGNMENT) +
+ ALIGN(size_av1d_lb_pe_top_data(frame_width, frame_height),
+ DMA_ALIGNMENT) +
+ ALIGN(size_av1d_lb_vsp_top(frame_width, frame_height),
+ DMA_ALIGNMENT) +
+ ALIGN(size_av1d_lb_recon_dma_metadata_wr
+ (frame_width, frame_height), DMA_ALIGNMENT) * 2 +
+ ALIGN(size_av1d_qp(frame_width, frame_height), DMA_ALIGNMENT);
+ opbwr8 = size_av1d_lb_opb_wr1_nv12_ubwc(frame_width, frame_height);
+ opbwr10 = size_av1d_lb_opb_wr1_tp10_ubwc(frame_width, frame_height);
+ opbwrbufsize = opbwr8 >= opbwr10 ? opbwr8 : opbwr10;
+ size = ALIGN((size + opbwrbufsize), DMA_ALIGNMENT);
+ if (is_opb) {
+ size_vpss_lb(frame_width, frame_height);
+ size = ALIGN((size + vpss_lb_size) * 2, DMA_ALIGNMENT);
+ }
+
+ return size;
+}
+
+static u32 size_av1d_ibc_nv12_ubwc(u32 frame_width, u32 frame_height)
+{
+ u32 size;
+ u32 y_width_a = 128, y_height_a = 32;
+ u32 uv_width_a = 128, uv_height_a = 32;
+ u32 ybufsize, uvbufsize, y_width, y_height, uv_width, uv_height;
+ u32 y_meta_width_a = 64, y_meta_height_a = 16;
+ u32 uv_meta_width_a = 64, uv_meta_height_a = 16;
+ u32 meta_height, meta_stride, meta_size;
+ u32 tile_width_y = HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH;
+ u32 tile_height_y = HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT;
+ u32 tile_width_uv = HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_WIDTH;
+ u32 tile_height_uv = HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_HEIGHT;
+
+ y_width = ALIGN(frame_width, y_width_a);
+ y_height = ALIGN(frame_height, y_height_a);
+ uv_width = ALIGN(frame_width, uv_width_a);
+ uv_height = ALIGN(((frame_height + 1) >> 1), uv_height_a);
+ ybufsize = ALIGN((y_width * y_height), HFI_ALIGNMENT_4096);
+ uvbufsize = ALIGN(uv_width * uv_height, HFI_ALIGNMENT_4096);
+ size = ybufsize + uvbufsize;
+ meta_stride = ALIGN(((frame_width + (tile_width_y - 1)) / tile_width_y),
+ y_meta_width_a);
+ meta_height = ALIGN(((frame_height + (tile_height_y - 1)) / tile_height_y),
+ y_meta_height_a);
+ meta_size = ALIGN(meta_stride * meta_height, HFI_ALIGNMENT_4096);
+ size += meta_size;
+ meta_stride = ALIGN(((((frame_width + 1) >> 1) + (tile_width_uv - 1)) /
+ tile_width_uv), uv_meta_width_a);
+ meta_height = ALIGN(((((frame_height + 1) >> 1) + (tile_height_uv - 1)) /
+ tile_height_uv), uv_meta_height_a);
+ meta_size = ALIGN(meta_stride * meta_height, HFI_ALIGNMENT_4096);
+ size += meta_size;
+
+ return size;
+}
+
+static u32 size_av1d_ibc_tp10_ubwc(u32 frame_width, u32 frame_height)
+{
+ u32 size;
+ u32 y_width_a = 256, y_height_a = 16,
+ uv_width_a = 256, uv_height_a = 16;
+ u32 ybufsize, uvbufsize, y_width, y_height, uv_width, uv_height;
+ u32 y_meta_width_a = 64, y_meta_height_a = 16,
+ uv_meta_width_a = 64, uv_meta_height_a = 16;
+ u32 meta_height, meta_stride, meta_size;
+ u32 tile_width_y = HFI_COLOR_FORMAT_YUV420_TP10_UBWC_Y_TILE_WIDTH;
+ u32 tile_height_y = HFI_COLOR_FORMAT_YUV420_TP10_UBWC_Y_TILE_HEIGHT;
+ u32 tile_width_uv = HFI_COLOR_FORMAT_YUV420_TP10_UBWC_UV_TILE_WIDTH;
+ u32 tile_height_uv = HFI_COLOR_FORMAT_YUV420_TP10_UBWC_UV_TILE_HEIGHT;
+
+ y_width = ALIGN(frame_width, 192);
+ y_width = ALIGN(y_width * 4 / 3, y_width_a);
+ y_height = ALIGN(frame_height, y_height_a);
+ uv_width = ALIGN(frame_width, 192);
+ uv_width = ALIGN(uv_width * 4 / 3, uv_width_a);
+ uv_height = ALIGN(((frame_height + 1) >> 1), uv_height_a);
+ ybufsize = ALIGN(y_width * y_height, HFI_ALIGNMENT_4096);
+ uvbufsize = ALIGN(uv_width * uv_height, HFI_ALIGNMENT_4096);
+ size = ybufsize + uvbufsize;
+ meta_stride = ALIGN(((frame_width + (tile_width_y - 1)) / tile_width_y),
+ y_meta_width_a);
+ meta_height = ALIGN(((frame_height + (tile_height_y - 1)) / tile_height_y),
+ y_meta_height_a);
+ meta_size = ALIGN(((frame_height + (meta_height - 1)) / meta_height), meta_stride);
+ size += meta_size;
+ meta_stride = ALIGN(((((frame_width + 1) >> 1) + (tile_width_uv - 1)) /
+ tile_width_uv), uv_meta_width_a);
+ meta_height = ALIGN(((((frame_height + 1) >> 1) + (tile_height_uv - 1)) /
+ tile_height_uv), uv_meta_height_a);
+ meta_size = ALIGN(meta_stride * meta_height, HFI_ALIGNMENT_4096);
+ size += meta_size;
+
+ return size;
+}
+
+static u32 hfi_buffer_ibc_av1d(u32 frame_width, u32 frame_height)
+{
+ u32 size, ibc8, ibc10;
+
+ ibc8 = size_av1d_ibc_nv12_ubwc(frame_width, frame_height);
+ ibc10 = size_av1d_ibc_tp10_ubwc(frame_width, frame_height);
+ size = ibc8 >= ibc10 ? ibc8 : ibc10;
+
+ return ALIGN(size, DMA_ALIGNMENT);
+}
+
static u32 iris_vpu_dec_bin_size(struct iris_inst *inst)
{
u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
@@ -472,6 +675,8 @@ static u32 iris_vpu_dec_bin_size(struct iris_inst *inst)
return hfi_buffer_bin_h265d(width, height, num_vpp_pipes);
else if (inst->codec == V4L2_PIX_FMT_VP9)
return hfi_buffer_bin_vp9d(width, height, num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_AV1)
+ return hfi_buffer_bin_av1d(width, height, num_vpp_pipes);
return 0;
}
@@ -487,18 +692,33 @@ static u32 iris_vpu_dec_comv_size(struct iris_inst *inst)
return hfi_buffer_comv_h264d(width, height, num_comv);
else if (inst->codec == V4L2_PIX_FMT_HEVC)
return hfi_buffer_comv_h265d(width, height, num_comv);
-
+ else if (inst->codec == V4L2_PIX_FMT_AV1) {
+ if (inst->fw_caps[DRAP].value)
+ return 0;
+ else
+ return hfi_buffer_comv_av1d(width, height, num_comv);
+ }
return 0;
}
static u32 iris_vpu_dec_persist_size(struct iris_inst *inst)
{
+ struct platform_inst_caps *caps;
+
if (inst->codec == V4L2_PIX_FMT_H264)
return hfi_buffer_persist_h264d();
else if (inst->codec == V4L2_PIX_FMT_HEVC)
return hfi_buffer_persist_h265d(0);
else if (inst->codec == V4L2_PIX_FMT_VP9)
return hfi_buffer_persist_vp9d();
+ else if (inst->codec == V4L2_PIX_FMT_AV1) {
+ caps = inst->core->iris_platform_data->inst_caps;
+ if (inst->fw_caps[DRAP].value)
+ return hfi_buffer_persist_av1d(caps->max_frame_width,
+ caps->max_frame_height, 16);
+ else
+ return hfi_buffer_persist_av1d(0, 0, 0);
+ }
return 0;
}
@@ -545,6 +765,8 @@ static u32 iris_vpu_dec_line_size(struct iris_inst *inst)
else if (inst->codec == V4L2_PIX_FMT_VP9)
return hfi_buffer_line_vp9d(width, height, out_min_count, is_opb,
num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_AV1)
+ return hfi_buffer_line_av1d(width, height, is_opb, num_vpp_pipes);
return 0;
}
@@ -556,6 +778,15 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst)
iris_vpu_dec_line_size(inst);
}
+static u32 iris_vpu_dec_partial_size(struct iris_inst *inst)
+{
+ struct v4l2_format *f = inst->fmt_src;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+
+ return hfi_buffer_ibc_av1d(width, height);
+}
+
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)
@@ -1369,7 +1600,9 @@ static int output_min_count(struct iris_inst *inst)
/* fw_min_count > 0 indicates reconfig event has already arrived */
if (inst->fw_min_count) {
- if (iris_split_mode_enabled(inst) && inst->codec == V4L2_PIX_FMT_VP9)
+ if (iris_split_mode_enabled(inst) &&
+ (inst->codec == V4L2_PIX_FMT_VP9 ||
+ inst->codec == V4L2_PIX_FMT_VP9))
return min_t(u32, 4, inst->fw_min_count);
else
return inst->fw_min_count;
@@ -1377,6 +1610,8 @@ static int output_min_count(struct iris_inst *inst)
if (inst->codec == V4L2_PIX_FMT_VP9)
output_min_count = 9;
+ else if (inst->codec == V4L2_PIX_FMT_AV1)
+ output_min_count = 11;
return output_min_count;
}
@@ -1399,6 +1634,7 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
{BUF_PERSIST, iris_vpu_dec_persist_size },
{BUF_DPB, iris_vpu_dec_dpb_size },
{BUF_SCRATCH_1, iris_vpu_dec_scratch1_size },
+ {BUF_PARTIAL, iris_vpu_dec_partial_size },
};
static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = {
@@ -1437,14 +1673,20 @@ static u32 internal_buffer_count(struct iris_inst *inst,
buffer_type == BUF_PERSIST) {
return 1;
} else if (buffer_type == BUF_COMV || buffer_type == BUF_NON_COMV) {
- if (inst->codec == V4L2_PIX_FMT_H264 || inst->codec == V4L2_PIX_FMT_HEVC)
+ if (inst->codec == V4L2_PIX_FMT_H264 ||
+ inst->codec == V4L2_PIX_FMT_HEVC ||
+ inst->codec == V4L2_PIX_FMT_AV1)
return 1;
}
+
return 0;
}
static inline int iris_vpu_dpb_count(struct iris_inst *inst)
{
+ if (inst->codec == V4L2_PIX_FMT_AV1)
+ return 11;
+
if (iris_split_mode_enabled(inst)) {
return inst->fw_min_count ?
inst->fw_min_count : inst->buffers[BUF_OUTPUT].min_count;
@@ -1463,9 +1705,13 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type
return MIN_BUFFERS;
else
return output_min_count(inst);
+ case BUF_NON_COMV:
+ if (inst->codec == V4L2_PIX_FMT_AV1)
+ return 0;
+ else
+ return 1;
case BUF_BIN:
case BUF_COMV:
- case BUF_NON_COMV:
case BUF_LINE:
case BUF_PERSIST:
return internal_buffer_count(inst, buffer_type);
@@ -1473,6 +1719,7 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type
case BUF_SCRATCH_2:
case BUF_VPSS:
case BUF_ARP:
+ case BUF_PARTIAL:
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 1ff1b07ecbaa85345ca948affeb1c4a1c55e36b0..71fb2a408797c3b5e2eb25222b2dfd356f532d96 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
@@ -11,6 +11,7 @@ struct iris_inst;
#define MIN_BUFFERS 4
#define DMA_ALIGNMENT 256
+#define HFI_ALIGNMENT_4096 4096
#define NUM_HW_PIC_BUF 32
#define LCU_MAX_SIZE_PELS 64
@@ -80,6 +81,22 @@ struct iris_inst;
#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384
#define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640
+#define AV1_CABAC_HDR_RATIO_HD_TOT 2
+#define AV1_CABAC_RES_RATIO_HD_TOT 2
+#define AV1D_LCU_MAX_SIZE_PELS 128
+#define AV1D_LCU_MIN_SIZE_PELS 64
+#define AV1D_MAX_TILE_COLS 64
+#define MAX_PE_NBR_DATA_LCU32_LINE_BUFFER_SIZE 192
+#define MAX_PE_NBR_DATA_LCU16_LINE_BUFFER_SIZE 96
+#define AV1D_NUM_HW_PIC_BUF 16
+#define AV1D_NUM_FRAME_HEADERS 16
+#define SIZE_AV1D_SEQUENCE_HEADER 768
+#define SIZE_AV1D_METADATA 512
+#define SIZE_AV1D_FRAME_HEADER 1280
+#define SIZE_AV1D_TILE_OFFSET 65536
+#define SIZE_AV1D_QM 3328
+#define SIZE_AV1D_PROB_TABLE 22784
+
#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)
@@ -145,6 +162,94 @@ static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height)
return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 128;
}
+static inline u32 size_av1d_lb_fe_top_data(u32 frame_width, u32 frame_height)
+{
+ return (ALIGN(frame_width, AV1D_LCU_MAX_SIZE_PELS) * ((16 * 10) >> 3) +
+ ALIGN(frame_width, AV1D_LCU_MAX_SIZE_PELS) / 2 * ((16 * 6) >> 3) * 2);
+}
+
+static inline u32 size_av1d_lb_fe_left_data(u32 frame_width, u32 frame_height)
+{
+ return (32 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 16) +
+ 16 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) / 2 +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 8) * 2 +
+ 24 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 16) +
+ 24 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) / 2 +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 12) * 2 +
+ 24 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 16) +
+ 16 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 16) +
+ 16 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) / 2 +
+ ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS * 12) * 2);
+}
+
+static inline u32 size_av1d_lb_fe_top_ctrl(u32 frame_width, u32 frame_height)
+{
+ return (10 * ((frame_width + AV1D_LCU_MIN_SIZE_PELS - 1) /
+ AV1D_LCU_MIN_SIZE_PELS) * 128 / 8);
+}
+
+static inline u32 size_av1d_lb_fe_left_ctrl(u32 frame_width, u32 frame_height)
+{
+ return (16 * ((ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) / 16) +
+ (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS)) +
+ 3 * 16 * (ALIGN(frame_height, AV1D_LCU_MAX_SIZE_PELS) /
+ AV1D_LCU_MIN_SIZE_PELS));
+}
+
+static inline u32 size_av1d_lb_se_top_ctrl(u32 frame_width, u32 frame_height)
+{
+ return (((frame_width + 7) / 8) * 16);
+}
+
+static inline u32 size_av1d_lb_se_left_ctrl(u32 frame_width, u32 frame_height)
+{
+ return (max(((frame_height + 15) / 16) *
+ MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE,
+ max(((frame_height + 31) / 32) *
+ MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE,
+ ((frame_height + 63) / 64) *
+ MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)));
+}
+
+static inline u32 size_av1d_lb_pe_top_data(u32 frame_width, u32 frame_height)
+{
+ return (max(((frame_width + 15) / 16) *
+ MAX_PE_NBR_DATA_LCU16_LINE_BUFFER_SIZE,
+ max(((frame_width + 31) / 32) *
+ MAX_PE_NBR_DATA_LCU32_LINE_BUFFER_SIZE,
+ ((frame_width + 63) / 64) *
+ MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE)));
+}
+
+static inline u32 size_av1d_lb_vsp_top(u32 frame_width, u32 frame_height)
+{
+ return (max(((frame_width + 63) / 64) * 1280,
+ ((frame_width + 127) / 128) * 2304));
+}
+
+static inline u32 size_av1d_lb_recon_dma_metadata_wr(u32 frame_width,
+ u32 frame_height)
+{
+ return ((ALIGN(frame_height, 8) / (4 / 2)) * 64);
+}
+
+static inline u32 size_av1d_qp(u32 frame_width, u32 frame_height)
+{
+ return size_h264d_qp(frame_width, frame_height);
+}
+
int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type);
--
2.34.1
Powered by blists - more mailing lists