From nobody Sat Dec 27 18:57:17 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CE8839863; Mon, 18 Dec 2023 11:40:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="BwZrPQCo" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 3BIAto4o007911; Mon, 18 Dec 2023 11:40:04 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= from:to:cc:subject:date:message-id:in-reply-to:references; s= qcppdkim1; bh=DjeCHraDg5N5KWkgTBSLo6OX0aOTajhJqdyfe0iWaX8=; b=Bw ZrPQCo3m2x7GTbnlBE5tsR4gOI7b2JwjOcFjV4XV/iWzQWLs2G5K6Jgw0Wwo4MVo Ut/I85lEOtytVKtVOorkPTqlIDJ1lUX6xKpcs66SQAab4Tsafmz34Wqxc8HZHijC F4jEntymbQ8xpq0iFXkYUJdy3uZGepHqmMGVP7/COmdm2a247xwj2ZuvdJSlvVb1 574hqMRLrZjB/mS5r5K68CxIrCn8TV7QyFrAGmPtb/B8jVreKG0MpLoJwvPow0jB 0YnyWDcAqBQXdgsL9YFVlh1YlSy0mJhHUx/13wqQxazBAtM+oAa3uNyM1vOvtZtO gtz5VnTqCJCQaMxRbiBQ== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3v2mb9g4xx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 18 Dec 2023 11:40:03 +0000 (GMT) Received: from pps.filterd (APBLRPPMTA01.qualcomm.com [127.0.0.1]) by APBLRPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 3BIBe0wv004854; Mon, 18 Dec 2023 11:40:00 GMT Received: from pps.reinject (localhost [127.0.0.1]) by APBLRPPMTA01.qualcomm.com (PPS) with ESMTP id 3v14ym00ag-1; Mon, 18 Dec 2023 11:40:00 +0000 Received: from APBLRPPMTA01.qualcomm.com (APBLRPPMTA01.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 3BIBX8re030072; Mon, 18 Dec 2023 11:36:10 GMT Received: from hu-sgudaval-hyd.qualcomm.com (hu-dikshita-hyd.qualcomm.com [10.213.110.13]) by APBLRPPMTA01.qualcomm.com (PPS) with ESMTP id 3BIBX8rs030066; Mon, 18 Dec 2023 11:36:09 +0000 Received: by hu-sgudaval-hyd.qualcomm.com (Postfix, from userid 347544) id 71B33238E; Mon, 18 Dec 2023 17:03:04 +0530 (+0530) From: Dikshita Agarwal To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, stanimir.k.varbanov@gmail.com, quic_vgarodia@quicinc.com, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org, mchehab@kernel.org, bryan.odonoghue@linaro.org Cc: linux-arm-msm@vger.kernel.org, quic_abhinavk@quicinc.com, Dikshita Agarwal Subject: [PATCH v2 33/34] media: iris: add vb2 streaming and buffer ops for encoder Date: Mon, 18 Dec 2023 17:02:28 +0530 Message-Id: <1702899149-21321-34-git-send-email-quic_dikshita@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1702899149-21321-1-git-send-email-quic_dikshita@quicinc.com> References: <1702899149-21321-1-git-send-email-quic_dikshita@quicinc.com> X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: bnmkmXwdjsNr_IO3z2ssx7KfZtGHpn73 X-Proofpoint-GUID: bnmkmXwdjsNr_IO3z2ssx7KfZtGHpn73 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_01,2023-12-07_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 impostorscore=0 adultscore=0 mlxscore=0 clxscore=1015 spamscore=0 mlxlogscore=999 phishscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2311290000 definitions=main-2312180084 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" During stream on, set some mandatory properties to firmware to start a session. Set all v4l2 properties set by client, to firmware prepared with the dependency graph. Also, configure the hardware internal buffers required for frame processing. Send HFI_CMD_START on capture and output planes to start the processing on respective planes. The instance state is changed accordingly. During stream off, send HFI_CMD_STOP to firmware which is a synchronous command. After the response is received from firmware, the session is closed on firmware and instance state is changed accordingly. Buffers are submitted and received via HFI_CMD_BUFFER. Add Internal buffer size calculations for Encoder. Signed-off-by: Dikshita Agarwal --- .../media/platform/qcom/vcodec/iris/hfi_defines.h | 11 + .../media/platform/qcom/vcodec/iris/iris_buffer.c | 296 ++++++++-- .../media/platform/qcom/vcodec/iris/iris_ctrls.c | 49 +- .../media/platform/qcom/vcodec/iris/iris_ctrls.h | 1 + .../media/platform/qcom/vcodec/iris/iris_helpers.c | 169 +++++- .../media/platform/qcom/vcodec/iris/iris_helpers.h | 6 + drivers/media/platform/qcom/vcodec/iris/iris_hfi.c | 22 +- .../platform/qcom/vcodec/iris/iris_hfi_packet.c | 137 +++-- .../platform/qcom/vcodec/iris/iris_hfi_packet.h | 9 +- .../platform/qcom/vcodec/iris/iris_hfi_response.c | 143 +++-- drivers/media/platform/qcom/vcodec/iris/iris_vb2.c | 62 +- .../media/platform/qcom/vcodec/iris/iris_vdec.c | 137 +---- .../media/platform/qcom/vcodec/iris/iris_venc.c | 423 ++++++++++++++ .../media/platform/qcom/vcodec/iris/iris_venc.h | 3 + .../platform/qcom/vcodec/iris/platform_common.h | 5 + .../platform/qcom/vcodec/iris/platform_sm8550.c | 2 + .../platform/qcom/vcodec/iris/vpu_iris3_buffer.c | 198 ++++++- .../platform/qcom/vcodec/iris/vpu_iris3_buffer.h | 624 +++++++++++++++++= ++++ .../platform/qcom/vcodec/iris/vpu_iris3_power.c | 2 +- 19 files changed, 1992 insertions(+), 307 deletions(-) diff --git a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h b/driver= s/media/platform/qcom/vcodec/iris/hfi_defines.h index bc32c99..59765de 100644 --- a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h +++ b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h @@ -284,6 +284,10 @@ enum hfi_picture_type { =20 #define HFI_PROP_NO_OUTPUT 0x0300016a =20 +#define HFI_PROP_BUFFER_MARK 0x0300016c + +#define HFI_PROP_RAW_RESOLUTION 0x03000178 + #define HFI_PROP_DPB_LIST 0x0300017A =20 #define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C @@ -372,4 +376,11 @@ enum hfi_buffer_firmware_flags { HFI_BUF_FW_FLAG_PSC_LAST =3D 0x20000000, }; =20 +enum hfi_hevc_profile_type { + HFI_H265_PROFILE_MAIN =3D 0, + HFI_H265_PROFILE_MAIN_STILL_PICTURE =3D 1, + HFI_H265_PROFILE_MAIN_10 =3D 2, + HFI_H265_PROFILE_MAIN_10_STILL_PICTURE =3D 3, +}; + #endif diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c b/driver= s/media/platform/qcom/vcodec/iris/iris_buffer.c index f85b52c..18418e4e 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c @@ -10,6 +10,7 @@ #include "hfi_defines.h" #include "iris_hfi_packet.h" #include "iris_instance.h" +#include "vpu_iris3_buffer.h" =20 static const u32 dec_ip_int_buf_type[] =3D { BUF_BIN, @@ -22,15 +23,51 @@ static const u32 dec_op_int_buf_type[] =3D { BUF_DPB, }; =20 +static const u32 enc_ip_int_buf_type[] =3D { + BUF_VPSS, +}; + +static const u32 enc_op_int_buf_type[] =3D { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, + BUF_DPB, +}; + static int input_min_count(struct iris_inst *inst) { - return MIN_BUFFERS; + u32 input_min_count =3D 0; + u32 total_hb_layer =3D 0; + + if (inst->domain =3D=3D DECODER) { + input_min_count =3D MIN_BUFFERS; + } else if (inst->domain =3D=3D ENCODER) { + total_hb_layer =3D is_hierb_type_requested(inst) ? + inst->cap[ENH_LAYER_COUNT].value + 1 : 0; + if (inst->codec =3D=3D H264 && + !inst->cap[LAYER_ENABLE].value) { + total_hb_layer =3D 0; + } + input_min_count =3D + hfi_iris3_enc_min_input_buf_count(total_hb_layer); + } else { + return 0; + } + + return input_min_count; } =20 static int output_min_count(struct iris_inst *inst) { int output_min_count; =20 + if (inst->domain !=3D DECODER && inst->domain !=3D ENCODER) + return 0; + + if (inst->domain =3D=3D ENCODER) + return MIN_BUFFERS; + /* fw_min_count > 0 indicates reconfig event has already arrived */ if (inst->fw_min_count) { if (is_split_mode_enabled(inst) && inst->codec =3D=3D VP9) @@ -83,16 +120,21 @@ static u32 internal_buffer_count(struct iris_inst *ins= t, { u32 count =3D 0; =20 - if (buffer_type =3D=3D BUF_BIN || buffer_type =3D=3D BUF_LINE || - buffer_type =3D=3D BUF_PERSIST) { - count =3D 1; - } else if (buffer_type =3D=3D BUF_COMV || buffer_type =3D=3D BUF_NON_COMV= ) { - if (inst->codec =3D=3D H264 || inst->codec =3D=3D HEVC) + if (inst->domain =3D=3D ENCODER) + return 1; + + if (inst->domain =3D=3D DECODER) { + if (buffer_type =3D=3D BUF_BIN || buffer_type =3D=3D BUF_LINE || + buffer_type =3D=3D BUF_PERSIST) { count =3D 1; - else + } else if (buffer_type =3D=3D BUF_COMV || buffer_type =3D=3D BUF_NON_COM= V) { + if (inst->codec =3D=3D H264 || inst->codec =3D=3D HEVC) + count =3D 1; + else + count =3D 0; + } else { count =3D 0; - } else { - count =3D 0; + } } =20 return count; @@ -102,6 +144,9 @@ static int dpb_count(struct iris_inst *inst) { int count =3D 0; =20 + if (inst->domain =3D=3D ENCODER) + return get_recon_buf_count(inst); + if (is_split_mode_enabled(inst)) { count =3D inst->fw_min_count ? inst->fw_min_count : inst->buffers.output.min_count; @@ -123,6 +168,7 @@ int iris_get_buf_min_count(struct iris_inst *inst, case BUF_NON_COMV: case BUF_LINE: case BUF_PERSIST: + case BUF_ARP: return internal_buffer_count(inst, buffer_type); case BUF_DPB: return dpb_count(inst); @@ -131,7 +177,7 @@ int iris_get_buf_min_count(struct iris_inst *inst, } } =20 -static u32 input_buffer_size(struct iris_inst *inst) +static u32 dec_input_buffer_size(struct iris_inst *inst) { u32 base_res_mbs =3D NUM_MBS_4k; u32 frame_size, num_mbs; @@ -163,7 +209,7 @@ static u32 input_buffer_size(struct iris_inst *inst) return ALIGN(frame_size, SZ_4K); } =20 -static u32 output_buffer_size(struct iris_inst *inst) +static u32 dec_output_buffer_size(struct iris_inst *inst) { struct v4l2_format *f; u32 size; @@ -175,17 +221,97 @@ static u32 output_buffer_size(struct iris_inst *inst) return size; } =20 +static u32 enc_input_buffer_size(struct iris_inst *inst) +{ + struct v4l2_format *f; + u32 size; + + f =3D inst->fmt_src; + + size =3D video_raw_buffer_size(f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.w= idth, + f->fmt.pix_mp.height); + return size; +} + +static inline +u32 hfi_buffer_bitstream_enc(u32 frame_width, u32 frame_height, + u32 rc_type, bool is_ten_bit) +{ + u32 aligned_width, aligned_height, bitstream_size, yuv_size; + + aligned_width =3D ALIGN(frame_width, 32); + aligned_height =3D ALIGN(frame_height, 32); + bitstream_size =3D aligned_width * aligned_height * 3; + yuv_size =3D (aligned_width * aligned_height * 3) >> 1; + if (aligned_width * aligned_height > (4096 * 2176)) + /* bitstream_size =3D 0.25 * yuv_size; */ + bitstream_size =3D (bitstream_size >> 3); + else if (aligned_width * aligned_height > (1280 * 720)) + /* bitstream_size =3D 0.5 * yuv_size; */ + bitstream_size =3D (bitstream_size >> 2); + + if ((rc_type =3D=3D HFI_RC_CQ || rc_type =3D=3D HFI_RC_OFF) && + bitstream_size < yuv_size) + bitstream_size =3D (bitstream_size << 1); + + if (is_ten_bit) + bitstream_size =3D (bitstream_size) + (bitstream_size >> 2); + + return ALIGN(bitstream_size, HFI_ALIGNMENT_4096); +} + +static u32 enc_output_buffer_size(struct iris_inst *inst) +{ + u32 hfi_rc_type =3D HFI_RC_VBR_CFR; + enum codec_type codec; + int bitrate_mode, frame_rc; + bool is_ten_bit =3D false; + struct v4l2_format *f; + u32 frame_size; + + f =3D inst->fmt_dst; + codec =3D v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat); + if (codec =3D=3D HEVC) + is_ten_bit =3D true; + + bitrate_mode =3D inst->cap[BITRATE_MODE].value; + frame_rc =3D inst->cap[FRAME_RC_ENABLE].value; + if (!frame_rc) + hfi_rc_type =3D HFI_RC_OFF; + else if (bitrate_mode =3D=3D V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + hfi_rc_type =3D HFI_RC_CQ; + + frame_size =3D hfi_buffer_bitstream_enc(f->fmt.pix_mp.width, + f->fmt.pix_mp.height, + hfi_rc_type, is_ten_bit); + + return frame_size; +} + int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - switch (buffer_type) { - case BUF_INPUT: - return input_buffer_size(inst); - case BUF_OUTPUT: - return output_buffer_size(inst); - default: - return 0; + if (inst->domain =3D=3D DECODER) { + switch (buffer_type) { + case BUF_INPUT: + return dec_input_buffer_size(inst); + case BUF_OUTPUT: + return dec_output_buffer_size(inst); + default: + break; + } + } else if (inst->domain =3D=3D ENCODER) { + switch (buffer_type) { + case BUF_INPUT: + return enc_input_buffer_size(inst); + case BUF_OUTPUT: + return enc_output_buffer_size(inst); + default: + break; + } } + + return 0; } =20 struct iris_buffers *iris_get_buffer_list(struct iris_inst *inst, @@ -300,14 +426,30 @@ int iris_get_internal_buffers(struct iris_inst *inst, int ret =3D 0; u32 i =3D 0; =20 - if (plane =3D=3D INPUT_MPLANE) { - for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { - ret =3D iris_get_internal_buf_info(inst, dec_ip_int_buf_type[i]); - if (ret) - return ret; + if (inst->domain =3D=3D DECODER) { + if (plane =3D=3D INPUT_MPLANE) { + for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { + ret =3D iris_get_internal_buf_info(inst, dec_ip_int_buf_type[i]); + if (ret) + return ret; + } + } else { + return iris_get_internal_buf_info(inst, BUF_DPB); + } + } else if (inst->domain =3D=3D ENCODER) { + if (plane =3D=3D INPUT_MPLANE) { + for (i =3D 0; i < ARRAY_SIZE(enc_ip_int_buf_type); i++) { + ret =3D iris_get_internal_buf_info(inst, enc_ip_int_buf_type[i]); + if (ret) + return ret; + } + } else { + for (i =3D 0; i < ARRAY_SIZE(enc_op_int_buf_type); i++) { + ret =3D iris_get_internal_buf_info(inst, enc_op_int_buf_type[i]); + if (ret) + return ret; + } } - } else { - return iris_get_internal_buf_info(inst, BUF_DPB); } =20 return ret; @@ -377,10 +519,18 @@ int iris_create_input_internal_buffers(struct iris_in= st *inst) int ret =3D 0; u32 i =3D 0; =20 - for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { - ret =3D iris_create_internal_buffers(inst, dec_ip_int_buf_type[i]); - if (ret) - return ret; + if (inst->domain =3D=3D DECODER) { + for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { + ret =3D iris_create_internal_buffers(inst, dec_ip_int_buf_type[i]); + if (ret) + return ret; + } + } else if (inst->domain =3D=3D ENCODER) { + for (i =3D 0; i < ARRAY_SIZE(enc_ip_int_buf_type); i++) { + ret =3D iris_create_internal_buffers(inst, enc_ip_int_buf_type[i]); + if (ret) + return ret; + } } =20 return ret; @@ -388,7 +538,20 @@ int iris_create_input_internal_buffers(struct iris_ins= t *inst) =20 int iris_create_output_internal_buffers(struct iris_inst *inst) { - return iris_create_internal_buffers(inst, BUF_DPB); + int ret =3D 0; + u32 i =3D 0; + + if (inst->domain =3D=3D DECODER) { + return iris_create_internal_buffers(inst, BUF_DPB); + } else if (inst->domain =3D=3D ENCODER) { + for (i =3D 0; i < ARRAY_SIZE(enc_op_int_buf_type); i++) { + ret =3D iris_create_internal_buffers(inst, enc_op_int_buf_type[i]); + if (ret) + return ret; + } + } + + return ret; } =20 static int set_num_comv(struct iris_inst *inst) @@ -413,7 +576,7 @@ static int iris_queue_internal_buffers(struct iris_inst= *inst, struct iris_buffers *buffers; int ret =3D 0; =20 - if (buffer_type =3D=3D BUF_COMV) { + if (inst->domain =3D=3D DECODER && buffer_type =3D=3D BUF_COMV) { ret =3D set_num_comv(inst); if (ret) return ret; @@ -442,10 +605,18 @@ int iris_queue_input_internal_buffers(struct iris_ins= t *inst) int ret =3D 0; u32 i; =20 - for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { - ret =3D iris_queue_internal_buffers(inst, dec_ip_int_buf_type[i]); - if (ret) - return ret; + if (inst->domain =3D=3D DECODER) { + for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { + ret =3D iris_queue_internal_buffers(inst, dec_ip_int_buf_type[i]); + if (ret) + return ret; + } + } else if (inst->domain =3D=3D ENCODER) { + for (i =3D 0; i < ARRAY_SIZE(enc_ip_int_buf_type); i++) { + ret =3D iris_queue_internal_buffers(inst, enc_ip_int_buf_type[i]); + if (ret) + return ret; + } } =20 return ret; @@ -453,7 +624,20 @@ int iris_queue_input_internal_buffers(struct iris_inst= *inst) =20 int iris_queue_output_internal_buffers(struct iris_inst *inst) { - return iris_queue_internal_buffers(inst, BUF_DPB); + int ret =3D 0; + u32 i =3D 0; + + if (inst->domain =3D=3D DECODER) { + return iris_queue_internal_buffers(inst, BUF_DPB); + } else if (inst->domain =3D=3D ENCODER) { + for (i =3D 0; i < ARRAY_SIZE(enc_op_int_buf_type); i++) { + ret =3D iris_queue_internal_buffers(inst, enc_op_int_buf_type[i]); + if (ret) + return ret; + } + } + + return ret; } =20 int iris_destroy_internal_buffer(struct iris_inst *inst, @@ -489,16 +673,26 @@ int iris_destroy_internal_buffers(struct iris_inst *i= nst, { struct iris_buffer *buf, *dummy; struct iris_buffers *buffers; - const u32 *internal_buf_type; + const u32 *internal_buf_type =3D NULL; int ret =3D 0; - u32 i, len; - - if (plane =3D=3D INPUT_MPLANE) { - internal_buf_type =3D dec_ip_int_buf_type; - len =3D ARRAY_SIZE(dec_ip_int_buf_type); - } else { - internal_buf_type =3D dec_op_int_buf_type; - len =3D ARRAY_SIZE(dec_op_int_buf_type); + u32 i, len =3D 0; + + if (inst->domain =3D=3D DECODER) { + if (plane =3D=3D INPUT_MPLANE) { + internal_buf_type =3D dec_ip_int_buf_type; + len =3D ARRAY_SIZE(dec_ip_int_buf_type); + } else { + internal_buf_type =3D dec_op_int_buf_type; + len =3D ARRAY_SIZE(dec_op_int_buf_type); + } + } else if (inst->domain =3D=3D ENCODER) { + if (plane =3D=3D INPUT_MPLANE) { + internal_buf_type =3D enc_ip_int_buf_type; + len =3D ARRAY_SIZE(enc_ip_int_buf_type); + } else { + internal_buf_type =3D enc_op_int_buf_type; + len =3D ARRAY_SIZE(enc_op_int_buf_type); + } } =20 for (i =3D 0; i < len; i++) { @@ -552,10 +746,12 @@ static int iris_release_input_internal_buffers(struct= iris_inst *inst) int ret =3D 0; u32 i =3D 0; =20 - for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { - ret =3D iris_release_internal_buffers(inst, dec_ip_int_buf_type[i]); - if (ret) - return ret; + if (inst->domain =3D=3D DECODER) { + for (i =3D 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) { + ret =3D iris_release_internal_buffers(inst, dec_ip_int_buf_type[i]); + if (ret) + return ret; + } } =20 return ret; @@ -566,7 +762,7 @@ int iris_alloc_and_queue_session_int_bufs(struct iris_i= nst *inst, { int ret; =20 - if (buffer_type !=3D BUF_PERSIST) + if (buffer_type !=3D BUF_ARP && buffer_type !=3D BUF_PERSIST) return -EINVAL; =20 ret =3D iris_get_internal_buf_info(inst, buffer_type); diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c b/drivers= /media/platform/qcom/vcodec/iris/iris_ctrls.c index af99ac73..559b0dd 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c @@ -723,11 +723,20 @@ int set_stage(struct iris_inst *inst, =20 hfi_id =3D inst->cap[cap_id].hfi_id; =20 - inp_f =3D inst->fmt_src; - height =3D inp_f->fmt.pix_mp.height; - width =3D inp_f->fmt.pix_mp.width; - if (res_is_less_than(width, height, 1280, 720)) - work_mode =3D STAGE_1; + if (inst->domain =3D=3D DECODER) { + inp_f =3D inst->fmt_src; + height =3D inp_f->fmt.pix_mp.height; + width =3D inp_f->fmt.pix_mp.width; + if (res_is_less_than(width, height, 1280, 720)) + work_mode =3D STAGE_1; + } else if (inst->domain =3D=3D ENCODER) { + if (inst->cap[SLICE_MODE].value =3D=3D + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) + work_mode =3D STAGE_1; + + if (!inst->cap[GOP_SIZE].value) + work_mode =3D STAGE_2; + } =20 return iris_hfi_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE, get_port_info(inst, cap_id), @@ -743,6 +752,12 @@ int set_pipe(struct iris_inst *inst, work_route =3D inst->cap[cap_id].value; hfi_id =3D inst->cap[cap_id].hfi_id; =20 + if (inst->domain =3D=3D ENCODER) { + if (inst->cap[SLICE_MODE].value =3D=3D + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) + work_route =3D PIPE_1; + } + return iris_hfi_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE, get_port_info(inst, cap_id), HFI_PAYLOAD_U32, @@ -763,6 +778,30 @@ int set_level(struct iris_inst *inst, enum plat_inst_c= ap_type cap_id) &hfi_value, sizeof(u32)); } =20 +int decide_quality_mode(struct iris_inst *inst) +{ + u32 fps, mbpf, mbps, max_hq_mbpf, max_hq_mbps; + u32 mode =3D POWER_SAVE_MODE; + struct iris_core *core; + + if (inst->domain !=3D ENCODER) + return 0; + + mbpf =3D NUM_MBS_PER_FRAME(inst->crop.height, inst->crop.width); + fps =3D max3(inst->cap[QUEUED_RATE].value >> 16, + inst->cap[FRAME_RATE].value >> 16, + inst->cap[OPERATING_RATE].value >> 16); + mbps =3D mbpf * fps; + core =3D inst->core; + max_hq_mbpf =3D core->cap[MAX_MBPF_HQ].value; + max_hq_mbps =3D core->cap[MAX_MBPS_HQ].value; + + if (mbpf <=3D max_hq_mbpf && mbps <=3D max_hq_mbps) + mode =3D MAX_QUALITY_MODE; + + return mode; +} + int set_req_sync_frame(struct iris_inst *inst, enum plat_inst_cap_type cap= _id) { u32 hfi_id, hfi_val; diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h b/drivers= /media/platform/qcom/vcodec/iris/iris_ctrls.h index 5421d9f..404d98c 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h +++ b/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h @@ -33,6 +33,7 @@ int adjust_v4l2_properties(struct iris_inst *inst); int ctrls_init(struct iris_inst *inst, bool init); int set_q16(struct iris_inst *inst, enum plat_inst_cap_type cap_id); int set_level(struct iris_inst *inst, enum plat_inst_cap_type cap_id); +int decide_quality_mode(struct iris_inst *inst); int set_req_sync_frame(struct iris_inst *inst, enum plat_inst_cap_type cap= _id); int set_flip(struct iris_inst *inst, enum plat_inst_cap_type cap_id); int set_rotation(struct iris_inst *inst, enum plat_inst_cap_type cap_id); diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c b/drive= rs/media/platform/qcom/vcodec/iris/iris_helpers.c index c84bb51..a770157 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c @@ -44,15 +44,15 @@ u32 get_port_info(struct iris_inst *inst, if (inst->cap[cap_id].flags & CAP_FLAG_INPUT_PORT && inst->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) { if (inst->vb2q_dst->streaming) - return get_hfi_port(INPUT_MPLANE); + return get_hfi_port(inst, INPUT_MPLANE); else - return get_hfi_port(OUTPUT_MPLANE); + return get_hfi_port(inst, OUTPUT_MPLANE); } =20 if (inst->cap[cap_id].flags & CAP_FLAG_INPUT_PORT) - return get_hfi_port(INPUT_MPLANE); + return get_hfi_port(inst, INPUT_MPLANE); else if (inst->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) - return get_hfi_port(OUTPUT_MPLANE); + return get_hfi_port(inst, OUTPUT_MPLANE); else return HFI_PORT_NONE; } @@ -86,9 +86,14 @@ int get_mbpf(struct iris_inst *inst) int height =3D 0, width =3D 0; struct v4l2_format *inp_f; =20 - inp_f =3D inst->fmt_src; - width =3D max(inp_f->fmt.pix_mp.width, inst->crop.width); - height =3D max(inp_f->fmt.pix_mp.height, inst->crop.height); + if (inst->domain =3D=3D DECODER) { + inp_f =3D inst->fmt_src; + width =3D max(inp_f->fmt.pix_mp.width, inst->crop.width); + height =3D max(inp_f->fmt.pix_mp.height, inst->crop.height); + } else if (inst->domain =3D=3D ENCODER) { + width =3D inst->crop.width; + height =3D inst->crop.height; + } =20 return NUM_MBS_PER_FRAME(height, width); } @@ -100,6 +105,9 @@ inline bool is_linear_colorformat(u32 colorformat) =20 bool is_split_mode_enabled(struct iris_inst *inst) { + if (inst->domain !=3D DECODER) + return false; + if (is_linear_colorformat(inst->fmt_dst->fmt.pix_mp.pixelformat)) return true; =20 @@ -118,6 +126,24 @@ inline bool is_8bit_colorformat(enum colorformat_type = colorformat) colorformat =3D=3D FMT_NV21; } =20 +inline bool is_scaling_enabled(struct iris_inst *inst) +{ + return inst->crop.left !=3D inst->compose.left || + inst->crop.top !=3D inst->compose.top || + inst->crop.width !=3D inst->compose.width || + inst->crop.height !=3D inst->compose.height; +} + +inline bool is_hierb_type_requested(struct iris_inst *inst) +{ + return (inst->codec =3D=3D H264 && + inst->cap[LAYER_TYPE].value =3D=3D + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) || + (inst->codec =3D=3D HEVC && + inst->cap[LAYER_TYPE].value =3D=3D + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B); +} + u32 v4l2_codec_from_driver(struct iris_inst *inst, enum codec_type codec) { const struct codec_info *codec_info; @@ -319,17 +345,24 @@ static int check_resolution_supported(struct iris_ins= t *inst) u32 width =3D 0, height =3D 0, min_width, min_height, max_width, max_height; =20 - width =3D inst->fmt_src->fmt.pix_mp.width; - height =3D inst->fmt_src->fmt.pix_mp.height; + if (inst->domain =3D=3D DECODER) { + width =3D inst->fmt_src->fmt.pix_mp.width; + height =3D inst->fmt_src->fmt.pix_mp.height; + } else if (inst->domain =3D=3D ENCODER) { + width =3D inst->crop.width; + height =3D inst->crop.height; + } =20 min_width =3D inst->cap[FRAME_WIDTH].min; max_width =3D inst->cap[FRAME_WIDTH].max; min_height =3D inst->cap[FRAME_HEIGHT].min; max_height =3D inst->cap[FRAME_HEIGHT].max; =20 - if (!(min_width <=3D width && width <=3D max_width) || - !(min_height <=3D height && height <=3D max_height)) - return -EINVAL; + if (inst->domain =3D=3D DECODER || inst->domain =3D=3D ENCODER) { + if (!(min_width <=3D width && width <=3D max_width) || + !(min_height <=3D height && height <=3D max_height)) + return -EINVAL; + } =20 return 0; } @@ -470,7 +503,7 @@ int queue_buffer(struct iris_inst *inst, struct iris_bu= ffer *buf) { int ret; =20 - if (buf->type =3D=3D BUF_OUTPUT) + if (inst->domain =3D=3D DECODER && buf->type =3D=3D BUF_OUTPUT) process_requeued_readonly_buffers(inst, buf); =20 ret =3D iris_hfi_queue_buffer(inst, buf); @@ -653,7 +686,7 @@ static int iris_flush_read_only_buffers(struct iris_ins= t *inst, { struct iris_buffer *ro_buf, *dummy; =20 - if (type !=3D BUF_OUTPUT) + if (inst->domain !=3D DECODER || type !=3D BUF_OUTPUT) return 0; =20 list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, li= st) { @@ -899,6 +932,114 @@ int codec_change(struct iris_inst *inst, u32 v4l2_cod= ec) return ret; } =20 +int process_streamon_input(struct iris_inst *inst) +{ + enum iris_inst_sub_state set_sub_state =3D IRIS_INST_SUB_NONE; + int ret; + + iris_scale_power(inst); + + ret =3D iris_hfi_start(inst, INPUT_MPLANE); + if (ret) + return ret; + + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret =3D 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) { + if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { + ret =3D iris_hfi_pause(inst, INPUT_MPLANE); + if (ret) + return ret; + set_sub_state =3D IRIS_INST_SUB_INPUT_PAUSE; + } + } + + ret =3D iris_inst_state_change_streamon(inst, INPUT_MPLANE); + if (ret) + return ret; + + ret =3D iris_inst_change_sub_state(inst, 0, set_sub_state); + + return ret; +} + +int process_streamon_output(struct iris_inst *inst) +{ + enum iris_inst_sub_state clear_sub_state =3D IRIS_INST_SUB_NONE; + bool drain_pending =3D false; + int ret; + + iris_scale_power(inst); + + if (inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST) + clear_sub_state =3D IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; + + if (inst->domain =3D=3D DECODER && inst->sub_state & IRIS_INST_SUB_INPUT_= PAUSE) { + ret =3D iris_alloc_and_queue_input_int_bufs(inst); + if (ret) + return ret; + ret =3D set_stage(inst, STAGE); + if (ret) + return ret; + ret =3D set_pipe(inst, PIPE); + if (ret) + return ret; + } + + drain_pending =3D inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; + + if (!drain_pending && inst->state =3D=3D IRIS_INST_INPUT_STREAMING) { + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret =3D iris_hfi_resume(inst, INPUT_MPLANE, HFI_CMD_SETTINGS_CHANGE); + if (ret) + return ret; + clear_sub_state |=3D IRIS_INST_SUB_INPUT_PAUSE; + } + } + + ret =3D iris_hfi_start(inst, OUTPUT_MPLANE); + if (ret) + return ret; + + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) + clear_sub_state |=3D IRIS_INST_SUB_OUTPUT_PAUSE; + + ret =3D iris_inst_state_change_streamon(inst, OUTPUT_MPLANE); + if (ret) + return ret; + + ret =3D iris_inst_change_sub_state(inst, clear_sub_state, 0); + + return ret; +} + +int vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf) +{ + struct vb2_v4l2_buffer *vbuf; + + if (!vb2 || !buf) + return -EINVAL; + + vbuf =3D to_vb2_v4l2_buffer(vb2); + + buf->fd =3D vb2->planes[0].m.fd; + buf->data_offset =3D vb2->planes[0].data_offset; + buf->data_size =3D vb2->planes[0].bytesused - vb2->planes[0].data_offset; + buf->buffer_size =3D vb2->planes[0].length; + buf->timestamp =3D vb2->timestamp; + buf->flags =3D vbuf->flags; + buf->attr =3D 0; + + return 0; +} + int iris_pm_get(struct iris_core *core) { int ret; diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h b/drive= rs/media/platform/qcom/vcodec/iris/iris_helpers.h index 39cec8c..bf8448a 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h +++ b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h @@ -31,7 +31,9 @@ int close_session(struct iris_inst *inst); bool is_linear_colorformat(u32 colorformat); bool is_10bit_colorformat(enum colorformat_type colorformat); bool is_8bit_colorformat(enum colorformat_type colorformat); +bool is_scaling_enabled(struct iris_inst *inst); bool is_split_mode_enabled(struct iris_inst *inst); +bool is_hierb_type_requested(struct iris_inst *inst); int signal_session_msg_receipt(struct iris_inst *inst, enum signal_session_response cmd); struct iris_inst *to_instance(struct iris_core *core, u32 session_id); @@ -54,6 +56,10 @@ void iris_destroy_buffers(struct iris_inst *inst); int session_streamoff(struct iris_inst *inst, u32 plane); int process_resume(struct iris_inst *inst); int codec_change(struct iris_inst *inst, u32 v4l2_codec); +int process_streamon_input(struct iris_inst *inst); +int process_streamon_output(struct iris_inst *inst); +int vb2_buffer_to_driver(struct vb2_buffer *vb2, + struct iris_buffer *buf); int iris_pm_get(struct iris_core *core); int iris_pm_put(struct iris_core *core, bool autosuspend); int iris_pm_get_put(struct iris_core *core); diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c b/drivers/m= edia/platform/qcom/vcodec/iris/iris_hfi.c index 00e598d..4a54293 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c @@ -356,7 +356,7 @@ int iris_hfi_session_set_default_header(struct iris_ins= t *inst) ret =3D hfi_packet_session_property(inst, HFI_PROP_DEC_DEFAULT_HEADER, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32, &default_header, sizeof(u32)); @@ -394,7 +394,7 @@ int iris_hfi_start(struct iris_inst *inst, u32 plane) HFI_CMD_START, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - get_hfi_port(plane), + get_hfi_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -434,7 +434,7 @@ int iris_hfi_stop(struct iris_inst *inst, u32 plane) (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED | HFI_HOST_FLAGS_NON_DISCARDABLE), - get_hfi_port(plane), + get_hfi_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -472,7 +472,7 @@ int iris_hfi_session_subscribe_mode(struct iris_inst *i= nst, cmd, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - get_hfi_port(plane), + get_hfi_port(inst, plane), inst->session_id, payload_type, payload, @@ -511,7 +511,7 @@ int iris_hfi_pause(struct iris_inst *inst, u32 plane) HFI_CMD_PAUSE, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - get_hfi_port(plane), + get_hfi_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -550,7 +550,7 @@ int iris_hfi_resume(struct iris_inst *inst, u32 plane, = u32 payload) HFI_CMD_RESUME, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - get_hfi_port(plane), + get_hfi_port(inst, plane), inst->session_id, HFI_PAYLOAD_U32, &payload, @@ -590,7 +590,7 @@ int iris_hfi_drain(struct iris_inst *inst, u32 plane) (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED | HFI_HOST_FLAGS_NON_DISCARDABLE), - get_hfi_port(plane), + get_hfi_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -739,14 +739,14 @@ int iris_hfi_queue_buffer(struct iris_inst *inst, goto unlock; } =20 - ret =3D get_hfi_buffer(buffer, &hfi_buffer); + ret =3D get_hfi_buffer(inst, buffer, &hfi_buffer); if (ret) goto unlock; =20 ret =3D hfi_packet_session_command(inst, HFI_CMD_BUFFER, HFI_HOST_FLAGS_INTR_REQUIRED, - get_hfi_port_from_buffer_type(buffer->type), + get_hfi_port_from_buffer_type(inst, buffer->type), inst->session_id, HFI_PAYLOAD_STRUCTURE, &hfi_buffer, @@ -780,7 +780,7 @@ int iris_hfi_release_buffer(struct iris_inst *inst, goto unlock; } =20 - ret =3D get_hfi_buffer(buffer, &hfi_buffer); + ret =3D get_hfi_buffer(inst, buffer, &hfi_buffer); if (ret) goto unlock; =20 @@ -790,7 +790,7 @@ int iris_hfi_release_buffer(struct iris_inst *inst, HFI_CMD_BUFFER, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - get_hfi_port_from_buffer_type(buffer->type), + get_hfi_port_from_buffer_type(inst, buffer->type), inst->session_id, HFI_PAYLOAD_STRUCTURE, &hfi_buffer, diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c b/dr= ivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c index dd27fa4..e9f3749 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c @@ -3,64 +3,108 @@ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights res= erved. */ =20 +#include "iris_common.h" #include "iris_core.h" #include "iris_helpers.h" #include "iris_hfi_packet.h" #include "hfi_defines.h" =20 -u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type) +u32 get_hfi_port_from_buffer_type(struct iris_inst *inst, enum iris_buffer= _type buffer_type) { u32 hfi_port =3D HFI_PORT_NONE; =20 - switch (buffer_type) { - case BUF_INPUT: - case BUF_BIN: - case BUF_COMV: - case BUF_NON_COMV: - case BUF_LINE: - hfi_port =3D HFI_PORT_BITSTREAM; - break; - case BUF_OUTPUT: - case BUF_DPB: - hfi_port =3D HFI_PORT_RAW; - break; - case BUF_PERSIST: - hfi_port =3D HFI_PORT_NONE; - break; - default: - break; + if (inst->domain =3D=3D DECODER) { + switch (buffer_type) { + case BUF_INPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + hfi_port =3D HFI_PORT_BITSTREAM; + break; + case BUF_OUTPUT: + case BUF_DPB: + hfi_port =3D HFI_PORT_RAW; + break; + case BUF_PERSIST: + hfi_port =3D HFI_PORT_NONE; + break; + default: + break; + } + } else if (inst->domain =3D=3D ENCODER) { + switch (buffer_type) { + case BUF_INPUT: + case BUF_VPSS: + hfi_port =3D HFI_PORT_RAW; + break; + case BUF_OUTPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + case BUF_DPB: + hfi_port =3D HFI_PORT_BITSTREAM; + break; + case BUF_ARP: + hfi_port =3D HFI_PORT_NONE; + break; + default: + break; + } } =20 return hfi_port; } =20 -u32 get_hfi_port(u32 plane) +u32 get_hfi_port(struct iris_inst *inst, u32 plane) { u32 hfi_port =3D HFI_PORT_NONE; =20 - switch (plane) { - case INPUT_MPLANE: - hfi_port =3D HFI_PORT_BITSTREAM; - break; - case OUTPUT_MPLANE: - hfi_port =3D HFI_PORT_RAW; - break; - default: - break; + if (inst->domain =3D=3D DECODER) { + switch (plane) { + case INPUT_MPLANE: + hfi_port =3D HFI_PORT_BITSTREAM; + break; + case OUTPUT_MPLANE: + hfi_port =3D HFI_PORT_RAW; + break; + default: + break; + } + } else if (inst->domain =3D=3D ENCODER) { + switch (plane) { + case INPUT_MPLANE: + hfi_port =3D HFI_PORT_RAW; + break; + case OUTPUT_MPLANE: + hfi_port =3D HFI_PORT_BITSTREAM; + break; + default: + break; + } } =20 return hfi_port; } =20 -static u32 hfi_buf_type_from_driver(enum iris_buffer_type buffer_type) +static u32 hfi_buf_type_from_driver(enum domain_type domain, enum iris_buf= fer_type buffer_type) { switch (buffer_type) { case BUF_INPUT: - return HFI_BUFFER_BITSTREAM; + if (domain =3D=3D DECODER) + return HFI_BUFFER_BITSTREAM; + else + return HFI_BUFFER_RAW; case BUF_OUTPUT: - return HFI_BUFFER_RAW; + if (domain =3D=3D DECODER) + return HFI_BUFFER_RAW; + else + return HFI_BUFFER_BITSTREAM; case BUF_BIN: return HFI_BUFFER_BIN; + case BUF_ARP: + return HFI_BUFFER_ARP; case BUF_COMV: return HFI_BUFFER_COMV; case BUF_NON_COMV: @@ -76,13 +120,19 @@ static u32 hfi_buf_type_from_driver(enum iris_buffer_t= ype buffer_type) } } =20 -u32 hfi_buf_type_to_driver(enum hfi_buffer_type buf_type) +u32 hfi_buf_type_to_driver(enum domain_type domain, enum hfi_buffer_type b= uf_type) { switch (buf_type) { case HFI_BUFFER_BITSTREAM: - return BUF_INPUT; + if (domain =3D=3D DECODER) + return BUF_INPUT; + else + return BUF_OUTPUT; case HFI_BUFFER_RAW: - return BUF_OUTPUT; + if (domain =3D=3D DECODER) + return BUF_OUTPUT; + else + return BUF_INPUT; case HFI_BUFFER_BIN: return BUF_BIN; case HFI_BUFFER_ARP: @@ -108,9 +158,15 @@ u32 get_hfi_codec(struct iris_inst *inst) { switch (inst->codec) { case H264: - return HFI_CODEC_DECODE_AVC; + if (inst->domain =3D=3D ENCODER) + return HFI_CODEC_ENCODE_AVC; + else + return HFI_CODEC_DECODE_AVC; case HEVC: - return HFI_CODEC_DECODE_HEVC; + if (inst->domain =3D=3D ENCODER) + return HFI_CODEC_ENCODE_HEVC; + else + return HFI_CODEC_DECODE_HEVC; case VP9: return HFI_CODEC_DECODE_VP9; default: @@ -337,10 +393,11 @@ u32 get_v4l2_matrix_coefficients(u32 hfi_coefficients) return coefficients; } =20 -int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf) +int get_hfi_buffer(struct iris_inst *inst, + struct iris_buffer *buffer, struct hfi_buffer *buf) { - memset(buf, 0, sizeof(*buf)); - buf->type =3D hfi_buf_type_from_driver(buffer->type); + memset(buf, 0, sizeof(struct hfi_buffer)); + buf->type =3D hfi_buf_type_from_driver(inst->domain, buffer->type); buf->index =3D buffer->index; buf->base_address =3D buffer->device_addr; buf->addr_offset =3D 0; @@ -350,7 +407,7 @@ int get_hfi_buffer(struct iris_buffer *buffer, struct h= fi_buffer *buf) * buffer size otherwise it will truncate or ignore the data after 256 * aligned size which may lead to error concealment */ - if (buffer->type =3D=3D BUF_INPUT) + if (inst->domain =3D=3D DECODER && buffer->type =3D=3D BUF_INPUT) buf->buffer_size =3D ALIGN(buffer->buffer_size, 256); buf->data_offset =3D buffer->data_offset; buf->data_size =3D buffer->data_size; diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h b/dr= ivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h index 82148b7..734a070 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h +++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h @@ -80,8 +80,8 @@ enum hfi_packet_port_type { HFI_PORT_RAW =3D 0x00000002, }; =20 -u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type); -u32 get_hfi_port(u32 plane); +u32 get_hfi_port_from_buffer_type(struct iris_inst *inst, enum iris_buffer= _type buffer_type); +u32 get_hfi_port(struct iris_inst *inst, u32 plane); u32 get_hfi_colorformat(u32 colorformat); u32 get_hfi_codec(struct iris_inst *inst); u32 get_hfi_color_primaries(u32 primaries); @@ -90,8 +90,9 @@ u32 get_hfi_matrix_coefficients(u32 coefficients); u32 get_v4l2_color_primaries(u32 hfi_primaries); u32 get_v4l2_transfer_char(u32 hfi_characterstics); u32 get_v4l2_matrix_coefficients(u32 hfi_coefficients); -u32 hfi_buf_type_to_driver(enum hfi_buffer_type buf_type); -int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf); +u32 hfi_buf_type_to_driver(enum domain_type domain, enum hfi_buffer_type b= uf_type); +int get_hfi_buffer(struct iris_inst *inst, + struct iris_buffer *buffer, struct hfi_buffer *buf); =20 int hfi_packet_sys_init(struct iris_core *core, u8 *pkt, u32 pkt_size); diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c b/= drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c index 1b667a5..08bdb8f 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c @@ -71,7 +71,8 @@ static bool is_valid_hfi_buffer_type(u32 buffer_type) static bool is_valid_hfi_port(u32 port, u32 buffer_type) { if (port =3D=3D HFI_PORT_NONE && - buffer_type !=3D HFI_BUFFER_PERSIST) + buffer_type !=3D HFI_BUFFER_ARP && + buffer_type !=3D HFI_BUFFER_PERSIST) return false; =20 if (port !=3D HFI_PORT_BITSTREAM && port !=3D HFI_PORT_RAW) @@ -103,8 +104,9 @@ static int get_driver_buffer_flags(struct iris_inst *in= st, u32 hfi_flags) if (inst->hfi_frame_info.overflow) driver_flags |=3D BUF_FLAG_ERROR; =20 - if (hfi_flags & HFI_BUF_FW_FLAG_LAST || - hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST) + if ((inst->domain =3D=3D ENCODER && (hfi_flags & HFI_BUF_FW_FLAG_LAST)) || + (inst->domain =3D=3D DECODER && (hfi_flags & HFI_BUF_FW_FLAG_LAST || + hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST))) driver_flags |=3D BUF_FLAG_LAST; =20 return driver_flags; @@ -309,9 +311,12 @@ static int handle_session_close(struct iris_inst *inst, static int handle_read_only_buffer(struct iris_inst *inst, struct iris_buffer *buf) { - struct iris_buffer *ro_buf, *iter; + struct iris_buffer *ro_buf, *iter =3D NULL; bool found =3D false; =20 + if (inst->domain !=3D DECODER && inst->domain !=3D ENCODER) + return 0; + list_for_each_entry(iter, &inst->buffers.read_only.list, list) { if (iter->device_addr =3D=3D buf->device_addr) { found =3D true; @@ -344,6 +349,9 @@ static int handle_non_read_only_buffer(struct iris_inst= *inst, { struct iris_buffer *ro_buf; =20 + if (inst->domain !=3D DECODER && inst->domain !=3D ENCODER) + return 0; + list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) { if (ro_buf->device_addr =3D=3D buffer->base_address) { ro_buf->attr &=3D ~BUF_ATTR_READ_ONLY; @@ -414,9 +422,9 @@ static int handle_input_buffer(struct iris_inst *inst, static int handle_output_buffer(struct iris_inst *inst, struct hfi_buffer *hfi_buffer) { - struct iris_buffers *buffers; struct iris_buffer *buf, *iter; - bool found; + struct iris_buffers *buffers; + bool found, fatal =3D false; int ret =3D 0; =20 if (hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST) { @@ -425,17 +433,19 @@ static int handle_output_buffer(struct iris_inst *ins= t, return ret; } =20 - if (hfi_buffer->flags & HFI_BUF_FW_FLAG_RELEASE_DONE) - return handle_release_output_buffer(inst, hfi_buffer); + if (inst->domain =3D=3D DECODER) { + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_RELEASE_DONE) + return handle_release_output_buffer(inst, hfi_buffer); =20 - if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { - ret =3D iris_inst_sub_state_change_drc_last(inst); - if (ret) - return ret; - } + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { + ret =3D iris_inst_sub_state_change_drc_last(inst); + if (ret) + return ret; + } =20 - if (!(hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY)) - ret =3D handle_non_read_only_buffer(inst, hfi_buffer); + if (!(hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY)) + ret =3D handle_non_read_only_buffer(inst, hfi_buffer); + } =20 buffers =3D iris_get_buffer_list(inst, BUF_OUTPUT); if (!buffers) @@ -446,9 +456,12 @@ static int handle_output_buffer(struct iris_inst *inst, if (!(iter->attr & BUF_ATTR_QUEUED)) continue; =20 - found =3D (iter->index =3D=3D hfi_buffer->index && - iter->device_addr =3D=3D hfi_buffer->base_address && - iter->data_offset =3D=3D hfi_buffer->data_offset); + if (inst->domain =3D=3D DECODER) + found =3D (iter->index =3D=3D hfi_buffer->index && + iter->device_addr =3D=3D hfi_buffer->base_address && + iter->data_offset =3D=3D hfi_buffer->data_offset); + else + found =3D iter->index =3D=3D hfi_buffer->index; =20 if (found) { buf =3D iter; @@ -465,14 +478,27 @@ static int handle_output_buffer(struct iris_inst *ins= t, buf->attr &=3D ~BUF_ATTR_QUEUED; buf->attr |=3D BUF_ATTR_DEQUEUED; =20 - if (inst->buffers.dpb.size && hfi_buffer->flags & HFI_BUF_FW_FLAG_READONL= Y) - iris_inst_change_state(inst, IRIS_INST_ERROR); + if (inst->domain =3D=3D ENCODER) { + if (inst->hfi_frame_info.data_corrupt) + fatal =3D true; + if (inst->hfi_frame_info.overflow) { + if (!hfi_buffer->data_size && inst->hfi_rc_type =3D=3D HFI_RC_CBR_CFR) + fatal =3D true; + } + if (fatal) + iris_inst_change_state(inst, IRIS_INST_ERROR); + } + + if (inst->domain =3D=3D DECODER) { + if (inst->buffers.dpb.size && hfi_buffer->flags & HFI_BUF_FW_FLAG_READON= LY) + iris_inst_change_state(inst, IRIS_INST_ERROR); =20 - if (hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY) { - buf->attr |=3D BUF_ATTR_READ_ONLY; - ret =3D handle_read_only_buffer(inst, buf); - } else { - buf->attr &=3D ~BUF_ATTR_READ_ONLY; + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY) { + buf->attr |=3D BUF_ATTR_READ_ONLY; + ret =3D handle_read_only_buffer(inst, buf); + } else { + buf->attr &=3D ~BUF_ATTR_READ_ONLY; + } } =20 buf->flags =3D get_driver_buffer_flags(inst, hfi_buffer->flags); @@ -521,7 +547,7 @@ static int handle_release_internal_buffer(struct iris_i= nst *inst, int ret =3D 0; bool found; =20 - buffers =3D iris_get_buffer_list(inst, hfi_buf_type_to_driver(buffer->typ= e)); + buffers =3D iris_get_buffer_list(inst, hfi_buf_type_to_driver(inst->domai= n, buffer->type)); if (!buffers) return -EINVAL; =20 @@ -550,12 +576,22 @@ static int handle_session_stop(struct iris_inst *inst, int ret =3D 0; enum signal_session_response signal_type =3D -1; =20 - if (pkt->port =3D=3D HFI_PORT_RAW) { - signal_type =3D SIGNAL_CMD_STOP_OUTPUT; - ret =3D iris_inst_sub_state_change_pause(inst, OUTPUT_MPLANE); - } else if (pkt->port =3D=3D HFI_PORT_BITSTREAM) { - signal_type =3D SIGNAL_CMD_STOP_INPUT; - ret =3D iris_inst_sub_state_change_pause(inst, INPUT_MPLANE); + if (inst->domain =3D=3D DECODER) { + if (pkt->port =3D=3D HFI_PORT_RAW) { + signal_type =3D SIGNAL_CMD_STOP_OUTPUT; + ret =3D iris_inst_sub_state_change_pause(inst, OUTPUT_MPLANE); + } else if (pkt->port =3D=3D HFI_PORT_BITSTREAM) { + signal_type =3D SIGNAL_CMD_STOP_INPUT; + ret =3D iris_inst_sub_state_change_pause(inst, INPUT_MPLANE); + } + } else if (inst->domain =3D=3D ENCODER) { + if (pkt->port =3D=3D HFI_PORT_RAW) { + signal_type =3D SIGNAL_CMD_STOP_INPUT; + ret =3D iris_inst_sub_state_change_pause(inst, INPUT_MPLANE); + } else if (pkt->port =3D=3D HFI_PORT_BITSTREAM) { + signal_type =3D SIGNAL_CMD_STOP_OUTPUT; + ret =3D iris_inst_sub_state_change_pause(inst, OUTPUT_MPLANE); + } } =20 if (signal_type !=3D -1) @@ -571,7 +607,7 @@ static int handle_session_buffer(struct iris_inst *inst, u32 hfi_handle_size =3D 0; int i, ret =3D 0; const struct iris_hfi_buffer_handle *hfi_handle_arr =3D NULL; - static const struct iris_hfi_buffer_handle input_hfi_handle[] =3D { + static const struct iris_hfi_buffer_handle dec_input_hfi_handle[] =3D { {HFI_BUFFER_BITSTREAM, handle_input_buffer }, {HFI_BUFFER_BIN, handle_release_internal_buffer }, {HFI_BUFFER_COMV, handle_release_internal_buffer }, @@ -579,10 +615,24 @@ static int handle_session_buffer(struct iris_inst *in= st, {HFI_BUFFER_LINE, handle_release_internal_buffer }, {HFI_BUFFER_PERSIST, handle_release_internal_buffer }, }; - static const struct iris_hfi_buffer_handle output_hfi_handle[] =3D { + static const struct iris_hfi_buffer_handle dec_output_hfi_handle[] =3D { {HFI_BUFFER_RAW, handle_output_buffer }, {HFI_BUFFER_DPB, handle_release_internal_buffer }, }; + static const struct iris_hfi_buffer_handle enc_input_hfi_handle[] =3D { + {HFI_BUFFER_RAW, handle_input_buffer }, + {HFI_BUFFER_VPSS, handle_release_internal_buffer }, + }; + static const struct iris_hfi_buffer_handle enc_output_hfi_handle[] =3D { + {HFI_BUFFER_BITSTREAM, handle_output_buffer }, + {HFI_BUFFER_BIN, handle_release_internal_buffer }, + {HFI_BUFFER_COMV, handle_release_internal_buffer }, + {HFI_BUFFER_NON_COMV, handle_release_internal_buffer }, + {HFI_BUFFER_LINE, handle_release_internal_buffer }, + {HFI_BUFFER_ARP, handle_release_internal_buffer }, + {HFI_BUFFER_DPB, handle_release_internal_buffer }, + }; + =20 if (pkt->payload_info =3D=3D HFI_PAYLOAD_NONE) return 0; @@ -599,12 +649,22 @@ static int handle_session_buffer(struct iris_inst *in= st, if (!is_valid_hfi_port(pkt->port, buffer->type)) return 0; =20 - if (pkt->port =3D=3D HFI_PORT_BITSTREAM) { - hfi_handle_size =3D ARRAY_SIZE(input_hfi_handle); - hfi_handle_arr =3D input_hfi_handle; - } else if (pkt->port =3D=3D HFI_PORT_RAW) { - hfi_handle_size =3D ARRAY_SIZE(output_hfi_handle); - hfi_handle_arr =3D output_hfi_handle; + if (inst->domain =3D=3D DECODER) { + if (pkt->port =3D=3D HFI_PORT_BITSTREAM) { + hfi_handle_size =3D ARRAY_SIZE(dec_input_hfi_handle); + hfi_handle_arr =3D dec_input_hfi_handle; + } else if (pkt->port =3D=3D HFI_PORT_RAW) { + hfi_handle_size =3D ARRAY_SIZE(dec_output_hfi_handle); + hfi_handle_arr =3D dec_output_hfi_handle; + } + } else if (inst->domain =3D=3D ENCODER) { + if (pkt->port =3D=3D HFI_PORT_RAW) { + hfi_handle_size =3D ARRAY_SIZE(enc_input_hfi_handle); + hfi_handle_arr =3D enc_input_hfi_handle; + } else if (pkt->port =3D=3D HFI_PORT_BITSTREAM) { + hfi_handle_size =3D ARRAY_SIZE(enc_output_hfi_handle); + hfi_handle_arr =3D enc_output_hfi_handle; + } } =20 if (!hfi_handle_arr || !hfi_handle_size) @@ -693,6 +753,9 @@ static int handle_dpb_list_property(struct iris_inst *i= nst, u8 *payload_start; u32 payload_size; =20 + if (inst->domain !=3D DECODER) + return -EINVAL; + payload_size =3D pkt->size - sizeof(*pkt); payload_start =3D (u8 *)((u8 *)pkt + sizeof(*pkt)); memset(inst->dpb_list_payload, 0, MAX_DPB_LIST_ARRAY_SIZE); diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c b/drivers/m= edia/platform/qcom/vcodec/iris/iris_vb2.c index c0878f1..1a434ff 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c @@ -13,6 +13,7 @@ #include "iris_power.h" #include "iris_vb2.h" #include "iris_vdec.h" +#include "iris_venc.h" =20 int iris_vb2_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, @@ -58,7 +59,8 @@ int iris_vb2_queue_setup(struct vb2_queue *q, return ret; } =20 - if (q->type =3D=3D V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if ((inst->domain =3D=3D DECODER && q->type =3D=3D V4L2_BUF_TYPE_VIDEO_OU= TPUT_MPLANE) || + (inst->domain =3D=3D ENCODER && q->type =3D=3D V4L2_BUF_TYPE_VIDEO_CA= PTURE_MPLANE)) { ret =3D adjust_v4l2_properties(inst); if (ret) return ret; @@ -112,6 +114,11 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsi= gned int count) goto error; } =20 + if (inst->domain !=3D DECODER && inst->domain !=3D ENCODER) { + ret =3D -EINVAL; + goto error; + } + ret =3D iris_pm_get(inst->core); if (ret) goto error; @@ -122,21 +129,34 @@ int iris_vb2_start_streaming(struct vb2_queue *q, uns= igned int count) if (ret) goto err_pm_get; =20 - ret =3D iris_hfi_session_set_default_header(inst); - if (ret) - goto err_pm_get; - - ret =3D iris_alloc_and_queue_session_int_bufs(inst, BUF_PERSIST); - if (ret) - goto err_pm_get; + if (inst->domain =3D=3D ENCODER) { + ret =3D iris_alloc_and_queue_session_int_bufs(inst, BUF_ARP); + if (ret) + goto err_pm_get; + } else if (inst->domain =3D=3D DECODER) { + ret =3D iris_hfi_session_set_default_header(inst); + if (ret) + goto err_pm_get; + + ret =3D iris_alloc_and_queue_session_int_bufs(inst, BUF_PERSIST); + if (ret) + goto err_pm_get; + } } =20 iris_scale_power(inst); =20 - if (q->type =3D=3D INPUT_MPLANE) - ret =3D vdec_streamon_input(inst); - else if (q->type =3D=3D OUTPUT_MPLANE) - ret =3D vdec_streamon_output(inst); + if (q->type =3D=3D INPUT_MPLANE) { + if (inst->domain =3D=3D DECODER) + ret =3D vdec_streamon_input(inst); + else if (inst->domain =3D=3D ENCODER) + ret =3D venc_streamon_input(inst); + } else if (q->type =3D=3D OUTPUT_MPLANE) { + if (inst->domain =3D=3D DECODER) + ret =3D vdec_streamon_output(inst); + else if (inst->domain =3D=3D ENCODER) + ret =3D venc_streamon_output(inst); + } if (ret) goto err_pm_get; =20 @@ -179,6 +199,11 @@ void iris_vb2_stop_streaming(struct vb2_queue *q) if (q->type !=3D INPUT_MPLANE && q->type !=3D OUTPUT_MPLANE) goto error; =20 + if (inst->domain !=3D DECODER && inst->domain !=3D ENCODER) { + ret =3D -EINVAL; + goto error; + } + ret =3D iris_pm_get_put(inst->core); if (ret) goto error; @@ -225,7 +250,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) if (ret) goto exit; =20 - ret =3D vdec_qbuf(inst, vb2); + if (inst->domain =3D=3D DECODER) + ret =3D vdec_qbuf(inst, vb2); + else if (inst->domain =3D=3D ENCODER) + ret =3D venc_qbuf(inst, vb2); =20 exit: if (ret) { @@ -270,7 +298,7 @@ void *iris_vb2_attach_dmabuf(struct vb2_buffer *vb, str= uct device *dev, buf->inst =3D inst; buf->dmabuf =3D dbuf; =20 - if (buf->type =3D=3D BUF_OUTPUT) { + if (inst->domain =3D=3D DECODER && buf->type =3D=3D BUF_OUTPUT) { list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, l= ist) { if (ro_buf->dmabuf !=3D buf->dmabuf) continue; @@ -307,7 +335,7 @@ int iris_vb2_map_dmabuf(void *buf_priv) return -EINVAL; } =20 - if (buf->type =3D=3D BUF_OUTPUT) { + if (inst->domain =3D=3D DECODER && buf->type =3D=3D BUF_OUTPUT) { list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, l= ist) { if (ro_buf->dmabuf !=3D buf->dmabuf) continue; @@ -356,7 +384,7 @@ void iris_vb2_unmap_dmabuf(void *buf_priv) return; } =20 - if (buf->type =3D=3D BUF_OUTPUT) { + if (inst->domain =3D=3D DECODER && buf->type =3D=3D BUF_OUTPUT) { list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, l= ist) { if (ro_buf->dmabuf !=3D buf->dmabuf) continue; @@ -393,7 +421,7 @@ void iris_vb2_detach_dmabuf(void *buf_priv) buf->sg_table =3D NULL; } =20 - if (buf->type =3D=3D BUF_OUTPUT) { + if (inst->domain =3D=3D DECODER && buf->type =3D=3D BUF_OUTPUT) { list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, l= ist) { if (ro_buf->dmabuf !=3D buf->dmabuf) continue; diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c b/drivers/= media/platform/qcom/vcodec/iris/iris_vdec.c index 300d0e9..b2d4739 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c @@ -362,7 +362,7 @@ static int vdec_set_bitstream_resolution(struct iris_in= st *inst) return iris_hfi_set_property(inst, HFI_PROP_BITSTREAM_RESOLUTION, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32, &resolution, sizeof(u32)); @@ -388,7 +388,7 @@ static int vdec_set_crop_offsets(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_CROP_OFFSETS, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_64_PACKED, &payload, sizeof(u64)); @@ -409,7 +409,7 @@ static int vdec_set_bit_depth(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_LUMA_CHROMA_BIT_DEPTH, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32, &bitdepth, sizeof(u32)); @@ -426,7 +426,7 @@ static int vdec_set_coded_frames(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_CODED_FRAMES, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32, &coded_frames, sizeof(u32)); @@ -442,7 +442,7 @@ static int vdec_set_min_output_count(struct iris_inst *= inst) return iris_hfi_set_property(inst, HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32, &min_output, sizeof(u32)); @@ -457,7 +457,7 @@ static int vdec_set_picture_order_count(struct iris_ins= t *inst) return iris_hfi_set_property(inst, HFI_PROP_PIC_ORDER_CNT_TYPE, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32, &poc, sizeof(u32)); @@ -509,7 +509,7 @@ static int vdec_set_colorspace(struct iris_inst *inst) ret =3D iris_hfi_set_property(inst, HFI_PROP_SIGNAL_COLOR_INFO, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_32_PACKED, &color_info, sizeof(u32)); @@ -527,7 +527,7 @@ static int vdec_set_profile(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_PROFILE, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32_ENUM, &profile, sizeof(u32)); @@ -543,7 +543,7 @@ static int vdec_set_level(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_LEVEL, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32_ENUM, &level, sizeof(u32)); @@ -559,7 +559,7 @@ static int vdec_set_tier(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_TIER, HFI_HOST_FLAGS_NONE, - get_hfi_port(INPUT_MPLANE), + get_hfi_port(inst, INPUT_MPLANE), HFI_PAYLOAD_U32_ENUM, &tier, sizeof(u32)); @@ -811,7 +811,7 @@ static int vdec_set_colorformat(struct iris_inst *inst) return iris_hfi_set_property(inst, HFI_PROP_COLOR_FORMAT, HFI_HOST_FLAGS_NONE, - get_hfi_port(OUTPUT_MPLANE), + get_hfi_port(inst, OUTPUT_MPLANE), HFI_PAYLOAD_U32, &hfi_colorformat, sizeof(u32)); @@ -839,7 +839,7 @@ static int vdec_set_linear_stride_scanline(struct iris_= inst *inst) return iris_hfi_set_property(inst, HFI_PROP_LINEAR_STRIDE_SCANLINE, HFI_HOST_FLAGS_NONE, - get_hfi_port(OUTPUT_MPLANE), + get_hfi_port(inst, OUTPUT_MPLANE), HFI_PAYLOAD_U64, &payload, sizeof(u64)); @@ -887,7 +887,7 @@ static int vdec_set_ubwc_stride_scanline(struct iris_in= st *inst) return iris_hfi_set_property(inst, HFI_PROP_UBWC_STRIDE_SCANLINE, HFI_HOST_FLAGS_NONE, - get_hfi_port(OUTPUT_MPLANE), + get_hfi_port(inst, OUTPUT_MPLANE), HFI_PAYLOAD_U32_ARRAY, &payload[0], sizeof(u32) * 4); @@ -1020,7 +1020,7 @@ static int vdec_subscribe_dst_change_param(struct iri= s_inst *inst) ret =3D iris_hfi_set_property(inst, prop_type, HFI_HOST_FLAGS_NONE, - get_hfi_port(OUTPUT_MPLANE), + get_hfi_port(inst, OUTPUT_MPLANE), payload_type, &payload, payload_size); @@ -1032,42 +1032,6 @@ static int vdec_subscribe_dst_change_param(struct ir= is_inst *inst) return ret; } =20 -static int process_streamon_input(struct iris_inst *inst) -{ - enum iris_inst_sub_state set_sub_state =3D IRIS_INST_SUB_NONE; - int ret; - - iris_scale_power(inst); - - ret =3D iris_hfi_start(inst, INPUT_MPLANE); - if (ret) - return ret; - - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret =3D 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) { - if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { - ret =3D iris_hfi_pause(inst, INPUT_MPLANE); - if (ret) - return ret; - set_sub_state =3D IRIS_INST_SUB_INPUT_PAUSE; - } - } - - ret =3D iris_inst_state_change_streamon(inst, INPUT_MPLANE); - if (ret) - return ret; - - ret =3D iris_inst_change_sub_state(inst, 0, set_sub_state); - - return ret; -} - int vdec_streamon_input(struct iris_inst *inst) { int ret; @@ -1114,58 +1078,6 @@ int vdec_streamon_input(struct iris_inst *inst) return ret; } =20 -static int process_streamon_output(struct iris_inst *inst) -{ - enum iris_inst_sub_state clear_sub_state =3D IRIS_INST_SUB_NONE; - bool drain_pending =3D false; - int ret; - - iris_scale_power(inst); - - if (inst->sub_state & IRIS_INST_SUB_DRC && - inst->sub_state & IRIS_INST_SUB_DRC_LAST) - clear_sub_state =3D IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; - - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret =3D iris_alloc_and_queue_input_int_bufs(inst); - if (ret) - return ret; - ret =3D set_stage(inst, STAGE); - if (ret) - return ret; - ret =3D set_pipe(inst, PIPE); - if (ret) - return ret; - } - - drain_pending =3D inst->sub_state & IRIS_INST_SUB_DRAIN && - inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; - - if (!drain_pending && inst->state =3D=3D IRIS_INST_INPUT_STREAMING) { - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret =3D iris_hfi_resume(inst, INPUT_MPLANE, HFI_CMD_SETTINGS_CHANGE); - if (ret) - return ret; - clear_sub_state |=3D IRIS_INST_SUB_INPUT_PAUSE; - } - } - - ret =3D iris_hfi_start(inst, OUTPUT_MPLANE); - if (ret) - return ret; - - if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) - clear_sub_state |=3D IRIS_INST_SUB_OUTPUT_PAUSE; - - ret =3D iris_inst_state_change_streamon(inst, OUTPUT_MPLANE); - if (ret) - return ret; - - ret =3D iris_inst_change_sub_state(inst, clear_sub_state, 0); - - return ret; -} - int vdec_streamon_output(struct iris_inst *inst) { int ret; @@ -1220,27 +1132,6 @@ int vdec_streamon_output(struct iris_inst *inst) return ret; } =20 -static int vb2_buffer_to_driver(struct vb2_buffer *vb2, - struct iris_buffer *buf) -{ - struct vb2_v4l2_buffer *vbuf; - - if (!vb2 || !buf) - return -EINVAL; - - vbuf =3D to_vb2_v4l2_buffer(vb2); - - buf->fd =3D vb2->planes[0].m.fd; - buf->data_offset =3D vb2->planes[0].data_offset; - buf->data_size =3D vb2->planes[0].bytesused - vb2->planes[0].data_offset; - buf->buffer_size =3D vb2->planes[0].length; - buf->timestamp =3D vb2->timestamp; - buf->flags =3D vbuf->flags; - buf->attr =3D 0; - - return 0; -} - int vdec_qbuf(struct iris_inst *inst, struct vb2_buffer *vb2) { struct iris_buffer *buf =3D NULL; diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_venc.c b/drivers/= media/platform/qcom/vcodec/iris/iris_venc.c index 802db40..28c6b20 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_venc.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_venc.c @@ -13,6 +13,23 @@ #include "iris_power.h" #include "iris_venc.h" =20 +#define SCALE_FACTOR 8 +#define UNSPECIFIED_COLOR_FORMAT 5 + +static const u32 enc_input_properties[] =3D { + HFI_PROP_NO_OUTPUT, +}; + +static const u32 enc_output_properties[] =3D { + HFI_PROP_PICTURE_TYPE, + HFI_PROP_BUFFER_MARK, +}; + +struct venc_prop_type_handle { + u32 type; + int (*handle)(struct iris_inst *inst); +}; + int venc_inst_init(struct iris_inst *inst) { struct v4l2_format *f; @@ -523,3 +540,409 @@ int venc_stop_cmd(struct iris_inst *inst) =20 return ret; } + +int venc_qbuf(struct iris_inst *inst, struct vb2_buffer *vb2) +{ + struct iris_buffer *buf =3D NULL; + int ret; + + buf =3D get_driver_buf(inst, vb2->type, vb2->index); + if (!buf) + return -EINVAL; + + ret =3D vb2_buffer_to_driver(vb2, buf); + if (ret) + return ret; + + if (!allow_qbuf(inst, vb2->type)) { + buf->attr |=3D BUF_ATTR_DEFERRED; + return 0; + } + + iris_scale_power(inst); + + return queue_buffer(inst, buf); +} + +static int check_scaling_supported(struct iris_inst *inst) +{ + u32 iwidth, owidth, iheight, oheight; + + if (!(inst->crop.left !=3D inst->compose.left || + inst->crop.top !=3D inst->compose.top || + inst->crop.width !=3D inst->compose.width || + inst->crop.height !=3D inst->compose.height)) + return 0; + + iwidth =3D inst->crop.width; + iheight =3D inst->crop.height; + owidth =3D inst->compose.width; + oheight =3D inst->compose.height; + + if (owidth > iwidth || oheight > iheight) + return -EINVAL; + + if (iwidth > owidth * SCALE_FACTOR || iheight > oheight * SCALE_FACTOR) + return -EINVAL; + + return 0; +} + +static int venc_set_colorformat(struct iris_inst *inst) +{ + u32 hfi_colorformat; + u32 pixelformat; + + pixelformat =3D inst->fmt_src->fmt.pix_mp.pixelformat; + hfi_colorformat =3D get_hfi_colorformat(pixelformat); + + return iris_hfi_set_property(inst, + HFI_PROP_COLOR_FORMAT, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, INPUT_MPLANE), + HFI_PAYLOAD_U32_ENUM, + &hfi_colorformat, + sizeof(u32)); +} + +static int venc_set_stride_scanline(struct iris_inst *inst) +{ + u32 color_format, stride_y, scanline_y; + u32 stride_uv =3D 0, scanline_uv =3D 0; + u32 payload[2]; + + color_format =3D inst->cap[PIX_FMTS].value; + if (!is_linear_colorformat(color_format)) + return 0; + + stride_y =3D color_format =3D=3D FMT_TP10C ? + ALIGN(inst->fmt_src->fmt.pix_mp.width, 192) : + ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + scanline_y =3D color_format =3D=3D FMT_TP10C ? + ALIGN(inst->fmt_src->fmt.pix_mp.height, 16) : + ALIGN(inst->fmt_src->fmt.pix_mp.height, 32); + + if (color_format =3D=3D FMT_NV12 || + color_format =3D=3D FMT_NV21) { + stride_uv =3D stride_y; + scanline_uv =3D scanline_y / 2; + } + + payload[0] =3D stride_y << 16 | scanline_y; + payload[1] =3D stride_uv << 16 | scanline_uv; + + return iris_hfi_set_property(inst, + HFI_PROP_LINEAR_STRIDE_SCANLINE, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, INPUT_MPLANE), + HFI_PAYLOAD_64_PACKED, + &payload, + sizeof(u64)); +} + +static int venc_set_raw_resolution(struct iris_inst *inst) +{ + u32 resolution; + + resolution =3D (inst->fmt_src->fmt.pix_mp.width << 16) | + inst->fmt_src->fmt.pix_mp.height; + + return iris_hfi_set_property(inst, + HFI_PROP_RAW_RESOLUTION, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, INPUT_MPLANE), + HFI_PAYLOAD_32_PACKED, + &resolution, + sizeof(u32)); +} + +static int venc_set_bitstream_resolution(struct iris_inst *inst) +{ + u32 resolution; + + resolution =3D (inst->fmt_dst->fmt.pix_mp.width << 16) | + inst->fmt_dst->fmt.pix_mp.height; + + return iris_hfi_set_property(inst, + HFI_PROP_BITSTREAM_RESOLUTION, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, OUTPUT_MPLANE), + HFI_PAYLOAD_32_PACKED, + &resolution, + sizeof(u32)); +} + +static int venc_set_inp_crop_offsets(struct iris_inst *inst) +{ + u32 left_offset, top_offset, right_offset, bottom_offset; + u32 crop[2] =3D {0}; + u32 width, height; + + left_offset =3D inst->crop.left; + top_offset =3D inst->crop.top; + width =3D inst->crop.width; + height =3D inst->crop.height; + + right_offset =3D (inst->fmt_src->fmt.pix_mp.width - width); + bottom_offset =3D (inst->fmt_src->fmt.pix_mp.height - height); + + crop[0] =3D left_offset << 16 | top_offset; + crop[1] =3D right_offset << 16 | bottom_offset; + + return iris_hfi_set_property(inst, + HFI_PROP_CROP_OFFSETS, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, INPUT_MPLANE), + HFI_PAYLOAD_64_PACKED, + &crop, + sizeof(u64)); +} + +static int venc_set_out_crop_offsets(struct iris_inst *inst) +{ + u32 left_offset, top_offset, right_offset, bottom_offset; + u32 crop[2] =3D {0}; + u32 width, height; + + left_offset =3D inst->compose.left; + top_offset =3D inst->compose.top; + width =3D inst->compose.width; + height =3D inst->compose.height; + if (inst->cap[ROTATION].value =3D=3D 90 || inst->cap[ROTATION].value =3D= =3D 270) { + width =3D inst->compose.height; + height =3D inst->compose.width; + } + + right_offset =3D (inst->fmt_dst->fmt.pix_mp.width - width); + bottom_offset =3D (inst->fmt_dst->fmt.pix_mp.height - height); + + crop[0] =3D left_offset << 16 | top_offset; + crop[1] =3D right_offset << 16 | bottom_offset; + + return iris_hfi_set_property(inst, + HFI_PROP_CROP_OFFSETS, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, OUTPUT_MPLANE), + HFI_PAYLOAD_64_PACKED, + &crop, + sizeof(u64)); +} + +static int venc_set_colorspace(struct iris_inst *inst) +{ + u32 video_signal_type_present_flag =3D 0, payload =3D 0; + u32 matrix_coeff =3D HFI_MATRIX_COEFF_RESERVED; + u32 video_format =3D UNSPECIFIED_COLOR_FORMAT; + struct v4l2_pix_format_mplane *pixmp =3D NULL; + u32 transfer_char =3D HFI_TRANSFER_RESERVED; + u32 colour_description_present_flag =3D 0; + u32 primaries =3D HFI_PRIMARIES_RESERVED; + u32 full_range =3D 0; + + pixmp =3D &inst->fmt_src->fmt.pix_mp; + if (pixmp->colorspace !=3D V4L2_COLORSPACE_DEFAULT || + pixmp->ycbcr_enc !=3D V4L2_YCBCR_ENC_DEFAULT || + pixmp->xfer_func !=3D V4L2_XFER_FUNC_DEFAULT) { + colour_description_present_flag =3D 1; + video_signal_type_present_flag =3D 1; + primaries =3D get_hfi_color_primaries(pixmp->colorspace); + matrix_coeff =3D get_hfi_matrix_coefficients(pixmp->ycbcr_enc); + transfer_char =3D get_hfi_transfer_char(pixmp->xfer_func); + } + + if (pixmp->quantization !=3D V4L2_QUANTIZATION_DEFAULT) { + video_signal_type_present_flag =3D 1; + full_range =3D pixmp->quantization =3D=3D + V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0; + } + + payload =3D (matrix_coeff & 0xFF) | + ((transfer_char << 8) & 0xFF00) | + ((primaries << 16) & 0xFF0000) | + ((colour_description_present_flag << 24) & 0x1000000) | + ((full_range << 25) & 0x2000000) | + ((video_format << 26) & 0x1C000000) | + ((video_signal_type_present_flag << 29) & 0x20000000); + + return iris_hfi_set_property(inst, + HFI_PROP_SIGNAL_COLOR_INFO, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, INPUT_MPLANE), + HFI_PAYLOAD_32_PACKED, + &payload, + sizeof(u32)); +} + +static int venc_set_quality_mode(struct iris_inst *inst) +{ + u32 mode; + + mode =3D decide_quality_mode(inst); + return iris_hfi_set_property(inst, + HFI_PROP_QUALITY_MODE, + HFI_HOST_FLAGS_NONE, + HFI_PORT_BITSTREAM, + HFI_PAYLOAD_U32_ENUM, + &mode, + sizeof(u32)); +} + +static int venc_set_input_properties(struct iris_inst *inst) +{ + int j, ret; + static const struct venc_prop_type_handle prop_type_handle_arr[] =3D { + {HFI_PROP_COLOR_FORMAT, venc_set_colorformat = }, + {HFI_PROP_RAW_RESOLUTION, venc_set_raw_resolution = }, + {HFI_PROP_CROP_OFFSETS, venc_set_inp_crop_offsets = }, + {HFI_PROP_LINEAR_STRIDE_SCANLINE, venc_set_stride_scanline = }, + {HFI_PROP_SIGNAL_COLOR_INFO, venc_set_colorspace = }, + }; + + for (j =3D 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) { + ret =3D prop_type_handle_arr[j].handle(inst); + if (ret) + return ret; + } + + return ret; +} + +static int venc_property_subscription(struct iris_inst *inst, u32 plane) +{ + u32 payload[32] =3D {0}; + u32 payload_size =3D 0; + u32 i; + + payload[0] =3D HFI_MODE_PROPERTY; + if (plane =3D=3D INPUT_MPLANE) { + for (i =3D 0; i < ARRAY_SIZE(enc_input_properties); i++) + payload[i + 1] =3D enc_input_properties[i]; + payload_size =3D (ARRAY_SIZE(enc_input_properties) + 1) * + sizeof(u32); + } else if (plane =3D=3D OUTPUT_MPLANE) { + for (i =3D 0; i < ARRAY_SIZE(enc_output_properties); i++) + payload[i + 1] =3D enc_output_properties[i]; + payload_size =3D (ARRAY_SIZE(enc_output_properties) + 1) * + sizeof(u32); + } else { + return -EINVAL; + } + + return iris_hfi_session_subscribe_mode(inst, + HFI_CMD_SUBSCRIBE_MODE, + plane, + HFI_PAYLOAD_U32_ARRAY, + &payload[0], + payload_size); +} + +int venc_streamon_input(struct iris_inst *inst) +{ + int ret; + + ret =3D check_session_supported(inst); + if (ret) + goto error; + + ret =3D check_scaling_supported(inst); + if (ret) + goto error; + + ret =3D venc_set_input_properties(inst); + if (ret) + goto error; + + ret =3D iris_get_internal_buffers(inst, INPUT_MPLANE); + if (ret) + goto error; + + ret =3D iris_destroy_internal_buffers(inst, INPUT_MPLANE); + if (ret) + goto error; + + ret =3D iris_create_input_internal_buffers(inst); + if (ret) + goto error; + + ret =3D iris_queue_input_internal_buffers(inst); + if (ret) + goto error; + + ret =3D venc_property_subscription(inst, INPUT_MPLANE); + if (ret) + goto error; + + ret =3D process_streamon_input(inst); + if (ret) + goto error; + + return ret; + +error: + return ret; +} + +static int venc_set_output_properties(struct iris_inst *inst) +{ + int j, ret; + static const struct venc_prop_type_handle prop_type_handle_arr[] =3D { + {HFI_PROP_BITSTREAM_RESOLUTION, venc_set_bitstream_resolution }, + {HFI_PROP_CROP_OFFSETS, venc_set_out_crop_offsets }, + }; + + for (j =3D 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) { + ret =3D prop_type_handle_arr[j].handle(inst); + if (ret) + return ret; + } + + return ret; +} + +int venc_streamon_output(struct iris_inst *inst) +{ + int ret; + + ret =3D venc_set_output_properties(inst); + if (ret) + goto error; + + ret =3D set_v4l2_properties(inst); + if (ret) + goto error; + + ret =3D venc_set_quality_mode(inst); + if (ret) + goto error; + + ret =3D iris_get_internal_buffers(inst, OUTPUT_MPLANE); + if (ret) + goto error; + + ret =3D iris_destroy_internal_buffers(inst, OUTPUT_MPLANE); + if (ret) + goto error; + + ret =3D iris_create_output_internal_buffers(inst); + if (ret) + goto error; + + ret =3D iris_queue_output_internal_buffers(inst); + if (ret) + goto error; + + ret =3D venc_property_subscription(inst, OUTPUT_MPLANE); + if (ret) + goto error; + + ret =3D process_streamon_output(inst); + if (ret) + goto error; + + return ret; + +error: + session_streamoff(inst, OUTPUT_MPLANE); + + return ret; +} diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_venc.h b/drivers/= media/platform/qcom/vcodec/iris/iris_venc.h index 24da63f..b289750 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_venc.h +++ b/drivers/media/platform/qcom/vcodec/iris/iris_venc.h @@ -20,5 +20,8 @@ int venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); int venc_start_cmd(struct iris_inst *inst); int venc_stop_cmd(struct iris_inst *inst); +int venc_qbuf(struct iris_inst *inst, struct vb2_buffer *vb2); +int venc_streamon_input(struct iris_inst *inst); +int venc_streamon_output(struct iris_inst *inst); =20 #endif diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_common.h b/dr= ivers/media/platform/qcom/vcodec/iris/platform_common.h index effecbb..42ac662 100644 --- a/drivers/media/platform/qcom/vcodec/iris/platform_common.h +++ b/drivers/media/platform/qcom/vcodec/iris/platform_common.h @@ -71,6 +71,11 @@ enum pipe_type { PIPE_4 =3D 4, }; =20 +enum quality_mode { + MAX_QUALITY_MODE =3D 0x1, + POWER_SAVE_MODE =3D 0x2, +}; + extern struct platform_data sm8550_data; =20 struct bw_info { diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c b/dr= ivers/media/platform/qcom/vcodec/iris/platform_sm8550.c index ef0aad7..17c5856 100644 --- a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c +++ b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c @@ -74,6 +74,8 @@ static struct plat_core_cap core_data_sm8550[] =3D { {CP_SIZE, 0x25800000}, {CP_NONPIXEL_START, 0x01000000}, {CP_NONPIXEL_SIZE, 0x24800000}, + {MAX_MBPF_HQ, 8160}, /* ((1920x1088)/256) */ + {MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */ }; =20 static struct plat_inst_cap instance_cap_data_sm8550[] =3D { diff --git a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c b/d= rivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c index 44f9342..9882f00 100644 --- a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c +++ b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c @@ -163,6 +163,186 @@ static u32 dec_dpb_size_iris3(struct iris_inst *inst) return size; } =20 +static u32 enc_bin_size_iris3(struct iris_inst *inst) +{ + u32 width, height, num_vpp_pipes, stage, profile; + struct iris_core *core; + struct v4l2_format *f; + u32 size =3D 0; + + core =3D inst->core; + + num_vpp_pipes =3D core->cap[NUM_VPP_PIPE].value; + stage =3D inst->cap[STAGE].value; + f =3D inst->fmt_dst; + width =3D f->fmt.pix_mp.width; + height =3D f->fmt.pix_mp.height; + profile =3D inst->cap[PROFILE].value; + + if (inst->codec =3D=3D H264) + size =3D hfi_buffer_bin_h264e(inst->hfi_rc_type, width, height, + stage, num_vpp_pipes, profile); + else if (inst->codec =3D=3D HEVC) + size =3D hfi_buffer_bin_h265e(inst->hfi_rc_type, width, height, + stage, num_vpp_pipes, profile); + + return size; +} + +u32 get_recon_buf_count(struct iris_inst *inst) +{ + s32 n_bframe, ltr_count, hp_layers =3D 0, hb_layers =3D 0; + bool is_hybrid_hp =3D false; + u32 num_buf_recon =3D 0; + u32 hfi_codec =3D 0; + + n_bframe =3D inst->cap[B_FRAME].value; + ltr_count =3D inst->cap[LTR_COUNT].value; + + if (inst->hfi_layer_type =3D=3D HFI_HIER_B) { + hb_layers =3D inst->cap[ENH_LAYER_COUNT].value + 1; + } else { + hp_layers =3D inst->cap[ENH_LAYER_COUNT].value + 1; + if (inst->hfi_layer_type =3D=3D HFI_HIER_P_HYBRID_LTR) + is_hybrid_hp =3D true; + } + + if (inst->codec =3D=3D H264) + hfi_codec =3D HFI_CODEC_ENCODE_AVC; + else if (inst->codec =3D=3D HEVC) + hfi_codec =3D HFI_CODEC_ENCODE_HEVC; + + num_buf_recon =3D hfi_iris3_enc_recon_buf_count(n_bframe, ltr_count, + hp_layers, hb_layers, + is_hybrid_hp, hfi_codec); + + return num_buf_recon; +} + +static u32 enc_comv_size_iris3(struct iris_inst *inst) +{ + u32 width, height, num_recon =3D 0; + struct v4l2_format *f; + u32 size =3D 0; + + f =3D inst->fmt_dst; + width =3D f->fmt.pix_mp.width; + height =3D f->fmt.pix_mp.height; + + num_recon =3D get_recon_buf_count(inst); + if (inst->codec =3D=3D H264) + size =3D hfi_buffer_comv_h264e(width, height, num_recon); + else if (inst->codec =3D=3D HEVC) + size =3D hfi_buffer_comv_h265e(width, height, num_recon); + + return size; +} + +static u32 enc_non_comv_size_iris3(struct iris_inst *inst) +{ + u32 width, height, num_vpp_pipes; + struct iris_core *core; + struct v4l2_format *f; + u32 size =3D 0; + + core =3D inst->core; + + num_vpp_pipes =3D core->cap[NUM_VPP_PIPE].value; + f =3D inst->fmt_dst; + width =3D f->fmt.pix_mp.width; + height =3D f->fmt.pix_mp.height; + + if (inst->codec =3D=3D H264) + size =3D hfi_buffer_non_comv_h264e(width, height, num_vpp_pipes); + else if (inst->codec =3D=3D HEVC) + size =3D hfi_buffer_non_comv_h265e(width, height, num_vpp_pipes); + + return size; +} + +static u32 enc_line_size_iris3(struct iris_inst *inst) +{ + u32 width, height, pixfmt, num_vpp_pipes; + struct iris_core *core; + bool is_tenbit =3D false; + struct v4l2_format *f; + u32 size =3D 0; + + core =3D inst->core; + num_vpp_pipes =3D core->cap[NUM_VPP_PIPE].value; + pixfmt =3D inst->cap[PIX_FMTS].value; + + f =3D inst->fmt_dst; + width =3D f->fmt.pix_mp.width; + height =3D f->fmt.pix_mp.height; + is_tenbit =3D (pixfmt =3D=3D FMT_TP10C); + + if (inst->codec =3D=3D H264) + size =3D hfi_buffer_line_h264e(width, height, is_tenbit, num_vpp_pipes); + else if (inst->codec =3D=3D HEVC) + size =3D hfi_buffer_line_h265e(width, height, is_tenbit, num_vpp_pipes); + + return size; +} + +static u32 enc_dpb_size_iris3(struct iris_inst *inst) +{ + u32 width, height, pixfmt; + struct v4l2_format *f; + bool is_tenbit; + u32 size =3D 0; + + f =3D inst->fmt_dst; + width =3D f->fmt.pix_mp.width; + height =3D f->fmt.pix_mp.height; + + pixfmt =3D inst->cap[PIX_FMTS].value; + is_tenbit =3D (pixfmt =3D=3D FMT_TP10C); + + if (inst->codec =3D=3D H264) + size =3D hfi_buffer_dpb_h264e(width, height); + else if (inst->codec =3D=3D HEVC) + size =3D hfi_buffer_dpb_h265e(width, height, is_tenbit); + + return size; +} + +static u32 enc_arp_size_iris3(struct iris_inst *inst) +{ + u32 size =3D 0; + + HFI_BUFFER_ARP_ENC(size); + + return size; +} + +static u32 enc_vpss_size_iris3(struct iris_inst *inst) +{ + bool ds_enable =3D false, is_tenbit =3D false; + struct v4l2_format *f; + u32 width, height; + u32 size =3D 0; + + ds_enable =3D is_scaling_enabled(inst); + + f =3D inst->fmt_dst; + if (inst->cap[ROTATION].value =3D=3D 90 || + inst->cap[ROTATION].value =3D=3D 270) { + width =3D f->fmt.pix_mp.height; + height =3D f->fmt.pix_mp.width; + } else { + width =3D f->fmt.pix_mp.width; + height =3D f->fmt.pix_mp.height; + } + + f =3D inst->fmt_src; + is_tenbit =3D is_10bit_colorformat(f->fmt.pix_mp.pixelformat); + + size =3D hfi_buffer_vpss_enc(width, height, ds_enable, 0, is_tenbit); + + return size; +} + struct iris_buf_type_handle { enum iris_buffer_type type; u32 (*handle)(struct iris_inst *inst); @@ -183,9 +363,23 @@ int iris_int_buf_size_iris3(struct iris_inst *inst, {BUF_PERSIST, dec_persist_size_iris3 }, {BUF_DPB, dec_dpb_size_iris3 }, }; + static const struct iris_buf_type_handle enc_internal_buf_type_handle[] = =3D { + {BUF_BIN, enc_bin_size_iris3 }, + {BUF_COMV, enc_comv_size_iris3 }, + {BUF_NON_COMV, enc_non_comv_size_iris3 }, + {BUF_LINE, enc_line_size_iris3 }, + {BUF_DPB, enc_dpb_size_iris3 }, + {BUF_ARP, enc_arp_size_iris3 }, + {BUF_VPSS, enc_vpss_size_iris3 }, + }; =20 - buf_type_handle_size =3D ARRAY_SIZE(dec_internal_buf_type_handle); - buf_type_handle_arr =3D dec_internal_buf_type_handle; + if (inst->domain =3D=3D DECODER) { + buf_type_handle_size =3D ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr =3D dec_internal_buf_type_handle; + } else if (inst->domain =3D=3D ENCODER) { + buf_type_handle_size =3D ARRAY_SIZE(enc_internal_buf_type_handle); + buf_type_handle_arr =3D enc_internal_buf_type_handle; + } =20 if (!buf_type_handle_arr || !buf_type_handle_size) return size; diff --git a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h b/d= rivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h index b520c79..c63b3ac 100644 --- a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h +++ b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h @@ -14,8 +14,10 @@ =20 #define DMA_ALIGNMENT 256 =20 +#define BUFFER_ALIGNMENT_4096_BYTES 4096 #define BUFFER_ALIGNMENT_512_BYTES 512 #define BUFFER_ALIGNMENT_256_BYTES 256 +#define BUFFER_ALIGNMENT_128_BYTES 128 #define BUFFER_ALIGNMENT_64_BYTES 64 #define BUFFER_ALIGNMENT_32_BYTES 32 #define BUFFER_ALIGNMENT_16_BYTES 16 @@ -26,6 +28,8 @@ #define HFI_COL_FMT_NV12C_Y_TILE_WIDTH (32) #define HFI_COL_FMT_NV12C_UV_TILE_HEIGHT (8) #define HFI_COL_FMT_NV12C_UV_TILE_WIDTH (16) +#define HFI_COL_FMT_TP10C_Y_TILE_HEIGHT (4) +#define HFI_COL_FMT_TP10C_Y_TILE_WIDTH (48) =20 #define NUM_HW_PIC_BUF 32 #define SIZE_HW_PIC(size_per_buf) (NUM_HW_PIC_BUF * (size_per_buf)) @@ -102,6 +106,27 @@ #define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE (64 * 2 * 3) #define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 =20 +#define HFI_BUFFER_ARP_ENC(size) (size =3D 204800) + +#define HFI_MAX_COL_FRAME 6 +#define HFI_VENUS_WIDTH_ALIGNMENT 128 +#define HFI_VENUS_HEIGHT_ALIGNMENT 32 +#define VENUS_METADATA_STRIDE_MULTIPLE 64 +#define VENUS_METADATA_HEIGHT_MULTIPLE 16 + +#ifndef SYSTEM_LAL_TILE10 +#define SYSTEM_LAL_TILE10 192 +#endif + +#define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, BUFFER_ALIGNMENT_256_BYTES)) +#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_WORKMODE_1 1 +#define HFI_WORKMODE_2 2 + static inline u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) @@ -842,4 +867,603 @@ u32 hfi_yuv420_tp10_ubwc_calc_buf_size(u32 y_stride, = u32 y_buf_height, int iris_int_buf_size_iris3(struct iris_inst *inst, enum iris_buffer_type buffer_type); =20 +static inline +u32 hfi_iris3_enc_recon_buf_count(s32 n_bframe, s32 ltr_count, + s32 _total_hp_layers, + s32 _total_hb_layers, + bool hybrid_hp, + u32 codec_standard) +{ + u32 num_ref =3D 1; + + if (n_bframe) + num_ref =3D 2; + + if (_total_hp_layers > 1) { + if (hybrid_hp) + num_ref =3D (_total_hp_layers + 1) >> 1; + else if (codec_standard =3D=3D HFI_CODEC_ENCODE_HEVC) + num_ref =3D (_total_hp_layers + 1) >> 1; + else if (codec_standard =3D=3D HFI_CODEC_ENCODE_AVC && + _total_hp_layers < 4) + num_ref =3D (_total_hp_layers - 1); + else + num_ref =3D _total_hp_layers; + } + + if (ltr_count) + num_ref =3D num_ref + ltr_count; + + if (_total_hb_layers > 1) { + if (codec_standard =3D=3D HFI_CODEC_ENCODE_HEVC) + num_ref =3D (_total_hb_layers); + else if (codec_standard =3D=3D HFI_CODEC_ENCODE_AVC) + num_ref =3D (1 << (_total_hb_layers - 2)) + 1; + } + + return num_ref + 1; +} + +static inline +u32 size_bin_bitstream_enc(u32 rc_type, u32 frame_width, u32 frame_height, + u32 work_mode, u32 lcu_size, u32 profile) +{ + u32 size_aligned_width =3D 0, size_aligned_height =3D 0; + u32 bitstream_size_eval =3D 0; + + size_aligned_width =3D ALIGN((frame_width), lcu_size); + size_aligned_height =3D ALIGN((frame_height), lcu_size); + if (work_mode =3D=3D HFI_WORKMODE_2) { + if (rc_type =3D=3D HFI_RC_CQ || rc_type =3D=3D HFI_RC_OFF) { + bitstream_size_eval =3D (((size_aligned_width) * + (size_aligned_height) * 3) >> 1); + } else { + bitstream_size_eval =3D ((size_aligned_width) * + (size_aligned_height) * 3); + if ((size_aligned_width * size_aligned_height) > (4096 * 2176)) + bitstream_size_eval >>=3D 3; + else if ((size_aligned_width * size_aligned_height) > (480 * 320)) + bitstream_size_eval >>=3D 2; + + if (profile =3D=3D HFI_H265_PROFILE_MAIN_10 || + profile =3D=3D HFI_H265_PROFILE_MAIN_10_STILL_PICTURE) + bitstream_size_eval =3D (bitstream_size_eval * 5 >> 2); + } + } else { + bitstream_size_eval =3D size_aligned_width * size_aligned_height * 3; + } + + return ALIGN(bitstream_size_eval, BUFFER_ALIGNMENT_256_BYTES); +} + +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_single_pipe_eval =3D 0, sao_bin_buffer_size =3D 0; + u32 size_aligned_width =3D 0, size_aligned_height =3D 0; + u32 _padded_bin_sz =3D 0; + + size_aligned_width =3D ALIGN((frame_width), lcu_size); + size_aligned_height =3D ALIGN((frame_height), lcu_size); + if ((size_aligned_width * size_aligned_height) > (3840 * 2160)) + size_single_pipe_eval =3D (bitbin_size / num_vpp_pipes); + else if (num_vpp_pipes > 2) + size_single_pipe_eval =3D bitbin_size / 2; + else + size_single_pipe_eval =3D bitbin_size; + + sao_bin_buffer_size =3D + (64 * ((((frame_width) + BUFFER_ALIGNMENT_32_BYTES) * + ((frame_height) + BUFFER_ALIGNMENT_32_BYTES)) >> 10)) + 384; + _padded_bin_sz =3D ALIGN(size_single_pipe_eval, BUFFER_ALIGNMENT_256_BYTE= S); + size_single_pipe_eval =3D sao_bin_buffer_size + _padded_bin_sz; + size_single_pipe_eval =3D ALIGN(size_single_pipe_eval, BUFFER_ALIGNMENT_2= 56_BYTES); + + return size_single_pipe_eval; +} + +static inline +u32 hfi_buffer_bin_enc(u32 rc_type, u32 frame_width, u32 frame_height, u32= lcu_size, + u32 work_mode, u32 num_vpp_pipes, u32 profile) +{ + u32 bitstream_size =3D 0, total_bitbin_buffers =3D 0; + u32 size_single_pipe =3D 0, bitbin_size =3D 0; + u32 _size =3D 0; + + bitstream_size =3D size_bin_bitstream_enc(rc_type, frame_width, + frame_height, work_mode, + lcu_size, profile); + + if (work_mode =3D=3D HFI_WORKMODE_2) { + total_bitbin_buffers =3D 3; + bitbin_size =3D bitstream_size * 12 / 10; + bitbin_size =3D ALIGN(bitbin_size, BUFFER_ALIGNMENT_256_BYTES); + } else if ((lcu_size =3D=3D 16) || (num_vpp_pipes > 1)) { + total_bitbin_buffers =3D 1; + bitbin_size =3D bitstream_size; + } + + if (total_bitbin_buffers > 0) { + size_single_pipe =3D size_enc_single_pipe(rc_type, bitbin_size, + num_vpp_pipes, frame_width, + frame_height, lcu_size); + bitbin_size =3D size_single_pipe * num_vpp_pipes; + _size =3D ALIGN(bitbin_size, BUFFER_ALIGNMENT_256_BYTES) * + total_bitbin_buffers + 512; + } else { + /* Avoid 512 Bytes allocation in case of 1Pipe HEVC Direct Mode*/ + _size =3D 0; + } + + return _size; +} + +static inline +u32 hfi_buffer_bin_h264e(u32 rc_type, u32 frame_width, u32 frame_height, + u32 work_mode, u32 num_vpp_pipes, u32 profile) +{ + return hfi_buffer_bin_enc(rc_type, frame_width, frame_height, 16, + work_mode, num_vpp_pipes, profile); +} + +static inline +u32 hfi_buffer_bin_h265e(u32 rc_type, u32 frame_width, u32 frame_height, + u32 work_mode, u32 num_vpp_pipes, u32 profile) +{ + return hfi_buffer_bin_enc(rc_type, frame_width, frame_height, 32, + work_mode, num_vpp_pipes, profile); +} + +static inline +u32 size_enc_slice_info_buf(u32 num_lcu_in_frame) +{ + return ALIGN((256 + (num_lcu_in_frame << 4)), BUFFER_ALIGNMENT_256_BYTES); +} + +static inline +u32 size_line_buf_ctrl(u32 frame_width_coded) +{ + return ALIGN(frame_width_coded, BUFFER_ALIGNMENT_256_BYTES); +} + +static inline +u32 size_line_buf_ctrl_id2(u32 frame_width_coded) +{ + return ALIGN(frame_width_coded, BUFFER_ALIGNMENT_256_BYTES); +} + +static inline +u32 size_linebuff_data(bool is_ten_bit, u32 frame_width_coded) +{ + u32 _size =3D 0; + + _size =3D is_ten_bit ? + (((((10 * (frame_width_coded) + 1024) + (BUFFER_ALIGNMENT_256_BYTES - 1)= ) & + (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 1) + + (((((10 * (frame_width_coded) + 1024) >> 1) + (BUFFER_ALIGNMENT_256_BYT= ES - 1)) & + (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 2)) : + (((((8 * (frame_width_coded) + 1024) + (BUFFER_ALIGNMENT_256_BYTES - 1))= & + (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 1) + + (((((8 * (frame_width_coded) + 1024) >> 1) + (BUFFER_ALIGNMENT_256_BYTE= S - 1)) & + (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 2)); + + return _size; +} + +static inline +u32 size_left_linebuff_ctrl(u32 standard, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + u32 _size =3D 0; + + _size =3D standard =3D=3D HFI_CODEC_ENCODE_HEVC ? + (((frame_height_coded) + + (BUFFER_ALIGNMENT_32_BYTES)) / BUFFER_ALIGNMENT_32_BYTES * 4 * 16) : + (((frame_height_coded) + 15) / 16 * 5 * 16); + + if ((num_vpp_pipes_enc) > 1) { + _size +=3D BUFFER_ALIGNMENT_512_BYTES; + _size =3D ALIGN(_size, BUFFER_ALIGNMENT_512_BYTES) * + num_vpp_pipes_enc; + } + + return ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES); +} + +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) + BUFFER_ALIGNMENT_2= 56_BYTES) + + (BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1) & + (~((BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1)) * 1; +} + +static inline +u32 size_top_linebuff_ctrl_fe(u32 frame_width_coded, u32 standard) +{ + u32 _size =3D 0; + + _size =3D standard =3D=3D HFI_CODEC_ENCODE_HEVC ? + (64 * ((frame_width_coded) >> 5)) : + (BUFFER_ALIGNMENT_256_BYTES + 16 * ((frame_width_coded) >> 4)); + + return ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES); +} + +static inline +u32 size_left_linebuff_ctrl_fe(u32 frame_height_coded, u32 num_vpp_pipes_e= nc) +{ + return (((BUFFER_ALIGNMENT_256_BYTES + 64 * ((frame_height_coded) >> 4)) + + (BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1) & + (~((BUFFER_ALIGNMENT_256_BYTES << (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) +{ + u32 _size =3D 0; + + _size =3D ((BUFFER_ALIGNMENT_256_BYTES + 64 * ((frame_height_coded) / + (8 * (is_ten_bit ? 4 : 8))))); + _size =3D ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES); + + return (_size * 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) +{ + u32 _size =3D 0; + + _size =3D ((BUFFER_ALIGNMENT_256_BYTES + 64 * ((frame_height_coded) / + (4 * (is_ten_bit ? 4 : 8))))); + _size =3D ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES); + + return (_size * 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)), + BUFFER_ALIGNMENT_256_BYTES); +} + +static inline +u32 size_frame_rc_buf_size(u32 standard, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + u32 _size =3D 0; + + _size =3D (standard =3D=3D HFI_CODEC_ENCODE_HEVC) ? + (256 + 16 * (14 + ((((frame_height_coded) >> 5) + 7) >> 3))) : + (256 + 16 * (14 + ((((frame_height_coded) >> 4) + 7) >> 3))); + _size *=3D 11; + if (num_vpp_pipes_enc > 1) + _size =3D ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES) * num_vpp_pipes_enc; + + return ALIGN(_size, BUFFER_ALIGNMENT_512_BYTES) * HFI_MAX_COL_FRAME; +} + +static inline u32 enc_bitcnt_buf_size(u32 num_lcu_in_frame) +{ + return ALIGN((256 + (4 * (num_lcu_in_frame))), BUFFER_ALIGNMENT_256_BYTES= ); +} + +static inline u32 enc_bitmap_buf_size(u32 num_lcu_in_frame) +{ + return ALIGN((256 + ((num_lcu_in_frame) >> 3)), BUFFER_ALIGNMENT_256_BYTE= S); +} + +static inline u32 size_line_buf_sde(u32 frame_width_coded) +{ + return ALIGN((256 + (16 * ((frame_width_coded) >> 4))), BUFFER_ALIGNMENT_= 256_BYTES); +} + +static inline u32 size_override_buf(u32 num_lcumb) +{ + return ALIGN(((16 * (((num_lcumb) + 7) >> 3))), BUFFER_ALIGNMENT_256_BYTE= S) * 2; +} + +static inline u32 size_ir_buf(u32 num_lcu_in_frame) +{ + return ALIGN((((((num_lcu_in_frame) << 1) + 7) & (~7)) * 3), BUFFER_ALIGN= MENT_256_BYTES); +} + +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)), + BUFFER_ALIGNMENT_256_BYTES); +} + +static inline +u32 size_top_line_buf_first_stg_sao(u32 frame_width_coded) +{ + return ALIGN((16 * ((frame_width_coded) >> 5)), BUFFER_ALIGNMENT_256_BYTE= S); +} + +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 line_buff_data_size =3D 0, left_line_buff_ctrl_size =3D 0; + u32 frame_width_coded =3D 0, frame_height_coded =3D 0; + u32 left_line_buff_metadata_recon__uv__size =3D 0; + u32 left_line_buff_metadata_recon__y__size =3D 0; + u32 width_in_lcus =3D 0, height_in_lcus =3D 0; + u32 left_line_buff_recon_pix_size =3D 0; + u32 top_line_buff_ctrl_fe_size =3D 0; + u32 line_buff_recon_pix_size =3D 0; + + width_in_lcus =3D ((frame_width) + (lcu_size) - 1) / (lcu_size); + height_in_lcus =3D ((frame_height) + (lcu_size) - 1) / (lcu_size); + frame_width_coded =3D width_in_lcus * (lcu_size); + frame_height_coded =3D height_in_lcus * (lcu_size); + line_buff_data_size =3D size_linebuff_data(is_ten_bit, frame_width_coded); + left_line_buff_ctrl_size =3D + size_left_linebuff_ctrl(standard, frame_height_coded, num_vpp_pipes_enc); + left_line_buff_recon_pix_size =3D + size_left_linebuff_recon_pix(is_ten_bit, frame_height_coded, + num_vpp_pipes_enc); + top_line_buff_ctrl_fe_size =3D + size_top_linebuff_ctrl_fe(frame_width_coded, standard); + left_line_buff_metadata_recon__y__size =3D + size_left_linebuff_metadata_recon_y(frame_height_coded, is_ten_bit, + num_vpp_pipes_enc); + left_line_buff_metadata_recon__uv__size =3D + size_left_linebuff_metadata_recon_uv(frame_height_coded, is_ten_bit, + num_vpp_pipes_enc); + line_buff_recon_pix_size =3D size_linebuff_recon_pix(is_ten_bit, frame_wi= dth_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 inline +u32 hfi_buffer_line_h264e(u32 frame_width, u32 frame_height, bool is_ten_b= it, + u32 num_vpp_pipes) +{ + return hfi_buffer_line_enc(frame_width, frame_height, 0, + num_vpp_pipes, 16, + HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_line_h265e(u32 frame_width, u32 frame_height, bool is_ten_b= it, + u32 num_vpp_pipes) +{ + return hfi_buffer_line_enc(frame_width, frame_height, + is_ten_bit, num_vpp_pipes, 32, + HFI_CODEC_ENCODE_HEVC); +} + +static inline +u32 hfi_buffer_comv_enc(u32 frame_width, u32 frame_height, u32 lcu_size, + u32 num_recon, u32 standard) +{ + u32 width_in_lcus, height_in_lcus, num_lcu_in_frame; + u32 size_colloc_mv =3D 0, size_colloc_rc =3D 0; + u32 mb_height =3D ((frame_height) + 15) >> 4; + u32 mb_width =3D ((frame_width) + 15) >> 4; + + width_in_lcus =3D ((frame_width) + (lcu_size) - 1) / (lcu_size); + height_in_lcus =3D ((frame_height) + (lcu_size) - 1) / (lcu_size); + num_lcu_in_frame =3D width_in_lcus * height_in_lcus; + size_colloc_mv =3D (standard =3D=3D HFI_CODEC_ENCODE_HEVC) ? + (16 * ((num_lcu_in_frame << 2) + BUFFER_ALIGNMENT_32_BYTES)) : + (3 * 16 * (width_in_lcus * height_in_lcus + BUFFER_ALIGNMENT_32_BYTES)); + size_colloc_mv =3D ALIGN(size_colloc_mv, BUFFER_ALIGNMENT_256_BYTES) * nu= m_recon; + size_colloc_rc =3D (((mb_width + 7) >> 3) * 16 * 2 * mb_height); + size_colloc_rc =3D ALIGN(size_colloc_rc, BUFFER_ALIGNMENT_256_BYTES) * HF= I_MAX_COL_FRAME; + + return size_colloc_mv + size_colloc_rc; +} + +static inline +u32 hfi_buffer_comv_h264e(u32 frame_width, u32 frame_height, u32 num_recon) +{ + return hfi_buffer_comv_enc(frame_width, frame_height, 16, + num_recon, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_comv_h265e(u32 frame_width, u32 frame_height, u32 num_recon) +{ + return hfi_buffer_comv_enc(frame_width, frame_height, 32, + num_recon, HFI_CODEC_ENCODE_HEVC); +} + +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 frame_width_coded =3D 0, frame_height_coded =3D 0; + u32 width_in_lcus =3D 0, height_in_lcus =3D 0; + u32 num_lcu_in_frame =3D 0, num_lcumb =3D 0; + u32 frame_rc_buf_size =3D 0; + + width_in_lcus =3D ((frame_width) + (lcu_size) - 1) / (lcu_size); + height_in_lcus =3D ((frame_height) + (lcu_size) - 1) / (lcu_size); + num_lcu_in_frame =3D width_in_lcus * height_in_lcus; + frame_width_coded =3D width_in_lcus * (lcu_size); + frame_height_coded =3D height_in_lcus * (lcu_size); + num_lcumb =3D (frame_height_coded / lcu_size) * + ((frame_width_coded + lcu_size * 8) / lcu_size); + frame_rc_buf_size =3D + 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 inline +u32 hfi_buffer_non_comv_h264e(u32 frame_width, u32 frame_height, + u32 num_vpp_pipes_enc) +{ + return hfi_buffer_non_comv_enc(frame_width, frame_height, + num_vpp_pipes_enc, 16, + HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_non_comv_h265e(u32 frame_width, u32 frame_height, + u32 num_vpp_pipes_enc) +{ + return hfi_buffer_non_comv_enc(frame_width, frame_height, + num_vpp_pipes_enc, 32, + HFI_CODEC_ENCODE_HEVC); +} + +static inline +u32 size_enc_ref_buffer(u32 frame_width, u32 frame_height) +{ + u32 u_buffer_width =3D 0, u_buffer_height =3D 0; + u32 u_chroma_buffer_height =3D 0; + + u_buffer_height =3D ALIGN(frame_height, HFI_VENUS_HEIGHT_ALIGNMENT); + u_chroma_buffer_height =3D frame_height >> 1; + u_chroma_buffer_height =3D ALIGN(u_chroma_buffer_height, HFI_VENUS_HEIGHT= _ALIGNMENT); + u_buffer_width =3D ALIGN(frame_width, HFI_VENUS_WIDTH_ALIGNMENT); + + 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_buf_height =3D 0, ref_luma_stride_in_bytes =3D 0; + u32 chroma_size =3D 0, ref_buf_size =3D 0; + u32 u_ref_stride =3D 0, luma_size =3D 0; + u32 ref_chrm_height_in_bytes =3D 0; + + ref_buf_height =3D (frame_height + (HFI_VENUS_HEIGHT_ALIGNMENT - 1)) & + (~(HFI_VENUS_HEIGHT_ALIGNMENT - 1)); + ref_luma_stride_in_bytes =3D ((frame_width + SYSTEM_LAL_TILE10 - 1) / SYS= TEM_LAL_TILE10) * + SYSTEM_LAL_TILE10; + u_ref_stride =3D 4 * (ref_luma_stride_in_bytes / 3); + u_ref_stride =3D (u_ref_stride + (BUFFER_ALIGNMENT_128_BYTES - 1)) & + (~(BUFFER_ALIGNMENT_128_BYTES - 1)); + luma_size =3D ref_buf_height * u_ref_stride; + ref_chrm_height_in_bytes =3D (((frame_height + 1) >> 1) + (BUFFER_ALIGNME= NT_32_BYTES - 1)) & + (~(BUFFER_ALIGNMENT_32_BYTES - 1)); + chroma_size =3D u_ref_stride * ref_chrm_height_in_bytes; + luma_size =3D (luma_size + (BUFFER_ALIGNMENT_4096_BYTES - 1)) & + (~(BUFFER_ALIGNMENT_4096_BYTES - 1)); + chroma_size =3D (chroma_size + (BUFFER_ALIGNMENT_4096_BYTES - 1)) & + (~(BUFFER_ALIGNMENT_4096_BYTES - 1)); + ref_buf_size =3D luma_size + chroma_size; + + return ref_buf_size; +} + +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 =3D 0, ref_buf_size =3D 0; + u32 _size =3D 0; + + if (!is_ten_bit) { + ref_buf_size =3D size_enc_ref_buffer(frame_width, frame_height); + metadata_stride =3D + hfi_ubwc_calc_metadata_plane_stride(frame_width, 64, + HFI_COL_FMT_NV12C_Y_TILE_WIDTH); + metadata_buf_height =3D + hfi_ubwc_metadata_plane_bufheight(frame_height, 16, + HFI_COL_FMT_NV12C_Y_TILE_HEIGHT); + meta_size_y =3D + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_heigh= t); + meta_size_c =3D + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_heigh= t); + _size =3D ref_buf_size + meta_size_y + meta_size_c; + } else { + ten_bit_ref_buf_size =3D size_enc_ten_bit_ref_buffer(frame_width, frame_= height); + metadata_stride =3D + hfi_ubwc_calc_metadata_plane_stride(frame_width, + VENUS_METADATA_STRIDE_MULTIPLE, + HFI_COL_FMT_TP10C_Y_TILE_WIDTH); + metadata_buf_height =3D + hfi_ubwc_metadata_plane_bufheight(frame_height, + VENUS_METADATA_HEIGHT_MULTIPLE, + HFI_COL_FMT_TP10C_Y_TILE_HEIGHT); + meta_size_y =3D + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_heigh= t); + meta_size_c =3D + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_heigh= t); + _size =3D ten_bit_ref_buf_size + meta_size_y + meta_size_c; + } + + return _size; +} + +static inline +u32 hfi_buffer_dpb_h264e(u32 frame_width, u32 frame_height) +{ + return hfi_buffer_dpb_enc(frame_width, frame_height, 0); +} + +static inline +u32 hfi_buffer_dpb_h265e(u32 frame_width, u32 frame_height, bool is_ten_bi= t) +{ + return hfi_buffer_dpb_enc(frame_width, frame_height, is_ten_bit); +} + +static inline +u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable, + u32 blur, bool is_ten_bit) +{ + u32 vpss_size =3D 0; + + if (ds_enable || blur) + vpss_size =3D hfi_buffer_dpb_enc(dswidth, dsheight, is_ten_bit); + + return vpss_size; +} + +static inline +u32 hfi_iris3_enc_min_input_buf_count(u32 totalhblayers) +{ + u32 numinput =3D 3; + + if (totalhblayers >=3D 2) + numinput =3D (1 << (totalhblayers - 1)) + 2; + + return numinput; +} + +u32 enc_output_buffer_size_iris3(struct iris_inst *inst); +u32 get_recon_buf_count(struct iris_inst *inst); + #endif diff --git a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c b/dr= ivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c index 58498af..2828227 100644 --- a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c +++ b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c @@ -54,7 +54,7 @@ u64 iris_calc_freq_iris3(struct iris_inst *inst, u32 data= _size) if (inst->cap[STAGE].value =3D=3D STAGE_1) vsp_cycles =3D vsp_cycles * 3; =20 - vsp_cycles +=3D mbs_per_second * base_cycles; + vsp_cycles +=3D mbs_per_second * base_cycles; =20 freq =3D max3(vpp_cycles, vsp_cycles, fw_cycles); =20 --=20 2.7.4