From patchwork Wed Nov 20 14:45:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844626 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 9612C1C1F35; Wed, 20 Nov 2024 14:46:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114019; cv=none; b=gZNyjVQR2TZR1pfxIKHkEHnvvzZmFvRyCS7yWqy4N51W9UYLePtzR8JcwOkwy1jPgFieQDl7WDbq/emSVWRRmYGToK1w4mI6W5qlcW3RL+rZ9Ss7GN0NDYdGkMxaGSYT2UvQXhRmphUsicSdBLOQ+6MRC4X2OKPEhJKzD9+a9E4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114019; c=relaxed/simple; bh=IWcnki9LfCirlQqIhyJuLTt/qgZeOsvb1MfVSAqvJis=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=DEJpbO74uWp2TzuatiD2hcwRfg1BN3i3JqtfnPiER4x/ASANBqQ2ODbS4WsFMjV6Tk83kxmSH/U+7ODPSFS9mgBIOfClnqa5l8TU3VrVX1d2NehomBMPJyS5Za59vroNFzZXQLVOSZ7yoc/P2wL4YjOmvufpyJcX9BX/4X2mq4M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=ZI421nhd; arc=none smtp.client-ip=205.220.168.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="ZI421nhd" Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FJxr029748; Wed, 20 Nov 2024 14:46:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= WmOuYTw1pDg+OZMl0eJC/8hf/SQ7HFdDT54mXy6gdS8=; b=ZI421nhdfDiz8WeK pGZDn0I6MEnWeKgyAQcdhPYTIKMefloHd0+oAqrw2R5okeCR/I4twYT9R4nfPYST h1PsIXRyKeU//rMZFga3NOuVYI+RvDF6o12ZFiaw5ZoeqkhhiOO+YZAIPW7zI6Ri 9CsW87omCQIervRCgI/0ndOc6tzKg55nF67+mtAB+lscDAl2Si5g7Ppa/ynoJIbp xMo4EycbxgU2ac+d5pKuaAFkDPga7PI6l7RXTxR+u8pbYyegaUiLlmSZYdxMusqI GcVqJKm/0fnJeHf5CgDbhf9iaCbe1ou7QUFWs3r8LVRqVvxDVNcmL9+W2XfvFtvy bghLXQ== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4319529e2w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:46:47 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEklNc024905 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:46:47 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:46:41 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:15:53 +0530 Subject: [PATCH v6 03/28] media: iris: implement iris v4l2 file ops Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-3-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=13878; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=IWcnki9LfCirlQqIhyJuLTt/qgZeOsvb1MfVSAqvJis=; b=lYil5uK6G2riJ1ntd0/hzegshL8fdAYyn7g//SUQ/Dr4f0MI/H/SxYEeNoZv+BwEA087k+GGg 63QWwSXZN+WAV6D948IpFhvqZzg9eeA6Ea3QOQAEc986CyFKOeLsIxC X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: CORzSE7f7kw9yPD8XpBTw-sOqn-hh0h7 X-Proofpoint-GUID: CORzSE7f7kw9yPD8XpBTw-sOqn-hh0h7 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 phishscore=0 adultscore=0 priorityscore=1501 impostorscore=0 suspectscore=0 lowpriorityscore=0 mlxscore=0 clxscore=1015 spamscore=0 malwarescore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 Implement open, close and poll ops. Open: Configure the vb2 queue and v4l2 file handler. Allocate a video instance and add the instance to core instance list. Close: Free the instance and remove it from core instance list. Poll: Wait for an event on vb2 src and vb2 dst queues. Reviewed-by: Bryan O'Donoghue Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/Kconfig | 1 + drivers/media/platform/qcom/iris/Makefile | 5 +- drivers/media/platform/qcom/iris/iris_core.h | 2 + drivers/media/platform/qcom/iris/iris_hfi_gen1.h | 13 ++ .../platform/qcom/iris/iris_hfi_gen1_command.c | 12 ++ drivers/media/platform/qcom/iris/iris_hfi_gen2.h | 22 +++ .../platform/qcom/iris/iris_hfi_gen2_command.c | 11 ++ drivers/media/platform/qcom/iris/iris_instance.h | 31 +++++ .../platform/qcom/iris/iris_platform_common.h | 1 + .../platform/qcom/iris/iris_platform_sm8550.c | 2 + drivers/media/platform/qcom/iris/iris_probe.c | 3 + drivers/media/platform/qcom/iris/iris_vidc.c | 147 +++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_vidc.h | 15 +++ 13 files changed, 264 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig index 34a2f81c5db3..8debddec87a5 100644 --- a/drivers/media/platform/qcom/iris/Kconfig +++ b/drivers/media/platform/qcom/iris/Kconfig @@ -2,6 +2,7 @@ config VIDEO_QCOM_IRIS tristate "Qualcomm iris V4L2 decoder driver" depends on VIDEO_DEV depends on ARCH_QCOM || COMPILE_TEST + select V4L2_MEM2MEM_DEV help This is a V4L2 driver for Qualcomm iris video accelerator hardware. It accelerates decoding operations on various diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 7e701361492e..6de584090a3a 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -1,4 +1,7 @@ -iris-objs += iris_platform_sm8550.o \ +iris-objs += iris_hfi_gen1_command.o \ + iris_hfi_gen2_command.o \ + iris_platform_sm8550.o \ iris_probe.o \ + iris_vidc.o \ obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 27bc2ca71e1b..aebb4eba7e15 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -25,6 +25,7 @@ struct icc_info { * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure * @vdev_dec: iris video device structure for decoder + * @iris_v4l2_file_ops: iris v4l2 file ops * @icc_tbl: table of iris interconnects * @icc_count: count of iris interconnects * @pmdomain_tbl: table of iris power domains @@ -41,6 +42,7 @@ struct iris_core { int irq; struct v4l2_device v4l2_dev; struct video_device *vdev_dec; + const struct v4l2_file_operations *iris_v4l2_file_ops; struct icc_bulk_data *icc_tbl; u32 icc_count; struct dev_pm_domain_list *pmdomain_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h new file mode 100644 index 000000000000..5d05be7470e0 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_HFI_GEN1_H__ +#define __IRIS_HFI_GEN1_H__ + +struct iris_inst; + +struct iris_inst *iris_hfi_gen1_get_instance(void); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c new file mode 100644 index 000000000000..20c68f4ffb72 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_hfi_gen1.h" +#include "iris_instance.h" + +struct iris_inst *iris_hfi_gen1_get_instance(void) +{ + return kzalloc(sizeof(struct iris_inst), GFP_KERNEL); +} diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h new file mode 100644 index 000000000000..c159ed7f64f9 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_HFI_GEN2_H__ +#define __IRIS_HFI_GEN2_H__ + +#include "iris_instance.h" + +/** + * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2 + * + * @inst: pointer to iris_instance structure + */ +struct iris_inst_hfi_gen2 { + struct iris_inst inst; +}; + +struct iris_inst *iris_hfi_gen2_get_instance(void); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c new file mode 100644 index 000000000000..3ee33c8befae --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_hfi_gen2.h" + +struct iris_inst *iris_hfi_gen2_get_instance(void) +{ + return kzalloc(sizeof(struct iris_inst_hfi_gen2), GFP_KERNEL); +} diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h new file mode 100644 index 000000000000..527a270f12d4 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_INSTANCE_H__ +#define __IRIS_INSTANCE_H__ + +#include "iris_core.h" + +/** + * struct iris_inst - holds per video instance parameters + * + * @core: pointer to core structure + * @ctx_q_lock: lock to serialize queues related ioctls + * @lock: lock to seralise forward and reverse threads + * @fh: reference of v4l2 file handler + * @m2m_dev: a reference to m2m device structure + * @m2m_ctx: a reference to m2m context structure + */ + +struct iris_inst { + struct iris_core *core; + struct mutex ctx_q_lock;/* lock to serialize queues related ioctls */ + struct mutex lock; /* lock to serialize forward and reverse threads */ + struct v4l2_fh fh; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; +}; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 31c53dad8136..f82081ea135f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -20,6 +20,7 @@ struct platform_clk_data { }; struct iris_platform_data { + struct iris_inst *(*get_instance)(void); const struct icc_info *icc_tbl; unsigned int icc_tbl_size; const char * const *pmdomain_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 3dd91523d783..dba8d3c22ce5 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -4,6 +4,7 @@ */ #include "iris_core.h" +#include "iris_hfi_gen2.h" #include "iris_platform_common.h" static const struct icc_info sm8550_icc_table[] = { @@ -24,6 +25,7 @@ static const struct platform_clk_data sm8550_clk_table[] = { }; struct iris_platform_data sm8550_data = { + .get_instance = iris_hfi_gen2_get_instance, .icc_tbl = sm8550_icc_table, .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), .clk_rst_tbl = sm8550_clk_reset_table, diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 911e3bc1b434..ce16d894c809 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -11,6 +11,7 @@ #include #include "iris_core.h" +#include "iris_vidc.h" static int iris_init_icc(struct iris_core *core) { @@ -139,6 +140,7 @@ static int iris_register_video_device(struct iris_core *core) strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); vdev->release = video_device_release; + vdev->fops = core->iris_v4l2_file_ops; vdev->vfl_dir = VFL_DIR_M2M; vdev->v4l2_dev = &core->v4l2_dev; vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; @@ -192,6 +194,7 @@ static int iris_probe(struct platform_device *pdev) core->iris_platform_data = of_device_get_match_data(core->dev); + iris_init_ops(core); ret = iris_init_resources(core); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c new file mode 100644 index 000000000000..e91d661c6280 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include + +#include "iris_vidc.h" +#include "iris_instance.h" +#include "iris_platform_common.h" + +#define IRIS_DRV_NAME "iris_driver" +#define IRIS_BUS_NAME "platform:iris_icc" +#define STEP_WIDTH 1 +#define STEP_HEIGHT 1 + +static void iris_v4l2_fh_init(struct iris_inst *inst) +{ + v4l2_fh_init(&inst->fh, inst->core->vdev_dec); + v4l2_fh_add(&inst->fh); +} + +static void iris_v4l2_fh_deinit(struct iris_inst *inst) +{ + v4l2_fh_del(&inst->fh); + v4l2_fh_exit(&inst->fh); +} + +static inline struct iris_inst *iris_get_inst(struct file *filp, void *fh) +{ + return container_of(filp->private_data, struct iris_inst, fh); +} + +static void iris_m2m_device_run(void *priv) +{ +} + +static void iris_m2m_job_abort(void *priv) +{ + struct iris_inst *inst = priv; + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + + v4l2_m2m_job_finish(inst->m2m_dev, m2m_ctx); +} + +static const struct v4l2_m2m_ops iris_m2m_ops = { + .device_run = iris_m2m_device_run, + .job_abort = iris_m2m_job_abort, +}; + +static int +iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) +{ + struct iris_inst *inst = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->drv_priv = inst; + src_vq->dev = inst->core->dev; + src_vq->lock = &inst->ctx_q_lock; + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->drv_priv = inst; + dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; + + return vb2_queue_init(dst_vq); +} + +int iris_open(struct file *filp) +{ + struct iris_core *core = video_drvdata(filp); + struct iris_inst *inst; + int ret; + + inst = core->iris_platform_data->get_instance(); + if (!inst) + return -ENOMEM; + + inst->core = core; + + mutex_init(&inst->ctx_q_lock); + + iris_v4l2_fh_init(inst); + + inst->m2m_dev = v4l2_m2m_init(&iris_m2m_ops); + if (IS_ERR_OR_NULL(inst->m2m_dev)) { + ret = -EINVAL; + goto fail_v4l2_fh_deinit; + } + + inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, iris_m2m_queue_init); + if (IS_ERR_OR_NULL(inst->m2m_ctx)) { + ret = -EINVAL; + goto fail_m2m_release; + } + + inst->fh.m2m_ctx = inst->m2m_ctx; + filp->private_data = &inst->fh; + + return 0; + +fail_m2m_release: + v4l2_m2m_release(inst->m2m_dev); +fail_v4l2_fh_deinit: + iris_v4l2_fh_deinit(inst); + mutex_destroy(&inst->ctx_q_lock); + kfree(inst); + + return ret; +} + +int iris_close(struct file *filp) +{ + struct iris_inst *inst = iris_get_inst(filp, NULL); + + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); + iris_v4l2_fh_deinit(inst); + mutex_destroy(&inst->ctx_q_lock); + kfree(inst); + filp->private_data = NULL; + + return 0; +} + +static struct v4l2_file_operations iris_v4l2_file_ops = { + .owner = THIS_MODULE, + .open = iris_open, + .release = iris_close, + .unlocked_ioctl = video_ioctl2, + .poll = v4l2_m2m_fop_poll, + .mmap = v4l2_m2m_fop_mmap, +}; + +void iris_init_ops(struct iris_core *core) +{ + core->iris_v4l2_file_ops = &iris_v4l2_file_ops; +} diff --git a/drivers/media/platform/qcom/iris/iris_vidc.h b/drivers/media/platform/qcom/iris/iris_vidc.h new file mode 100644 index 000000000000..a26054ff55b5 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_vidc.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_VIDC_H__ +#define __IRIS_VIDC_H__ + +struct iris_core; + +void iris_init_ops(struct iris_core *core); +int iris_open(struct file *filp); +int iris_close(struct file *filp); + +#endif From patchwork Wed Nov 20 14:45:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844625 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 30DA91C6F55; Wed, 20 Nov 2024 14:47:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114029; cv=none; b=nvAvSB6crQd5KjDepL4v9NjdPEJlFLx7xmSZPx+fdAr/jQn6YSJr4HuYnrMEjuhx2EhAv6p9WnD+IsqpQijLFOZfxUk6vbWaCbM8jckQUZnj9pqCeRPs03X/TMxU98Bwz3W60jaT9o+JFHHbaLxWFsmYGfrkb3hQiLRRgr0X86Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114029; c=relaxed/simple; bh=yo4wEsfKluGMJhK9rgxoR6DFEK2OtcSu2L6+bU/Qkfc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=qUnVEyukOXWIBwktDB9rj3m6xBuTIHWE2OYhwmxZkO+UP7Nm18NI8H0QrQqStjN5mDfcMMdzvJYTWh80ioM0yKAilFO89dQOHAnga5qNEM59mCIztaYHAWwfJ7cswcarCWWK0JaGFKaTatvTGgHJ033Xjtrm4q1l3Qn2YQ9CSL0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=hvh4R5PT; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="hvh4R5PT" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FRc9010545; Wed, 20 Nov 2024 14:46:59 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= ojm9NMLyFDrwVfF8kbSoBLoNqjrrljFnxHuKJhFd8Dg=; b=hvh4R5PT4HQyMkJT FLBBncUsplKOvTjG+SF63YfsaiwMfdcbqHU7/5AyFlXlTGJrjxCHvzX9NZ/FPQS6 2GCSysXXhenA/zWKeKDeYeFubS5hbNv7zMxgj0wG1+669zSIuu7QkawUYKhh8+vc nBpXt33QSSZSOyYadtKL1Hka9KJGWP7EL5kdOZHiSTETn9HCAQ7v8JdetI/DK/Ap BcUrWRvzIsJDPnzotIqMAkkZbNHQusKhr2ZgG3WsSQF/1xjQDkwIUK2gwmMsX008 NHJbJQXfecG461+BVPK57Gsuc4lfqVbofgjyH0V0p+pVEJIOmpCQJ/c1wHh3iNLO 4vUNeA== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 43091me59c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:46:59 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEkwSc003677 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:46:58 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:46:53 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:15:55 +0530 Subject: [PATCH v6 05/28] media: iris: implement video firmware load/unload Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-5-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=8150; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=yo4wEsfKluGMJhK9rgxoR6DFEK2OtcSu2L6+bU/Qkfc=; b=DYWZYq50rqLtMrhJnzsPh4FgSEca07OrGKSeNyGmzeJPK8tAa6NYvkxU8Y3jh5vPlwA9Jxj0C aaE6JX3vcEgDV5o+2nRRBlwL0entnDnvNsFatyC+85WACzqRbwNAlEg X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: jJwiZWKfLXb0jvR_ei1lOa1SB84sOCXE X-Proofpoint-GUID: jJwiZWKfLXb0jvR_ei1lOa1SB84sOCXE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 spamscore=0 priorityscore=1501 phishscore=0 malwarescore=0 clxscore=1015 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 adultscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 Load/unload firmware in memory via mdt loader. Firmware is loaded as part of core initialization and unloaded as part of core de-initialization. Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/Kconfig | 2 + drivers/media/platform/qcom/iris/Makefile | 1 + drivers/media/platform/qcom/iris/iris_core.c | 8 ++ drivers/media/platform/qcom/iris/iris_firmware.c | 105 +++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_firmware.h | 14 +++ .../platform/qcom/iris/iris_platform_common.h | 12 +++ .../platform/qcom/iris/iris_platform_sm8550.c | 10 ++ 7 files changed, 152 insertions(+) diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig index 8debddec87a5..f92cc7fe9378 100644 --- a/drivers/media/platform/qcom/iris/Kconfig +++ b/drivers/media/platform/qcom/iris/Kconfig @@ -3,6 +3,8 @@ config VIDEO_QCOM_IRIS depends on VIDEO_DEV depends on ARCH_QCOM || COMPILE_TEST select V4L2_MEM2MEM_DEV + select QCOM_MDT_LOADER if ARCH_QCOM + select QCOM_SCM help This is a V4L2 driver for Qualcomm iris video accelerator hardware. It accelerates decoding operations on various diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 93711f108a77..6906caa2c481 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -1,4 +1,5 @@ iris-objs += iris_core.o \ + iris_firmware.o \ iris_hfi_gen1_command.o \ iris_hfi_gen2_command.o \ iris_hfi_queue.o \ diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 360a54909ef6..8c7d53c57086 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -4,11 +4,13 @@ */ #include "iris_core.h" +#include "iris_firmware.h" #include "iris_state.h" void iris_core_deinit(struct iris_core *core) { mutex_lock(&core->lock); + iris_fw_unload(core); iris_hfi_queues_deinit(core); core->state = IRIS_CORE_DEINIT; mutex_unlock(&core->lock); @@ -33,10 +35,16 @@ int iris_core_init(struct iris_core *core) if (ret) goto error; + ret = iris_fw_load(core); + if (ret) + goto error_queue_deinit; + mutex_unlock(&core->lock); return 0; +error_queue_deinit: + iris_hfi_queues_deinit(core); error: core->state = IRIS_CORE_DEINIT; exit: diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c new file mode 100644 index 000000000000..d40508889f9d --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "iris_core.h" +#include "iris_firmware.h" + +#define MAX_FIRMWARE_NAME_SIZE 128 + +static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) +{ + u32 pas_id = core->iris_platform_data->pas_id; + const struct firmware *firmware = NULL; + struct device *dev = core->dev; + struct reserved_mem *rmem; + struct device_node *node; + phys_addr_t mem_phys; + size_t res_size; + ssize_t fw_size; + void *mem_virt; + int ret; + + if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) + return -EINVAL; + + node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (!node) + return -EINVAL; + + rmem = of_reserved_mem_lookup(node); + of_node_put(node); + if (!rmem) + return -EINVAL; + + mem_phys = rmem->base; + res_size = rmem->size; + + ret = request_firmware(&firmware, fw_name, dev); + if (ret) + return ret; + + fw_size = qcom_mdt_get_size(firmware); + if (fw_size < 0 || res_size < (size_t)fw_size) { + ret = -EINVAL; + goto err_release_fw; + } + + mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC); + if (!mem_virt) + goto err_release_fw; + + ret = qcom_mdt_load(dev, firmware, fw_name, + pas_id, mem_virt, mem_phys, res_size, NULL); + if (ret) + goto err_mem_unmap; + + ret = qcom_scm_pas_auth_and_reset(pas_id); + if (ret) + goto err_mem_unmap; + + return ret; + +err_mem_unmap: + memunmap(mem_virt); +err_release_fw: + release_firmware(firmware); + + return ret; +} + +int iris_fw_load(struct iris_core *core) +{ + struct tz_cp_config *cp_config = core->iris_platform_data->tz_cp_config_data; + int ret; + + ret = iris_load_fw_to_memory(core, core->iris_platform_data->fwname); + if (ret) { + dev_err(core->dev, "firmware download failed\n"); + return -ENOMEM; + } + + ret = qcom_scm_mem_protect_video_var(cp_config->cp_start, + cp_config->cp_size, + cp_config->cp_nonpixel_start, + cp_config->cp_nonpixel_size); + if (ret) { + dev_err(core->dev, "protect memory failed\n"); + qcom_scm_pas_shutdown(core->iris_platform_data->pas_id); + return ret; + } + + return ret; +} + +int iris_fw_unload(struct iris_core *core) +{ + return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id); +} diff --git a/drivers/media/platform/qcom/iris/iris_firmware.h b/drivers/media/platform/qcom/iris/iris_firmware.h new file mode 100644 index 000000000000..266bdd92a124 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_firmware.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_FIRMWARE_H__ +#define __IRIS_FIRMWARE_H__ + +struct iris_core; + +int iris_fw_load(struct iris_core *core); +int iris_fw_unload(struct iris_core *core); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index b4d63d6677c5..42c1fe8e4fa6 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -6,6 +6,8 @@ #ifndef __IRIS_PLATFORM_COMMON_H__ #define __IRIS_PLATFORM_COMMON_H__ +#define IRIS_PAS_ID 9 + extern struct iris_platform_data sm8550_data; enum platform_clk_type { @@ -19,6 +21,13 @@ struct platform_clk_data { const char *clk_name; }; +struct tz_cp_config { + u32 cp_start; + u32 cp_size; + u32 cp_nonpixel_start; + u32 cp_nonpixel_size; +}; + struct iris_platform_data { struct iris_inst *(*get_instance)(void); const struct icc_info *icc_tbl; @@ -32,6 +41,9 @@ struct iris_platform_data { const char * const *clk_rst_tbl; unsigned int clk_rst_tbl_size; u64 dma_mask; + const char *fwname; + u32 pas_id; + struct tz_cp_config *tz_cp_config_data; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 9b305b8e2110..96d9d6e816a0 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -24,6 +24,13 @@ static const struct platform_clk_data sm8550_clk_table[] = { {IRIS_HW_CLK, "vcodec0_core" }, }; +static struct tz_cp_config tz_cp_config_sm8550 = { + .cp_start = 0, + .cp_size = 0x25800000, + .cp_nonpixel_start = 0x01000000, + .cp_nonpixel_size = 0x24800000, +}; + struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, .icc_tbl = sm8550_icc_table, @@ -37,4 +44,7 @@ struct iris_platform_data sm8550_data = { .clk_tbl = sm8550_clk_table, .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), .dma_mask = GENMASK(31, 29) - 1, + .fwname = "qcom/vpu/vpu30_p4.mbn", + .pas_id = IRIS_PAS_ID, + .tz_cp_config_data = &tz_cp_config_sm8550, }; From patchwork Wed Nov 20 14:45:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844624 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 B39601C9DE6; Wed, 20 Nov 2024 14:47:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114046; cv=none; b=YZzY42Y3kwGDphBsKAEksjqbobe2wCOO/pEtQjlCWgSQgHjZn2IgR+BQBllI1q9EUhtr1WqbNtCgNA0jcppH5jt6EhXgpydBCq1XWQTsIa3/54OlMU1nU4BE6ZpsKVVsGRXXNEhJkBwwGhYp57NPTKfxAOi+nktgBLhi0CcDL/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114046; c=relaxed/simple; bh=qAf3axy1KmjP+rWcgEsQpqpBmeYGkChfzsRkflBs+Vg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=ShkN+1mOATpw8FD6zouVuErEjEb5yF2ahVmOMwBwXOVLFav/IBAf+IBWWlVlpDW7FmCiA6IJN959DDE8a9YWX1FmjNV+WI1mrawJGrs9hA8+itSTs91vOhCAVSPpirmY1ZiCreOjDENEVkr/3m3F7dDJ2Eyw3YkD+GKw+57i/9Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=krOUpaHc; arc=none smtp.client-ip=205.220.168.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="krOUpaHc" Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FKaq003935; Wed, 20 Nov 2024 14:47:11 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= BImRj4OtHER1w3h4Byt/Kthv9V7VlS0nTu3qtt+7g1E=; b=krOUpaHcgJvgYYpo eGryGXGck8pvmfwFVTTexVVF55izWWqhwXezeUJqVT/m1v73didOLhtYJ+6Qgu5/ nLJ4Nt4FCELcSHaX1ptT0LfLLflYA2oXDk1BAjFl08VoMsPeq0XbzQISGfIEVx/p nUC3H8gtV09eXQgAghx2QsCQGKpnfld0d8U0KfOFfQNVuKId1AiTK4XIF03S0GZS k5wu0ooKdKWpBDGLgAcqewdEJMiJwhrYg82yU7vD5Xt7sAUm6bBu9pJ0WoIHcUS5 Ao9fcxVxWErCxnhyNTZYirelS0kXE4l1gOA+gwXQe8hZxgZB7BMjQ0kWV8Yc1kad M+1zKw== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 431ce38x43-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:10 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKElAmQ025580 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:10 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:47:04 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:15:57 +0530 Subject: [PATCH v6 07/28] media: iris: introduce host firmware interface with necessary hooks Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-7-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=50528; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=qAf3axy1KmjP+rWcgEsQpqpBmeYGkChfzsRkflBs+Vg=; b=asxwuYOMAr2qu2+5TomOUVdWBGMYNJRgtmwREAeDYZSVoVwSRDSlDDR2Hhape99jEn+RvA8lh kjCa/BsQOB1BVlvzWyw0H7UIpaUcsuWjgsIxpBDi5NFEb9lhJbbb7X1 X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: XxUoE4SbjiJvSyJJNE_OjBJvjsagpEtv X-Proofpoint-ORIG-GUID: XxUoE4SbjiJvSyJJNE_OjBJvjsagpEtv X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 clxscore=1015 priorityscore=1501 impostorscore=0 bulkscore=0 mlxscore=0 adultscore=0 spamscore=0 mlxlogscore=999 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 Host firmware interface (HFI) is well defined set of interfaces for communication between host driver and firmware. The commands and responses are exchanged in form of packets. One or multiple packets are grouped under packet header. Each packet has packet type which describes the specific HFI and payload which holds the corresponding value for that HFI. Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/Makefile | 4 + drivers/media/platform/qcom/iris/iris_core.c | 24 ++- drivers/media/platform/qcom/iris/iris_core.h | 20 ++ drivers/media/platform/qcom/iris/iris_hfi_common.c | 50 +++++ drivers/media/platform/qcom/iris/iris_hfi_common.h | 60 ++++++ drivers/media/platform/qcom/iris/iris_hfi_gen1.h | 3 + .../platform/qcom/iris/iris_hfi_gen1_command.c | 61 ++++++ .../platform/qcom/iris/iris_hfi_gen1_defines.h | 94 +++++++++ .../platform/qcom/iris/iris_hfi_gen1_response.c | 176 +++++++++++++++++ drivers/media/platform/qcom/iris/iris_hfi_gen2.h | 4 + .../platform/qcom/iris/iris_hfi_gen2_command.c | 74 +++++++ .../platform/qcom/iris/iris_hfi_gen2_defines.h | 46 +++++ .../platform/qcom/iris/iris_hfi_gen2_packet.c | 161 +++++++++++++++ .../platform/qcom/iris/iris_hfi_gen2_packet.h | 69 +++++++ .../platform/qcom/iris/iris_hfi_gen2_response.c | 215 +++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_hfi_queue.c | 173 +++++++++++++++++ drivers/media/platform/qcom/iris/iris_hfi_queue.h | 5 + .../platform/qcom/iris/iris_platform_common.h | 17 ++ .../platform/qcom/iris/iris_platform_sm8550.c | 14 ++ drivers/media/platform/qcom/iris/iris_probe.c | 26 +++ drivers/media/platform/qcom/iris/iris_vpu_common.c | 43 +++++ drivers/media/platform/qcom/iris/iris_vpu_common.h | 3 + 22 files changed, 1341 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 792f1d6ac8f3..76ca5287c49f 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -1,7 +1,11 @@ iris-objs += iris_core.o \ iris_firmware.o \ + iris_hfi_common.o \ iris_hfi_gen1_command.o \ + iris_hfi_gen1_response.o \ iris_hfi_gen2_command.o \ + iris_hfi_gen2_packet.o \ + iris_hfi_gen2_response.o \ iris_hfi_queue.o \ iris_platform_sm8550.o \ iris_probe.o \ diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 5ad66ac113ae..7e19bdd0a19b 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -17,6 +17,24 @@ void iris_core_deinit(struct iris_core *core) mutex_unlock(&core->lock); } +static int iris_wait_for_system_response(struct iris_core *core) +{ + u32 hw_response_timeout_val = core->iris_platform_data->hw_response_timeout; + int ret; + + if (core->state == IRIS_CORE_ERROR) + return -EIO; + + ret = wait_for_completion_timeout(&core->core_init_done, + msecs_to_jiffies(hw_response_timeout_val)); + if (!ret) { + core->state = IRIS_CORE_ERROR; + return -ETIMEDOUT; + } + + return 0; +} + int iris_core_init(struct iris_core *core) { int ret; @@ -44,9 +62,13 @@ int iris_core_init(struct iris_core *core) if (ret) goto error_unload_fw; + ret = iris_hfi_core_init(core); + if (ret) + goto error_unload_fw; + mutex_unlock(&core->lock); - return 0; + return iris_wait_for_system_response(core); error_unload_fw: iris_fw_unload(core); diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 516082aa58c9..c0f3c189d779 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -9,6 +9,7 @@ #include #include +#include "iris_hfi_common.h" #include "iris_hfi_queue.h" #include "iris_platform_common.h" #include "iris_state.h" @@ -19,6 +20,9 @@ struct icc_info { u32 bw_max_kbps; }; +#define IRIS_FW_VERSION_LENGTH 128 +#define IFACEQ_CORE_PKT_SIZE (1024 * 4) + /** * struct iris_core - holds core parameters valid for all instances * @@ -45,6 +49,14 @@ struct icc_info { * @message_queue: shared interface queue to receive responses from firmware * @debug_queue: shared interface queue to receive debug info from firmware * @lock: a lock for this strucure + * @response_packet: a pointer to response packet from fw to driver + * @header_id: id of packet header + * @packet_id: id of packet + * @hfi_ops: iris hfi command ops + * @hfi_response_ops: iris hfi response ops + * @core_init_done: structure of signal completion for system response + * @intr_status: interrupt status + * @sys_error_handler: a delayed work for handling system fatal error */ struct iris_core { @@ -71,6 +83,14 @@ struct iris_core { struct iris_iface_q_info message_queue; struct iris_iface_q_info debug_queue; struct mutex lock; /* lock for core related operations */ + u8 *response_packet; + u32 header_id; + u32 packet_id; + const struct iris_hfi_command_ops *hfi_ops; + const struct iris_hfi_response_ops *hfi_response_ops; + struct completion core_init_done; + u32 intr_status; + struct delayed_work sys_error_handler; }; int iris_core_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c new file mode 100644 index 000000000000..a19b988c9a88 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_hfi_common.h" +#include "iris_vpu_common.h" + +int iris_hfi_core_init(struct iris_core *core) +{ + const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops; + int ret; + + ret = hfi_ops->sys_init(core); + if (ret) + return ret; + + ret = hfi_ops->sys_image_version(core); + if (ret) + return ret; + + return hfi_ops->sys_interframe_powercollapse(core); +} + +irqreturn_t iris_hfi_isr(int irq, void *data) +{ + disable_irq_nosync(irq); + + return IRQ_WAKE_THREAD; +} + +irqreturn_t iris_hfi_isr_handler(int irq, void *data) +{ + struct iris_core *core = data; + + if (!core) + return IRQ_NONE; + + mutex_lock(&core->lock); + iris_vpu_clear_interrupt(core); + mutex_unlock(&core->lock); + + core->hfi_response_ops->hfi_response_handler(core); + + if (!iris_vpu_watchdog(core, core->intr_status)) + enable_irq(irq); + + return IRQ_HANDLED; +} diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h new file mode 100644 index 000000000000..b46a2f21102a --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_HFI_COMMON_H__ +#define __IRIS_HFI_COMMON_H__ + +#include +#include + +struct iris_core; + +enum hfi_packet_port_type { + HFI_PORT_NONE = 0x00000000, + HFI_PORT_BITSTREAM = 0x00000001, + HFI_PORT_RAW = 0x00000002, +}; + +enum hfi_packet_payload_info { + HFI_PAYLOAD_NONE = 0x00000000, + HFI_PAYLOAD_U32 = 0x00000001, + HFI_PAYLOAD_S32 = 0x00000002, + HFI_PAYLOAD_U64 = 0x00000003, + HFI_PAYLOAD_S64 = 0x00000004, + HFI_PAYLOAD_STRUCTURE = 0x00000005, + HFI_PAYLOAD_BLOB = 0x00000006, + HFI_PAYLOAD_STRING = 0x00000007, + HFI_PAYLOAD_Q16 = 0x00000008, + HFI_PAYLOAD_U32_ENUM = 0x00000009, + HFI_PAYLOAD_32_PACKED = 0x0000000a, + HFI_PAYLOAD_U32_ARRAY = 0x0000000b, + HFI_PAYLOAD_S32_ARRAY = 0x0000000c, + HFI_PAYLOAD_64_PACKED = 0x0000000d, +}; + +enum hfi_packet_host_flags { + HFI_HOST_FLAGS_NONE = 0x00000000, + HFI_HOST_FLAGS_INTR_REQUIRED = 0x00000001, + HFI_HOST_FLAGS_RESPONSE_REQUIRED = 0x00000002, + HFI_HOST_FLAGS_NON_DISCARDABLE = 0x00000004, + HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008, +}; + +struct iris_hfi_command_ops { + int (*sys_init)(struct iris_core *core); + int (*sys_image_version)(struct iris_core *core); + int (*sys_interframe_powercollapse)(struct iris_core *core); +}; + +struct iris_hfi_response_ops { + void (*hfi_response_handler)(struct iris_core *core); +}; + +int iris_hfi_core_init(struct iris_core *core); + +irqreturn_t iris_hfi_isr(int irq, void *data); +irqreturn_t iris_hfi_isr_handler(int irq, void *data); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h index 5d05be7470e0..19b8e9054a75 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h @@ -6,8 +6,11 @@ #ifndef __IRIS_HFI_GEN1_H__ #define __IRIS_HFI_GEN1_H__ +struct iris_core; struct iris_inst; +void iris_hfi_gen1_command_ops_init(struct iris_core *core); +void iris_hfi_gen1_response_ops_init(struct iris_core *core); struct iris_inst *iris_hfi_gen1_get_instance(void); #endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 20c68f4ffb72..07007d8812ba 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -4,8 +4,69 @@ */ #include "iris_hfi_gen1.h" +#include "iris_hfi_gen1_defines.h" #include "iris_instance.h" +static int iris_hfi_gen1_sys_init(struct iris_core *core) +{ + struct hfi_sys_init_pkt sys_init_pkt; + + sys_init_pkt.hdr.size = sizeof(sys_init_pkt); + sys_init_pkt.hdr.pkt_type = HFI_CMD_SYS_INIT; + sys_init_pkt.arch_type = HFI_VIDEO_ARCH_OX; + + return iris_hfi_queue_cmd_write_locked(core, &sys_init_pkt, sys_init_pkt.hdr.size); +} + +static int iris_hfi_gen1_sys_image_version(struct iris_core *core) +{ + struct hfi_sys_get_property_pkt packet; + + packet.hdr.size = sizeof(packet); + packet.hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY; + packet.num_properties = 1; + packet.data = HFI_PROPERTY_SYS_IMAGE_VERSION; + + return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size); +} + +static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core) +{ + struct hfi_sys_set_property_pkt *pkt; + struct hfi_enable *hfi; + u32 packet_size; + int ret; + + packet_size = struct_size(pkt, data, 1) + sizeof(*hfi); + pkt = kzalloc(packet_size, GFP_KERNEL); + if (!pkt) + return -ENOMEM; + + hfi = (struct hfi_enable *)&pkt->data[1]; + + pkt->hdr.size = packet_size; + pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; + pkt->num_properties = 1; + pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL; + hfi->enable = true; + + ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size); + kfree(pkt); + + return ret; +} + +static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { + .sys_init = iris_hfi_gen1_sys_init, + .sys_image_version = iris_hfi_gen1_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, +}; + +void iris_hfi_gen1_command_ops_init(struct iris_core *core) +{ + core->hfi_ops = &iris_hfi_gen1_command_ops; +} + struct iris_inst *iris_hfi_gen1_get_instance(void) { return kzalloc(sizeof(struct iris_inst), GFP_KERNEL); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h new file mode 100644 index 000000000000..8af824a42bcf --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_HFI_GEN1_DEFINES_H__ +#define __IRIS_HFI_GEN1_DEFINES_H__ + +#include + +#define HFI_VIDEO_ARCH_OX 0x1 +#define HFI_ERR_NONE 0x0 + +#define HFI_CMD_SYS_INIT 0x10001 +#define HFI_CMD_SYS_SET_PROPERTY 0x10005 +#define HFI_CMD_SYS_GET_PROPERTY 0x10006 + +#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 +#define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 + +#define HFI_EVENT_SYS_ERROR 0x1 + +#define HFI_MSG_SYS_INIT 0x20001 +#define HFI_MSG_SYS_COV 0x20009 +#define HFI_MSG_SYS_PROPERTY_INFO 0x2000a + +#define HFI_MSG_EVENT_NOTIFY 0x21001 + +struct hfi_pkt_hdr { + u32 size; + u32 pkt_type; +}; + +struct hfi_sys_init_pkt { + struct hfi_pkt_hdr hdr; + u32 arch_type; +}; + +struct hfi_sys_set_property_pkt { + struct hfi_pkt_hdr hdr; + u32 num_properties; + u32 data[]; +}; + +struct hfi_sys_get_property_pkt { + struct hfi_pkt_hdr hdr; + u32 num_properties; + u32 data; +}; + +struct hfi_msg_event_notify_pkt { + struct hfi_pkt_hdr hdr; + u32 event_id; + u32 event_data1; + u32 event_data2; + u32 ext_event_data[]; +}; + +struct hfi_msg_sys_init_done_pkt { + struct hfi_pkt_hdr hdr; + u32 error_type; + u32 num_properties; + u32 data[]; +}; + +struct hfi_msg_sys_property_info_pkt { + struct hfi_pkt_hdr hdr; + u32 num_properties; + u32 property; + u8 data[]; +}; + +struct hfi_enable { + u32 enable; +}; + +struct hfi_msg_sys_debug_pkt { + struct hfi_pkt_hdr hdr; + u32 msg_type; + u32 msg_size; + u32 time_stamp_hi; + u32 time_stamp_lo; + u8 msg_data[]; +}; + +struct hfi_msg_sys_coverage_pkt { + struct hfi_pkt_hdr hdr; + u32 msg_size; + u32 time_stamp_hi; + u32 time_stamp_lo; + u8 msg_data[]; +}; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c new file mode 100644 index 000000000000..78fefa4176f9 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_hfi_gen1.h" +#include "iris_hfi_gen1_defines.h" +#include "iris_instance.h" + +static void +iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) +{ + struct hfi_msg_event_notify_pkt *pkt = packet; + + if (pkt->event_id == HFI_EVENT_SYS_ERROR) + dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n", + pkt->event_id, pkt->event_data1, pkt->event_data2); + + core->state = IRIS_CORE_ERROR; + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); +} + +static void iris_hfi_gen1_sys_init_done(struct iris_core *core, void *packet) +{ + struct hfi_msg_sys_init_done_pkt *pkt = packet; + + if (pkt->error_type != HFI_ERR_NONE) { + core->state = IRIS_CORE_ERROR; + return; + } + + complete(&core->core_init_done); +} + +static void +iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core, + struct hfi_msg_sys_property_info_pkt *pkt) +{ + int req_bytes = pkt->hdr.size - sizeof(*pkt); + char fw_version[IRIS_FW_VERSION_LENGTH]; + u8 *str_image_version; + u32 i; + + if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1) { + dev_err(core->dev, "bad packet\n"); + return; + } + + str_image_version = pkt->data; + if (!str_image_version) { + dev_err(core->dev, "firmware version not available\n"); + return; + } + + for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) { + if (str_image_version[i] != '\0') + fw_version[i] = str_image_version[i]; + else + fw_version[i] = ' '; + } + fw_version[i] = '\0'; + dev_dbg(core->dev, "firmware version: %s\n", fw_version); +} + +static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void *packet) +{ + struct hfi_msg_sys_property_info_pkt *pkt = packet; + + if (!pkt->num_properties) { + dev_dbg(core->dev, "no properties\n"); + return; + } + + switch (pkt->property) { + case HFI_PROPERTY_SYS_IMAGE_VERSION: + iris_hfi_gen1_sys_get_prop_image_version(core, pkt); + break; + default: + dev_dbg(core->dev, "unknown property data\n"); + break; + } +} + +struct iris_hfi_gen1_response_pkt_info { + u32 pkt; + u32 pkt_sz; +}; + +static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { + { + .pkt = HFI_MSG_EVENT_NOTIFY, + .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), + }, + { + .pkt = HFI_MSG_SYS_INIT, + .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), + }, + { + .pkt = HFI_MSG_SYS_PROPERTY_INFO, + .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), + }, +}; + +static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) +{ + struct hfi_pkt_hdr *hdr = (struct hfi_pkt_hdr *)response; + const struct iris_hfi_gen1_response_pkt_info *pkt_info; + struct device *dev = core->dev; + bool found = false; + u32 i; + + for (i = 0; i < ARRAY_SIZE(pkt_infos); i++) { + pkt_info = &pkt_infos[i]; + if (pkt_info->pkt != hdr->pkt_type) + continue; + found = true; + break; + } + + if (!found || hdr->size < pkt_info->pkt_sz) { + dev_err(dev, "bad packet size (%d should be %d, pkt type:%x, found %d)\n", + hdr->size, pkt_info->pkt_sz, hdr->pkt_type, found); + + return; + } + + switch (hdr->pkt_type) { + case HFI_MSG_SYS_INIT: + iris_hfi_gen1_sys_init_done(core, hdr); + break; + case HFI_MSG_SYS_PROPERTY_INFO: + iris_hfi_gen1_sys_property_info(core, hdr); + break; + case HFI_MSG_EVENT_NOTIFY: + iris_hfi_gen1_sys_event_notify(core, hdr); + break; + default: + break; + } +} + +static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet) +{ + struct hfi_msg_sys_coverage_pkt *pkt; + + while (!iris_hfi_queue_dbg_read(core, packet)) { + pkt = (struct hfi_msg_sys_coverage_pkt *)packet; + + if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) { + struct hfi_msg_sys_debug_pkt *pkt = + (struct hfi_msg_sys_debug_pkt *)packet; + + dev_dbg(core->dev, "%s", pkt->msg_data); + } + } +} + +static void iris_hfi_gen1_response_handler(struct iris_core *core) +{ + memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr)); + while (!iris_hfi_queue_msg_read(core, core->response_packet)) { + iris_hfi_gen1_handle_response(core, core->response_packet); + memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr)); + } + + iris_hfi_gen1_flush_debug_queue(core, core->response_packet); +} + +static const struct iris_hfi_response_ops iris_hfi_gen1_response_ops = { + .hfi_response_handler = iris_hfi_gen1_response_handler, +}; + +void iris_hfi_gen1_response_ops_init(struct iris_core *core) +{ + core->hfi_response_ops = &iris_hfi_gen1_response_ops; +} diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h index c159ed7f64f9..c43b51774978 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h @@ -8,6 +8,8 @@ #include "iris_instance.h" +struct iris_core; + /** * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2 * @@ -17,6 +19,8 @@ struct iris_inst_hfi_gen2 { struct iris_inst inst; }; +void iris_hfi_gen2_command_ops_init(struct iris_core *core); +void iris_hfi_gen2_response_ops_init(struct iris_core *core); struct iris_inst *iris_hfi_gen2_get_instance(void); #endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 3ee33c8befae..5eaebe170214 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -4,6 +4,80 @@ */ #include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_packet.h" + +#define NUM_SYS_INIT_PACKETS 8 + +#define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \ + NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32))) + +#define SYS_IFPC_PKT_SIZE (sizeof(struct iris_hfi_header) + \ + sizeof(struct iris_hfi_packet) + sizeof(u32)) + +#define SYS_NO_PAYLOAD_PKT_SIZE (sizeof(struct iris_hfi_header) + \ + sizeof(struct iris_hfi_packet)) + +static int iris_hfi_gen2_sys_init(struct iris_core *core) +{ + struct iris_hfi_header *hdr; + int ret; + + hdr = kzalloc(SYS_INIT_PKT_SIZE, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + iris_hfi_gen2_packet_sys_init(core, hdr); + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); + + kfree(hdr); + + return ret; +} + +static int iris_hfi_gen2_sys_image_version(struct iris_core *core) +{ + struct iris_hfi_header *hdr; + int ret; + + hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + iris_hfi_gen2_packet_image_version(core, hdr); + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); + + kfree(hdr); + + return ret; +} + +static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core) +{ + struct iris_hfi_header *hdr; + int ret; + + hdr = kzalloc(SYS_IFPC_PKT_SIZE, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr); + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); + + kfree(hdr); + + return ret; +} + +static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { + .sys_init = iris_hfi_gen2_sys_init, + .sys_image_version = iris_hfi_gen2_sys_image_version, + .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, +}; + +void iris_hfi_gen2_command_ops_init(struct iris_core *core) +{ + core->hfi_ops = &iris_hfi_gen2_command_ops; +} struct iris_inst *iris_hfi_gen2_get_instance(void) { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h new file mode 100644 index 000000000000..2640caa7f9c0 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_HFI_GEN2_DEFINES_H__ +#define __IRIS_HFI_GEN2_DEFINES_H__ + +#include + +#define HFI_VIDEO_ARCH_LX 0x1 + +#define HFI_CMD_BEGIN 0x01000000 +#define HFI_CMD_INIT 0x01000001 +#define HFI_CMD_END 0x01FFFFFF + +#define HFI_PROP_BEGIN 0x03000000 +#define HFI_PROP_IMAGE_VERSION 0x03000001 +#define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE 0x03000002 +#define HFI_PROP_UBWC_MAX_CHANNELS 0x03000003 +#define HFI_PROP_UBWC_MAL_LENGTH 0x03000004 +#define HFI_PROP_UBWC_HBB 0x03000005 +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL1 0x03000006 +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL2 0x03000007 +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 +#define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 +#define HFI_PROP_END 0x03FFFFFF + +#define HFI_SYSTEM_ERROR_BEGIN 0x05000000 +#define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 +#define HFI_SYSTEM_ERROR_END 0x05FFFFFF + +enum hfi_packet_firmware_flags { + HFI_FW_FLAGS_SUCCESS = 0x00000001, + HFI_FW_FLAGS_INFORMATION = 0x00000002, + HFI_FW_FLAGS_SESSION_ERROR = 0x00000004, + HFI_FW_FLAGS_SYSTEM_ERROR = 0x00000008, +}; + +struct hfi_debug_header { + u32 size; + u32 debug_level; + u32 reserved[2]; +}; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c new file mode 100644 index 000000000000..986013aa62df --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_hfi_common.h" +#include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_packet.h" + +static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr, + u32 session_id, u32 header_id) +{ + memset(hdr, 0, sizeof(*hdr)); + + hdr->size = sizeof(*hdr); + hdr->session_id = session_id; + hdr->header_id = header_id; + hdr->num_packets = 0; +} + +static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 pkt_type, + u32 pkt_flags, u32 payload_type, u32 port, + u32 packet_id, void *payload, u32 payload_size) +{ + struct iris_hfi_packet *pkt = (struct iris_hfi_packet *)((u8 *)hdr + hdr->size); + u32 pkt_size = sizeof(*pkt) + payload_size; + + memset(pkt, 0, pkt_size); + pkt->size = pkt_size; + pkt->type = pkt_type; + pkt->flags = pkt_flags; + pkt->payload_info = payload_type; + pkt->port = port; + pkt->packet_id = packet_id; + if (payload_size) + memcpy(&pkt->payload[0], payload, payload_size); + + hdr->num_packets++; + hdr->size += pkt->size; +} + +void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr) +{ + u32 payload = 0; + + iris_hfi_gen2_create_header(hdr, 0, core->header_id++); + + payload = HFI_VIDEO_ARCH_LX; + iris_hfi_gen2_create_packet(hdr, + HFI_CMD_INIT, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED | + HFI_HOST_FLAGS_NON_DISCARDABLE), + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->max_channels; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_MAX_CHANNELS, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->mal_length; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_MAL_LENGTH, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->highest_bank_bit; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_HBB, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->bank_swzl_level; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_BANK_SWZL_LEVEL1, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->bank_swz2_level; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_BANK_SWZL_LEVEL2, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->bank_swz3_level; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_BANK_SWZL_LEVEL3, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + payload = core->iris_platform_data->ubwc_config->bank_spreading; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_UBWC_BANK_SPREADING, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); +} + +void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr) +{ + iris_hfi_gen2_create_header(hdr, 0, core->header_id++); + + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_IMAGE_VERSION, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED | + HFI_HOST_FLAGS_GET_PROPERTY), + HFI_PAYLOAD_NONE, + HFI_PORT_NONE, + core->packet_id++, + NULL, 0); +} + +void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, + struct iris_hfi_header *hdr) +{ + u32 payload = 1; /* HFI_TRUE */ + + iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++); + + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_INTRA_FRAME_POWER_COLLAPSE, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); +} diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h new file mode 100644 index 000000000000..10dcb6e4c3d9 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_HFI_GEN2_PACKET_H__ +#define __IRIS_HFI_GEN2_PACKET_H__ + +#include "iris_hfi_gen2_defines.h" + +struct iris_core; + +/** + * struct iris_hfi_header + * + * @size: size of the total packet in bytes including hfi_header + * @session_id: For session level hfi_header session_id is non-zero. + * For system level hfi_header session_id is zero. + * @header_id: unique header id for each hfi_header + * @reserved: reserved for future use + * @num_packets: number of hfi_packet that are included with the hfi_header + */ +struct iris_hfi_header { + u32 size; + u32 session_id; + u32 header_id; + u32 reserved[4]; + u32 num_packets; +}; + +/** + * struct iris_hfi_packet + * + * @size: size of the hfi_packet in bytes including payload + * @type: one of the below hfi_packet types: + * HFI_CMD_*, + * HFI_PROP_*, + * HFI_ERROR_*, + * HFI_INFO_*, + * HFI_SYS_ERROR_* + * @flags: hfi_packet flags. It is represented as bit masks. + * host packet flags are "enum hfi_packet_host_flags" + * firmware packet flags are "enum hfi_packet_firmware_flags" + * @payload_info: payload information indicated by "enum hfi_packet_payload_info" + * @port: hfi_packet port type indicated by "enum hfi_packet_port_type" + * This is bitmask and may be applicable to multiple ports. + * @packet_id: host hfi_packet contains unique packet id. + * firmware returns host packet id in response packet + * wherever applicable. If not applicable firmware sets it to zero. + * @reserved: reserved for future use. + * @payload: flexible array of payload having additional packet information. + */ +struct iris_hfi_packet { + u32 size; + u32 type; + u32 flags; + u32 payload_info; + u32 port; + u32 packet_id; + u32 reserved[2]; + u32 payload[]; +}; + +void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr); +void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); +void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, + struct iris_hfi_header *hdr); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c new file mode 100644 index 000000000000..007e4a7b6782 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_defines.h" +#include "iris_hfi_gen2_packet.h" +#include "iris_vpu_common.h" + +struct iris_hfi_gen2_core_hfi_range { + u32 begin; + u32 end; + int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt); +}; + +static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt) +{ + u8 *response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE; + u32 response_pkt_size = *(u32 *)response_pkt; + + if (!response_pkt_size) + return -EINVAL; + + if (response_pkt_size < sizeof(struct iris_hfi_packet)) + return -EINVAL; + + if (response_pkt + response_pkt_size > response_limit) + return -EINVAL; + + return 0; +} + +static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris_hfi_header *hdr) +{ + struct iris_hfi_packet *packet; + int ret; + u8 *pkt; + u32 i; + + if (hdr->size < sizeof(*hdr) + sizeof(*packet)) + return -EINVAL; + + pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); + + for (i = 0; i < hdr->num_packets; i++) { + packet = (struct iris_hfi_packet *)pkt; + ret = iris_hfi_gen2_validate_packet(pkt, core->response_packet); + if (ret) + return ret; + + pkt += packet->size; + } + + return 0; +} + +static int iris_hfi_gen2_handle_system_error(struct iris_core *core, + struct iris_hfi_packet *pkt) +{ + dev_err(core->dev, "received system error of type %#x\n", pkt->type); + + core->state = IRIS_CORE_ERROR; + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); + + return 0; +} + +static int iris_hfi_gen2_handle_system_init(struct iris_core *core, + struct iris_hfi_packet *pkt) +{ + if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) { + core->state = IRIS_CORE_ERROR; + return 0; + } + + complete(&core->core_init_done); + + return 0; +} + +static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core, + struct iris_hfi_packet *pkt) +{ + u8 *str_image_version = (u8 *)pkt + sizeof(*pkt); + u32 req_bytes = pkt->size - sizeof(*pkt); + char fw_version[IRIS_FW_VERSION_LENGTH]; + u32 i; + + if (req_bytes < IRIS_FW_VERSION_LENGTH - 1) + return -EINVAL; + + for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) { + if (str_image_version[i] != '\0') + fw_version[i] = str_image_version[i]; + else + fw_version[i] = ' '; + } + fw_version[i] = '\0'; + dev_dbg(core->dev, "firmware version: %s\n", fw_version); + + return 0; +} + +static int iris_hfi_gen2_handle_system_property(struct iris_core *core, + struct iris_hfi_packet *pkt) +{ + switch (pkt->type) { + case HFI_PROP_IMAGE_VERSION: + return iris_hfi_gen2_handle_image_version_property(core, pkt); + default: + return 0; + } +} + +static int iris_hfi_gen2_handle_system_response(struct iris_core *core, + struct iris_hfi_header *hdr) +{ + u8 *start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); + struct iris_hfi_packet *packet; + u32 i, j; + u8 *pkt; + int ret; + static const struct iris_hfi_gen2_core_hfi_range range[] = { + {HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END, iris_hfi_gen2_handle_system_error }, + {HFI_PROP_BEGIN, HFI_PROP_END, iris_hfi_gen2_handle_system_property }, + {HFI_CMD_BEGIN, HFI_CMD_END, iris_hfi_gen2_handle_system_init }, + }; + + for (i = 0; i < ARRAY_SIZE(range); i++) { + pkt = start_pkt; + for (j = 0; j < hdr->num_packets; j++) { + packet = (struct iris_hfi_packet *)pkt; + if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) { + ret = iris_hfi_gen2_handle_system_error(core, packet); + return ret; + } + + if (packet->type > range[i].begin && packet->type < range[i].end) { + ret = range[i].handle(core, packet); + if (ret) + return ret; + + if (packet->type > HFI_SYSTEM_ERROR_BEGIN && + packet->type < HFI_SYSTEM_ERROR_END) + return 0; + } + pkt += packet->size; + } + } + + return 0; +} + +static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response) +{ + struct iris_hfi_header *hdr = (struct iris_hfi_header *)response; + int ret; + + ret = iris_hfi_gen2_validate_hdr_packet(core, hdr); + if (ret) + return iris_hfi_gen2_handle_system_error(core, NULL); + + return iris_hfi_gen2_handle_system_response(core, hdr); +} + +static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet) +{ + struct hfi_debug_header *pkt; + u8 *log; + + while (!iris_hfi_queue_dbg_read(core, packet)) { + pkt = (struct hfi_debug_header *)packet; + + if (pkt->size < sizeof(*pkt)) + continue; + + if (pkt->size >= IFACEQ_CORE_PKT_SIZE) + continue; + + packet[pkt->size] = '\0'; + log = (u8 *)packet + sizeof(*pkt) + 1; + dev_dbg(core->dev, "%s", log); + } +} + +static void iris_hfi_gen2_response_handler(struct iris_core *core) +{ + if (iris_vpu_watchdog(core, core->intr_status)) { + struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT}; + + dev_err(core->dev, "cpu watchdog error received\n"); + core->state = IRIS_CORE_ERROR; + iris_hfi_gen2_handle_system_error(core, &pkt); + + return; + } + + memset(core->response_packet, 0, sizeof(struct iris_hfi_header)); + while (!iris_hfi_queue_msg_read(core, core->response_packet)) { + iris_hfi_gen2_handle_response(core, core->response_packet); + memset(core->response_packet, 0, sizeof(struct iris_hfi_header)); + } + + iris_hfi_gen2_flush_debug_queue(core, core->response_packet); +} + +static const struct iris_hfi_response_ops iris_hfi_gen2_response_ops = { + .hfi_response_handler = iris_hfi_gen2_response_handler, +}; + +void iris_hfi_gen2_response_ops_init(struct iris_core *core) +{ + core->hfi_response_ops = &iris_hfi_gen2_response_ops; +} diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index bb7e0d747f0f..136b1862c53f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -5,6 +5,179 @@ #include "iris_core.h" #include "iris_hfi_queue.h" +#include "iris_vpu_common.h" + +static int iris_hfi_queue_write(struct iris_iface_q_info *qinfo, void *packet, u32 packet_size) +{ + struct iris_hfi_queue_header *queue = qinfo->qhdr; + u32 write_idx = queue->write_idx * sizeof(u32); + u32 read_idx = queue->read_idx * sizeof(u32); + u32 empty_space, new_write_idx, residue; + u32 *write_ptr; + + if (write_idx < read_idx) + empty_space = read_idx - write_idx; + else + empty_space = IFACEQ_QUEUE_SIZE - (write_idx - read_idx); + if (empty_space < packet_size) + return -ENOSPC; + + queue->tx_req = 0; + + new_write_idx = write_idx + packet_size; + write_ptr = (u32 *)((u8 *)qinfo->kernel_vaddr + write_idx); + + if (write_ptr < (u32 *)qinfo->kernel_vaddr || + write_ptr > (u32 *)(qinfo->kernel_vaddr + + IFACEQ_QUEUE_SIZE)) + return -EINVAL; + + if (new_write_idx < IFACEQ_QUEUE_SIZE) { + memcpy(write_ptr, packet, packet_size); + } else { + residue = new_write_idx - IFACEQ_QUEUE_SIZE; + memcpy(write_ptr, packet, (packet_size - residue)); + memcpy(qinfo->kernel_vaddr, + packet + (packet_size - residue), residue); + new_write_idx = residue; + } + + /* Make sure packet is written before updating the write index */ + mb(); + queue->write_idx = new_write_idx / sizeof(u32); + + /* Make sure write index is updated before an interrupt is raised */ + mb(); + + return 0; +} + +static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet) +{ + struct iris_hfi_queue_header *queue = qinfo->qhdr; + u32 write_idx = queue->write_idx * sizeof(u32); + u32 read_idx = queue->read_idx * sizeof(u32); + u32 packet_size, receive_request = 0; + u32 new_read_idx, residue; + u32 *read_ptr; + int ret = 0; + + if (queue->queue_type == IFACEQ_MSGQ_ID) + receive_request = 1; + + if (read_idx == write_idx) { + queue->rx_req = receive_request; + /* Ensure qhdr is updated in main memory */ + mb(); + return -ENODATA; + } + + read_ptr = qinfo->kernel_vaddr + read_idx; + if (read_ptr < (u32 *)qinfo->kernel_vaddr || + read_ptr > (u32 *)(qinfo->kernel_vaddr + + IFACEQ_QUEUE_SIZE - sizeof(*read_ptr))) + return -ENODATA; + + packet_size = *read_ptr; + if (!packet_size) + return -EINVAL; + + new_read_idx = read_idx + packet_size; + if (packet_size <= IFACEQ_CORE_PKT_SIZE) { + if (new_read_idx < IFACEQ_QUEUE_SIZE) { + memcpy(packet, read_ptr, packet_size); + } else { + residue = new_read_idx - IFACEQ_QUEUE_SIZE; + memcpy(packet, read_ptr, (packet_size - residue)); + memcpy((packet + (packet_size - residue)), + qinfo->kernel_vaddr, residue); + new_read_idx = residue; + } + } else { + new_read_idx = write_idx; + ret = -EBADMSG; + } + + queue->rx_req = receive_request; + + queue->read_idx = new_read_idx / sizeof(u32); + /* Ensure qhdr is updated in main memory */ + mb(); + + return ret; +} + +int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size) +{ + struct iris_iface_q_info *q_info = &core->command_queue; + + if (core->state == IRIS_CORE_ERROR) + return -EINVAL; + + if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) { + iris_vpu_raise_interrupt(core); + } else { + dev_err(core->dev, "queue full\n"); + return -ENODATA; + } + + return 0; +} + +int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size) +{ + int ret; + + mutex_lock(&core->lock); + ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size); + mutex_unlock(&core->lock); + + return ret; +} + +int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt) +{ + struct iris_iface_q_info *q_info = &core->message_queue; + int ret = 0; + + mutex_lock(&core->lock); + if (core->state != IRIS_CORE_INIT) { + ret = -EINVAL; + goto unlock; + } + + if (iris_hfi_queue_read(q_info, pkt)) { + ret = -ENODATA; + goto unlock; + } + +unlock: + mutex_unlock(&core->lock); + + return ret; +} + +int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt) +{ + struct iris_iface_q_info *q_info = &core->debug_queue; + int ret = 0; + + mutex_lock(&core->lock); + if (core->state != IRIS_CORE_INIT) { + ret = -EINVAL; + goto unlock; + } + + if (iris_hfi_queue_read(q_info, pkt)) { + ret = -ENODATA; + goto unlock; + } + +unlock: + mutex_unlock(&core->lock); + + return ret; +} static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id, struct iris_iface_q_info *iface_q) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.h b/drivers/media/platform/qcom/iris/iris_hfi_queue.h index 99a3b83d063f..2174fc5ce618 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.h @@ -174,4 +174,9 @@ struct iris_iface_q_info { int iris_hfi_queues_init(struct iris_core *core); void iris_hfi_queues_deinit(struct iris_core *core); +int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size); +int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size); +int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt); +int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt); + #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 7e661e8928bd..adf639d1a109 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -6,7 +6,10 @@ #ifndef __IRIS_PLATFORM_COMMON_H__ #define __IRIS_PLATFORM_COMMON_H__ +struct iris_core; + #define IRIS_PAS_ID 9 +#define HW_RESPONSE_TIMEOUT_VALUE (1000) /* milliseconds */ extern struct iris_platform_data sm8550_data; @@ -28,7 +31,19 @@ struct tz_cp_config { u32 cp_nonpixel_size; }; +struct ubwc_config_data { + u32 max_channels; + u32 mal_length; + u32 highest_bank_bit; + u32 bank_swzl_level; + u32 bank_swz2_level; + u32 bank_swz3_level; + u32 bank_spreading; +}; + struct iris_platform_data { + void (*init_hfi_command_ops)(struct iris_core *core); + void (*init_hfi_response_ops)(struct iris_core *core); struct iris_inst *(*get_instance)(void); const struct icc_info *icc_tbl; unsigned int icc_tbl_size; @@ -45,6 +60,8 @@ struct iris_platform_data { u32 pas_id; struct tz_cp_config *tz_cp_config_data; u32 core_arch; + u32 hw_response_timeout; + struct ubwc_config_data *ubwc_config; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 4f40bfeeecf1..b749d355e8ad 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -26,6 +26,16 @@ static const struct platform_clk_data sm8550_clk_table[] = { {IRIS_HW_CLK, "vcodec0_core" }, }; +static struct ubwc_config_data ubwc_config_sm8550 = { + .max_channels = 8, + .mal_length = 32, + .highest_bank_bit = 16, + .bank_swzl_level = 0, + .bank_swz2_level = 1, + .bank_swz3_level = 1, + .bank_spreading = 1, +}; + static struct tz_cp_config tz_cp_config_sm8550 = { .cp_start = 0, .cp_size = 0x25800000, @@ -35,6 +45,8 @@ static struct tz_cp_config tz_cp_config_sm8550 = { struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, .icc_tbl = sm8550_icc_table, .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), .clk_rst_tbl = sm8550_clk_reset_table, @@ -50,4 +62,6 @@ struct iris_platform_data sm8550_data = { .pas_id = IRIS_PAS_ID, .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, }; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 3015e6cb347f..02887b3dbe0e 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -177,6 +177,15 @@ static void iris_remove(struct platform_device *pdev) mutex_destroy(&core->lock); } +static void iris_sys_error_handler(struct work_struct *work) +{ + struct iris_core *core = + container_of(work, struct iris_core, sys_error_handler.work); + + iris_core_deinit(core); + iris_core_init(core); +} + static int iris_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -191,6 +200,13 @@ static int iris_probe(struct platform_device *pdev) core->state = IRIS_CORE_DEINIT; mutex_init(&core->lock); + init_completion(&core->core_init_done); + + core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL); + if (!core->response_packet) + return -ENOMEM; + + INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler); core->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(core->reg_base)) @@ -202,7 +218,17 @@ static int iris_probe(struct platform_device *pdev) core->iris_platform_data = of_device_get_match_data(core->dev); + ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr, + iris_hfi_isr_handler, IRQF_TRIGGER_HIGH, "iris", core); + if (ret) + return ret; + + disable_irq_nosync(core->irq); + iris_init_ops(core); + core->iris_platform_data->init_hfi_command_ops(core); + core->iris_platform_data->init_hfi_response_ops(core); + ret = iris_init_resources(core); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 959ed46e8f47..34817573f61b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -11,10 +11,15 @@ #define CPU_BASE_OFFS 0x000A0000 #define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) +#define CPU_IC_BASE_OFFS (CPU_BASE_OFFS) + +#define CPU_CS_A2HSOFTINTCLR (CPU_CS_BASE_OFFS + 0x1C) +#define CLEAR_XTENSA2HOST_INTR BIT(0) #define CTRL_INIT (CPU_CS_BASE_OFFS + 0x48) #define CTRL_STATUS (CPU_CS_BASE_OFFS + 0x4C) +#define CTRL_INIT_IDLE_MSG_BMSK 0x40000000 #define CTRL_ERROR_STATUS__M 0xfe #define QTBL_INFO (CPU_CS_BASE_OFFS + 0x50) @@ -31,6 +36,14 @@ #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) +#define CPU_IC_SOFTINT (CPU_IC_BASE_OFFS + 0x150) +#define CPU_IC_SOFTINT_H2A_SHFT 0x0 + +#define WRAPPER_BASE_OFFS 0x000B0000 +#define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) +#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) +#define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) + static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) { u32 queue_size, value; @@ -87,3 +100,33 @@ int iris_vpu_boot_firmware(struct iris_core *core) return 0; } + +void iris_vpu_raise_interrupt(struct iris_core *core) +{ + writel(1 << CPU_IC_SOFTINT_H2A_SHFT, core->reg_base + CPU_IC_SOFTINT); +} + +void iris_vpu_clear_interrupt(struct iris_core *core) +{ + u32 intr_status, mask; + + intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS); + mask = (WRAPPER_INTR_STATUS_A2H_BMSK | + WRAPPER_INTR_STATUS_A2HWD_BMSK | + CTRL_INIT_IDLE_MSG_BMSK); + + if (intr_status & mask) + core->intr_status |= intr_status; + + writel(CLEAR_XTENSA2HOST_INTR, core->reg_base + CPU_CS_A2HSOFTINTCLR); +} + +int iris_vpu_watchdog(struct iris_core *core, u32 intr_status) +{ + if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) { + dev_err(core->dev, "received watchdog interrupt\n"); + return -ETIME; + } + + return 0; +} diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index bafcf46520fd..c38c055d3d14 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -9,5 +9,8 @@ struct iris_core; int iris_vpu_boot_firmware(struct iris_core *core); +void iris_vpu_raise_interrupt(struct iris_core *core); +void iris_vpu_clear_interrupt(struct iris_core *core); +int iris_vpu_watchdog(struct iris_core *core, u32 intr_status); #endif From patchwork Wed Nov 20 14:46:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844623 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 0293E1CB503; Wed, 20 Nov 2024 14:47:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114058; cv=none; b=WBu5DBUIPBwANXYpdSQJs3G6o27VXhbckOIQz4yqfnjvLRi+eIzD/cNb31uGD42knvOosBe8/S7c2s4gqnKGhHMYkgaCV49bDxImdAFDW6Pl1jhlkDMqMtkBnt6GLja3XigvCvy+T1FiVYMFAumiWlMEhTiwRpI5/NPXu3wmS0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114058; c=relaxed/simple; bh=fsI5+s60Ggs5P6BkpJA8GTIx7iS9tOhViFbJqfwt6o4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=q4pGHpyA1KC4W6Gjej1wHObuFkm4iXDv1rjH+Ph4Ol2VQKFpIKEQyMgyz4EHcFKawImguh2kI9M/cAj8HGZDf3B7pPOSHcMEzidw3/7tCT5CdJGg7EKI9Kwl5JAKuYXxr88YjT5BOe4gsCON4ZiQVV2buyiHjA0Er5ah/KHUvZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=eV8kvTpH; arc=none smtp.client-ip=205.220.168.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="eV8kvTpH" Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FLTZ003945; Wed, 20 Nov 2024 14:47:28 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= ncm+55HxVFxvwiOF133UwhR+BJVDo9bYpLkUHjhWGIs=; b=eV8kvTpHxdEndJA1 F0lmFOZCvgUHwVL+GLyMnJE4/d1c1uoNFiwnpqDT8f4u1kKuL9kESawcoEUuZftF jlEZRZ8ZvmOhduvPnnDXUY6jm4jqb9H+FvP6lzpGi2GHiV22tpabMz2eEFceAjfA Y3OOKIEd26VR9hvLLDuSfnaVpjA2/PFDFEhOdx2DQLNWciJO22Aouqf9qqTp92rS Mhlge5j3bkICm7Sq5qDZ9IgpTS0S8TXRye1lUoYKQM5fDeE/ALsQ5+yuXi4dOsDf h51JKP7szaj3U3h0LpJmP+4uDuI07kFBoWDVahko4ssb9pZoo/HYCeVtVeFFH/NS NhCv8g== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 431ce38x4n-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:27 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKElRRi009244 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:27 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:47:21 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:00 +0530 Subject: [PATCH v6 10/28] media: iris: implement s_fmt, g_fmt and try_fmt ioctls Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-10-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" , Vedang Nagar X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=8029; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=N1o0yQDp8PF7VdBDglaxAnLCybX4ZCyvJkuI7KppLkk=; b=Y2rL32FU51bBSCcdIyyg93qRhCcdB+JnvawxayhWlZ+RPBDPIBQE7kbj27DpK1T2MdtqHOG07 x8ABPDRXDOYD+PzNUFANeyvL0p3JVVavrDd1FkhCxpEW/mHt4xqYC9d X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: f-9l81zNZ4rzpAQesU_TJvEYHczrx82p X-Proofpoint-ORIG-GUID: f-9l81zNZ4rzpAQesU_TJvEYHczrx82p X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 clxscore=1015 priorityscore=1501 impostorscore=0 bulkscore=0 mlxscore=0 adultscore=0 spamscore=0 mlxlogscore=999 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 From: Vedang Nagar Implement s_fmt, g_fmt and try_fmt ioctl ops with necessary hooks. Signed-off-by: Vedang Nagar Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vdec.c | 122 +++++++++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_vdec.h | 2 + drivers/media/platform/qcom/iris/iris_vidc.c | 48 +++++++++++ 3 files changed, 172 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 2ed50ad5d58b..11a2507fc35f 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -3,6 +3,8 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include + #include "iris_buffer.h" #include "iris_instance.h" #include "iris_vdec.h" @@ -10,6 +12,7 @@ #define DEFAULT_WIDTH 320 #define DEFAULT_HEIGHT 240 +#define DEFAULT_CODEC_ALIGNMENT 16 void iris_vdec_inst_init(struct iris_inst *inst) { @@ -54,3 +57,122 @@ void iris_vdec_inst_deinit(struct iris_inst *inst) kfree(inst->fmt_dst); kfree(inst->fmt_src); } + +int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_format *f_inst; + struct vb2_queue *src_q; + + memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) { + f_inst = inst->fmt_src; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; + } + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { + f_inst = inst->fmt_dst; + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + } + + src_q = v4l2_m2m_get_src_vq(m2m_ctx); + if (vb2_is_streaming(src_q)) { + f_inst = inst->fmt_src; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + } + break; + default: + return -EINVAL; + } + + if (pixmp->field == V4L2_FIELD_ANY) + pixmp->field = V4L2_FIELD_NONE; + + pixmp->num_planes = 1; + + return 0; +} + +int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_format *fmt, *output_fmt; + struct vb2_queue *q; + u32 codec_align; + + iris_vdec_try_fmt(inst, f); + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) + return -EINVAL; + + fmt = inst->fmt_src; + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + codec_align = DEFAULT_CODEC_ALIGNMENT; + fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align); + fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align); + fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); + inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + + output_fmt = inst->fmt_dst; + output_fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; + output_fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; + output_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + + inst->crop.left = 0; + inst->crop.top = 0; + inst->crop.width = f->fmt.pix_mp.width; + inst->crop.height = f->fmt.pix_mp.height; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt = inst->fmt_dst; + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); + if (q->streaming) { + f->fmt.pix_mp.height = inst->fmt_src->fmt.pix_mp.height; + f->fmt.pix_mp.width = inst->fmt_src->fmt.pix_mp.width; + } + if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) + return -EINVAL; + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; + fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); + fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); + fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128); + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + + if (!q->streaming) { + inst->crop.top = 0; + inst->crop.left = 0; + inst->crop.width = f->fmt.pix_mp.width; + inst->crop.height = f->fmt.pix_mp.height; + } + break; + default: + return -EINVAL; + } + memcpy(f, fmt, sizeof(*fmt)); + + return 0; +} diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index 353b73b76230..85e93f33e9e7 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -10,5 +10,7 @@ struct iris_inst; void iris_vdec_inst_init(struct iris_inst *inst); void iris_vdec_inst_deinit(struct iris_inst *inst); +int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index ab3b63171c1d..6707eb9917fe 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -217,6 +217,48 @@ int iris_close(struct file *filp) return 0; } +static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) +{ + struct iris_inst *inst = iris_get_inst(filp, NULL); + int ret; + + mutex_lock(&inst->lock); + ret = iris_vdec_try_fmt(inst, f); + mutex_unlock(&inst->lock); + + return ret; +} + +static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) +{ + struct iris_inst *inst = iris_get_inst(filp, NULL); + int ret; + + mutex_lock(&inst->lock); + ret = iris_vdec_s_fmt(inst, f); + mutex_unlock(&inst->lock); + + return ret; +} + +static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) +{ + struct iris_inst *inst = iris_get_inst(filp, NULL); + int ret = 0; + + mutex_lock(&inst->lock); + if (V4L2_TYPE_IS_OUTPUT(f->type)) + memcpy(f, inst->fmt_src, sizeof(*f)); + else if (V4L2_TYPE_IS_CAPTURE(f->type)) + memcpy(f, inst->fmt_dst, sizeof(*f)); + else + ret = -EINVAL; + + mutex_unlock(&inst->lock); + + return ret; +} + static struct v4l2_file_operations iris_v4l2_file_ops = { .owner = THIS_MODULE, .open = iris_open, @@ -231,6 +273,12 @@ static const struct vb2_ops iris_vb2_ops = { }; static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { + .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, + .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane, + .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane, + .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane, + .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, }; From patchwork Wed Nov 20 14:46:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844622 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 1282E1BDA84; Wed, 20 Nov 2024 14:47:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114065; cv=none; b=rtRIXD5OLEmTwwOyTvHscD4wYIKF5w/jOap+jXLt6/D5dp23yPl2Axs2nbK6100YrHWrdOc96AtqtTIj8d3LFlpKc/sapaPtV+RVq+k1unaXh9B96qmvgsSuKzeENsqF8pFpQ5dC/SCLZhMTqhmrxSRdwIwjkB1/hobF9Oxx4ls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114065; c=relaxed/simple; bh=NFFB08JiUa5oaVr25UGih8riWPGiU2UeXOT5RyHYprw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=HrTXkW2zmK3LZzpl2PdLyZKtMxax2wbFmuxcNqRJcbVuMpfZqjiHZshH+nrcAGXYxt0ynhJAYKioTjhWReoMn6iW7Wlwifak3Q007tr716T5wAxdgZ/GTkn6KJaUeZXl+y37pB0xrliET4BXwcjcasRpYD91WFRqhXVxmdStjtk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=ZN4/lrQk; arc=none smtp.client-ip=205.220.168.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="ZN4/lrQk" Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FL8V027891; Wed, 20 Nov 2024 14:47:34 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= k6Yb4CXWPc378xgZbcx2Hpn03X9JMRQr45m9MhZLRkE=; b=ZN4/lrQkOSO8oc2o 5ormYl2X/plVuTt/N7nJL5cf9goHxBrlbiBoRgPy2KxXqE2rM8qeMe+pN9JqlHLw 1jraCNdrPIWlVUx4bpoXxSYwojLp0r5ueUztMPtbJ3rFKq6izPWojuHVjiRFoMQw IZa/devcz76pmEQrwFyBtzCWHOu5q/PlFlaV3O/Roo8XVCEwiJyRfl241MPuSC7L R3Nxaf3PG4w2DLYQYbFGh4M6J5oKSnfrDVsLjbCA1Nd0Av9izF2kfLEtkHkAfK+W e5QxeYVqVKDGF5PiZFj05FTvn7rZLUCyYAK5AXpaNdpA8RAa70D824TSwynKgvIo dVWT+Q== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 431bv790pj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:33 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKElXwU032016 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:33 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:47:27 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:01 +0530 Subject: [PATCH v6 11/28] media: iris: implement g_selection ioctl Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-11-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" , Vedang Nagar X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=1910; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=a1JT6No3PTjphy1UIm65kpGhP88STeudAiuLPm9VnZ0=; b=TI8U4fcjQhrp3ui0XoBzDMfNUg29p+bisz1qz31DYOv2oZpdTvpV/5uq63Fyb90Tii/bmJSZE CIWZVd01FaRAADuMSdKzJed6BWSfjcMYUadp/TdnbzKuZye9A3ETqQB X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: wUYN1UYjcFt4f-w6hD2kXXa46L-8Hdpd X-Proofpoint-GUID: wUYN1UYjcFt4f-w6hD2kXXa46L-8Hdpd X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 mlxscore=0 spamscore=0 mlxlogscore=999 impostorscore=0 phishscore=0 clxscore=1015 priorityscore=1501 lowpriorityscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 From: Vedang Nagar Implement g_selection ioctl in the driver with necessary hooks. Signed-off-by: Vedang Nagar Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vidc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 6707eb9917fe..6a32fd8d6123 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -259,6 +259,33 @@ static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format return ret; } +static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) +{ + struct iris_inst *inst = iris_get_inst(filp, NULL); + + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + switch (s->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_PADDED: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE: + s->r.left = inst->crop.left; + s->r.top = inst->crop.top; + s->r.width = inst->crop.width; + s->r.height = inst->crop.height; + break; + default: + return -EINVAL; + } + + return 0; +} + static struct v4l2_file_operations iris_v4l2_file_ops = { .owner = THIS_MODULE, .open = iris_open, @@ -280,6 +307,7 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_g_selection = iris_g_selection, }; void iris_init_ops(struct iris_core *core) From patchwork Wed Nov 20 14:46:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844621 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 2769F1BF7E5; Wed, 20 Nov 2024 14:47:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114081; cv=none; b=ll+UfmobRlrUxbIN89Awtnij5Wb/ing95pf0m4dXdMMrqEiKlHqqIHFz5waYqpiA+hZHMZ8gfPZ6IyhKAAdNtrCvT3RPUX0XaUa8P6pFYH0sXltgvYILt0OTYsC819JwyDwbnvHcTEfyBWXpeJsLCs3IIg9yOwpjZeljGW+JOyw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114081; c=relaxed/simple; bh=6c4fOrsfRMdsXn8zmGdJGS5A67/6xQaJIdex3v6Px+U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=DVc7WmnB+RAC+tviJeZS2j8atNLbr/18Wsl66fsKLvr9jRTbA6EYQTVQCn4/4+6m3RZE11uborNt58hk/zGXv5pza9rzvrZWi2uee/gcMCLiVFJN8jldOh1XuwF17ODYwG9MmfBHQGQpiEObsViW6KGsKs2iKJ5COUW4Hhtbf1Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=KX5+bLXy; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="KX5+bLXy" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FVjV005827; Wed, 20 Nov 2024 14:47:46 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= p9kbJ0kkLOPigYM5y54n9rJhGGTK4WG/YqunICV6Qgw=; b=KX5+bLXyGD4B9AVv r/lXp9N/oTacnGuWa+9nUih7t7dHjnf0PgJb+NWkwgVp7Z5aqCMW/Db5wzUVhPHZ nqMA72u5EGZxcvbb20qYKVa2/+SBFajXQcimJ/Xfd35zBPzAHQ3cn+b7Evv+l9tA L+1eD0DvU/NVtOdGuPGYQJk8JTVtBOSnrB1wAUbGc5REmBITFR6ggYjgRtPuUx9u fuyBIFeeglOoO1NitIJnF9lsvwEgzYwW5AIdfW6Vb9hKeCkOQCRT0RuOx3D0LSne Dyjad8Ncw93AT9uSvE2pf4g4gvsqy01XhXTH3Wc9UFMdR+5cAcCCgRGA5prInsCA kNntow== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4308y7x7ey-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:46 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEliTq006207 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:44 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:47:39 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:03 +0530 Subject: [PATCH v6 13/28] media: iris: implement subscribe_event and unsubscribe_event ioctls Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-13-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" , Vedang Nagar X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=4457; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=1DvM7J74kUtS4JtLaQfrazG5fg8bqhKNeG/nGTYgEBw=; b=AQPdfdT41fcC9/fygKaq9HOP6WcDrm5G8+bEAfLlU9NqFuj+/eGdKjERLA9eSY4Lq3+lyIEY6 bLGef6DpoqGDK9B+FGafgdi99pniS5giiwDSCMC82zw63VKbnjPA91C X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: TD5spztk_WU-y2Z-FdUiJpECYyb58xDr X-Proofpoint-GUID: TD5spztk_WU-y2Z-FdUiJpECYyb58xDr X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 spamscore=0 mlxlogscore=999 clxscore=1015 suspectscore=0 adultscore=0 priorityscore=1501 phishscore=0 impostorscore=0 bulkscore=0 lowpriorityscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 From: Vedang Nagar Implement subscribe_event and unsubscribe_event iocts with necessary hooks. Signed-off-by: Vedang Nagar Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_instance.h | 2 ++ drivers/media/platform/qcom/iris/iris_vdec.c | 25 ++++++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_vdec.h | 1 + drivers/media/platform/qcom/iris/iris_vidc.c | 10 ++++++++++ 4 files changed, 38 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 1e9a6075357f..ef4515d2086c 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -30,6 +30,7 @@ * @once_per_session_set: boolean to set once per session property * @m2m_dev: a reference to m2m device structure * @m2m_ctx: a reference to m2m context structure + * @subscriptions: variable to hold current events subscriptions */ struct iris_inst { @@ -48,6 +49,7 @@ struct iris_inst { bool once_per_session_set; struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_ctx *m2m_ctx; + unsigned int subscriptions; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 742b45432481..9afeb681b7a7 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -3,6 +3,7 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include "iris_buffer.h" @@ -193,3 +194,27 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) return 0; } + +int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub) +{ + int ret = 0; + + switch (sub->type) { + case V4L2_EVENT_EOS: + ret = v4l2_event_subscribe(&inst->fh, sub, 0, NULL); + inst->subscriptions |= V4L2_EVENT_EOS; + break; + case V4L2_EVENT_SOURCE_CHANGE: + ret = v4l2_src_change_event_subscribe(&inst->fh, sub); + inst->subscriptions |= V4L2_EVENT_SOURCE_CHANGE; + break; + case V4L2_EVENT_CTRL: + ret = v4l2_ctrl_subscribe_event(&inst->fh, sub); + inst->subscriptions |= V4L2_EVENT_CTRL; + break; + default: + return -EINVAL; + } + + return ret; +} diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index ae456676e578..f64ce3234e6a 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -13,5 +13,6 @@ void iris_vdec_inst_deinit(struct iris_inst *inst); int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index bc77dfc2ba67..3a138172e674 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -4,6 +4,7 @@ */ #include +#include #include #include @@ -322,6 +323,13 @@ static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection * return 0; } +static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) +{ + struct iris_inst *inst = container_of(fh, struct iris_inst, fh); + + return iris_vdec_subscribe_event(inst, sub); +} + static struct v4l2_file_operations iris_v4l2_file_ops = { .owner = THIS_MODULE, .open = iris_open, @@ -347,6 +355,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { .vidioc_enum_framesizes = iris_enum_framesizes, .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, .vidioc_g_selection = iris_g_selection, + .vidioc_subscribe_event = iris_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; void iris_init_ops(struct iris_core *core) From patchwork Wed Nov 20 14:46:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844620 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 5BD731D12E1; Wed, 20 Nov 2024 14:48:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114086; cv=none; b=eEehd4AmUKDTpXDxcW52XATd89CJBzKetSnBSYS+79YuL4oVraEo8hmc/yHtq0S/ORb7XIoFnzrm+nXwqXYo74R2wIR1ef97ICL3EbUXjW/hrp0ZalhTNSHGxu/pBslJGNpP0Kk/zcb3tQ1+wf7kJLdFEXF4I7hiPA4Cuu9gINI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114086; c=relaxed/simple; bh=uklTNfRvn93oDUOOGb7Rt3eMNn8n+Bdva7W01HFUHsQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=XVu1DEKPTpuon4rLdB3MwItR5/pd528oqNJt/yEdE1jKC+uiGKLjknic237DxO6lCZfVMm2G8K+t2eCEwn4Q3cAT0GbRNKMObikWwZImpzoYUpPcMJraMWEctmwB10mOJaEzlBz2qnyim1baXvACO8zpcLHWRegGnAg6YNV2Mf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=MQVCgOeg; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="MQVCgOeg" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FR5W010566; Wed, 20 Nov 2024 14:47:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= rhNjMSJ8PyftnURTVgdn/GmnuKlkYoEtzxOv3wqgXjs=; b=MQVCgOegfeMMlgO+ OndNB+uvuFjpQVxSFMBqLNU2sdDQ74PIiEimDpbnBjrqQIfaC4iK6l0mlJgnlQsR qpKFDUtTiWHivwJnmY9IKJf1W/g8UBObiZiZnFBSSCKts2acAhsD5i6I1x8LE4Uq v33hDEXa68EkN7HyO5GA5m2xu9nuTsm+lWiM5K1Eao6t2AFpPW+HZrqzZBzoUbDb ycuxk9H7XPnd8xoM3SLMorRszxhHCzHG2Cy3s9egWV+yYtUvqfeucoj58DA32dpc kGwQk0OyeGBWIBfJv5TtXN5F80io8JZNnZTfpMmpDVk10VVFUjE0gRTWZZbfIEvf e1drsg== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 43091me5bq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:58 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEluns009413 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:47:56 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:47:50 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:05 +0530 Subject: [PATCH v6 15/28] media: iris: implement query_cap ioctl Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-15-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" , Vedang Nagar X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=1500; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=7nhvofIcy0J7GxdmjMAQeF7e+V6iN2t9WVnS8YDTDWg=; b=RaSU0g1Vef5QWnQSfIeCkEqqICb+qN3jKgHUbyBiDQN5EotbUV045869fgZtnq95SQdPx22yI 1bb0XlrQHtZABOW864kPhJRhlE0sx1lQXTkSQ0/RoyImehUyHF+t28y X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: DLGRkIKXCN34IkLLnsEQuCQTTB80JLSE X-Proofpoint-GUID: DLGRkIKXCN34IkLLnsEQuCQTTB80JLSE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 spamscore=0 priorityscore=1501 phishscore=0 malwarescore=0 clxscore=1015 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 adultscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 From: Vedang Nagar Implement query_cap ioctl with necessary hooks. Signed-off-by: Vedang Nagar Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_vidc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 820d98da3190..26fdf03ab972 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -303,6 +303,14 @@ static int iris_enum_framesizes(struct file *filp, void *fh, return 0; } +static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap) +{ + strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver)); + strscpy(cap->card, "Iris Decoder", sizeof(cap->card)); + + return 0; +} + static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) { struct iris_inst *inst = iris_get_inst(filp, NULL); @@ -361,6 +369,7 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, .vidioc_enum_framesizes = iris_enum_framesizes, .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querycap = iris_querycap, .vidioc_g_selection = iris_g_selection, .vidioc_subscribe_event = iris_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, From patchwork Wed Nov 20 14:46:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844619 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 E206B1D362B; Wed, 20 Nov 2024 14:48:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114105; cv=none; b=X+VepHuPqlkYnh3BV/fz/wvii1EaEilDD4dvSdCpdkHWIp93TKsVqTPJMHQlZbdlHl2HFRH7U3hGdZ8uCwpT3xmUIbqJunD/X6ZZzoyIKDDLeA3Zu2YqFBI+Y7t5IdAkc/MZirI4ZGCCmQtsRfWr3ombrON3p3ZHSF2wrzSn5J4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114105; c=relaxed/simple; bh=qxr/MjB4XEto1VAgJyM66Wo+TBnXtORw6E4SMofNWpI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=VexmGQEvtOKmgS5/c+mxcgCUPbsTTEH+1c0IZPNv5FvM9EPA5AjDdlJWd4kMXdos+fw0TzxBS8CBgDZXy+Mq3blWakNFK3l1EuzpMkp9yUaOBKXX3fDiOoKBSmmHf+wwptp7EOeLCApIVp6cFWyyuvskfaeUvHp0/OyUKcXTSWw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=m7uaCqZ0; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="m7uaCqZ0" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FWRR008008; Wed, 20 Nov 2024 14:48:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= aysxN6GBM92RugQQK6Q7Q3o4fFOVrFHGEVtgFLwWQlk=; b=m7uaCqZ0Gog3Alid ZFFnf83XCrEfPMjR14xAkI+S/+QrdYzeiTovWEgkrU+OX+oF0irXU5h92mJ5yH4T 14sy4avpLNCpyFsUjz614NLLhjhaJW97SVOqzLOci0J6Mc4IYWAk0I0wznwQJxgi 92nT0ENLsarvb6Ue1G6FTMT6tbz3IKEhpjOTpJ9MGD9vfs4Dvd4j7qjm+vgQuZ7U O2tGYalJlOIl+ADjYoFbvVWiGrjDwVKZiQMv0CgTfKoXsVSQRm0/C7T2llIAQWSD vp1BDciVn7Yk6xyCNXCYqNJiY6XMhl34jDasyWFJADIwJv6dVYsPWHL9xWU99YTl KcCO1w== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4318uvhfs6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:15 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEmEBE009790 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:14 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:48:08 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:08 +0530 Subject: [PATCH v6 18/28] media: iris: subscribe parameters and properties to firmware for hfi_gen2 Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-18-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" , Vedang Nagar X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=11401; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=Sk94m+sgObG4sKPEJxj20fyGrNruCrJ0xJyJA31zPx8=; b=Vp0b8+I6u9GsfI0mlrn9nENWHNmp11ii/gfqlZpURwhijgHxHcvq2Snq6HH2p7MNRtf14ZVyb V7PmwNteMTzAtFU4L+zekov+eJg9T2FFzfwwY1Eh3wl+TfedR6RdT6l X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: nwF789MgBsJKrq-nYZeoof-5fWrIhMQm X-Proofpoint-GUID: nwF789MgBsJKrq-nYZeoof-5fWrIhMQm X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 bulkscore=0 priorityscore=1501 phishscore=0 adultscore=0 malwarescore=0 mlxscore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0 suspectscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 From: Vedang Nagar For hfi_gen2, subscribe for different bitstream parameters to firmware, to get notified for change in any of the subscribed parameters. Signed-off-by: Vedang Nagar Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_gen2.h | 6 + .../platform/qcom/iris/iris_hfi_gen2_command.c | 174 +++++++++++++++++++++ .../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 ++ .../platform/qcom/iris/iris_platform_common.h | 4 + .../platform/qcom/iris/iris_platform_sm8550.c | 13 ++ 5 files changed, 206 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h index 676bcb3dc81f..0a946c1e3a4c 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h @@ -18,12 +18,18 @@ struct iris_core; * * @inst: pointer to iris_instance structure * @packet: HFI packet + * @ipsc_properties_set: boolean to set ipsc properties to fw + * @opsc_properties_set: boolean to set opsc properties to fw * @src_subcr_params: subscription params to fw on input port + * @dst_subcr_params: subscription params to fw on output port */ struct iris_inst_hfi_gen2 { struct iris_inst inst; struct iris_hfi_header *packet; + bool ipsc_properties_set; + bool opsc_properties_set; struct hfi_subscription_params src_subcr_params; + struct hfi_subscription_params dst_subcr_params; }; void iris_hfi_gen2_command_ops_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 0845b75aafe9..dddaa074cae1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -437,6 +437,9 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst) if (inst->state != IRIS_INST_DEINIT) return -EALREADY; + inst_hfi_gen2->ipsc_properties_set = false; + inst_hfi_gen2->opsc_properties_set = false; + inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL); if (!inst_hfi_gen2->packet) return -ENOMEM; @@ -501,9 +504,180 @@ static int iris_hfi_gen2_session_close(struct iris_inst *inst) return ret; } +static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst, + u32 cmd, u32 plane, u32 payload_type, + void *payload, u32 payload_size) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + + iris_hfi_gen2_packet_session_command(inst, + cmd, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED), + iris_hfi_gen2_get_port(plane), + inst->session_id, + payload_type, + payload, + payload_size); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + +static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plane) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + struct hfi_subscription_params subsc_params; + u32 prop_type, payload_size, payload_type; + struct iris_core *core = inst->core; + const u32 *change_param; + u32 change_param_size; + u32 payload[32] = {0}; + u32 hfi_port = 0, i; + int ret; + + if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) || + (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) { + dev_err(core->dev, "invalid plane\n"); + return 0; + } + + change_param = core->iris_platform_data->input_config_params; + change_param_size = core->iris_platform_data->input_config_params_size; + + payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE; + + for (i = 0; i < change_param_size; i++) + payload[i + 1] = change_param[i]; + + ret = iris_hfi_gen2_session_subscribe_mode(inst, + HFI_CMD_SUBSCRIBE_MODE, + plane, + HFI_PAYLOAD_U32_ARRAY, + &payload[0], + ((change_param_size + 1) * sizeof(u32))); + if (ret) + return ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + inst_hfi_gen2->ipsc_properties_set = true; + } else { + hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + memcpy(&inst_hfi_gen2->dst_subcr_params, + &inst_hfi_gen2->src_subcr_params, + sizeof(inst_hfi_gen2->src_subcr_params)); + subsc_params = inst_hfi_gen2->dst_subcr_params; + for (i = 0; i < change_param_size; i++) { + payload[0] = 0; + payload[1] = 0; + payload_size = 0; + payload_type = 0; + prop_type = change_param[i]; + switch (prop_type) { + case HFI_PROP_BITSTREAM_RESOLUTION: + payload[0] = subsc_params.bitstream_resolution; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + case HFI_PROP_CROP_OFFSETS: + payload[0] = subsc_params.crop_offsets[0]; + payload[1] = subsc_params.crop_offsets[1]; + payload_size = sizeof(u64); + payload_type = HFI_PAYLOAD_64_PACKED; + break; + case HFI_PROP_CODED_FRAMES: + payload[0] = subsc_params.coded_frames; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT: + payload[0] = subsc_params.fw_min_count; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + case HFI_PROP_PIC_ORDER_CNT_TYPE: + payload[0] = subsc_params.pic_order_cnt; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + case HFI_PROP_SIGNAL_COLOR_INFO: + payload[0] = subsc_params.color_info; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + case HFI_PROP_PROFILE: + payload[0] = subsc_params.profile; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + case HFI_PROP_LEVEL: + payload[0] = subsc_params.level; + payload_size = sizeof(u32); + payload_type = HFI_PAYLOAD_U32; + break; + default: + prop_type = 0; + ret = -EINVAL; + break; + } + if (prop_type) { + ret = iris_hfi_gen2_session_set_property(inst, + prop_type, + HFI_HOST_FLAGS_NONE, + hfi_port, + payload_type, + &payload, + payload_size); + if (ret) + return ret; + } + } + inst_hfi_gen2->opsc_properties_set = true; + } + + return 0; +} + +static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane) +{ + struct iris_core *core = inst->core; + u32 subscribe_prop_size, i; + const u32 *subcribe_prop; + u32 payload[32] = {0}; + + payload[0] = HFI_MODE_PROPERTY; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + subscribe_prop_size = core->iris_platform_data->dec_input_prop_size; + subcribe_prop = core->iris_platform_data->dec_input_prop; + } else { + subscribe_prop_size = core->iris_platform_data->dec_output_prop_size; + subcribe_prop = core->iris_platform_data->dec_output_prop; + } + + for (i = 0; i < subscribe_prop_size; i++) + payload[i + 1] = subcribe_prop[i]; + + return iris_hfi_gen2_session_subscribe_mode(inst, + HFI_CMD_SUBSCRIBE_MODE, + plane, + HFI_PAYLOAD_U32_ARRAY, + &payload[0], + (subscribe_prop_size + 1) * sizeof(u32)); +} + static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + int ret = 0; + + ret = iris_hfi_gen2_subscribe_change_param(inst, plane); + if (ret) + return ret; + + ret = iris_hfi_gen2_subscribe_property(inst, plane); + if (ret) + return ret; iris_hfi_gen2_packet_session_command(inst, HFI_CMD_START, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index f518466f093a..cc7ba875d24f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -17,6 +17,7 @@ #define HFI_CMD_CLOSE 0x01000004 #define HFI_CMD_START 0x01000005 #define HFI_CMD_STOP 0x01000006 +#define HFI_CMD_SUBSCRIBE_MODE 0x0100000B #define HFI_CMD_END 0x01FFFFFF #define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001 @@ -42,13 +43,16 @@ #define HFI_PROP_PIPE 0x0300010b #define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f #define HFI_PROP_CODED_FRAMES 0x03000120 +#define HFI_PROP_CABAC_SESSION 0x03000121 #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 #define HFI_PROP_QUALITY_MODE 0x03000148 #define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155 +#define HFI_PROP_PICTURE_TYPE 0x03000162 #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 +#define HFI_PROP_NO_OUTPUT 0x0300016a #define HFI_PROP_END 0x03FFFFFF #define HFI_SESSION_ERROR_BEGIN 0x04000000 @@ -64,6 +68,11 @@ #define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 #define HFI_SYSTEM_ERROR_END 0x05FFFFFF +enum hfi_property_mode_type { + HFI_MODE_PORT_SETTINGS_CHANGE = 0x00000001, + HFI_MODE_PROPERTY = 0x00000002, +}; + enum hfi_color_format { HFI_COLOR_FMT_OPAQUE = 0, HFI_COLOR_FMT_NV12 = 1, diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 5643fb55b09e..50965450cbb9 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -147,6 +147,10 @@ struct iris_platform_data { unsigned int input_config_params_size; const u32 *output_config_params; unsigned int output_config_params_size; + const u32 *dec_input_prop; + unsigned int dec_input_prop_size; + const u32 *dec_output_prop; + unsigned int dec_output_prop_size; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 4b7372805d69..0f1eb530b232 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -183,6 +183,15 @@ static const u32 sm8550_vdec_output_config_params[] = { HFI_PROP_LINEAR_STRIDE_SCANLINE, }; +static const u32 sm8550_vdec_subscribe_input_properties[] = { + HFI_PROP_NO_OUTPUT, +}; + +static const u32 sm8550_vdec_subscribe_output_properties[] = { + HFI_PROP_PICTURE_TYPE, + HFI_PROP_CABAC_SESSION, +}; + struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, @@ -219,4 +228,8 @@ struct iris_platform_data sm8550_data = { sm8550_vdec_output_config_params, .output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop = sm8550_vdec_subscribe_output_properties, + .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), }; From patchwork Wed Nov 20 14:46:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844618 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 AAC2D1D63EC; Wed, 20 Nov 2024 14:48:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114116; cv=none; b=XR49GEJwRRt1l9UgVKHOF2sschZ0Hn8oOraMw5gO9he3ATfaQms4CFX/9hWDnTqrjW9J/cKgP2k3JzAkywNSTtBT3QhhCMI8pRFcW0GVrIW/v3xivhSVZrWMAWtdkAtBoXj08Ecy8ac0KGi8hVCRKQq9GXTmMztEEXxLkBdeV/I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114116; c=relaxed/simple; bh=D0Edk3YEFFndWTMS4GYz5y7bqGQdoW0/OIAmcCM0qOE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=PMqZUWjhPTeWaiA8b4FUPTFJAJQOD2Ik0+gAXNItRZ3w6uZZTUROr08OsLhqo3JVHuwpK2GdMyqGKiS7g9ix5txmdIuGmDnN70fqBGo/QCR0/59/J1p/A4Vx073/Rf6FbpxtZ60wVeN3qD2E+aTzFiITeh0ugEF7+l7e1naeLRo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=ERqZCw79; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="ERqZCw79" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FRcI010545; Wed, 20 Nov 2024 14:48:21 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= ktwPJxjpYn6YG7fOWgMq8dFEhm9mWPflsG6D1xBOaps=; b=ERqZCw79sRrhcAXH //Wlr1D5B3EYe0wDmiyusDnNZuB2bBwldeX7gqwhXWPeoQF79j/uXjjK5uto68l2 cOAtG36SsPKq7dvLBqXEXb+t/uiL76vhwzQTRzRErQBi1vzv9fK55ZdcG1cvOh/q JSXHiATkawQZnLzNBPR5r+4vbg2JzjNUIRYT8yi5Y4q7n9ofYoBde89rNFwMfGIr CcmtkFny7nnj86ZhUAKDehZDgy2Smvwaz6X2S8KF9dwUE0AB7veRN5JsqQ9jVVTh ivt/S/6lSNbGSFYiAN0W31DUapCtEqWT6H9mRP2NGJK6APxf4JSt8VlQXZAAQQcM HTeAkQ== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 43091me5cx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:21 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEmK2b005705 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:20 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:48:14 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:09 +0530 Subject: [PATCH v6 19/28] media: iris: allocate, initialize and queue internal buffers Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-19-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=48528; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=D0Edk3YEFFndWTMS4GYz5y7bqGQdoW0/OIAmcCM0qOE=; b=sW+QEFs9Oyzcf8IO1SEMVt5EaOFH2wV2aSM8zgZuTO6GEESlcF4KJ0HIXc4O54zbLRH/f1PRu vtQlxccamsRAdnxthf+1wcChuLGilcvxy0RZFH5n13fq0OL7sxEWDmB X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: pCmQ_OuSTkqHkp-KNI9LWnaXiYENgW36 X-Proofpoint-GUID: pCmQ_OuSTkqHkp-KNI9LWnaXiYENgW36 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 spamscore=0 priorityscore=1501 phishscore=0 malwarescore=0 clxscore=1015 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 adultscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 Implement functions for creating, queueing, releasing and destroying buffers for internal usage. Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_buffer.c | 206 ++++++++++++++++++ drivers/media/platform/qcom/iris/iris_buffer.h | 7 + drivers/media/platform/qcom/iris/iris_hfi_common.h | 4 + .../platform/qcom/iris/iris_hfi_gen1_command.c | 127 ++++++++++- .../platform/qcom/iris/iris_hfi_gen1_defines.h | 37 ++++ .../platform/qcom/iris/iris_hfi_gen1_response.c | 4 + .../platform/qcom/iris/iris_hfi_gen2_command.c | 132 ++++++++++++ .../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 + .../platform/qcom/iris/iris_hfi_gen2_packet.h | 41 ++++ .../platform/qcom/iris/iris_hfi_gen2_response.c | 149 ++++++++++++- .../platform/qcom/iris/iris_platform_common.h | 5 + .../platform/qcom/iris/iris_platform_sm8550.c | 17 ++ drivers/media/platform/qcom/iris/iris_vdec.c | 32 +++ drivers/media/platform/qcom/iris/iris_vidc.c | 11 + drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 233 ++++++++++++++++++++- drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 77 ++++++- 16 files changed, 1087 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 58d45d23393b..e9d372580b5f 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -7,6 +7,7 @@ #include "iris_buffer.h" #include "iris_instance.h" +#include "iris_vpu_buffer.h" #define PIXELS_4K 4096 #define MAX_WIDTH 4096 @@ -228,6 +229,211 @@ int iris_get_buffer_size(struct iris_inst *inst, } } +static void iris_fill_internal_buf_info(struct iris_inst *inst, + enum iris_buffer_type buffer_type) +{ + struct iris_buffers *buffers = &inst->buffers[buffer_type]; + + buffers->size = iris_vpu_buf_size(inst, buffer_type); + buffers->min_count = iris_vpu_buf_count(inst, buffer_type); +} + +void iris_get_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + const u32 *internal_buf_type; + u32 internal_buffer_count, i; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } +} + +static int iris_create_internal_buffer(struct iris_inst *inst, + enum iris_buffer_type buffer_type, u32 index) +{ + struct iris_buffers *buffers = &inst->buffers[buffer_type]; + struct iris_core *core = inst->core; + struct iris_buffer *buffer; + + if (!buffers->size) + return 0; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + INIT_LIST_HEAD(&buffer->list); + buffer->type = buffer_type; + buffer->index = index; + buffer->buffer_size = buffers->size; + buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; + list_add_tail(&buffer->list, &buffers->list); + + buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size, + &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); + if (!buffer->kvaddr) + return -ENOMEM; + + return 0; +} + +int iris_create_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + u32 internal_buffer_count, i, j; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + int ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } + + for (i = 0; i < internal_buffer_count; i++) { + buffers = &inst->buffers[internal_buf_type[i]]; + for (j = 0; j < buffers->min_count; j++) { + ret = iris_create_internal_buffer(inst, internal_buf_type[i], j); + if (ret) + return ret; + } + } + + return 0; +} + +int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + int ret; + + ret = hfi_ops->session_queue_buf(inst, buf); + if (ret) + return ret; + + buf->attr &= ~BUF_ATTR_DEFERRED; + buf->attr |= BUF_ATTR_QUEUED; + + return 0; +} + +int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + struct iris_buffer *buffer, *next; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + u32 internal_buffer_count, i; + int ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } + + for (i = 0; i < internal_buffer_count; i++) { + buffers = &inst->buffers[internal_buf_type[i]]; + list_for_each_entry_safe(buffer, next, &buffers->list, list) { + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + continue; + if (buffer->attr & BUF_ATTR_QUEUED) + continue; + ret = iris_queue_buffer(inst, buffer); + if (ret) + return ret; + } + } + + return 0; +} + +int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer) +{ + struct iris_core *core = inst->core; + + list_del(&buffer->list); + dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, + buffer->device_addr, buffer->dma_attrs); + kfree(buffer); + + return 0; +} + +int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + struct iris_buffer *buf, *next; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + u32 i, len; + int ret; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + len = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + len = platform_data->dec_op_int_buf_tbl_size; + } + + for (i = 0; i < len; i++) { + buffers = &inst->buffers[internal_buf_type[i]]; + list_for_each_entry_safe(buf, next, &buffers->list, list) { + ret = iris_destroy_internal_buffer(inst, buf); + if (ret) + return ret; + } + } + + return 0; +} + +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) +{ + struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST]; + struct iris_buffer *buffer, *next; + int ret; + u32 i; + + if (!list_empty(&buffers->list)) + return 0; + + iris_fill_internal_buf_info(inst, BUF_PERSIST); + + for (i = 0; i < buffers->min_count; i++) { + ret = iris_create_internal_buffer(inst, BUF_PERSIST, i); + if (ret) + return ret; + } + + list_for_each_entry_safe(buffer, next, &buffers->list, list) { + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + continue; + if (buffer->attr & BUF_ATTR_QUEUED) + continue; + ret = iris_queue_buffer(inst, buffer); + if (ret) + return ret; + } + + return 0; +} + void iris_vb2_queue_error(struct iris_inst *inst) { struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h index 62941e23410e..e202524663eb 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_buffer.h @@ -102,6 +102,13 @@ struct iris_buffers { }; int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); +int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); +int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); void iris_vb2_queue_error(struct iris_inst *inst); #endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 1fba5a9292af..c54c88658633 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -9,6 +9,8 @@ #include #include +#include "iris_buffer.h" + struct iris_inst; struct iris_core; @@ -114,6 +116,8 @@ struct iris_hfi_command_ops { void *payload, u32 payload_size); int (*session_open)(struct iris_inst *inst); int (*session_start)(struct iris_inst *inst, u32 plane); + int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer); + int (*session_release_buf)(struct iris_inst *inst, struct iris_buffer *buffer); int (*session_stop)(struct iris_inst *inst, u32 plane); int (*session_close)(struct iris_inst *inst); }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 26fe65ddba8a..603ca485992d 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -8,6 +8,24 @@ #include "iris_instance.h" #include "iris_vpu_buffer.h" +static u32 iris_hfi_gen1_buf_type_from_driver(enum iris_buffer_type buffer_type) +{ + switch (buffer_type) { + case BUF_INPUT: + return HFI_BUFFER_INPUT; + case BUF_OUTPUT: + return HFI_BUFFER_OUTPUT; + case BUF_PERSIST: + return HFI_BUFFER_INTERNAL_PERSIST_1; + case BUF_BIN: + return HFI_BUFFER_INTERNAL_SCRATCH; + case BUF_SCRATCH_1: + return HFI_BUFFER_INTERNAL_SCRATCH_1; + default: + return -EINVAL; + } +} + static int iris_hfi_gen1_sys_init(struct iris_core *core) { struct hfi_sys_init_pkt sys_init_pkt; @@ -183,6 +201,111 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) return ret; } +static int iris_hfi_gen1_queue_internal_buffer(struct iris_inst *inst, struct iris_buffer *buf) +{ + struct hfi_session_set_buffers_pkt *int_pkt; + u32 buffer_type, i; + u32 packet_size; + int ret; + + packet_size = struct_size(int_pkt, buffer_info, 1); + int_pkt = kzalloc(packet_size, GFP_KERNEL); + if (!int_pkt) + return -ENOMEM; + + int_pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_BUFFERS; + int_pkt->shdr.session_id = inst->session_id; + int_pkt->buffer_size = buf->buffer_size; + int_pkt->min_buffer_size = buf->buffer_size; + int_pkt->num_buffers = 1; + int_pkt->extradata_size = 0; + int_pkt->shdr.hdr.size = packet_size; + for (i = 0; i < int_pkt->num_buffers; i++) + int_pkt->buffer_info[i] = buf->device_addr; + buffer_type = iris_hfi_gen1_buf_type_from_driver(buf->type); + if (buffer_type == -EINVAL) { + ret = -EINVAL; + goto exit; + } + + int_pkt->buffer_type = buffer_type; + ret = iris_hfi_queue_cmd_write(inst->core, int_pkt, int_pkt->shdr.hdr.size); + +exit: + kfree(int_pkt); + + return ret; +} + +static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) +{ + switch (buf->type) { + case BUF_PERSIST: + case BUF_BIN: + case BUF_SCRATCH_1: + return iris_hfi_gen1_queue_internal_buffer(inst, buf); + default: + return -EINVAL; + } +} + +static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct iris_buffer *buf) +{ + struct hfi_session_release_buffer_pkt *pkt; + u32 packet_size, buffer_type, i; + int ret; + + buffer_type = iris_hfi_gen1_buf_type_from_driver(buf->type); + if (buffer_type == -EINVAL) + return -EINVAL; + + if (buffer_type == HFI_BUFFER_INPUT) + return 0; + + packet_size = sizeof(*pkt) + sizeof(struct hfi_buffer_info); + pkt = kzalloc(packet_size, GFP_KERNEL); + if (!pkt) + return -ENOMEM; + + pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_RELEASE_BUFFERS; + pkt->shdr.session_id = inst->session_id; + pkt->buffer_size = buf->buffer_size; + pkt->num_buffers = 1; + + if (buffer_type == HFI_BUFFER_OUTPUT || + buffer_type == HFI_BUFFER_OUTPUT2) { + struct hfi_buffer_info *bi; + + bi = (struct hfi_buffer_info *)pkt->buffer_info; + for (i = 0; i < pkt->num_buffers; i++) { + bi->buffer_addr = buf->device_addr; + bi->extradata_addr = 0; + } + pkt->shdr.hdr.size = packet_size; + } else { + for (i = 0; i < pkt->num_buffers; i++) + pkt->buffer_info[i] = buf->device_addr; + pkt->extradata_size = 0; + pkt->shdr.hdr.size = + sizeof(struct hfi_session_set_buffers_pkt) + + ((pkt->num_buffers) * sizeof(u32)); + } + + pkt->response_req = true; + pkt->buffer_type = buffer_type; + + ret = iris_hfi_queue_cmd_write(inst->core, pkt, pkt->shdr.hdr.size); + if (ret) + goto exit; + + ret = iris_wait_for_session_response(inst, false); + +exit: + kfree(pkt); + + return ret; +} + static int iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet, struct iris_inst *inst, u32 ptype, void *pdata) @@ -495,7 +618,7 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) if (iris_split_mode_enabled(inst)) { bufsz.type = HFI_BUFFER_OUTPUT; - bufsz.size = iris_vpu_dec_dpb_size(inst); + bufsz.size = iris_vpu_buf_size(inst, BUF_DPB); ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); if (ret) @@ -600,6 +723,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { .session_set_config_params = iris_hfi_gen1_session_set_config_params, .session_set_property = iris_hfi_gen1_session_set_property, .session_start = iris_hfi_gen1_session_start, + .session_queue_buf = iris_hfi_gen1_session_queue_buffer, + .session_release_buf = iris_hfi_gen1_session_unset_buffers, .session_stop = iris_hfi_gen1_session_stop, .session_close = iris_hfi_gen1_session_close, }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index 67e7575351d4..cabd91eafc92 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -24,11 +24,13 @@ #define HFI_CMD_SYS_SESSION_END 0x10008 #define HFI_CMD_SESSION_SET_PROPERTY 0x11001 +#define HFI_CMD_SESSION_SET_BUFFERS 0x11002 #define HFI_CMD_SESSION_LOAD_RESOURCES 0x211001 #define HFI_CMD_SESSION_START 0x211002 #define HFI_CMD_SESSION_STOP 0x211003 #define HFI_CMD_SESSION_FLUSH 0x211008 +#define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c #define HFI_ERR_SESSION_UNSUPPORTED_SETTING 0x1008 @@ -53,6 +55,9 @@ #define HFI_BUFFER_INPUT 0x1 #define HFI_BUFFER_OUTPUT 0x2 #define HFI_BUFFER_OUTPUT2 0x3 +#define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 +#define HFI_BUFFER_INTERNAL_SCRATCH 0x6 +#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7 #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 @@ -80,6 +85,7 @@ #define HFI_MSG_SESSION_STOP 0x221003 #define HFI_MSG_SESSION_FLUSH 0x221006 #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a +#define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c struct hfi_pkt_hdr { u32 size; @@ -128,11 +134,36 @@ struct hfi_sys_pc_prep_pkt { struct hfi_pkt_hdr hdr; }; +struct hfi_session_set_buffers_pkt { + struct hfi_session_hdr_pkt shdr; + u32 buffer_type; + u32 buffer_size; + u32 extradata_size; + u32 min_buffer_size; + u32 num_buffers; + u32 buffer_info[]; +}; + struct hfi_session_flush_pkt { struct hfi_session_hdr_pkt shdr; u32 flush_type; }; +struct hfi_session_release_buffer_pkt { + struct hfi_session_hdr_pkt shdr; + u32 buffer_type; + u32 buffer_size; + u32 extradata_size; + u32 response_req; + u32 num_buffers; + u32 buffer_info[]; +}; + +struct hfi_buffer_info { + u32 buffer_addr; + u32 extradata_addr; +}; + struct hfi_msg_event_notify_pkt { struct hfi_session_hdr_pkt shdr; u32 event_id; @@ -227,6 +258,12 @@ struct hfi_multi_stream { u32 enable; }; +struct hfi_msg_session_release_buffers_done_pkt { + struct hfi_msg_session_hdr_pkt shdr; + u32 num_buffers; + u32 buffer_info[]; +}; + struct hfi_msg_sys_debug_pkt { struct hfi_pkt_hdr hdr; u32 msg_type; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index db5858ec04ea..a84bb00388d9 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -176,6 +176,10 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { .pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt), }, + { + .pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, + .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), + }, }; static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index dddaa074cae1..cc75231f07f1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -100,6 +100,24 @@ static u32 iris_hfi_gen2_get_port(u32 plane) } } +static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type) +{ + switch (buffer_type) { + case BUF_INPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + return HFI_PORT_BITSTREAM; + case BUF_OUTPUT: + case BUF_DPB: + return HFI_PORT_RAW; + case BUF_PERSIST: + default: + return HFI_PORT_NONE; + } +} + static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet_type, u32 flag, u32 plane, u32 payload_type, void *payload, u32 payload_size) @@ -719,6 +737,118 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane) return iris_wait_for_session_response(inst, false); } +static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) +{ + switch (buffer_type) { + case BUF_INPUT: + return HFI_BUFFER_BITSTREAM; + case BUF_OUTPUT: + return HFI_BUFFER_RAW; + case BUF_BIN: + return HFI_BUFFER_BIN; + case BUF_COMV: + return HFI_BUFFER_COMV; + case BUF_NON_COMV: + return HFI_BUFFER_NON_COMV; + case BUF_LINE: + return HFI_BUFFER_LINE; + case BUF_DPB: + return HFI_BUFFER_DPB; + case BUF_PERSIST: + return HFI_BUFFER_PERSIST; + default: + return 0; + } +} + +static int iris_set_num_comv(struct iris_inst *inst) +{ + struct platform_inst_caps *caps; + struct iris_core *core = inst->core; + u32 num_comv; + + caps = core->iris_platform_data->inst_caps; + num_comv = caps->num_comv; + + return core->hfi_ops->session_set_property(inst, + HFI_PROP_COMV_BUFFER_COUNT, + HFI_HOST_FLAGS_NONE, + HFI_PORT_BITSTREAM, + HFI_PAYLOAD_U32, + &num_comv, sizeof(u32)); +} + +static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf) +{ + memset(buf, 0, sizeof(*buf)); + buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type); + buf->index = buffer->index; + buf->base_address = buffer->device_addr; + buf->addr_offset = 0; + buf->buffer_size = buffer->buffer_size; + + if (buffer->type == BUF_INPUT) + buf->buffer_size = ALIGN(buffer->buffer_size, 256); + buf->data_offset = buffer->data_offset; + buf->data_size = buffer->data_size; + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + buf->flags |= HFI_BUF_HOST_FLAG_RELEASE; + buf->flags |= HFI_BUF_HOST_FLAGS_CB_NON_SECURE; + buf->timestamp = buffer->timestamp; +} + +static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iris_buffer *buffer) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + struct iris_hfi_buffer hfi_buffer; + u32 port; + int ret; + + iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + if (buffer->type == BUF_COMV) { + ret = iris_set_num_comv(inst); + if (ret) + return ret; + } + + port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_BUFFER, + HFI_HOST_FLAGS_INTR_REQUIRED, + port, + inst->session_id, + HFI_PAYLOAD_STRUCTURE, + &hfi_buffer, + sizeof(hfi_buffer)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + +static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct iris_buffer *buffer) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + struct iris_hfi_buffer hfi_buffer; + u32 port; + + iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE; + port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); + + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_BUFFER, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED), + port, + inst->session_id, + HFI_PAYLOAD_STRUCTURE, + &hfi_buffer, + sizeof(hfi_buffer)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { .sys_init = iris_hfi_gen2_sys_init, .sys_image_version = iris_hfi_gen2_sys_image_version, @@ -728,6 +858,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { .session_set_config_params = iris_hfi_gen2_session_set_config_params, .session_set_property = iris_hfi_gen2_session_set_property, .session_start = iris_hfi_gen2_session_start, + .session_queue_buf = iris_hfi_gen2_session_queue_buffer, + .session_release_buf = iris_hfi_gen2_session_release_buffer, .session_stop = iris_hfi_gen2_session_stop, .session_close = iris_hfi_gen2_session_close, }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index cc7ba875d24f..3db132909eba 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -17,6 +17,7 @@ #define HFI_CMD_CLOSE 0x01000004 #define HFI_CMD_START 0x01000005 #define HFI_CMD_STOP 0x01000006 +#define HFI_CMD_BUFFER 0x01000009 #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B #define HFI_CMD_END 0x01FFFFFF @@ -53,6 +54,7 @@ #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 #define HFI_PROP_NO_OUTPUT 0x0300016a +#define HFI_PROP_COMV_BUFFER_COUNT 0x03000193 #define HFI_PROP_END 0x03FFFFFF #define HFI_SESSION_ERROR_BEGIN 0x04000000 @@ -105,6 +107,13 @@ enum hfi_buffer_type { HFI_BUFFER_VPSS = 0x0000000D, }; +enum hfi_buffer_host_flags { + HFI_BUF_HOST_FLAG_RELEASE = 0x00000001, + HFI_BUF_HOST_FLAG_READONLY = 0x00000010, + HFI_BUF_HOST_FLAG_CODEC_CONFIG = 0x00000100, + HFI_BUF_HOST_FLAGS_CB_NON_SECURE = 0x00000200, +}; + enum hfi_packet_firmware_flags { HFI_FW_FLAGS_SUCCESS = 0x00000001, HFI_FW_FLAGS_INFORMATION = 0x00000002, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h index 0333e37572f6..25b9582349ca 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h @@ -61,6 +61,47 @@ struct iris_hfi_packet { u32 payload[]; }; +/** + * struct iris_hfi_buffer + * + * @type: buffer type indicated by "enum hfi_buffer_type" + * FW needs to return proper type for any buffer command. + * @index: index of the buffer + * @base_address: base address of the buffer. + * This buffer address is always 4KBytes aligned. + * @addr_offset: accessible buffer offset from base address + * Decoder bitstream buffer: 256 Bytes aligned + * Firmware can uniquely identify a buffer based on + * base_address & addr_offset. + * HW can read memory only from base_address+addr_offset. + * @buffer_size: accessible buffer size in bytes starting from addr_offset + * @data_offset: data starts from "base_address + addr_offset + data_offset" + * RAW buffer: data_offset is 0. Restriction: 4KBytes aligned + * decoder bitstream buffer: no restriction (can be any value) + * @data_size: data size in bytes + * @flags: buffer flags. It is represented as bit masks. + * host buffer flags are "enum hfi_buffer_host_flags" + * firmware buffer flags are "enum hfi_buffer_firmware_flags" + * @timestamp: timestamp of the buffer in nano seconds (ns) + * It is Presentation timestamp (PTS) for encoder & decoder. + * Decoder: it is pass through from bitstream to raw buffer. + * firmware does not need to return as part of input buffer done. + * For any internal buffers: there is no timestamp. Host sets as 0. + * @reserved: reserved for future use + */ +struct iris_hfi_buffer { + u32 type; + u32 index; + u64 base_address; + u32 addr_offset; + u32 buffer_size; + u32 data_offset; + u32 data_size; + u64 timestamp; + u32 flags; + u32 reserved[5]; +}; + u32 iris_hfi_gen2_get_color_primaries(u32 primaries); u32 iris_hfi_gen2_get_transfer_char(u32 characterstics); u32 iris_hfi_gen2_get_matrix_coefficients(u32 coefficients); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index ebd82ef13424..9639c7eabd6b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -25,6 +25,94 @@ struct iris_hfi_gen2_packet_handle { int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); }; +static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) +{ + switch (buf_type) { + case HFI_BUFFER_BITSTREAM: + return BUF_INPUT; + case HFI_BUFFER_RAW: + return BUF_OUTPUT; + case HFI_BUFFER_BIN: + return BUF_BIN; + case HFI_BUFFER_ARP: + return BUF_ARP; + case HFI_BUFFER_COMV: + return BUF_COMV; + case HFI_BUFFER_NON_COMV: + return BUF_NON_COMV; + case HFI_BUFFER_LINE: + return BUF_LINE; + case HFI_BUFFER_DPB: + return BUF_DPB; + case HFI_BUFFER_PERSIST: + return BUF_PERSIST; + default: + return 0; + } +} + +static bool iris_hfi_gen2_is_valid_hfi_buffer_type(u32 buffer_type) +{ + switch (buffer_type) { + case HFI_BUFFER_BITSTREAM: + case HFI_BUFFER_RAW: + case HFI_BUFFER_BIN: + case HFI_BUFFER_ARP: + case HFI_BUFFER_COMV: + case HFI_BUFFER_NON_COMV: + case HFI_BUFFER_LINE: + case HFI_BUFFER_DPB: + case HFI_BUFFER_PERSIST: + case HFI_BUFFER_VPSS: + return true; + default: + return false; + } +} + +static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type) +{ + if (port == HFI_PORT_NONE && buffer_type != HFI_BUFFER_PERSIST) + return false; + + if (port != HFI_PORT_BITSTREAM && port != HFI_PORT_RAW) + return false; + + return true; +} + +static bool iris_hfi_gen2_validate_packet_payload(struct iris_hfi_packet *pkt) +{ + u32 payload_size = 0; + + switch (pkt->payload_info) { + case HFI_PAYLOAD_U32: + case HFI_PAYLOAD_S32: + case HFI_PAYLOAD_Q16: + case HFI_PAYLOAD_U32_ENUM: + case HFI_PAYLOAD_32_PACKED: + payload_size = 4; + break; + case HFI_PAYLOAD_U64: + case HFI_PAYLOAD_S64: + case HFI_PAYLOAD_64_PACKED: + payload_size = 8; + break; + case HFI_PAYLOAD_STRUCTURE: + if (pkt->type == HFI_CMD_BUFFER) + payload_size = sizeof(struct iris_hfi_buffer); + break; + default: + payload_size = 0; + break; + } + + if (pkt->size < sizeof(struct iris_hfi_packet) + payload_size) + return false; + + return true; +} + static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt) { u8 *response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE; @@ -146,9 +234,65 @@ static void iris_hfi_gen2_handle_session_close(struct iris_inst *inst, complete(&inst->completion); } +static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, + struct iris_hfi_buffer *buffer) +{ + struct iris_buffer *buf, *iter; + struct iris_buffers *buffers; + u32 buf_type; + int ret = 0; + bool found; + + buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type); + buffers = &inst->buffers[buf_type]; + + found = false; + list_for_each_entry(iter, &buffers->list, list) { + if (iter->device_addr == buffer->base_address) { + found = true; + buf = iter; + break; + } + } + if (!found) + return -EINVAL; + + buf->attr &= ~BUF_ATTR_QUEUED; + + if (buf->attr & BUF_ATTR_PENDING_RELEASE) + ret = iris_destroy_internal_buffer(inst, buf); + + return ret; +} + +static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, + struct iris_hfi_packet *pkt) +{ + struct iris_hfi_buffer *buffer; + + if (pkt->payload_info == HFI_PAYLOAD_NONE) + return 0; + + if (!iris_hfi_gen2_validate_packet_payload(pkt)) { + iris_inst_change_state(inst, IRIS_INST_ERROR); + return 0; + } + + buffer = (struct iris_hfi_buffer *)((u8 *)pkt + sizeof(*pkt)); + if (!iris_hfi_gen2_is_valid_hfi_buffer_type(buffer->type)) + return 0; + + if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type)) + return 0; + + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); +} + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, struct iris_hfi_packet *pkt) { + int ret = 0; + switch (pkt->type) { case HFI_CMD_CLOSE: iris_hfi_gen2_handle_session_close(inst, pkt); @@ -156,11 +300,14 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, case HFI_CMD_STOP: complete(&inst->completion); break; + case HFI_CMD_BUFFER: + ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); + break; default: break; } - return 0; + return ret; } static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 50965450cbb9..de0388a100c3 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -67,6 +67,7 @@ struct platform_inst_caps { u32 min_frame_height; u32 max_frame_height; u32 max_mbpf; + u32 num_comv; }; enum platform_inst_fw_cap_type { @@ -151,6 +152,10 @@ struct iris_platform_data { unsigned int dec_input_prop_size; const u32 *dec_output_prop; unsigned int dec_output_prop_size; + const u32 *dec_ip_int_buf_tbl; + unsigned int dec_ip_int_buf_tbl_size; + const u32 *dec_op_int_buf_tbl; + unsigned int dec_op_int_buf_tbl_size; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 0f1eb530b232..2a45e605e140 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -126,6 +126,7 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = { .min_frame_height = 96, .max_frame_height = 8192, .max_mbpf = (8192 * 4352) / 256, + .num_comv = 0, }; static void iris_set_sm8550_preset_registers(struct iris_core *core) @@ -192,6 +193,17 @@ static const u32 sm8550_vdec_subscribe_output_properties[] = { HFI_PROP_CABAC_SESSION, }; +static const u32 sm8550_dec_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, +}; + +static const u32 sm8550_dec_op_int_buf_tbl[] = { + BUF_DPB, +}; + struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, @@ -232,4 +244,9 @@ struct iris_platform_data sm8550_data = { .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop = sm8550_vdec_subscribe_output_properties, .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + + .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), }; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 45f0751976be..c26396bb11c5 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -276,6 +276,24 @@ int iris_vdec_streamon_input(struct iris_inst *inst) if (ret) return ret; + ret = iris_alloc_and_queue_persist_bufs(inst); + if (ret) + return ret; + + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + return iris_vdec_process_streamon_input(inst); } @@ -300,10 +318,24 @@ int iris_vdec_streamon_output(struct iris_inst *inst) if (ret) return ret; + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + + ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + ret = iris_vdec_process_streamon_output(inst); if (ret) goto error; + ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + return ret; error: diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index eb850f7da82c..4e7780110212 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -149,6 +149,15 @@ int iris_open(struct file *filp) mutex_init(&inst->lock); mutex_init(&inst->ctx_q_lock); + + INIT_LIST_HEAD(&inst->buffers[BUF_BIN].list); + INIT_LIST_HEAD(&inst->buffers[BUF_ARP].list); + INIT_LIST_HEAD(&inst->buffers[BUF_COMV].list); + INIT_LIST_HEAD(&inst->buffers[BUF_NON_COMV].list); + INIT_LIST_HEAD(&inst->buffers[BUF_LINE].list); + INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list); + INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list); + INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list); init_completion(&inst->completion); init_completion(&inst->flush_completion); @@ -221,6 +230,8 @@ int iris_close(struct file *filp) iris_session_close(inst); iris_inst_change_state(inst, IRIS_INST_DEINIT); iris_v4l2_fh_deinit(inst); + iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_remove_session(inst); mutex_unlock(&inst->lock); mutex_destroy(&inst->ctx_q_lock); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 0a65a17f13d2..dce25e410d80 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -6,7 +6,167 @@ #include "iris_instance.h" #include "iris_vpu_buffer.h" -u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) +static u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv = ((frame_width * frame_height) <= BIN_BUFFER_THRESHOLD) ? + ((BIN_BUFFER_THRESHOLD * 3) >> 1) : + ((frame_width * frame_height * 3) >> 1); + size_bin_hdr = size_yuv * H264_CABAC_HDR_RATIO_HD_TOT; + size_bin_res = size_yuv * H264_CABAC_RES_RATIO_HD_TOT; + size_bin_hdr = ALIGN(size_bin_hdr / num_vpp_pipes, + DMA_ALIGNMENT) * num_vpp_pipes; + size_bin_res = ALIGN(size_bin_res / num_vpp_pipes, + DMA_ALIGNMENT) * num_vpp_pipes; + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 n_aligned_h = ALIGN(frame_height, 16); + u32 n_aligned_w = ALIGN(frame_width, 16); + + return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + +static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount) +{ + u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16); + u32 frame_width_in_mbs = DIV_ROUND_UP(frame_width, 16); + u32 col_zero_aligned_width = (frame_width_in_mbs << 2); + u32 col_mv_aligned_width = (frame_width_in_mbs << 7); + u32 col_zero_size, size_colloc; + + col_mv_aligned_width = ALIGN(col_mv_aligned_width, 16); + col_zero_aligned_width = ALIGN(col_zero_aligned_width, 16); + col_zero_size = col_zero_aligned_width * + ((frame_height_in_mbs + 1) >> 1); + col_zero_size = ALIGN(col_zero_size, 64); + col_zero_size <<= 1; + col_zero_size = ALIGN(col_zero_size, 512); + size_colloc = col_mv_aligned_width * ((frame_height_in_mbs + 1) >> 1); + size_colloc = ALIGN(size_colloc, 64); + size_colloc <<= 1; + size_colloc = ALIGN(size_colloc, 512); + size_colloc += (col_zero_size + SIZE_H264D_BUFTAB_T * 2); + + return (size_colloc * (_comv_bufcount)) + 512; +} + +static u32 size_h264d_bse_cmd_buf(u32 frame_height) +{ + u32 height = ALIGN(frame_height, 32); + + return min_t(u32, (DIV_ROUND_UP(height, 16) * 48), H264D_MAX_SLICE) * + SIZE_H264D_BSE_CMD_PER_BUF; +} + +static u32 size_h264d_vpp_cmd_buf(u32 frame_height) +{ + u32 size, height = ALIGN(frame_height, 32); + + size = min_t(u32, (DIV_ROUND_UP(height, 16) * 48), H264D_MAX_SLICE) * + SIZE_H264D_VPP_CMD_PER_BUF; + + return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; +} + +static u32 hfi_buffer_persist_h264d(void) +{ + return ALIGN(SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264 + + H264_DISPLAY_BUF_SIZE * H264_NUM_FRM_INFO + + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA, + DMA_ALIGNMENT); +} + +static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_bse, size_vpp, size; + + size_bse = size_h264d_bse_cmd_buf(frame_height); + size_vpp = size_h264d_vpp_cmd_buf(frame_height); + size = ALIGN(size_bse, DMA_ALIGNMENT) + + ALIGN(size_vpp, DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + +static u32 size_vpss_lb(u32 frame_width, u32 frame_height) +{ + u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size; + u32 opb_wr_top_line_chroma_buffer_size; + u32 opb_wr_top_line_luma_buffer_size; + u32 macrotiling_size = 32; + + opb_wr_top_line_luma_buffer_size = + ALIGN(frame_width, macrotiling_size) / macrotiling_size * 256; + opb_wr_top_line_luma_buffer_size = + ALIGN(opb_wr_top_line_luma_buffer_size, DMA_ALIGNMENT) + + (MAX_TILE_COLUMNS - 1) * 256; + opb_wr_top_line_luma_buffer_size = + max_t(u32, opb_wr_top_line_luma_buffer_size, (32 * ALIGN(frame_height, 8))); + opb_wr_top_line_chroma_buffer_size = opb_wr_top_line_luma_buffer_size; + opb_lb_wr_llb_uv_buffer_size = + ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, 32); + opb_lb_wr_llb_y_buffer_size = + ALIGN((ALIGN(frame_height, 8) / (4 / 2)) * 64, 32); + return opb_wr_top_line_luma_buffer_size + + opb_wr_top_line_chroma_buffer_size + + opb_lb_wr_llb_uv_buffer_size + + opb_lb_wr_llb_y_buffer_size; +} + +static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, + bool is_opb, u32 num_vpp_pipes) +{ + u32 vpss_lb_size = 0; + u32 size; + + size = ALIGN(size_h264d_lb_fe_top_data(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_top_ctrl(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h264d_lb_se_top_ctrl(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_se_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h264d_lb_pe_top_data(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) * 2 + + ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT); + size = ALIGN(size, DMA_ALIGNMENT); + if (is_opb) + vpss_lb_size = size_vpss_lb(frame_width, frame_height); + + return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT); +} + +static u32 iris_vpu_dec_bin_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_bin_h264d(width, height, num_vpp_pipes); +} + +static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) +{ + u32 num_comv = VIDEO_MAX_FRAME; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_comv_h264d(width, height, num_comv); +} + +static u32 iris_vpu_dec_persist_size(struct iris_inst *inst) +{ + return hfi_buffer_persist_h264d(); +} + +static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) return iris_get_buffer_size(inst, BUF_DPB); @@ -14,6 +174,70 @@ u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_non_comv_h264d(width, height, num_vpp_pipes); +} + +static u32 iris_vpu_dec_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + bool is_opb = false; + + if (iris_split_mode_enabled(inst)) + is_opb = true; + + return hfi_buffer_line_h264d(width, height, is_opb, num_vpp_pipes); +} + +static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) +{ + return iris_vpu_dec_comv_size(inst) + + iris_vpu_dec_non_comv_size(inst) + + iris_vpu_dec_line_size(inst); +} + +struct iris_vpu_buf_type_handle { + enum iris_buffer_type type; + u32 (*handle)(struct iris_inst *inst); +}; + +int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + const struct iris_vpu_buf_type_handle *buf_type_handle_arr; + u32 size = 0, buf_type_handle_size, i; + + static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_dec_bin_size }, + {BUF_COMV, iris_vpu_dec_comv_size }, + {BUF_NON_COMV, iris_vpu_dec_non_comv_size }, + {BUF_LINE, iris_vpu_dec_line_size }, + {BUF_PERSIST, iris_vpu_dec_persist_size }, + {BUF_DPB, iris_vpu_dec_dpb_size }, + {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, + }; + + buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr = dec_internal_buf_type_handle; + + for (i = 0; i < buf_type_handle_size; i++) { + if (buf_type_handle_arr[i].type == buffer_type) { + size = buf_type_handle_arr[i].handle(inst); + break; + } + } + + return size; +} + static inline int iris_vpu_dpb_count(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) { @@ -31,6 +255,13 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type return MIN_BUFFERS; case BUF_OUTPUT: return inst->fw_min_count; + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + case BUF_PERSIST: + case BUF_SCRATCH_1: + return 1; /* internal buffer count needed by firmware is 1 */ case BUF_DPB: return iris_vpu_dpb_count(inst); default: diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 865539d626b7..62af6ea6ba1f 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -10,7 +10,82 @@ struct iris_inst; #define MIN_BUFFERS 4 -u32 iris_vpu_dec_dpb_size(struct iris_inst *inst); +#define DMA_ALIGNMENT 256 + +#define NUM_HW_PIC_BUF 32 +#define SIZE_HW_PIC(size_per_buf) (NUM_HW_PIC_BUF * (size_per_buf)) + +#define MAX_TILE_COLUMNS 32 +#define BIN_BUFFER_THRESHOLD (1280 * 736) +#define VPP_CMD_MAX_SIZE (BIT(20)) +#define H264D_MAX_SLICE 1800 + +#define SIZE_H264D_BUFTAB_T 256 +#define SIZE_H264D_BSE_CMD_PER_BUF (32 * 4) +#define SIZE_H264D_VPP_CMD_PER_BUF 512 + +#define NUM_SLIST_BUF_H264 (256 + 32) +#define SIZE_SLIST_BUF_H264 512 +#define H264_DISPLAY_BUF_SIZE 3328 +#define H264_NUM_FRM_INFO 66 + +#define SIZE_SEI_USERDATA 4096 + +#define H264_CABAC_HDR_RATIO_HD_TOT 1 +#define H264_CABAC_RES_RATIO_HD_TOT 3 +#define SIZE_H264D_HW_PIC_T (BIT(11)) + +#define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 +#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 16 +#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 +#define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 + +static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) +{ + return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; +} + +static inline u32 size_h264d_lb_fe_top_ctrl(u32 frame_width) +{ + return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); +} + +static inline u32 size_h264d_lb_fe_left_ctrl(u32 frame_height) +{ + return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); +} + +static inline u32 size_h264d_lb_se_top_ctrl(u32 frame_width) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); +} + +static inline u32 size_h264d_lb_se_left_ctrl(u32 frame_height) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); +} + +static inline u32 size_h264d_lb_pe_top_data(u32 frame_width) +{ + return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); +} + +static inline u32 size_h264d_lb_vsp_top(u32 frame_width) +{ + return (DIV_ROUND_UP(frame_width, 16) << 7); +} + +static inline u32 size_h264d_lb_recon_dma_metadata_wr(u32 frame_height) +{ + return ALIGN(frame_height, 16) * 32; +} + +static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height) +{ + return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 128; +} + +int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif From patchwork Wed Nov 20 14:46:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844617 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 10B121D86F6; Wed, 20 Nov 2024 14:48:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114127; cv=none; b=VjdsCcPKqeQa/Sez8OoTPNrT20Vg6oYD/UaMj5CIGC6EIJnTho6igp9Ot9Sm2RCPtNfkfxSKG3mK5Q3kxumiioYCssKfEPdyt6dK37GTJJeEwZVFwjh3mq7QA5oEZTij7aGUj8pyNgdio0ZlrlajNSmGU2h2va+wKJIzHxxqAY4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114127; c=relaxed/simple; bh=kH4w0l8ZrMX4PrOfbxTZt7tEOxaiZFg8oQZgx+uAmwc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=lormfabOLpW4qla5RZjbgzkPMhwKbc1gloK52dWcA1pvG+TVjtDd2PQAG2dUwQa9EOgKK8QlsUqz51QlLUgInVKOxOjmMMzsmQ2GPvORieDPKGZuT0xB42yAkWKQl/qwBt+Icggcd4R6HNb1eCJqErSnu4XWp9MEPT0N5HontQA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=VpsdK4cr; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="VpsdK4cr" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FLel005921; Wed, 20 Nov 2024 14:48:32 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= yxDS48S5Bhq6OgzRYPqF14jqQ2L0Il5DMVC0u7Y2DAo=; b=VpsdK4crmwnAqXCK amWTcJ2zQ+yWO2zS5AHXfBcfU5mZw3rOaWZPG/TB9UZFvkZWAJqT5jP60922iqe3 gqTE2pyZfYF4y89d5IyjYiWd2A5M+yudckyJN7C80f249RFXNLLMO70rOsMF5uKn JzGh1t6B0sPDCguO1shPsSMG1LSM2u+62EV0fd0WFGwPOHgTURmOj7yg18ltxCS/ /B6DxDGayf9D1FiPdwOQGzOXEBDjQDjGVXs5jnK6Wo6OfmAnF4XmMQjhSxoFLDe5 w9lrar7G6kqrw6hNZWS2qKXfMpOQFlYoCwgLrqXSjBtdiAPDcSaKoGTXhszrgv2x J5U2pg== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4317t21mv0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:32 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEmVme010495 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:31 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:48:25 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:11 +0530 Subject: [PATCH v6 21/28] media: iris: add support for dynamic resolution change Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-21-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=35221; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=kH4w0l8ZrMX4PrOfbxTZt7tEOxaiZFg8oQZgx+uAmwc=; b=7VI+BPZArba1BR8WfxLlV+P5Y8dtS8/ouiC+NnDCBe1KlcgRDRpIsbe6ZIr7PM2eKT/6N2Ay2 1QXGvbrOUt7BHFB+MW/oGRQhVeYFDC3YecBalgkqvwHMKuV8EtwNo86 X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: dRL5sn9Qs2t_TiEW1GiA6vt4kNvgwO4u X-Proofpoint-ORIG-GUID: dRL5sn9Qs2t_TiEW1GiA6vt4kNvgwO4u X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 mlxlogscore=999 spamscore=0 bulkscore=0 lowpriorityscore=0 mlxscore=0 malwarescore=0 impostorscore=0 phishscore=0 adultscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 Handle the response sent by firmware, when source change is detected by firmware. Read the parameter subscribed to firmware for source change to detect the parameter with changed value. Raise the source change event to client and update the instance sub state. Mark the last buffer from before the source change with the V4L2_BUF_FLAG_LAST flag and return to client. Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_common.c | 64 +++++++ drivers/media/platform/qcom/iris/iris_hfi_common.h | 3 + .../platform/qcom/iris/iris_hfi_gen1_defines.h | 82 ++++++++ .../platform/qcom/iris/iris_hfi_gen1_response.c | 208 +++++++++++++++++++++ .../platform/qcom/iris/iris_hfi_gen2_defines.h | 4 + .../platform/qcom/iris/iris_hfi_gen2_response.c | 183 +++++++++++++++++- drivers/media/platform/qcom/iris/iris_instance.h | 2 + drivers/media/platform/qcom/iris/iris_state.c | 64 +++++++ drivers/media/platform/qcom/iris/iris_state.h | 33 ++++ drivers/media/platform/qcom/iris/iris_vb2.c | 19 ++ drivers/media/platform/qcom/iris/iris_vdec.c | 15 ++ drivers/media/platform/qcom/iris/iris_vdec.h | 1 + 12 files changed, 677 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c index 29f56c2bf74c..92112eb16c11 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c @@ -10,6 +10,70 @@ #include "iris_hfi_common.h" #include "iris_vpu_common.h" +u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries) +{ + switch (hfi_primaries) { + case HFI_PRIMARIES_RESERVED: + return V4L2_COLORSPACE_DEFAULT; + case HFI_PRIMARIES_BT709: + return V4L2_COLORSPACE_REC709; + case HFI_PRIMARIES_BT470_SYSTEM_M: + return V4L2_COLORSPACE_470_SYSTEM_M; + case HFI_PRIMARIES_BT470_SYSTEM_BG: + return V4L2_COLORSPACE_470_SYSTEM_BG; + case HFI_PRIMARIES_BT601_525: + return V4L2_COLORSPACE_SMPTE170M; + case HFI_PRIMARIES_SMPTE_ST240M: + return V4L2_COLORSPACE_SMPTE240M; + case HFI_PRIMARIES_BT2020: + return V4L2_COLORSPACE_BT2020; + case V4L2_COLORSPACE_DCI_P3: + return HFI_PRIMARIES_SMPTE_RP431_2; + default: + return V4L2_COLORSPACE_DEFAULT; + } +} + +u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics) +{ + switch (hfi_characterstics) { + case HFI_TRANSFER_RESERVED: + return V4L2_XFER_FUNC_DEFAULT; + case HFI_TRANSFER_BT709: + return V4L2_XFER_FUNC_709; + case HFI_TRANSFER_SMPTE_ST240M: + return V4L2_XFER_FUNC_SMPTE240M; + case HFI_TRANSFER_SRGB_SYCC: + return V4L2_XFER_FUNC_SRGB; + case HFI_TRANSFER_SMPTE_ST2084_PQ: + return V4L2_XFER_FUNC_SMPTE2084; + default: + return V4L2_XFER_FUNC_DEFAULT; + } +} + +u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients) +{ + switch (hfi_coefficients) { + case HFI_MATRIX_COEFF_RESERVED: + return V4L2_YCBCR_ENC_DEFAULT; + case HFI_MATRIX_COEFF_BT709: + return V4L2_YCBCR_ENC_709; + case HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625: + return V4L2_YCBCR_ENC_XV601; + case HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625: + return V4L2_YCBCR_ENC_601; + case HFI_MATRIX_COEFF_SMPTE_ST240: + return V4L2_YCBCR_ENC_SMPTE240M; + case HFI_MATRIX_COEFF_BT2020_NON_CONSTANT: + return V4L2_YCBCR_ENC_BT2020; + case HFI_MATRIX_COEFF_BT2020_CONSTANT: + return V4L2_YCBCR_ENC_BT2020_CONST_LUM; + default: + return V4L2_YCBCR_ENC_DEFAULT; + } +} + int iris_hfi_core_init(struct iris_core *core) { const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index c54c88658633..6241098dc31d 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -138,6 +138,9 @@ struct hfi_subscription_params { u32 level; }; +u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries); +u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics); +u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients); int iris_hfi_core_init(struct iris_core *core); int iris_hfi_pm_suspend(struct iris_core *core); int iris_hfi_pm_resume(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index 108449d703e1..416e9a19a26f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -44,18 +44,28 @@ #define HFI_EVENT_SYS_ERROR 0x1 #define HFI_EVENT_SESSION_ERROR 0x2 +#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES 0x1000001 +#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002 +#define HFI_EVENT_SESSION_SEQUENCE_CHANGED 0x1000003 + #define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100 #define HFI_FLUSH_OUTPUT 0x1000002 #define HFI_FLUSH_OUTPUT2 0x1000003 #define HFI_FLUSH_ALL 0x1000004 +#define HFI_INDEX_EXTRADATA_INPUT_CROP 0x0700000e + #define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL 0x201001 #define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO 0x201002 #define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE 0x201008 #define HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL 0x20100c +#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS 0x202001 + #define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 +#define HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS 0x120300e +#define HFI_PROPERTY_CONFIG_VDEC_ENTROPY 0x1204004 #define HFI_BUFFER_INPUT 0x1 #define HFI_BUFFER_OUTPUT 0x2 @@ -69,11 +79,15 @@ #define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001 #define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003 +#define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT 0x1005 #define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 #define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 #define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002 #define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001 +#define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007 +#define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009 +#define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a #define HFI_CORE_ID_1 1 #define HFI_COLOR_FORMAT_NV12 0x02 #define HFI_COLOR_FORMAT_NV12_UBWC 0x8002 @@ -249,6 +263,11 @@ struct hfi_enable { u32 enable; }; +struct hfi_profile_level { + u32 profile; + u32 level; +}; + struct hfi_framesize { u32 buffer_type; u32 width; @@ -267,6 +286,37 @@ struct hfi_video_work_route { u32 video_work_route; }; +struct hfi_bit_depth { + u32 buffer_type; + u32 bit_depth; +}; + +struct hfi_pic_struct { + u32 progressive_only; +}; + +struct hfi_colour_space { + u32 colour_space; +}; + +struct hfi_extradata_input_crop { + u32 size; + u32 version; + u32 port_index; + u32 left; + u32 top; + u32 width; + u32 height; +}; + +struct hfi_dpb_counts { + u32 max_dpb_count; + u32 max_ref_frames; + u32 max_dec_buffering; + u32 max_reorder_frames; + u32 fw_min_count; +}; + struct hfi_uncompressed_format_select { u32 buffer_type; u32 format; @@ -301,6 +351,38 @@ struct hfi_multi_stream { u32 enable; }; +struct hfi_buffer_requirements { + u32 type; + u32 size; + u32 region_size; + u32 hold_count; + u32 count_min; + u32 count_actual; + u32 contiguous; + u32 alignment; +}; + +struct hfi_event_data { + u32 error; + u32 height; + u32 width; + u32 event_type; + u32 packet_buffer; + u32 extradata_buffer; + u32 tag; + u32 profile; + u32 level; + u32 bit_depth; + u32 pic_struct; + u32 colour_space; + u32 entropy_mode; + u32 buf_count; + struct { + u32 left, top; + u32 width, height; + } input_crop; +}; + struct hfi_msg_session_empty_buffer_done_pkt { struct hfi_msg_session_hdr_pkt shdr; u32 offset; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 23a8bf29e381..3a47d9f39695 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -3,11 +3,216 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include "iris_hfi_gen1.h" #include "iris_hfi_gen1_defines.h" #include "iris_instance.h" +#include "iris_vdec.h" +#include "iris_vpu_buffer.h" + +static void iris_hfi_gen1_read_changed_params(struct iris_inst *inst, + struct hfi_msg_event_notify_pkt *pkt) +{ + struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; + struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; + u32 num_properties_changed = pkt->event_data2; + u8 *data_ptr = (u8 *)&pkt->ext_event_data[0]; + u32 primaries, matrix_coeff, transfer_char; + struct hfi_dpb_counts *iris_vpu_dpb_count; + struct hfi_profile_level *profile_level; + struct hfi_buffer_requirements *bufreq; + struct hfi_extradata_input_crop *crop; + struct hfi_colour_space *colour_info; + struct iris_core *core = inst->core; + u32 colour_description_present_flag; + u32 video_signal_type_present_flag; + struct hfi_event_data event = {0}; + struct hfi_bit_depth *pixel_depth; + struct hfi_pic_struct *pic_struct; + struct hfi_framesize *frame_sz; + struct vb2_queue *dst_q; + struct v4l2_ctrl *ctrl; + u32 full_range, ptype; + + do { + ptype = *((u32 *)data_ptr); + switch (ptype) { + case HFI_PROPERTY_PARAM_FRAME_SIZE: + data_ptr += sizeof(u32); + frame_sz = (struct hfi_framesize *)data_ptr; + event.width = frame_sz->width; + event.height = frame_sz->height; + data_ptr += sizeof(*frame_sz); + break; + case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: + data_ptr += sizeof(u32); + profile_level = (struct hfi_profile_level *)data_ptr; + event.profile = profile_level->profile; + event.level = profile_level->level; + data_ptr += sizeof(*profile_level); + break; + case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: + data_ptr += sizeof(u32); + pixel_depth = (struct hfi_bit_depth *)data_ptr; + event.bit_depth = pixel_depth->bit_depth; + data_ptr += sizeof(*pixel_depth); + break; + case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: + data_ptr += sizeof(u32); + pic_struct = (struct hfi_pic_struct *)data_ptr; + event.pic_struct = pic_struct->progressive_only; + data_ptr += sizeof(*pic_struct); + break; + case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: + data_ptr += sizeof(u32); + colour_info = (struct hfi_colour_space *)data_ptr; + event.colour_space = colour_info->colour_space; + data_ptr += sizeof(*colour_info); + break; + case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: + data_ptr += sizeof(u32); + event.entropy_mode = *(u32 *)data_ptr; + data_ptr += sizeof(u32); + break; + case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: + data_ptr += sizeof(u32); + bufreq = (struct hfi_buffer_requirements *)data_ptr; + event.buf_count = bufreq->count_min; + data_ptr += sizeof(*bufreq); + break; + case HFI_INDEX_EXTRADATA_INPUT_CROP: + data_ptr += sizeof(u32); + crop = (struct hfi_extradata_input_crop *)data_ptr; + event.input_crop.left = crop->left; + event.input_crop.top = crop->top; + event.input_crop.width = crop->width; + event.input_crop.height = crop->height; + data_ptr += sizeof(*crop); + break; + case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS: + data_ptr += sizeof(u32); + iris_vpu_dpb_count = (struct hfi_dpb_counts *)data_ptr; + event.buf_count = iris_vpu_dpb_count->fw_min_count; + data_ptr += sizeof(*iris_vpu_dpb_count); + break; + default: + break; + } + num_properties_changed--; + } while (num_properties_changed > 0); + + pixmp_ip->width = event.width; + pixmp_ip->height = event.height; + + pixmp_op->width = ALIGN(event.width, 128); + pixmp_op->height = ALIGN(event.height, 32); + pixmp_op->plane_fmt[0].bytesperline = ALIGN(event.width, 128); + pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + + matrix_coeff = FIELD_GET(GENMASK(7, 0), event.colour_space); + transfer_char = FIELD_GET(GENMASK(15, 8), event.colour_space); + primaries = FIELD_GET(GENMASK(23, 16), event.colour_space); + colour_description_present_flag = FIELD_GET(GENMASK(24, 24), event.colour_space); + full_range = FIELD_GET(GENMASK(25, 25), event.colour_space); + video_signal_type_present_flag = FIELD_GET(GENMASK(29, 29), event.colour_space); + + pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; + pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; + pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT; + + if (video_signal_type_present_flag) { + pixmp_op->quantization = + full_range ? + V4L2_QUANTIZATION_FULL_RANGE : + V4L2_QUANTIZATION_LIM_RANGE; + if (colour_description_present_flag) { + pixmp_op->colorspace = + iris_hfi_get_v4l2_color_primaries(primaries); + pixmp_op->xfer_func = + iris_hfi_get_v4l2_transfer_char(transfer_char); + pixmp_op->ycbcr_enc = + iris_hfi_get_v4l2_matrix_coefficients(matrix_coeff); + } + } + + pixmp_ip->colorspace = pixmp_op->colorspace; + pixmp_ip->xfer_func = pixmp_op->xfer_func; + pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc; + pixmp_ip->quantization = pixmp_op->quantization; + + if (event.input_crop.width > 0 && event.input_crop.height > 0) { + inst->crop.left = event.input_crop.left; + inst->crop.top = event.input_crop.top; + inst->crop.width = event.input_crop.width; + inst->crop.height = event.input_crop.height; + } else { + inst->crop.left = 0; + inst->crop.top = 0; + inst->crop.width = event.width; + inst->crop.height = event.height; + } + + inst->fw_min_count = event.buf_count; + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = pixmp_op->plane_fmt[0].sizeimage; + ctrl = v4l2_ctrl_find(&inst->ctrl_handler, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); + if (ctrl) + v4l2_ctrl_s_ctrl(ctrl, inst->buffers[BUF_OUTPUT].min_count); + + dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + dst_q->min_reqbufs_allocation = inst->buffers[BUF_OUTPUT].min_count; + + if (event.bit_depth || !event.pic_struct) { + dev_err(core->dev, "unsupported content, bit depth: %x, pic_struct = %x\n", + event.bit_depth, event.pic_struct); + iris_inst_change_state(inst, IRIS_INST_ERROR); + } +} + +static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, + struct hfi_msg_event_notify_pkt *pkt) +{ + struct hfi_session_flush_pkt flush_pkt; + u32 num_properties_changed; + int ret; + + ret = iris_inst_sub_state_change_drc(inst); + if (ret) + return; + + switch (pkt->event_data1) { + case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES: + case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES: + break; + default: + iris_inst_change_state(inst, IRIS_INST_ERROR); + return; + } + + num_properties_changed = pkt->event_data2; + if (!num_properties_changed) { + iris_inst_change_state(inst, IRIS_INST_ERROR); + return; + } + + iris_hfi_gen1_read_changed_params(inst, pkt); + + if (inst->state != IRIS_INST_ERROR) { + reinit_completion(&inst->flush_completion); + + flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); + flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; + flush_pkt.shdr.session_id = inst->session_id; + flush_pkt.flush_type = HFI_FLUSH_OUTPUT; + iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size); + } + + iris_vdec_src_change(inst); + iris_inst_sub_state_change_drc_last(inst); +} static void iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) @@ -66,6 +271,9 @@ static void iris_hfi_gen1_session_event_notify(struct iris_inst *inst, void *pac case HFI_EVENT_SESSION_ERROR: iris_hfi_gen1_event_session_error(inst, pkt); break; + case HFI_EVENT_SESSION_SEQUENCE_CHANGED: + iris_hfi_gen1_event_seq_changed(inst, pkt); + break; default: break; } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 69273885be21..32fcd9112a7e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -19,8 +19,11 @@ #define HFI_CMD_STOP 0x01000006 #define HFI_CMD_BUFFER 0x01000009 #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B +#define HFI_CMD_SETTINGS_CHANGE 0x0100000C #define HFI_CMD_END 0x01FFFFFF +#define HFI_BITMASK_BITSTREAM_WIDTH 0xffff0000 +#define HFI_BITMASK_BITSTREAM_HEIGHT 0x0000ffff #define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001 #define HFI_PROP_BEGIN 0x03000000 @@ -74,6 +77,7 @@ #define HFI_INFO_UNSUPPORTED 0x06000001 #define HFI_INFO_DATA_CORRUPT 0x06000002 #define HFI_INFO_BUFFER_OVERFLOW 0x06000004 +#define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007 #define HFI_INFORMATION_END 0x06FFFFFF enum hfi_property_mode_type { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index 77c4f92b76e1..28857a7a5112 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -8,6 +8,8 @@ #include "iris_hfi_gen2.h" #include "iris_hfi_gen2_defines.h" #include "iris_hfi_gen2_packet.h" +#include "iris_vdec.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" struct iris_hfi_gen2_core_hfi_range { @@ -199,6 +201,10 @@ static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst, info = "buffer overflow"; inst_hfi_gen2->hfi_frame_info.overflow = 1; break; + case HFI_INFO_HFI_FLAG_PSC_LAST: + info = "drc last flag"; + ret = iris_inst_sub_state_change_drc_last(inst); + break; default: info = "unknown"; break; @@ -326,6 +332,13 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst, struct v4l2_m2m_buffer *m2m_buffer, *n; struct iris_buffer *buf; bool found = false; + int ret; + + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { + ret = iris_inst_sub_state_change_drc_last(inst); + if (ret) + return ret; + } v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, m2m_buffer, n) { buf = to_iris_buffer(&m2m_buffer->vb); @@ -437,6 +450,115 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); } +static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; + struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; + u32 primaries, matrix_coeff, transfer_char; + struct hfi_subscription_params subsc_params; + u32 colour_description_present_flag; + u32 video_signal_type_present_flag; + struct iris_core *core = inst->core; + u32 full_range, width, height; + struct vb2_queue *dst_q; + struct v4l2_ctrl *ctrl; + + subsc_params = inst_hfi_gen2->src_subcr_params; + width = (subsc_params.bitstream_resolution & + HFI_BITMASK_BITSTREAM_WIDTH) >> 16; + height = subsc_params.bitstream_resolution & + HFI_BITMASK_BITSTREAM_HEIGHT; + + pixmp_ip->width = width; + pixmp_ip->height = height; + + pixmp_op->width = ALIGN(width, 128); + pixmp_op->height = ALIGN(height, 32); + pixmp_op->plane_fmt[0].bytesperline = ALIGN(width, 128); + pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + + matrix_coeff = subsc_params.color_info & 0xFF; + transfer_char = (subsc_params.color_info & 0xFF00) >> 8; + primaries = (subsc_params.color_info & 0xFF0000) >> 16; + colour_description_present_flag = + (subsc_params.color_info & 0x1000000) >> 24; + full_range = (subsc_params.color_info & 0x2000000) >> 25; + video_signal_type_present_flag = + (subsc_params.color_info & 0x20000000) >> 29; + + pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; + pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; + pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT; + + if (video_signal_type_present_flag) { + pixmp_op->quantization = + full_range ? + V4L2_QUANTIZATION_FULL_RANGE : + V4L2_QUANTIZATION_LIM_RANGE; + if (colour_description_present_flag) { + pixmp_op->colorspace = + iris_hfi_get_v4l2_color_primaries(primaries); + pixmp_op->xfer_func = + iris_hfi_get_v4l2_transfer_char(transfer_char); + pixmp_op->ycbcr_enc = + iris_hfi_get_v4l2_matrix_coefficients(matrix_coeff); + } + } + + pixmp_ip->colorspace = pixmp_op->colorspace; + pixmp_ip->xfer_func = pixmp_op->xfer_func; + pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc; + pixmp_ip->quantization = pixmp_op->quantization; + + inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF; + inst->crop.left = (subsc_params.crop_offsets[0] >> 16) & 0xFFFF; + inst->crop.height = pixmp_ip->height - + (subsc_params.crop_offsets[1] & 0xFFFF) - inst->crop.top; + inst->crop.width = pixmp_ip->width - + ((subsc_params.crop_offsets[1] >> 16) & 0xFFFF) - inst->crop.left; + + inst->fw_caps[PROFILE].value = subsc_params.profile; + inst->fw_caps[LEVEL].value = subsc_params.level; + inst->fw_caps[POC].value = subsc_params.pic_order_cnt; + + if (subsc_params.bit_depth != BIT_DEPTH_8 || + !(subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG)) { + dev_err(core->dev, "unsupported content, bit depth: %x, pic_struct = %x\n", + subsc_params.bit_depth, subsc_params.coded_frames); + iris_inst_change_state(inst, IRIS_INST_ERROR); + } + + inst->fw_min_count = subsc_params.fw_min_count; + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = pixmp_op->plane_fmt[0].sizeimage; + ctrl = v4l2_ctrl_find(&inst->ctrl_handler, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); + if (ctrl) + v4l2_ctrl_s_ctrl(ctrl, inst->buffers[BUF_OUTPUT].min_count); + + dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + dst_q->min_reqbufs_allocation = inst->buffers[BUF_OUTPUT].min_count; +} + +static int iris_hfi_gen2_handle_src_change(struct iris_inst *inst, + struct iris_hfi_packet *pkt) +{ + int ret; + + if (pkt->port != HFI_PORT_BITSTREAM) + return 0; + + ret = iris_inst_sub_state_change_drc(inst); + if (ret) + return ret; + + iris_hfi_gen2_read_input_subcr_params(inst); + iris_vdec_src_change(inst); + + return 0; +} + static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, struct iris_hfi_packet *pkt) { @@ -452,6 +574,9 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, case HFI_CMD_BUFFER: ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); break; + case HFI_CMD_SETTINGS_CHANGE: + ret = iris_hfi_gen2_handle_src_change(inst, pkt); + break; default: break; } @@ -585,16 +710,61 @@ static int iris_hfi_gen2_handle_system_response(struct iris_core *core, return 0; } +static void iris_hfi_gen2_init_src_change_param(struct iris_inst *inst) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + struct v4l2_pix_format_mplane *pixmp_ip = &inst->fmt_src->fmt.pix_mp; + struct v4l2_pix_format_mplane *pixmp_op = &inst->fmt_dst->fmt.pix_mp; + u32 bottom_offset = (pixmp_ip->height - inst->crop.height); + u32 right_offset = (pixmp_ip->width - inst->crop.width); + struct hfi_subscription_params *subsc_params; + u32 primaries, matrix_coeff, transfer_char; + u32 colour_description_present_flag = 0; + u32 video_signal_type_present_flag = 0; + u32 full_range, video_format = 0; + u32 left_offset = inst->crop.left; + u32 top_offset = inst->crop.top; + + subsc_params = &inst_hfi_gen2->src_subcr_params; + subsc_params->bitstream_resolution = + pixmp_ip->width << 16 | pixmp_ip->height; + subsc_params->crop_offsets[0] = + left_offset << 16 | top_offset; + subsc_params->crop_offsets[1] = + right_offset << 16 | bottom_offset; + subsc_params->fw_min_count = inst->buffers[BUF_OUTPUT].min_count; + + primaries = iris_hfi_gen2_get_color_primaries(pixmp_op->colorspace); + matrix_coeff = iris_hfi_gen2_get_matrix_coefficients(pixmp_op->ycbcr_enc); + transfer_char = iris_hfi_gen2_get_transfer_char(pixmp_op->xfer_func); + full_range = pixmp_op->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0; + subsc_params->color_info = + iris_hfi_gen2_get_color_info(matrix_coeff, transfer_char, primaries, + colour_description_present_flag, + full_range, video_format, + video_signal_type_present_flag); + + subsc_params->profile = inst->fw_caps[PROFILE].value; + subsc_params->level = inst->fw_caps[LEVEL].value; + subsc_params->pic_order_cnt = inst->fw_caps[POC].value; + subsc_params->bit_depth = inst->fw_caps[BIT_DEPTH].value; + if (inst->fw_caps[CODED_FRAMES].value == + CODED_FRAMES_PROGRESSIVE) + subsc_params->coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG; + else + subsc_params->coded_frames = 0; +} + static int iris_hfi_gen2_handle_session_response(struct iris_core *core, struct iris_hfi_header *hdr) { + u8 *pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); struct iris_inst_hfi_gen2 *inst_hfi_gen2; struct iris_hfi_packet *packet; struct iris_inst *inst; bool dequeue = false; int ret = 0; u32 i, j; - u8 *pkt; static const struct iris_hfi_gen2_inst_hfi_range range[] = { {HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END, iris_hfi_gen2_handle_session_error}, @@ -614,6 +784,17 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core, inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); memset(&inst_hfi_gen2->hfi_frame_info, 0, sizeof(struct iris_hfi_frame_info)); + for (i = 0; i < hdr->num_packets; i++) { + packet = (struct iris_hfi_packet *)pkt; + if (packet->type == HFI_CMD_SETTINGS_CHANGE) { + if (packet->port == HFI_PORT_BITSTREAM) { + iris_hfi_gen2_init_src_change_param(inst); + break; + } + } + pkt += packet->size; + } + pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); for (i = 0; i < ARRAY_SIZE(range); i++) { pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 6d6fe9e2e8c0..4a747c6cf809 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -31,6 +31,7 @@ * @buffers: array of different iris buffers * @fw_min_count: minimnum count of buffers needed by fw * @state: instance state + * @sub_state: instance sub state * @once_per_session_set: boolean to set once per session property * @m2m_dev: a reference to m2m device structure * @m2m_ctx: a reference to m2m context structure @@ -58,6 +59,7 @@ struct iris_inst { struct iris_buffers buffers[BUF_TYPE_MAX]; u32 fw_min_count; enum iris_inst_state state; + enum iris_inst_sub_state sub_state; bool once_per_session_set; struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_ctx *m2m_ctx; diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c index 44362e8fe18f..aad7e734d5c8 100644 --- a/drivers/media/platform/qcom/iris/iris_state.c +++ b/drivers/media/platform/qcom/iris/iris_state.c @@ -102,3 +102,67 @@ int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane) return iris_inst_change_state(inst, new_state); } + +int iris_inst_change_sub_state(struct iris_inst *inst, + enum iris_inst_sub_state clear_sub_state, + enum iris_inst_sub_state set_sub_state) +{ + enum iris_inst_sub_state prev_sub_state; + + if (inst->state == IRIS_INST_ERROR) + return 0; + + if (!clear_sub_state && !set_sub_state) + return 0; + + if ((clear_sub_state & set_sub_state) || + set_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE || + clear_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE) + return -EINVAL; + + prev_sub_state = inst->sub_state; + + inst->sub_state |= set_sub_state; + inst->sub_state &= ~clear_sub_state; + + if (inst->sub_state != prev_sub_state) + dev_dbg(inst->core->dev, "sub_state changed from %x to %x\n", + prev_sub_state, inst->sub_state); + + return 0; +} + +int iris_inst_sub_state_change_drc(struct iris_inst *inst) +{ + enum iris_inst_sub_state set_sub_state = 0; + + if (inst->sub_state & IRIS_INST_SUB_DRC) + return -EINVAL; + + if (inst->state == IRIS_INST_INPUT_STREAMING || + inst->state == IRIS_INST_INIT) + set_sub_state = IRIS_INST_SUB_FIRST_IPSC | IRIS_INST_SUB_INPUT_PAUSE; + else + set_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_INPUT_PAUSE; + + return iris_inst_change_sub_state(inst, 0, set_sub_state); +} + +int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) +{ + enum iris_inst_sub_state set_sub_state; + + if (inst->sub_state & IRIS_INST_SUB_DRC_LAST) + return -EINVAL; + + if (!(inst->sub_state & IRIS_INST_SUB_DRC) || + !(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) + return -EINVAL; + + if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) + return 0; + + set_sub_state = IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; + + return iris_inst_change_sub_state(inst, 0, set_sub_state); +} diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h index 8a25c0c27df4..11236001c1cc 100644 --- a/drivers/media/platform/qcom/iris/iris_state.h +++ b/drivers/media/platform/qcom/iris/iris_state.h @@ -91,9 +91,42 @@ enum iris_inst_state { IRIS_INST_ERROR, }; +#define IRIS_INST_SUB_STATES 8 +#define IRIS_INST_MAX_SUB_STATE_VALUE ((1 << IRIS_INST_SUB_STATES) - 1) + +/** + * enum iris_inst_sub_state + * + * IRIS_INST_SUB_FIRST_IPSC: indicates source change is received from firmware + * when output port is not yet streaming. + * IRIS_INST_SUB_DRC: indicates source change is received from firmware + * when output port is streaming and source change event is + * sent to client. + * IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware + * as part of source change. + * IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This + * indicates that firmware is paused to process + * any further input frames. + * IRIS_INST_SUB_OUTPUT_PAUSE: last buffer is received form firmware as part + * of drc sequence. This indicates that + * firmware is paused to process any further output frames. + */ +enum iris_inst_sub_state { + IRIS_INST_SUB_FIRST_IPSC = BIT(0), + IRIS_INST_SUB_DRC = BIT(1), + IRIS_INST_SUB_DRC_LAST = BIT(2), + IRIS_INST_SUB_INPUT_PAUSE = BIT(3), + IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4), +}; + int iris_inst_change_state(struct iris_inst *inst, enum iris_inst_state request_state); +int iris_inst_change_sub_state(struct iris_inst *inst, + enum iris_inst_sub_state clear_sub_state, + enum iris_inst_sub_state set_sub_state); int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane); int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane); +int iris_inst_sub_state_change_drc(struct iris_inst *inst); +int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index 770e51f9ef91..1ff2017673ed 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -4,6 +4,7 @@ */ #include +#include #include #include "iris_instance.h" @@ -180,6 +181,7 @@ int iris_vb2_buf_out_validate(struct vb2_buffer *vb) void iris_vb2_buf_queue(struct vb2_buffer *vb2) { + static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); struct v4l2_m2m_ctx *m2m_ctx; struct iris_inst *inst; @@ -203,6 +205,23 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) goto exit; } + if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { + if (inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST) { + vbuf->flags |= V4L2_BUF_FLAG_LAST; + vbuf->sequence = inst->sequence_cap++; + vbuf->field = V4L2_FIELD_NONE; + vb2_set_plane_payload(vb2, 0, 0); + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); + if (!v4l2_m2m_has_stopped(m2m_ctx) && + inst->subscriptions & V4L2_EVENT_EOS) { + v4l2_event_queue_fh(&inst->fh, &eos); + v4l2_m2m_mark_stopped(m2m_ctx); + } + goto exit; + } + } + v4l2_m2m_buf_queue(m2m_ctx, vbuf); ret = iris_vdec_qbuf(inst, vbuf); diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 4c99847cec6e..2f68133b4d03 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -226,6 +226,21 @@ int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_su return ret; } +void iris_vdec_src_change(struct iris_inst *inst) +{ + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_event event = {0}; + struct vb2_queue *src_q; + + src_q = v4l2_m2m_get_src_vq(m2m_ctx); + if (!vb2_is_streaming(src_q)) + return; + + event.type = V4L2_EVENT_SOURCE_CHANGE; + event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION; + v4l2_event_queue_fh(&inst->fh, &event); +} + static int iris_vdec_get_num_queued_buffers(struct iris_inst *inst, enum iris_buffer_type type) { diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index 998d4970a42b..dfcc2089a1ef 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -14,6 +14,7 @@ int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); +void iris_vdec_src_change(struct iris_inst *inst); int iris_vdec_streamon_input(struct iris_inst *inst); int iris_vdec_streamon_output(struct iris_inst *inst); int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); From patchwork Wed Nov 20 14:46:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844616 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 59DD31D9A5D; Wed, 20 Nov 2024 14:48:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114135; cv=none; b=ll81VdloUrPCTlj1hzJtj0lOnx4yzeKe3eikSKw1kFGcf+voYIkFJgibrpir1ohcJiojP2M4HptTi9Ra2YVgI+NBDHZ3xcpy5JHAnlK44IOIMyclXTZDqcpcIyzqy14wVKuQgih0qqwRNZomlTTWOXbFYrcRf+SvWbgk5cWYe94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114135; c=relaxed/simple; bh=HHkOKT736Utg1e0pVgLX2NOs0RpdDaNUMUncOnvzrj4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=uHuZPztPhiIY5hHSdfBXQ9jWqvouZ0pQy+bwsWXTaoRDY2IFCrMKEIrFQyjFtbaO+onr25mI+RRkmOYr+oapS0oIsYOeKZk8/jJBqvFlWCmLT91U2SkNJCA+mxYpHY7KbqCqtHNspxw2fuM4AajqZyIFdDRAU7Z4QymP9Ggsp8s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=YAsBqpoz; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="YAsBqpoz" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FRAB010551; Wed, 20 Nov 2024 14:48:44 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= ZprQ6shmZkHsifoT7ycROAFmYhcl2CD/F2mnnsY0e1E=; b=YAsBqpozG5eQXCJq 5lER+XUT+KQIeC1eZ6VxcsJfUKsce7NUbmDTEE2588CovMybxh75nhpl+HG0tWaB eIGAaF1+YvxGAgVGgkGq0APa0Ps1vkL9hCYrzlc/pEKZszWztR2q4Y371bpixjde DHbE7y21TpNx2BWLY7aR5dtDKgbyeR2HzLZZyP1FDYBU72wOTt9fRWZlRGFMW8FN v7NM1qYxIOnhMG4zmjFN6/11c6uWzmuU4r5ZAkaNBmkdaQavPVHMJyy+Nx7z6SB6 hMIpfdYNGK7FA5ZQeSBrLpdHUFeUOBALKmCsE+a/83lsLTrqL6CX9iGBdO5oK48i oQ3piQ== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 43091me5dy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:43 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEmg5j007478 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:42 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:48:37 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:13 +0530 Subject: [PATCH v6 23/28] media: iris: add support for drain sequence Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-23-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=25024; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=HHkOKT736Utg1e0pVgLX2NOs0RpdDaNUMUncOnvzrj4=; b=mTD4tihOigBjL+GKc1SDLnlXgy59c4aL4aK8cAKHyKcWEBNKUnY5iag8yaPAOd7iTl7HU0Bzc MnNASOG5ICNBsf+47kFuLS95jOSb8OvrpNcR4/TLrIwk7QQ55CFsbAr X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: 66LLuDFJmSXsi3mQOfBUWdakuqdtiu_i X-Proofpoint-GUID: 66LLuDFJmSXsi3mQOfBUWdakuqdtiu_i X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 spamscore=0 priorityscore=1501 phishscore=0 malwarescore=0 clxscore=1015 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 adultscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 handle the V4L2_DEC_CMD_STOP by initiating drain sequence to firmware. Process and decode all OUTPUT buffers queued by the client before the VIDIOC_DECODER_CMD() was issued and mark the last buffer with V4L2_BUF_FLAG_LAST flag. Decoder is stopped after processing the last buffer. Resume the decoder when one of below are issued by client: - V4L2_DEC_CMD_START - pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the CAPTURE queue - pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the OUTPUT queue Add the handling to resume decoding when client issues V4L2_DEC_CMD_START to resume decoding after source change is detected. Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/iris_hfi_common.h | 2 + .../platform/qcom/iris/iris_hfi_gen1_command.c | 13 ++++ .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 + .../platform/qcom/iris/iris_hfi_gen1_response.c | 15 ++++ .../platform/qcom/iris/iris_hfi_gen2_command.c | 43 ++++++++++ .../platform/qcom/iris/iris_hfi_gen2_defines.h | 2 + .../platform/qcom/iris/iris_hfi_gen2_response.c | 46 ++++++++++- drivers/media/platform/qcom/iris/iris_state.c | 68 ++++++++++++++++ drivers/media/platform/qcom/iris/iris_state.h | 13 +++- drivers/media/platform/qcom/iris/iris_vb2.c | 6 +- drivers/media/platform/qcom/iris/iris_vdec.c | 91 +++++++++++++++++++++- drivers/media/platform/qcom/iris/iris_vdec.h | 2 + drivers/media/platform/qcom/iris/iris_vidc.c | 37 +++++++++ 13 files changed, 331 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 8e14a61c9be4..b2c541367fc6 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -121,6 +121,8 @@ struct iris_hfi_command_ops { int (*session_pause)(struct iris_inst *inst, u32 plane); int (*session_resume_drc)(struct iris_inst *inst, u32 plane); int (*session_stop)(struct iris_inst *inst, u32 plane); + int (*session_drain)(struct iris_inst *inst, u32 plane); + int (*session_resume_drain)(struct iris_inst *inst, u32 plane); int (*session_close)(struct iris_inst *inst); }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index e0cb75a112e3..e1fbbb3c196d 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -368,6 +368,18 @@ static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct ir return ret; } +static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane) +{ + struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0}; + + ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); + ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + ip_pkt.shdr.session_id = inst->session_id; + ip_pkt.flags = HFI_BUFFERFLAG_EOS; + + return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); +} + static int iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet, struct iris_inst *inst, u32 ptype, void *pdata) @@ -789,6 +801,7 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { .session_release_buf = iris_hfi_gen1_session_unset_buffers, .session_resume_drc = iris_hfi_gen1_session_continue, .session_stop = iris_hfi_gen1_session_stop, + .session_drain = iris_hfi_gen1_session_drain, .session_close = iris_hfi_gen1_session_close, }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index c40e0a28b21f..9f246816a286 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -49,6 +49,7 @@ #define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002 #define HFI_EVENT_SESSION_SEQUENCE_CHANGED 0x1000003 +#define HFI_BUFFERFLAG_EOS 0x00000001 #define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100 #define HFI_FLUSH_OUTPUT 0x1000002 diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 3a47d9f39695..b72d503dd740 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -386,6 +386,7 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet; struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; struct v4l2_m2m_buffer *m2m_buffer, *n; + struct hfi_session_flush_pkt flush_pkt; u32 timestamp_hi = pkt->time_stamp_hi; u32 timestamp_lo = pkt->time_stamp_lo; struct iris_core *core = inst->core; @@ -394,11 +395,25 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) u32 output_tag = pkt->output_tag; struct iris_buffer *buf, *iter; struct iris_buffers *buffers; + u32 hfi_flags = pkt->flags; u32 offset = pkt->offset; u64 timestamp_us = 0; bool found = false; u32 flags = 0; + if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) { + reinit_completion(&inst->flush_completion); + + flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); + flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; + flush_pkt.shdr.session_id = inst->session_id; + flush_pkt.flush_type = HFI_FLUSH_OUTPUT; + iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); + iris_inst_sub_state_change_drain_last(inst); + + return; + } + if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) { buffers = &inst->buffers[BUF_DPB]; if (!buffers) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 8efc6a70a57a..a908b41e2868 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -774,6 +774,47 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane) inst_hfi_gen2->packet->size); } +static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 payload = HFI_CMD_DRAIN; + + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_RESUME, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED), + iris_hfi_gen2_get_port(plane), + inst->session_id, + HFI_PAYLOAD_U32, + &payload, + sizeof(u32)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + +static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + + if (!V4L2_TYPE_IS_OUTPUT(plane)) + return 0; + + iris_hfi_gen2_packet_session_command(inst, + HFI_CMD_DRAIN, + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | + HFI_HOST_FLAGS_INTR_REQUIRED | + HFI_HOST_FLAGS_NON_DISCARDABLE), + iris_hfi_gen2_get_port(plane), + inst->session_id, + HFI_PAYLOAD_NONE, + NULL, + 0); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) { switch (buffer_type) { @@ -900,6 +941,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { .session_pause = iris_hfi_gen2_session_pause, .session_resume_drc = iris_hfi_gen2_session_resume_drc, .session_stop = iris_hfi_gen2_session_stop, + .session_drain = iris_hfi_gen2_session_drain, + .session_resume_drain = iris_hfi_gen2_session_resume_drain, .session_close = iris_hfi_gen2_session_close, }; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index d759b7355711..214e2a579b8e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -17,6 +17,7 @@ #define HFI_CMD_CLOSE 0x01000004 #define HFI_CMD_START 0x01000005 #define HFI_CMD_STOP 0x01000006 +#define HFI_CMD_DRAIN 0x01000007 #define HFI_CMD_RESUME 0x01000008 #define HFI_CMD_BUFFER 0x01000009 #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B @@ -79,6 +80,7 @@ #define HFI_INFO_UNSUPPORTED 0x06000001 #define HFI_INFO_DATA_CORRUPT 0x06000002 #define HFI_INFO_BUFFER_OVERFLOW 0x06000004 +#define HFI_INFO_HFI_FLAG_DRAIN_LAST 0x06000006 #define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007 #define HFI_INFORMATION_END 0x06FFFFFF diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index 28857a7a5112..f043e74866bc 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -201,6 +201,10 @@ static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst, info = "buffer overflow"; inst_hfi_gen2->hfi_frame_info.overflow = 1; break; + case HFI_INFO_HFI_FLAG_DRAIN_LAST: + info = "drain last flag"; + ret = iris_inst_sub_state_change_drain_last(inst); + break; case HFI_INFO_HFI_FLAG_PSC_LAST: info = "drc last flag"; ret = iris_inst_sub_state_change_drc_last(inst); @@ -334,6 +338,12 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst, bool found = false; int ret; + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST) { + ret = iris_inst_sub_state_change_drain_last(inst); + if (ret) + return ret; + } + if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { ret = iris_inst_sub_state_change_drc_last(inst); if (ret) @@ -422,6 +432,21 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, return ret; } +static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst, + struct iris_hfi_packet *pkt) +{ + int ret = 0; + + if (pkt->port == HFI_PORT_RAW) + ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + else if (pkt->port == HFI_PORT_BITSTREAM) + ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + complete(&inst->completion); + + return ret; +} + static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, struct iris_hfi_packet *pkt) { @@ -450,6 +475,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); } +static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst, + struct iris_hfi_packet *pkt) +{ + int ret = 0; + + if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) { + iris_inst_change_state(inst, IRIS_INST_ERROR); + return 0; + } + + if (inst->sub_state & IRIS_INST_SUB_DRAIN) + ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_INPUT_PAUSE); + + return ret; +} + static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); @@ -569,7 +610,7 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, iris_hfi_gen2_handle_session_close(inst, pkt); break; case HFI_CMD_STOP: - complete(&inst->completion); + iris_hfi_gen2_handle_session_stop(inst, pkt); break; case HFI_CMD_BUFFER: ret = iris_hfi_gen2_handle_session_buffer(inst, pkt); @@ -577,6 +618,9 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst, case HFI_CMD_SETTINGS_CHANGE: ret = iris_hfi_gen2_handle_src_change(inst, pkt); break; + case HFI_CMD_DRAIN: + ret = iris_hfi_gen2_handle_session_drain(inst, pkt); + break; default: break; } diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c index aad7e734d5c8..f12306e735ec 100644 --- a/drivers/media/platform/qcom/iris/iris_state.c +++ b/drivers/media/platform/qcom/iris/iris_state.c @@ -3,6 +3,8 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include + #include "iris_instance.h" static bool iris_allow_inst_state_change(struct iris_inst *inst, @@ -148,6 +150,21 @@ int iris_inst_sub_state_change_drc(struct iris_inst *inst) return iris_inst_change_sub_state(inst, 0, set_sub_state); } +int iris_inst_sub_state_change_drain_last(struct iris_inst *inst) +{ + enum iris_inst_sub_state set_sub_state; + + if (inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) + return -EINVAL; + + if (!(inst->sub_state & IRIS_INST_SUB_DRAIN)) + return -EINVAL; + + set_sub_state = IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; + + return iris_inst_change_sub_state(inst, 0, set_sub_state); +} + int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) { enum iris_inst_sub_state set_sub_state; @@ -166,3 +183,54 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) return iris_inst_change_sub_state(inst, 0, set_sub_state); } + +int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane) +{ + enum iris_inst_sub_state set_sub_state; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + if (inst->sub_state & IRIS_INST_SUB_DRC && + !(inst->sub_state & IRIS_INST_SUB_DRC_LAST)) + return -EINVAL; + + if (inst->sub_state & IRIS_INST_SUB_DRAIN && + !(inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) + return -EINVAL; + + set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; + } else { + set_sub_state = IRIS_INST_SUB_OUTPUT_PAUSE; + } + + return iris_inst_change_sub_state(inst, 0, set_sub_state); +} + +static inline bool iris_drc_pending(struct iris_inst *inst) +{ + return inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST; +} + +static inline bool iris_drain_pending(struct iris_inst *inst) +{ + return inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; +} + +bool iris_allow_cmd(struct iris_inst *inst, u32 cmd) +{ + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + + if (cmd == V4L2_DEC_CMD_START) { + if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q)) + if (iris_drc_pending(inst) || iris_drain_pending(inst)) + return true; + } else if (cmd == V4L2_DEC_CMD_STOP) { + if (vb2_is_streaming(src_q)) + if (inst->sub_state != IRIS_INST_SUB_DRAIN) + return true; + } + + return false; +} diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h index 11236001c1cc..bf645f6f879c 100644 --- a/drivers/media/platform/qcom/iris/iris_state.h +++ b/drivers/media/platform/qcom/iris/iris_state.h @@ -104,6 +104,9 @@ enum iris_inst_state { * sent to client. * IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware * as part of source change. + * IRIS_INST_SUB_DRAIN: indicates drain is in progress. + * IRIS_INST_SUB_DRAIN_LAST: indicates last buffer is received from firmware + * as part of drain sequence. * IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This * indicates that firmware is paused to process * any further input frames. @@ -115,8 +118,10 @@ enum iris_inst_sub_state { IRIS_INST_SUB_FIRST_IPSC = BIT(0), IRIS_INST_SUB_DRC = BIT(1), IRIS_INST_SUB_DRC_LAST = BIT(2), - IRIS_INST_SUB_INPUT_PAUSE = BIT(3), - IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4), + IRIS_INST_SUB_DRAIN = BIT(3), + IRIS_INST_SUB_DRAIN_LAST = BIT(4), + IRIS_INST_SUB_INPUT_PAUSE = BIT(5), + IRIS_INST_SUB_OUTPUT_PAUSE = BIT(6), }; int iris_inst_change_state(struct iris_inst *inst, @@ -124,9 +129,13 @@ int iris_inst_change_state(struct iris_inst *inst, int iris_inst_change_sub_state(struct iris_inst *inst, enum iris_inst_sub_state clear_sub_state, enum iris_inst_sub_state set_sub_state); + int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane); int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane); int iris_inst_sub_state_change_drc(struct iris_inst *inst); +int iris_inst_sub_state_change_drain_last(struct iris_inst *inst); int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); +int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); +bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index 1ff2017673ed..f51fd6929f64 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -206,8 +206,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) } if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { - if (inst->sub_state & IRIS_INST_SUB_DRC && - inst->sub_state & IRIS_INST_SUB_DRC_LAST) { + if ((inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST) || + (inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) { vbuf->flags |= V4L2_BUF_FLAG_LAST; vbuf->sequence = inst->sequence_cap++; vbuf->field = V4L2_FIELD_NONE; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 012ae9f7f9a8..1ae0bb4830de 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -374,6 +374,7 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst) } if (inst->sub_state & IRIS_INST_SUB_DRC || + inst->sub_state & IRIS_INST_SUB_DRAIN || inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) { if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { if (hfi_ops->session_pause) { @@ -425,15 +426,20 @@ int iris_vdec_streamon_input(struct iris_inst *inst) static int iris_vdec_process_streamon_output(struct iris_inst *inst) { const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + bool drain_active = false, drc_active = false; enum iris_inst_sub_state clear_sub_state = 0; - bool drc_active = false; int ret = 0; + drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; + drc_active = inst->sub_state & IRIS_INST_SUB_DRC && inst->sub_state & IRIS_INST_SUB_DRC_LAST; if (drc_active) clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; + else if (drain_active) + clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { ret = iris_alloc_and_queue_input_int_bufs(inst); @@ -449,8 +455,12 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst) if (inst->state == IRIS_INST_INPUT_STREAMING && inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret = hfi_ops->session_resume_drc(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!drain_active) + ret = hfi_ops->session_resume_drc(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + else if (hfi_ops->session_resume_drain) + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (ret) return ret; clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; @@ -568,3 +578,78 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) return iris_queue_buffer(inst, buf); } + +int iris_vdec_start_cmd(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_inst_sub_state clear_sub_state = 0; + struct vb2_queue *dst_vq; + int ret; + + dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + + if (inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST) { + vb2_clear_last_buffer_dequeued(dst_vq); + clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; + + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret = hfi_ops->session_resume_drc(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; + } + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { + ret = hfi_ops->session_resume_drc(inst, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; + } + } else if (inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) { + vb2_clear_last_buffer_dequeued(dst_vq); + clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + if (hfi_ops->session_resume_drain) { + ret = + hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + } + + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; + } + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { + if (hfi_ops->session_resume_drain) { + ret = + hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + } + + clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; + } + } else { + dev_err(inst->core->dev, "start called before receiving last_flag\n"); + iris_inst_change_state(inst, IRIS_INST_ERROR); + return -EBUSY; + } + + return iris_inst_change_sub_state(inst, clear_sub_state, 0); +} + +int iris_vdec_stop_cmd(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + int ret; + + ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + return iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN); +} diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index dfcc2089a1ef..b24932dc511a 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -18,6 +18,8 @@ void iris_vdec_src_change(struct iris_inst *inst); int iris_vdec_streamon_input(struct iris_inst *inst); int iris_vdec_streamon_output(struct iris_inst *inst); int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_vdec_start_cmd(struct iris_inst *inst); +int iris_vdec_stop_cmd(struct iris_inst *inst); int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 8a1c35f99538..2281b291b736 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -365,6 +365,41 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs return iris_vdec_subscribe_event(inst, sub); } +static int iris_dec_cmd(struct file *filp, void *fh, + struct v4l2_decoder_cmd *dec) +{ + struct iris_inst *inst = iris_get_inst(filp, NULL); + int ret = 0; + + mutex_lock(&inst->lock); + + if (dec->cmd != V4L2_DEC_CMD_START && + dec->cmd != V4L2_DEC_CMD_STOP) { + ret = -EINVAL; + goto unlock; + } + + if (inst->state == IRIS_INST_DEINIT) + goto unlock; + + if (!iris_allow_cmd(inst, dec->cmd)) { + ret = -EBUSY; + goto unlock; + } + + if (dec->cmd == V4L2_DEC_CMD_START) + ret = iris_vdec_start_cmd(inst); + else if (dec->cmd == V4L2_DEC_CMD_STOP) + ret = iris_vdec_stop_cmd(inst); + else + ret = -EINVAL; + +unlock: + mutex_unlock(&inst->lock); + + return ret; +} + static struct v4l2_file_operations iris_v4l2_file_ops = { .owner = THIS_MODULE, .open = iris_open, @@ -408,6 +443,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { .vidioc_unsubscribe_event = v4l2_event_unsubscribe, .vidioc_streamon = v4l2_m2m_ioctl_streamon, .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, + .vidioc_decoder_cmd = iris_dec_cmd, }; void iris_init_ops(struct iris_core *core) From patchwork Wed Nov 20 14:46:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844615 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 7A2EA1DACBA; Wed, 20 Nov 2024 14:49:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114146; cv=none; b=newSqFR2Eono1Dhqa53BOA7APTbruvL47VA+mJwwes+3+SD0NMJ8TttO/9gDy2L0iBOhlLhnBvovXqkrG27JPHeqWJIEyf7cCyin1miqxthZRfa9IuCAe6LVa5cUbXZUQWTkIQ1dIHOAhQ7hELiSLbwKzHz2WNR2QM/bs+rgado= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114146; c=relaxed/simple; bh=AtTTwV1DqIGrzn0krmHUSdaXYV+uoTmDE2VLiKare4c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=Su1FjZOJj1PYd15KRaJOIhaX1f615dRucNSwy3HTMgI89j7UQNTJBZcMsMqXW+LJIug0MA7BKGDKv220OKBZQo9ptRGfxE3NDA6VVV+0EadCWp9c5WUqM6jUTIvwuBwpQ0hTmBZpLiMixucKTK/EeM0kJdHqJRx/IB9PXkVBz0k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=SwaC2d1R; arc=none smtp.client-ip=205.220.180.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="SwaC2d1R" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AK9FVjf005827; Wed, 20 Nov 2024 14:48:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= Nsd6NihEuNcFZcJzpOTeMhVs/rfuSj/u98YMz0VqLiM=; b=SwaC2d1R7U6eD9OQ r1inY/6LKADk7ohqB85c0k3z3Z6xHuVKQSNeR01QbWwbx2nZg59/0h0yEwU2NsIb NT6nHVryqyAfDzzCHcMgG49371Bo7zGXMdYCpwMWJYZYjnSxiKBfr9T9N1G8tIeu 0lZkTRvxfZ/Ugz5IDUAU/fkKoFkPZC0VpSqJJQvGeKXyuenC6lSqyIW3J1Hz/4tt I4i3Fo/4QAQbDliNklbA150vEAwgK+Ppx77nM6PyWmcDcHE/+lsmWeTZfCFiiNJk qXD1ihvgQI7T3v9i+opZdtzpOjPPtujwg9K62Ay0nRiEUX0RXr1UrL2SAF3vXsi9 ly6jlg== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4308y7x7hs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:55 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEmspU000821 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:48:54 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:48:48 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:15 +0530 Subject: [PATCH v6 25/28] media: iris: implement power scaling for vpu2 and vpu3 Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-25-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" , Vedang Nagar X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=16259; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=SpYJvGIFWBasfDFw/paSp5MMd7vW9JtC6su4lkxCsmY=; b=oHe3kBAwPEoORlyADwuL0DZLQXbSh/iVjKeO9Fjj/5eEqcDt0syyEsCypoNpMJ7fgY/DJMmYG cOl6p7leuu7A7SpCYUxmMGhaxWVzxF5dTP5Xv19Q2AIttiQRQTA/t8q X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: WEcxPaDgw3fhYWYLzSa8drmCiuDNTH4y X-Proofpoint-GUID: WEcxPaDgw3fhYWYLzSa8drmCiuDNTH4y X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 spamscore=0 mlxlogscore=999 clxscore=1015 suspectscore=0 adultscore=0 priorityscore=1501 phishscore=0 impostorscore=0 bulkscore=0 lowpriorityscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 From: Vedang Nagar Implement power scaling including vpu2 and vpu3 specific calculation for clock and bus bandwidth which depends on hardware configuration, codec format, resolution and frame rate. Signed-off-by: Vedang Nagar Signed-off-by: Dikshita Agarwal --- drivers/media/platform/qcom/iris/Makefile | 1 + drivers/media/platform/qcom/iris/iris_buffer.c | 3 + drivers/media/platform/qcom/iris/iris_instance.h | 6 + .../platform/qcom/iris/iris_platform_common.h | 23 ++++ .../platform/qcom/iris/iris_platform_sm8550.c | 12 ++ drivers/media/platform/qcom/iris/iris_power.c | 140 +++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_power.h | 13 ++ drivers/media/platform/qcom/iris/iris_vb2.c | 3 + drivers/media/platform/qcom/iris/iris_vdec.c | 7 ++ drivers/media/platform/qcom/iris/iris_vpu2.c | 27 ++++ drivers/media/platform/qcom/iris/iris_vpu3.c | 38 ++++++ drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 + 12 files changed, 274 insertions(+) diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index ab16189aa9e6..ca31db847273 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -10,6 +10,7 @@ iris-objs += iris_buffer.o \ iris_hfi_gen2_response.o \ iris_hfi_queue.o \ iris_platform_sm8550.o \ + iris_power.o \ iris_probe.o \ iris_resources.o \ iris_state.o \ diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index b77a138c0e6b..be781a3e5191 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -8,6 +8,7 @@ #include "iris_buffer.h" #include "iris_instance.h" +#include "iris_power.h" #include "iris_vpu_buffer.h" #define PIXELS_4K 4096 @@ -500,6 +501,8 @@ int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type bu struct iris_buffer *buf; int ret; + iris_scale_power(inst); + if (buf_type == BUF_INPUT) { v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { buf = to_iris_buffer(&buffer->vb); diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 4a747c6cf809..ed275626dc79 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -33,6 +33,9 @@ * @state: instance state * @sub_state: instance sub state * @once_per_session_set: boolean to set once per session property + * @max_input_data_size: max size of input data + * @power: structure of power info + * @icc_data: structure of interconnect data * @m2m_dev: a reference to m2m device structure * @m2m_ctx: a reference to m2m context structure * @subscriptions: variable to hold current events subscriptions @@ -61,6 +64,9 @@ struct iris_inst { enum iris_inst_state state; enum iris_inst_sub_state sub_state; bool once_per_session_set; + size_t max_input_data_size; + struct iris_inst_power power; + struct icc_vote_data icc_data; struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_ctx *m2m_ctx; unsigned int subscriptions; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index a5a7d6838d16..189dd081ad0a 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -20,6 +20,8 @@ struct iris_inst; #define CODED_FRAMES_PROGRESSIVE 0x0 #define DEFAULT_MAX_HOST_BUF_COUNT 64 #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 +#define DEFAULT_FPS 30 + enum stage_type { STAGE_1 = 1, STAGE_2 = 2, @@ -67,6 +69,10 @@ struct platform_inst_caps { u32 min_frame_height; u32 max_frame_height; u32 max_mbpf; + u32 mb_cycles_vsp; + u32 mb_cycles_vpp; + u32 mb_cycles_fw; + u32 mb_cycles_fw_vpp; u32 num_comv; }; @@ -106,11 +112,26 @@ struct platform_inst_fw_cap { enum platform_inst_fw_cap_type cap_id); }; +struct bw_info { + u32 mbs_per_sec; + u32 bw_ddr; +}; + struct iris_core_power { u64 clk_freq; u64 icc_bw; }; +struct iris_inst_power { + u64 min_freq; + u32 icc_bw; +}; + +struct icc_vote_data { + u32 height, width; + u32 fps; +}; + enum platform_pm_domain_type { IRIS_CTRL_POWER_DOMAIN, IRIS_HW_POWER_DOMAIN, @@ -124,6 +145,8 @@ struct iris_platform_data { void (*set_preset_registers)(struct iris_core *core); const struct icc_info *icc_tbl; unsigned int icc_tbl_size; + const struct bw_info *bw_tbl_dec; + unsigned int bw_tbl_dec_size; const char * const *pmdomain_tbl; unsigned int pmdomain_tbl_size; const char * const *opp_pd_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 68907ba6986f..d0891d89d8d8 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -126,6 +126,9 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = { .min_frame_height = 96, .max_frame_height = 8192, .max_mbpf = (8192 * 4352) / 256, + .mb_cycles_vpp = 200, + .mb_cycles_fw = 489583, + .mb_cycles_fw_vpp = 66234, .num_comv = 0, }; @@ -141,6 +144,13 @@ static const struct icc_info sm8550_icc_table[] = { static const char * const sm8550_clk_reset_table[] = { "bus" }; +static const struct bw_info sm8550_bw_table_dec[] = { + { ((4096 * 2160) / 256) * 60, 1608000 }, + { ((4096 * 2160) / 256) * 30, 826000 }, + { ((1920 * 1080) / 256) * 60, 567000 }, + { ((1920 * 1080) / 256) * 30, 294000 }, +}; + static const char * const sm8550_pmdomain_table[] = { "venus", "vcodec0" }; static const char * const sm8550_opp_pd_table[] = { "mxc", "mmcx" }; @@ -214,6 +224,8 @@ struct iris_platform_data sm8550_data = { .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), .clk_rst_tbl = sm8550_clk_reset_table, .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), + .bw_tbl_dec = sm8550_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), .pmdomain_tbl = sm8550_pmdomain_table, .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), .opp_pd_tbl = sm8550_opp_pd_table, diff --git a/drivers/media/platform/qcom/iris/iris_power.c b/drivers/media/platform/qcom/iris/iris_power.c new file mode 100644 index 000000000000..dbca42df0910 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_power.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include + +#include "iris_buffer.h" +#include "iris_instance.h" +#include "iris_power.h" +#include "iris_resources.h" +#include "iris_vpu_common.h" + +static u32 iris_calc_bw(struct iris_inst *inst, struct icc_vote_data *data) +{ + const struct bw_info *bw_tbl = NULL; + struct iris_core *core = inst->core; + u32 num_rows, i, mbs, mbps; + u32 icc_bw = 0; + + mbs = DIV_ROUND_UP(data->height, 16) * DIV_ROUND_UP(data->width, 16); + mbps = mbs * data->fps; + if (mbps == 0) + goto exit; + + bw_tbl = core->iris_platform_data->bw_tbl_dec; + num_rows = core->iris_platform_data->bw_tbl_dec_size; + + for (i = 0; i < num_rows; i++) { + if (i != 0 && mbps > bw_tbl[i].mbs_per_sec) + break; + + icc_bw = bw_tbl[i].bw_ddr; + } + +exit: + return icc_bw; +} + +static int iris_set_interconnects(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct iris_inst *instance; + u64 total_bw_ddr = 0; + int ret; + + mutex_lock(&core->lock); + list_for_each_entry(instance, &core->instances, list) { + if (!instance->max_input_data_size) + continue; + + total_bw_ddr += instance->power.icc_bw; + } + + ret = iris_set_icc_bw(core, total_bw_ddr); + + mutex_unlock(&core->lock); + + return ret; +} + +static int iris_vote_interconnects(struct iris_inst *inst) +{ + struct icc_vote_data *vote_data = &inst->icc_data; + struct v4l2_format *inp_f = inst->fmt_src; + + vote_data->width = inp_f->fmt.pix_mp.width; + vote_data->height = inp_f->fmt.pix_mp.height; + vote_data->fps = DEFAULT_FPS; + + inst->power.icc_bw = iris_calc_bw(inst, vote_data); + + return iris_set_interconnects(inst); +} + +static int iris_set_clocks(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct iris_inst *instance; + u64 freq = 0; + int ret; + + mutex_lock(&core->lock); + list_for_each_entry(instance, &core->instances, list) { + if (!instance->max_input_data_size) + continue; + + freq += instance->power.min_freq; + } + + core->power.clk_freq = freq; + ret = dev_pm_opp_set_rate(core->dev, freq); + mutex_unlock(&core->lock); + + return ret; +} + +static int iris_scale_clocks(struct iris_inst *inst) +{ + const struct vpu_ops *vpu_ops = inst->core->iris_platform_data->vpu_ops; + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_m2m_buffer *buffer, *n; + struct iris_buffer *buf; + size_t data_size = 0; + + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { + buf = to_iris_buffer(&buffer->vb); + data_size = max(data_size, buf->data_size); + } + + inst->max_input_data_size = data_size; + if (!inst->max_input_data_size) + return 0; + + inst->power.min_freq = vpu_ops->calc_freq(inst, inst->max_input_data_size); + + return iris_set_clocks(inst); +} + +int iris_scale_power(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + int ret; + + if (pm_runtime_suspended(core->dev)) { + ret = pm_runtime_resume_and_get(core->dev); + if (ret < 0) + return ret; + + pm_runtime_put_autosuspend(core->dev); + } + + ret = iris_scale_clocks(inst); + if (ret) + return ret; + + return iris_vote_interconnects(inst); +} diff --git a/drivers/media/platform/qcom/iris/iris_power.h b/drivers/media/platform/qcom/iris/iris_power.h new file mode 100644 index 000000000000..55212660e72d --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_power.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_POWER_H__ +#define __IRIS_POWER_H__ + +struct iris_inst; + +int iris_scale_power(struct iris_inst *inst); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index f3b126accec9..3bdf7e6141a9 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -10,6 +10,7 @@ #include "iris_instance.h" #include "iris_vb2.h" #include "iris_vdec.h" +#include "iris_power.h" static int iris_check_core_mbpf(struct iris_inst *inst) { @@ -187,6 +188,8 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) goto error; } + iris_scale_power(inst); + ret = iris_check_session_supported(inst); if (ret) goto error; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 1ae0bb4830de..b6513c4d59a4 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -9,6 +9,7 @@ #include "iris_buffer.h" #include "iris_ctrls.h" #include "iris_instance.h" +#include "iris_power.h" #include "iris_vdec.h" #include "iris_vpu_buffer.h" @@ -363,6 +364,8 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst) enum iris_inst_sub_state set_sub_state = 0; int ret; + iris_scale_power(inst); + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (ret) return ret; @@ -430,6 +433,8 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst) enum iris_inst_sub_state clear_sub_state = 0; int ret = 0; + iris_scale_power(inst); + drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; @@ -576,6 +581,8 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) return 0; } + iris_scale_power(inst); + return iris_queue_buffer(inst, buf); } diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c index bd8427411576..8f502aed43ce 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_vpu2.c @@ -6,6 +6,33 @@ #include "iris_instance.h" #include "iris_vpu_common.h" +static u64 iris_vpu2_calc_freq(struct iris_inst *inst, size_t data_size) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct v4l2_format *inp_f = inst->fmt_src; + u32 mbs_per_second, mbpf, height, width; + unsigned long vpp_freq, vsp_freq; + u32 fps = DEFAULT_FPS; + + width = max(inp_f->fmt.pix_mp.width, inst->crop.width); + height = max(inp_f->fmt.pix_mp.height, inst->crop.height); + + mbpf = NUM_MBS_PER_FRAME(height, width); + mbs_per_second = mbpf * fps; + + vpp_freq = mbs_per_second * caps->mb_cycles_vpp; + + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; + vsp_freq = mbs_per_second * caps->mb_cycles_vsp; + + /* 10 / 7 is overhead factor */ + vsp_freq += ((fps * data_size * 8) * 10) / 7; + + return max(vpp_freq, vsp_freq); +} + const struct vpu_ops iris_vpu2_ops = { .power_off_hw = iris_vpu_power_off_hw, + .calc_freq = iris_vpu2_calc_freq, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu3.c b/drivers/media/platform/qcom/iris/iris_vpu3.c index 10599f1fa789..b484638e6105 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3.c @@ -79,6 +79,44 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core) iris_vpu_power_off_hw(core); } +static u64 iris_vpu3_calculate_frequency(struct iris_inst *inst, size_t data_size) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct v4l2_format *inp_f = inst->fmt_src; + u32 height, width, mbs_per_second, mbpf; + u64 fw_cycles, fw_vpp_cycles; + u64 vsp_cycles, vpp_cycles; + u32 fps = DEFAULT_FPS; + + width = max(inp_f->fmt.pix_mp.width, inst->crop.width); + height = max(inp_f->fmt.pix_mp.height, inst->crop.height); + + mbpf = NUM_MBS_PER_FRAME(height, width); + mbs_per_second = mbpf * fps; + + fw_cycles = fps * caps->mb_cycles_fw; + fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp; + + vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value); + /* 21 / 20 is minimum overhead factor */ + vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles); + + /* 1.059 is multi-pipe overhead */ + if (inst->fw_caps[PIPE].value > 1) + vpp_cycles += div_u64(vpp_cycles * 59, 1000); + + vsp_cycles = fps * data_size * 8; + vsp_cycles = div_u64(vsp_cycles, 2); + /* VSP FW overhead 1.05 */ + vsp_cycles = div_u64(vsp_cycles * 21, 20); + + if (inst->fw_caps[STAGE].value == STAGE_1) + vsp_cycles = vsp_cycles * 3; + + return max3(vpp_cycles, vsp_cycles, fw_cycles); +} + const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, + .calc_freq = iris_vpu3_calculate_frequency, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index d3efa7c0ce9a..63fa1fa5a498 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -13,6 +13,7 @@ extern const struct vpu_ops iris_vpu3_ops; struct vpu_ops { void (*power_off_hw)(struct iris_core *core); + u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); }; int iris_vpu_boot_firmware(struct iris_core *core); From patchwork Wed Nov 20 14:46:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dikshita Agarwal X-Patchwork-Id: 844614 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 034491DDC2D; Wed, 20 Nov 2024 14:49:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114161; cv=none; b=Gst1x/mbSVVLktEVUPgEVaokwtsf4gr/mGtXNqH2XM/OboQnwM92CSPmOtZXP04xCoIKlbvqPkFDk0aBrVe/pxIr3GBi/gqQ/o3Ql7u+PhZZchpYJGGABZqJdkqf8/mSXZCzCUbpi2AUocKX77S9GT1BLNgKLVlanHgJouN2+uU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114161; c=relaxed/simple; bh=ljYka+yEPL7dtoadjp4FCBcNXplDLLPRhCJ9St112Pw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=CjRZTa0RU4oRuuYs1KnSemfIaUsgAYNNbHFXAoUGHwVhqpPiM9oK+eFLHovvynTvRl4rE/edH9aqm2kJ7x33tJzKyf/nvJ2Oh+EuzhnpC4BDHeR4BBNTz681kgFyx3fHCsgJBHb92XPENxRd4Otvcxlx7Ta72U0JPXkbSLIaDxY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=IaJ0u76B; arc=none smtp.client-ip=205.220.168.131 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=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="IaJ0u76B" Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AKAo9BA027179; Wed, 20 Nov 2024 14:49:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= Oxkw5D/JPs2UYjgb4jIX/CzNiPXlr+l6xOKDFt/4wo8=; b=IaJ0u76BSvUJlkw7 mBIQDg5rgT8/qkQCihfnx9cwjhFivODOWMP6kJtgVw0Bkq8nHCoelW1+/ijjmEfF +mk68PYxVuT6198zwMnzLBtdnCNujhLvVJ5RVw2P7Et4eO3+jMhtV23yFQasAgi8 A4Eeisb/e2PlU+llfRkwEJtELgUiWBboYOsWdoB6bAQvohkqKCTQvlTPPXTqney/ FiZ5vCjWlaH86UF1AawrDiNHG7PG1wKB1o1ybrmtrHQ23ibyXQMiqL6EdHbbamSw khPhFF/xJubJpoA0rpNIkYrAbLo2suLJdw2u2OqHmKzuz43O5bh/5CZA/UyPs6WL xmuinA== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 431eby8k2a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:49:12 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AKEnBVK008175 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 20 Nov 2024 14:49:11 GMT Received: from hu-dikshita-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 20 Nov 2024 06:49:06 -0800 From: Dikshita Agarwal Date: Wed, 20 Nov 2024 20:16:18 +0530 Subject: [PATCH v6 28/28] media: MAINTAINERS: add Qualcomm iris video accelerator driver Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <20241120-qcom-video-iris-v6-28-a8cf6704e992@quicinc.com> References: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> In-Reply-To: <20241120-qcom-video-iris-v6-0-a8cf6704e992@quicinc.com> To: Vikash Garodia , Abhinav Kumar , Mauro Carvalho Chehab , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Philipp Zabel CC: Hans Verkuil , Sebastian Fricke , Bryan O'Donoghue , Dmitry Baryshkov , Neil Armstrong , Nicolas Dufresne , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Jianhua Lu , , , , , "Dikshita Agarwal" X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732113983; l=1060; i=quic_dikshita@quicinc.com; s=20240917; h=from:subject:message-id; bh=ljYka+yEPL7dtoadjp4FCBcNXplDLLPRhCJ9St112Pw=; b=ovc4qxub2F5eMzuCXputinphaVPxI3cGetGOXmj8SAIjge1rcdnJhU0POnKBgb3hyr6MJVd9D ZBxR87dTCKWDnalOJB/WvPsFvZfKi/bI+Z8MPEaODLiQLFi32cm7Ldz X-Developer-Key: i=quic_dikshita@quicinc.com; a=ed25519; pk=EEvKY6Ar1OI5SWf44FJ1Ebo1KuQEVbbf5UNPO+UHVhM= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: hETFp3prU3poPUth79wLqhyv4yaz1gye X-Proofpoint-ORIG-GUID: hETFp3prU3poPUth79wLqhyv4yaz1gye X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 lowpriorityscore=0 malwarescore=0 mlxlogscore=836 spamscore=0 mlxscore=0 phishscore=0 suspectscore=0 bulkscore=0 adultscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411200098 Add an entry for iris video decoder accelerator driver. Signed-off-by: Vikash Garodia Signed-off-by: Dikshita Agarwal --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7a14891a8fa9..d647e59d9912 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19156,6 +19156,16 @@ S: Maintained F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml F: drivers/regulator/vqmmc-ipq4019-regulator.c +QUALCOMM IRIS VIDEO ACCELERATOR DRIVER +M: Vikash Garodia +M: Dikshita Agarwal +R: Abhinav Kumar +L: linux-media@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml +F: drivers/media/platform/qcom/iris/ + QUALCOMM NAND CONTROLLER DRIVER M: Manivannan Sadhasivam L: linux-mtd@lists.infradead.org