From patchwork Mon Aug 16 10:59:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438227 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BE3EC432BE for ; Mon, 16 Aug 2021 11:00:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8A55B61354 for ; Mon, 16 Aug 2021 11:00:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235964AbhHPLA5 (ORCPT ); Mon, 16 Aug 2021 07:00:57 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:41376 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S235941AbhHPLA4 (ORCPT ); Mon, 16 Aug 2021 07:00:56 -0400 X-UUID: 78217859e08049f8b6a909ef524d1f1a-20210816 X-UUID: 78217859e08049f8b6a909ef524d1f1a-20210816 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1652081063; Mon, 16 Aug 2021 19:00:19 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkexhb01.mediatek.inc (172.21.101.102) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:18 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:17 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , Tiffany Lin , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 1/9] dt-bindings: media: mtk-vcodec: Add binding for MT8195 two venc cores Date: Mon, 16 Aug 2021 18:59:26 +0800 Message-ID: <20210816105934.28265-2-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Enable MT8195 two H.264 venc cores, updates vcodec binding document. Signed-off-by: Irui Wang Acked-by: Rob Herring --- Documentation/devicetree/bindings/media/mediatek-vcodec.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt index de961699ba0a..eb2e24c32426 100644 --- a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt +++ b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt @@ -11,6 +11,8 @@ Required properties: "mediatek,mt8173-vcodec-dec" for MT8173 decoder. "mediatek,mt8192-vcodec-enc" for MT8192 encoder. "mediatek,mt8195-vcodec-enc" for MT8195 encoder. + "mediatek,mtk-venc-core0" for MT8195 avc core0 device. + "mediatek,mtk-venc-core1" for MT8195 avc core1 device. - reg : Physical base address of the video codec registers and length of memory mapped region. - interrupts : interrupt number to the cpu. From patchwork Mon Aug 16 10:59:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438225 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 25989C4320E for ; Mon, 16 Aug 2021 11:00:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0BF29611C4 for ; Mon, 16 Aug 2021 11:00:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235890AbhHPLA7 (ORCPT ); Mon, 16 Aug 2021 07:00:59 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:52956 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S235943AbhHPLA5 (ORCPT ); Mon, 16 Aug 2021 07:00:57 -0400 X-UUID: 258b15537135485e93bdfe0d5665038b-20210816 X-UUID: 258b15537135485e93bdfe0d5665038b-20210816 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 2006181287; Mon, 16 Aug 2021 19:00:22 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:21 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:20 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , Tiffany Lin , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 2/9] media: mtk-vcodec: Use component framework to manage encoder hardware Date: Mon, 16 Aug 2021 18:59:27 +0800 Message-ID: <20210816105934.28265-3-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org There are two venc cores for H264 inside MT8195, uses component framework to manage each hardware so that the two cores can be used through one venc driver. Adds new encoder hardware mode to indicate different hardware modes: VENC_SINGLE_CORE_MODE means only one core, the device has its own power/clk/irq, init_pm/request_irq helper can be used. VENC_FRAME_RACING_MODE means more than one core inside, the core device driver can use the init_pm/request_irq helper to initialize their own power/clk/irq. And the master device doesn't need use these helper anymore. Signed-off-by: Irui Wang --- drivers/media/platform/mtk-vcodec/Makefile | 1 + .../platform/mtk-vcodec/mtk_vcodec_drv.h | 22 ++ .../platform/mtk-vcodec/mtk_vcodec_enc.h | 2 + .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 189 +++++++++++++++--- .../platform/mtk-vcodec/mtk_vcodec_enc_hw.c | 179 +++++++++++++++++ .../platform/mtk-vcodec/mtk_vcodec_enc_hw.h | 36 ++++ 6 files changed, 397 insertions(+), 32 deletions(-) create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile index 4618d43dbbc8..661d4afeb628 100644 --- a/drivers/media/platform/mtk-vcodec/Makefile +++ b/drivers/media/platform/mtk-vcodec/Makefile @@ -20,6 +20,7 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \ mtk_vcodec_enc_pm.o \ venc_drv_if.o \ venc_vpu_if.o \ + mtk_vcodec_enc_hw.o \ mtk-vcodec-common-y := mtk_vcodec_intr.o \ diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h index 3f83710b4fa5..c160b9e505eb 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h @@ -8,6 +8,7 @@ #ifndef _MTK_VCODEC_DRV_H_ #define _MTK_VCODEC_DRV_H_ +#include #include #include #include @@ -92,6 +93,20 @@ enum mtk_fmt_type { MTK_FMT_FRAME = 2, }; +enum mtk_venc_hw_id { + MTK_VENC_CORE0 = 0, + MTK_VENC_CORE1 = 1, + MTK_VENC_HW_MAX, +}; + +/** + * enmu mtk_venc_hw_mode - Used to indicate different encode mode + */ +enum mtk_venc_hw_mode { + VENC_SINGLE_CORE_MODE = 0, + VENC_FRAME_RACING_MODE = 1, +}; + /* * struct mtk_video_fmt - Structure used to store information about pixelformats */ @@ -320,6 +335,7 @@ enum mtk_chip { * @output_formats: array of supported output formats * @num_output_formats: number of entries in output_formats * @core_id: stand for h264 or vp8 encode index + * @hw_mode: indicate encode mode */ struct mtk_vcodec_enc_pdata { enum mtk_chip chip; @@ -332,6 +348,7 @@ struct mtk_vcodec_enc_pdata { const struct mtk_video_fmt *output_formats; size_t num_output_formats; int core_id; + enum mtk_venc_hw_mode hw_mode; }; #define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext) @@ -372,6 +389,8 @@ struct mtk_vcodec_enc_pdata { * @pm: power management control * @dec_capability: used to identify decode capability, ex: 4k * @enc_capability: used to identify encode capability + * @enc_comp_node: used to store venc component node + * @enc_comp_dev: used to store venc component device */ struct mtk_vcodec_dev { struct v4l2_device v4l2_dev; @@ -407,6 +426,9 @@ struct mtk_vcodec_dev { struct mtk_vcodec_pm pm; unsigned int dec_capability; unsigned int enc_capability; + + struct device_node *enc_comp_node[MTK_VENC_HW_MAX]; + void *enc_comp_dev[MTK_VENC_HW_MAX]; }; static inline struct mtk_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h index 513ee7993e34..30b6d7f22ed7 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h @@ -21,6 +21,8 @@ #define MTK_VENC_IRQ_STATUS_OFFSET 0x05C #define MTK_VENC_IRQ_ACK_OFFSET 0x060 +extern struct platform_driver mtk_venc_comp_driver; + /** * struct mtk_video_enc_buf - Private data related to each VB2 buffer. * @m2m_buf: M2M buffer diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index 7b3e0ea4c410..f7538d4b5cbb 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -26,6 +26,81 @@ module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR); module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR); +static const struct of_device_id mtk_venc_comp_ids[] = { + { + .compatible = "mediatek,mtk-venc-core0", + .data = (void *)MTK_VENC_CORE0, + }, + { + .compatible = "mediatek,mtk-venc-core1", + .data = (void *)MTK_VENC_CORE1, + }, + {}, +}; + +static inline int mtk_venc_compare_of(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +static inline void mtk_venc_release_of(struct device *dev, void *data) +{ + of_node_put(data); +} + +static inline int mtk_venc_bind(struct device *dev) +{ + struct mtk_vcodec_dev *data = dev_get_drvdata(dev); + + return component_bind_all(dev, data); +} + +static inline void mtk_venc_unbind(struct device *dev) +{ + struct mtk_vcodec_dev *data = dev_get_drvdata(dev); + + component_unbind_all(dev, data); +} + +static const struct component_master_ops mtk_venc_ops = { + .bind = mtk_venc_bind, + .unbind = mtk_venc_unbind, +}; + +static struct component_match *mtk_venc_match_add(struct mtk_vcodec_dev *dev) +{ + struct platform_device *pdev = dev->plat_dev; + struct component_match *match = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(mtk_venc_comp_ids); i++) { + enum mtk_venc_hw_id comp_idx; + struct device_node *comp_node; + const struct of_device_id *of_id; + + comp_node = of_find_compatible_node(NULL, NULL, + mtk_venc_comp_ids[i].compatible); + if (!comp_node) + continue; + + of_id = of_match_node(mtk_venc_comp_ids, comp_node); + if (!of_id) { + dev_err(&pdev->dev, "Failed to get match node\n"); + return ERR_PTR(-EINVAL); + } + + comp_idx = (enum mtk_venc_hw_id)of_id->data; + dev->enc_comp_node[comp_idx] = comp_node; + + component_match_add_release(&pdev->dev, &match, + mtk_venc_release_of, + mtk_venc_compare_of, + comp_node); + } + + return match; +} + static const struct mtk_video_fmt mtk_video_formats_output[] = { { .fourcc = V4L2_PIX_FMT_NV12M, @@ -239,6 +314,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) phandle rproc_phandle; enum mtk_vcodec_fw_type fw_type; int ret; + struct component_match *match = NULL; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) @@ -264,39 +340,41 @@ static int mtk_vcodec_probe(struct platform_device *pdev) return PTR_ERR(dev->fw_handler); dev->venc_pdata = of_device_get_match_data(&pdev->dev); - ret = mtk_vcodec_init_enc_pm(dev); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to get mtk vcodec clock source!"); - goto err_enc_pm; - } + if (dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) { + ret = mtk_vcodec_init_enc_pm(dev); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get mtk vcodec clock source!"); + goto err_enc_pm; + } - pm_runtime_enable(&pdev->dev); + pm_runtime_enable(&pdev->dev); - dev->reg_base[dev->venc_pdata->core_id] = - devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(dev->reg_base[dev->venc_pdata->core_id])) { - ret = PTR_ERR(dev->reg_base[dev->venc_pdata->core_id]); - goto err_res; - } + dev->reg_base[dev->venc_pdata->core_id] = + devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(dev->reg_base[dev->venc_pdata->core_id])) { + ret = PTR_ERR(dev->reg_base[dev->venc_pdata->core_id]); + goto err_res; + } - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - dev_err(&pdev->dev, "failed to get irq resource"); - ret = -ENOENT; - goto err_res; - } + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get irq resource"); + ret = -ENOENT; + goto err_res; + } - dev->enc_irq = platform_get_irq(pdev, 0); - irq_set_status_flags(dev->enc_irq, IRQ_NOAUTOEN); - ret = devm_request_irq(&pdev->dev, dev->enc_irq, - mtk_vcodec_enc_irq_handler, - 0, pdev->name, dev); - if (ret) { - dev_err(&pdev->dev, - "Failed to install dev->enc_irq %d (%d) core_id (%d)", - dev->enc_irq, ret, dev->venc_pdata->core_id); - ret = -EINVAL; - goto err_res; + dev->enc_irq = platform_get_irq(pdev, 0); + irq_set_status_flags(dev->enc_irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&pdev->dev, dev->enc_irq, + mtk_vcodec_enc_irq_handler, + 0, pdev->name, dev); + if (ret) { + dev_err(&pdev->dev, + "Failed to install dev->enc_irq %d (%d) core_id (%d)", + dev->enc_irq, ret, dev->venc_pdata->core_id); + ret = -EINVAL; + goto err_res; + } } mutex_init(&dev->enc_mutex); @@ -362,6 +440,22 @@ static int mtk_vcodec_probe(struct platform_device *pdev) goto err_enc_reg; } + if (dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + match = mtk_venc_match_add(dev); + if (IS_ERR_OR_NULL(match)) { + mtk_v4l2_err("match venc component failed\n"); + ret = -EINVAL; + goto err_enc_reg; + } + ret = component_master_add_with_match(&pdev->dev, + &mtk_venc_ops, match); + if (ret) { + mtk_v4l2_err("Failed to bring up master"); + ret = -EINVAL; + goto err_enc_reg; + } + } + mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d", dev->venc_pdata->core_id, vfd_enc->num); @@ -376,7 +470,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev) err_enc_alloc: v4l2_device_unregister(&dev->v4l2_dev); err_res: - mtk_vcodec_release_enc_pm(dev); + if (dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) + mtk_vcodec_release_enc_pm(dev); err_enc_pm: mtk_vcodec_fw_release(dev->fw_handler); return ret; @@ -391,6 +486,7 @@ static const struct mtk_vcodec_enc_pdata mt8173_avc_pdata = { .min_bitrate = 1, .max_bitrate = 4000000, .core_id = VENC_SYS, + .hw_mode = VENC_SINGLE_CORE_MODE, }; static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = { @@ -402,6 +498,7 @@ static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = { .min_bitrate = 64, .max_bitrate = 4000000, .core_id = VENC_LT_SYS, + .hw_mode = VENC_SINGLE_CORE_MODE, }; static const struct mtk_vcodec_enc_pdata mt8183_pdata = { @@ -414,6 +511,7 @@ static const struct mtk_vcodec_enc_pdata mt8183_pdata = { .min_bitrate = 64, .max_bitrate = 40000000, .core_id = VENC_SYS, + .hw_mode = VENC_SINGLE_CORE_MODE, }; static const struct mtk_vcodec_enc_pdata mt8192_pdata = { @@ -426,6 +524,7 @@ static const struct mtk_vcodec_enc_pdata mt8192_pdata = { .min_bitrate = 64, .max_bitrate = 100000000, .core_id = VENC_SYS, + .hw_mode = VENC_SINGLE_CORE_MODE, }; static const struct mtk_vcodec_enc_pdata mt8195_pdata = { @@ -438,6 +537,7 @@ static const struct mtk_vcodec_enc_pdata mt8195_pdata = { .min_bitrate = 64, .max_bitrate = 100000000, .core_id = VENC_SYS, + .hw_mode = VENC_FRAME_RACING_MODE, }; static const struct of_device_id mtk_vcodec_enc_match[] = { @@ -466,8 +566,15 @@ static int mtk_vcodec_enc_remove(struct platform_device *pdev) video_unregister_device(dev->vfd_enc); v4l2_device_unregister(&dev->v4l2_dev); - mtk_vcodec_release_enc_pm(dev); + + if (dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) + mtk_vcodec_release_enc_pm(dev); + mtk_vcodec_fw_release(dev->fw_handler); + + if (dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) + component_master_del(&pdev->dev, &mtk_venc_ops); + return 0; } @@ -480,7 +587,25 @@ static struct platform_driver mtk_vcodec_enc_driver = { }, }; -module_platform_driver(mtk_vcodec_enc_driver); +static struct platform_driver * const mtk_venc_drivers[] = { + &mtk_venc_comp_driver, + &mtk_vcodec_enc_driver, +}; + +static int __init mtk_venc_init(void) +{ + return platform_register_drivers(mtk_venc_drivers, + ARRAY_SIZE(mtk_venc_drivers)); +} + +static void __exit mtk_venc_exit(void) +{ + platform_unregister_drivers(mtk_venc_drivers, + ARRAY_SIZE(mtk_venc_drivers)); +} + +module_init(mtk_venc_init); +module_exit(mtk_venc_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c new file mode 100644 index 000000000000..4e6a8a81ff67 --- /dev/null +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + */ + +#include +#include +#include +#include +#include + +#include "mtk_vcodec_enc_hw.h" +#include "mtk_vcodec_enc.h" + +static void clean_irq_status(unsigned int irq_status, void __iomem *addr) +{ + if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE) + writel(MTK_VENC_IRQ_STATUS_PAUSE, addr); + + if (irq_status & MTK_VENC_IRQ_STATUS_SWITCH) + writel(MTK_VENC_IRQ_STATUS_SWITCH, addr); + + if (irq_status & MTK_VENC_IRQ_STATUS_DRAM) + writel(MTK_VENC_IRQ_STATUS_DRAM, addr); + + if (irq_status & MTK_VENC_IRQ_STATUS_SPS) + writel(MTK_VENC_IRQ_STATUS_SPS, addr); + + if (irq_status & MTK_VENC_IRQ_STATUS_PPS) + writel(MTK_VENC_IRQ_STATUS_PPS, addr); + + if (irq_status & MTK_VENC_IRQ_STATUS_FRM) + writel(MTK_VENC_IRQ_STATUS_FRM, addr); +} + +static irqreturn_t mtk_enc_comp_irq_handler(int irq, void *priv) +{ + struct mtk_venc_comp_dev *dev = priv; + struct mtk_vcodec_ctx *ctx; + unsigned long flags; + void __iomem *addr; + + spin_lock_irqsave(&dev->master_dev->irqlock, flags); + ctx = dev->curr_ctx; + spin_unlock_irqrestore(&dev->master_dev->irqlock, flags); + if (!ctx) + return IRQ_HANDLED; + + addr = dev->reg_base + MTK_VENC_IRQ_ACK_OFFSET; + ctx->irq_status = readl(dev->reg_base + MTK_VENC_IRQ_STATUS_OFFSET); + clean_irq_status(ctx->irq_status, addr); + + return IRQ_HANDLED; +} + +static int mtk_venc_comp_bind(struct device *dev, + struct device *master, void *data) +{ + struct mtk_venc_comp_dev *comp_dev = dev_get_drvdata(dev); + struct mtk_vcodec_dev *master_dev = data; + int i; + + for (i = 0; i < MTK_VENC_HW_MAX; i++) { + if (dev->of_node != master_dev->enc_comp_node[i]) + continue; + + /*add component device by order*/ + if (comp_dev->core_id == MTK_VENC_CORE0) + master_dev->enc_comp_dev[MTK_VENC_CORE0] = comp_dev; + else if (comp_dev->core_id == MTK_VENC_CORE1) + master_dev->enc_comp_dev[MTK_VENC_CORE1] = comp_dev; + else + return -EINVAL; + + comp_dev->master_dev = master_dev; + break; + } + + if (i == MTK_VENC_HW_MAX) { + dev_err(dev, "Failed to get component node\n"); + return -EINVAL; + } + + return 0; +} + +static void mtk_venc_comp_unbind(struct device *dev, + struct device *master, void *data) +{ +} + +static const struct component_ops mtk_venc_component_ops = { + .bind = mtk_venc_comp_bind, + .unbind = mtk_venc_comp_unbind, +}; + +static int mtk_venc_comp_probe(struct platform_device *pdev) +{ + struct mtk_venc_comp_dev *comp_dev; + int ret; + + comp_dev = devm_kzalloc(&pdev->dev, sizeof(*comp_dev), GFP_KERNEL); + if (!comp_dev) + return -ENOMEM; + + comp_dev->plat_dev = pdev; + + comp_dev->core_id = + (enum mtk_venc_hw_id)of_device_get_match_data(&pdev->dev); + + comp_dev->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(comp_dev->reg_base)) { + dev_err(&pdev->dev, "Failed to get reg base"); + ret = PTR_ERR(comp_dev->reg_base); + goto err; + } + + comp_dev->enc_irq = platform_get_irq(pdev, 0); + if (comp_dev->enc_irq < 0) { + dev_err(&pdev->dev, "Failed to get irq resource"); + ret = comp_dev->enc_irq; + goto err; + } + + ret = devm_request_irq(&pdev->dev, comp_dev->enc_irq, + mtk_enc_comp_irq_handler, 0, + pdev->name, comp_dev); + if (ret) { + dev_err(&pdev->dev, + "Failed to install comp_dev->enc_irq %d (%d)", + comp_dev->enc_irq, ret); + ret = -EINVAL; + goto err; + } + + if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL)) + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34)); + + platform_set_drvdata(pdev, comp_dev); + + ret = component_add(&pdev->dev, &mtk_venc_component_ops); + if (ret) { + dev_err(&pdev->dev, "Failed to add component: %d\n", ret); + goto err; + } + + return 0; +err: + return ret; +} + +static int mtk_venc_comp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &mtk_venc_component_ops); + return 0; +} + +static const struct of_device_id mtk_venc_comp_ids[] = { + { + .compatible = "mediatek,mtk-venc-core0", + .data = (void *)MTK_VENC_CORE0, + }, + { + .compatible = "mediatek,mtk-venc-core1", + .data = (void *)MTK_VENC_CORE1, + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, mtk_venc_comp_ids); + +struct platform_driver mtk_venc_comp_driver = { + .probe = mtk_venc_comp_probe, + .remove = mtk_venc_comp_remove, + .driver = { + .name = "mtk-venc-comp", + .of_match_table = mtk_venc_comp_ids, + }, +}; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h new file mode 100644 index 000000000000..f9ae97e252dc --- /dev/null +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 MediaTek Inc. + */ + +#ifndef _MTK_VCODEC_ENC_HW_H_ +#define _MTK_VCODEC_ENC_HW_H_ + +#include +#include "mtk_vcodec_drv.h" + +/* + * struct mtk_venc_comp_dev - driver data + * @plat_dev: platform_device + * @master_dev: master device + * @pm: power management data + * @curr_ctx: the context that is waiting for venc hardware + * @reg_base: mapped address of venc registers + * @irq_status: venc hw irq status + * @enc_irq: venc device irq + * @core id: for venc core id: core#0, core#1... + */ +struct mtk_venc_comp_dev { + struct platform_device *plat_dev; + struct mtk_vcodec_dev *master_dev; + + struct mtk_vcodec_pm pm; + struct mtk_vcodec_ctx *curr_ctx; + + void __iomem *reg_base; + unsigned int irq_status; + int enc_irq; + int core_id; +}; + +#endif /* _MTK_VCODEC_ENC_HW_H_ */ From patchwork Mon Aug 16 10:59:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438229 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E15EDC4338F for ; Mon, 16 Aug 2021 11:00:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BD01C611C4 for ; Mon, 16 Aug 2021 11:00:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236138AbhHPLBI (ORCPT ); Mon, 16 Aug 2021 07:01:08 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:53198 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S236032AbhHPLBE (ORCPT ); Mon, 16 Aug 2021 07:01:04 -0400 X-UUID: 1967078d2e28441aad6b1e1da8d0cb6f-20210816 X-UUID: 1967078d2e28441aad6b1e1da8d0cb6f-20210816 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1880302440; Mon, 16 Aug 2021 19:00:29 +0800 Received: from mtkmbs10n2.mediatek.inc (172.21.101.183) by mtkmbs06n1.mediatek.inc (172.21.101.129) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:27 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs10n2.mediatek.inc (172.21.101.183) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 16 Aug 2021 19:00:27 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:26 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , "Tiffany Lin" , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 3/9] media: mtk-vcodec: Rewrite venc power manage interface Date: Mon, 16 Aug 2021 18:59:28 +0800 Message-ID: <20210816105934.28265-4-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The args "struct mtk_vcodec_dev *" doesn't appropriate for init/release_enc_pm functions because of component devices. For master device, it has no "pm/clk" properties in dtsi, component devices will init their own "pm/clk" instead. So rewrite the pm interface with args "platform_device *" and "mtk_vcodec_pm*". Signed-off-by: Irui Wang --- .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 6 ++-- .../platform/mtk-vcodec/mtk_vcodec_enc_hw.c | 13 ++++++++ .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 31 +++++++------------ .../platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 5 +-- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index f7538d4b5cbb..9c2224b199d0 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -341,7 +341,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) dev->venc_pdata = of_device_get_match_data(&pdev->dev); if (dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) { - ret = mtk_vcodec_init_enc_pm(dev); + ret = mtk_vcodec_init_enc_pm(dev->plat_dev, &dev->pm); if (ret < 0) { dev_err(&pdev->dev, "Failed to get mtk vcodec clock source!"); goto err_enc_pm; @@ -471,7 +471,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) v4l2_device_unregister(&dev->v4l2_dev); err_res: if (dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) - mtk_vcodec_release_enc_pm(dev); + mtk_vcodec_release_enc_pm(&dev->pm); err_enc_pm: mtk_vcodec_fw_release(dev->fw_handler); return ret; @@ -568,7 +568,7 @@ static int mtk_vcodec_enc_remove(struct platform_device *pdev) v4l2_device_unregister(&dev->v4l2_dev); if (dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) - mtk_vcodec_release_enc_pm(dev); + mtk_vcodec_release_enc_pm(&dev->pm); mtk_vcodec_fw_release(dev->fw_handler); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c index 4e6a8a81ff67..2a9112b0561d 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c @@ -10,6 +10,7 @@ #include #include "mtk_vcodec_enc_hw.h" +#include "mtk_vcodec_enc_pm.h" #include "mtk_vcodec_enc.h" static void clean_irq_status(unsigned int irq_status, void __iomem *addr) @@ -105,6 +106,14 @@ static int mtk_venc_comp_probe(struct platform_device *pdev) comp_dev->plat_dev = pdev; + ret = mtk_vcodec_init_enc_pm(pdev, &comp_dev->pm); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get venc component clock source!"); + return ret; + } + + pm_runtime_enable(&pdev->dev); + comp_dev->core_id = (enum mtk_venc_hw_id)of_device_get_match_data(&pdev->dev); @@ -146,11 +155,15 @@ static int mtk_venc_comp_probe(struct platform_device *pdev) return 0; err: + mtk_vcodec_release_enc_pm(&comp_dev->pm); return ret; } static int mtk_venc_comp_remove(struct platform_device *pdev) { + struct mtk_venc_comp_dev *comp_dev = platform_get_drvdata(pdev); + + mtk_vcodec_release_enc_pm(&comp_dev->pm); component_del(&pdev->dev, &mtk_venc_component_ops); return 0; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c index 1b2e4930ed27..5edeb93fca84 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c @@ -13,38 +13,29 @@ #include "mtk_vcodec_enc_pm.h" #include "mtk_vcodec_util.h" -int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev) +int mtk_vcodec_init_enc_pm(struct platform_device *pdev, + struct mtk_vcodec_pm *pm) { struct device_node *node; - struct platform_device *pdev; - struct mtk_vcodec_pm *pm; + struct platform_device *larb_pdev; struct mtk_vcodec_clk *enc_clk; struct mtk_vcodec_clk_info *clk_info; int ret = 0, i = 0; - struct device *dev; - pdev = mtkdev->plat_dev; - pm = &mtkdev->pm; - memset(pm, 0, sizeof(struct mtk_vcodec_pm)); - pm->mtkdev = mtkdev; - pm->dev = &pdev->dev; - dev = &pdev->dev; - enc_clk = &pm->venc_clk; - - node = of_parse_phandle(dev->of_node, "mediatek,larb", 0); + node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0); if (!node) { mtk_v4l2_err("no mediatek,larb found"); return -ENODEV; } - pdev = of_find_device_by_node(node); + larb_pdev = of_find_device_by_node(node); of_node_put(node); - if (!pdev) { + if (!larb_pdev) { mtk_v4l2_err("no mediatek,larb device found"); return -ENODEV; } - pm->larbvenc = &pdev->dev; - pdev = mtkdev->plat_dev; + pm->larbvenc = &larb_pdev->dev; pm->dev = &pdev->dev; + enc_clk = &pm->venc_clk; enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node, "clock-names"); @@ -87,10 +78,10 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev) return ret; } -void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev) +void mtk_vcodec_release_enc_pm(struct mtk_vcodec_pm *pm) { - pm_runtime_disable(mtkdev->pm.dev); - put_device(mtkdev->pm.larbvenc); + pm_runtime_disable(pm->dev); + put_device(pm->larbvenc); } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h index b7ecdfd74823..f4a4aa441185 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h @@ -9,8 +9,9 @@ #include "mtk_vcodec_drv.h" -int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *dev); -void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *dev); +int mtk_vcodec_init_enc_pm(struct platform_device *pdev, + struct mtk_vcodec_pm *pm); +void mtk_vcodec_release_enc_pm(struct mtk_vcodec_pm *pm); void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm); void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm); From patchwork Mon Aug 16 10:59:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438231 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 913B7C432BE for ; Mon, 16 Aug 2021 11:00:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7C14E61BE1 for ; Mon, 16 Aug 2021 11:00:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236096AbhHPLBM (ORCPT ); Mon, 16 Aug 2021 07:01:12 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:41646 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S235938AbhHPLBH (ORCPT ); Mon, 16 Aug 2021 07:01:07 -0400 X-UUID: cbd0c93bfe41465dbc6768a4c3dcd255-20210816 X-UUID: cbd0c93bfe41465dbc6768a4c3dcd255-20210816 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 969808951; Mon, 16 Aug 2021 19:00:31 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs05n2.mediatek.inc (172.21.101.140) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:30 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:29 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , Tiffany Lin , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 4/9] media: mtk-vcodec: Add venc power on/off interface Date: Mon, 16 Aug 2021 18:59:29 +0800 Message-ID: <20210816105934.28265-5-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Frame-racing mode need power on/off all venc available power, pm_runtime_xx helper is not appropriate called directly, add new power on/off interface for it. Signed-off-by: Irui Wang --- .../platform/mtk-vcodec/mtk_vcodec_enc.c | 18 +--- .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 9 +- .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 82 +++++++++++++++++++ .../platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 4 + 4 files changed, 96 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 416f356af363..d22f9c8fd063 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -16,6 +16,7 @@ #include "mtk_vcodec_intr.h" #include "mtk_vcodec_util.h" #include "venc_drv_if.h" +#include "mtk_vcodec_enc_pm.h" #define MTK_VENC_MIN_W 160U #define MTK_VENC_MIN_H 128U @@ -801,7 +802,7 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) */ if ((ctx->state == MTK_STATE_ABORT) || (ctx->state == MTK_STATE_FREE)) { ret = -EIO; - goto err_start_stream; + goto err_set_param; } /* Do the initialization when both start_streaming have been called */ @@ -813,12 +814,6 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) return 0; } - ret = pm_runtime_resume_and_get(&ctx->dev->plat_dev->dev); - if (ret < 0) { - mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret); - goto err_start_stream; - } - mtk_venc_set_param(ctx, ¶m); ret = venc_if_set_param(ctx, VENC_SET_PARAM_ENC, ¶m); if (ret) { @@ -845,11 +840,6 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) return 0; err_set_param: - ret = pm_runtime_put(&ctx->dev->plat_dev->dev); - if (ret < 0) - mtk_v4l2_err("pm_runtime_put fail %d", ret); - -err_start_stream: for (i = 0; i < q->num_buffers; ++i) { struct vb2_buffer *buf = vb2_get_buffer(q, i); @@ -903,10 +893,6 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q) if (ret) mtk_v4l2_err("venc_if_deinit failed=%d", ret); - ret = pm_runtime_put(&ctx->dev->plat_dev->dev); - if (ret < 0) - mtk_v4l2_err("pm_runtime_put fail %d", ret); - ctx->state = MTK_STATE_FREE; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index 9c2224b199d0..b78435e8223a 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -253,6 +253,12 @@ static int fops_vcodec_open(struct file *file) mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability); } + ret = mtk_vcodec_enc_power_on(ctx); + if (ret < 0) { + mtk_v4l2_err("encoder power on failed %d", ret); + goto err_load_fw; + } + mtk_v4l2_debug(2, "Create instance [%d]@%p m2m_ctx=%p ", ctx->id, ctx, ctx->m2m_ctx); @@ -285,11 +291,12 @@ static int fops_vcodec_release(struct file *file) mtk_v4l2_debug(1, "[%d] encoder", ctx->id); mutex_lock(&dev->dev_mutex); + v4l2_m2m_ctx_release(ctx->m2m_ctx); mtk_vcodec_enc_release(ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + mtk_vcodec_enc_power_off(ctx); list_del_init(&ctx->list); kfree(ctx); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c index 5edeb93fca84..d9df0e3701f1 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c @@ -12,6 +12,7 @@ #include "mtk_vcodec_enc_pm.h" #include "mtk_vcodec_util.h" +#include "mtk_vcodec_enc_hw.h" int mtk_vcodec_init_enc_pm(struct platform_device *pdev, struct mtk_vcodec_pm *pm) @@ -120,3 +121,84 @@ void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm) for (i = enc_clk->clk_num - 1; i >= 0; i--) clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk); } + +int mtk_venc_enable_comp_hw(struct mtk_vcodec_dev *dev) +{ + int i, ret; + struct mtk_venc_comp_dev *venc_comp; + + /* + * frame_racing mode needs power on all available component devices. + */ + for (i = 0; i < MTK_VENC_HW_MAX; i++) { + venc_comp = (struct mtk_venc_comp_dev *)dev->enc_comp_dev[i]; + if (!venc_comp) + return 0; + + ret = mtk_smi_larb_get(venc_comp->pm.larbvenc); + if (ret < 0) { + mtk_v4l2_err("power on core[%d] fail %d", i, ret); + goto pw_err; + } + } + return 0; + +pw_err: + for (i -= 1; i >= 0; i--) { + venc_comp = (struct mtk_venc_comp_dev *)dev->enc_comp_dev[i]; + + mtk_smi_larb_put(venc_comp->pm.larbvenc); + } + + return ret; +} + +int mtk_venc_disable_comp_hw(struct mtk_vcodec_dev *dev) +{ + int i; + struct mtk_venc_comp_dev *venc_comp; + + /*power off all available component device*/ + for (i = 0; i < MTK_VENC_HW_MAX; i++) { + venc_comp = (struct mtk_venc_comp_dev *)dev->enc_comp_dev[i]; + if (!venc_comp) + return 0; + + mtk_smi_larb_put(venc_comp->pm.larbvenc); + } + + return 0; +} + +int mtk_vcodec_enc_power_on(struct mtk_vcodec_ctx *ctx) +{ + int ret; + struct mtk_vcodec_dev *dev = ctx->dev; + + if (dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + ret = mtk_venc_enable_comp_hw(dev); + if (ret < 0) { + mtk_v4l2_err("enable venc comp hw fail :%d", ret); + return ret; + } + } else { + ret = mtk_smi_larb_get(dev->pm.larbvenc); + if (ret < 0) { + mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret); + return ret; + } + } + return 0; +} + +int mtk_vcodec_enc_power_off(struct mtk_vcodec_ctx *ctx) +{ + struct mtk_vcodec_dev *dev = ctx->dev; + + if (dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) + mtk_venc_disable_comp_hw(dev); + else + mtk_smi_larb_put(dev->pm.larbvenc); + + return 0; +} diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h index f4a4aa441185..2e76b858fed1 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h @@ -16,4 +16,8 @@ void mtk_vcodec_release_enc_pm(struct mtk_vcodec_pm *pm); void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm); void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm); +int mtk_venc_enable_comp_hw(struct mtk_vcodec_dev *dev); +int mtk_venc_disable_comp_hw(struct mtk_vcodec_dev *dev); +int mtk_vcodec_enc_power_on(struct mtk_vcodec_ctx *ctx); +int mtk_vcodec_enc_power_off(struct mtk_vcodec_ctx *ctx); #endif /* _MTK_VCODEC_ENC_PM_H_ */ From patchwork Mon Aug 16 10:59:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438233 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 003D4C4320E for ; Mon, 16 Aug 2021 11:00:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DF0176320E for ; Mon, 16 Aug 2021 11:00:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236140AbhHPLBP (ORCPT ); Mon, 16 Aug 2021 07:01:15 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:53354 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S236222AbhHPLBK (ORCPT ); Mon, 16 Aug 2021 07:01:10 -0400 X-UUID: f5233eb66ed64c1ebc9c4c2b6a271ffd-20210816 X-UUID: f5233eb66ed64c1ebc9c4c2b6a271ffd-20210816 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1983101265; Mon, 16 Aug 2021 19:00:35 +0800 Received: from mtkcas07.mediatek.inc (172.21.101.84) by mtkexhb01.mediatek.inc (172.21.101.102) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:34 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkcas07.mediatek.inc (172.21.101.84) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:33 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:32 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , "Tiffany Lin" , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 5/9] media: mtk-vcodec: Rewrite venc clock interface Date: Mon, 16 Aug 2021 18:59:30 +0800 Message-ID: <20210816105934.28265-6-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Frame-racing mode need enable the specific core's clk, add an another param for clock_on/clock_off interface. Signed-off-by: Irui Wang --- .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 104 ++++++++++++++---- .../platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 4 +- .../media/platform/mtk-vcodec/venc_drv_if.c | 10 +- 3 files changed, 86 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c index d9df0e3701f1..bfb9e21bfd26 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c @@ -86,25 +86,50 @@ void mtk_vcodec_release_enc_pm(struct mtk_vcodec_pm *pm) } -void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm) +void mtk_vcodec_enc_clock_on(struct mtk_vcodec_dev *dev, int core_id) { - struct mtk_vcodec_clk *enc_clk = &pm->venc_clk; - int ret, i = 0; + struct mtk_venc_comp_dev *venc; + struct mtk_vcodec_pm *enc_pm; + struct mtk_vcodec_clk *enc_clk; + struct clk *clk; + int ret, i; - for (i = 0; i < enc_clk->clk_num; i++) { - ret = clk_prepare_enable(enc_clk->clk_info[i].vcodec_clk); - if (ret) { - mtk_v4l2_err("venc clk_prepare_enable %d %s fail %d", i, - enc_clk->clk_info[i].clk_name, ret); - goto clkerr; + if (dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + venc = (struct mtk_venc_comp_dev *)dev->enc_comp_dev[core_id]; + enc_pm = &venc->pm; + enc_clk = &enc_pm->venc_clk; + + for (i = 0; i < enc_clk->clk_num; i++) { + clk = enc_clk->clk_info[i].vcodec_clk; + ret = clk_enable(clk); + if (ret) { + mtk_v4l2_err("clk_enable %d %s fail %d", i, + enc_clk->clk_info[i].clk_name, + ret); + goto comp_clk_err; + } } - } + } else { + enc_pm = &dev->pm; + enc_clk = &enc_pm->venc_clk; - ret = mtk_smi_larb_get(pm->larbvenc); - if (ret) { - mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret); - goto clkerr; + for (i = 0; i < enc_clk->clk_num; i++) { + clk = enc_clk->clk_info[i].vcodec_clk; + ret = clk_prepare_enable(clk); + if (ret) { + mtk_v4l2_err("clk_prepare_enable %d %s fail %d", + i, enc_clk->clk_info[i].clk_name, + ret); + goto clkerr; + } + } } + + return; + +comp_clk_err: + for (i -= 1; i >= 0; i--) + clk_disable(enc_clk->clk_info[i].vcodec_clk); return; clkerr: @@ -112,20 +137,35 @@ void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm) clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk); } -void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm) +void mtk_vcodec_enc_clock_off(struct mtk_vcodec_dev *dev, int core_id) { - struct mtk_vcodec_clk *enc_clk = &pm->venc_clk; - int i = 0; + struct mtk_venc_comp_dev *venc; + struct mtk_vcodec_pm *enc_pm; + struct mtk_vcodec_clk *enc_clk; + int i; - mtk_smi_larb_put(pm->larbvenc); - for (i = enc_clk->clk_num - 1; i >= 0; i--) - clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk); + if (dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + venc = (struct mtk_venc_comp_dev *)dev->enc_comp_dev[core_id]; + enc_pm = &venc->pm; + enc_clk = &enc_pm->venc_clk; + + for (i = enc_clk->clk_num - 1; i >= 0; i--) + clk_disable(enc_clk->clk_info[i].vcodec_clk); + } else { + enc_pm = &dev->pm; + enc_clk = &enc_pm->venc_clk; + + for (i = enc_clk->clk_num - 1; i >= 0; i--) + clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk); + } } int mtk_venc_enable_comp_hw(struct mtk_vcodec_dev *dev) { int i, ret; struct mtk_venc_comp_dev *venc_comp; + struct mtk_vcodec_clk *enc_clk; + int j = 0; /* * frame_racing mode needs power on all available component devices. @@ -140,23 +180,38 @@ int mtk_venc_enable_comp_hw(struct mtk_vcodec_dev *dev) mtk_v4l2_err("power on core[%d] fail %d", i, ret); goto pw_err; } + + enc_clk = &venc_comp->pm.venc_clk; + for (j = 0; j < enc_clk->clk_num; j++) { + ret = clk_prepare(enc_clk->clk_info[j].vcodec_clk); + if (ret) { + mtk_v4l2_err("prepare clk [%s] fail %d", + enc_clk->clk_info[j].clk_name, + ret); + goto pw_err; + } + } } return 0; pw_err: for (i -= 1; i >= 0; i--) { venc_comp = (struct mtk_venc_comp_dev *)dev->enc_comp_dev[i]; + enc_clk = &venc_comp->pm.venc_clk; + + for (j -= 1; j >= 0; j--) + clk_unprepare(enc_clk->clk_info[j].vcodec_clk); mtk_smi_larb_put(venc_comp->pm.larbvenc); } - return ret; } int mtk_venc_disable_comp_hw(struct mtk_vcodec_dev *dev) { - int i; + int i, j; struct mtk_venc_comp_dev *venc_comp; + struct mtk_vcodec_clk *enc_clk; /*power off all available component device*/ for (i = 0; i < MTK_VENC_HW_MAX; i++) { @@ -164,6 +219,11 @@ int mtk_venc_disable_comp_hw(struct mtk_vcodec_dev *dev) if (!venc_comp) return 0; + enc_clk = &venc_comp->pm.venc_clk; + + for (j = enc_clk->clk_num - 1; j >= 0; j--) + clk_unprepare(enc_clk->clk_info[j].vcodec_clk); + mtk_smi_larb_put(venc_comp->pm.larbvenc); } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h index 2e76b858fed1..f3a819cc0e56 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h @@ -13,8 +13,8 @@ int mtk_vcodec_init_enc_pm(struct platform_device *pdev, struct mtk_vcodec_pm *pm); void mtk_vcodec_release_enc_pm(struct mtk_vcodec_pm *pm); -void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm); -void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm); +void mtk_vcodec_enc_clock_on(struct mtk_vcodec_dev *dev, int core_id); +void mtk_vcodec_enc_clock_off(struct mtk_vcodec_dev *dev, int core_id); int mtk_venc_enable_comp_hw(struct mtk_vcodec_dev *dev); int mtk_venc_disable_comp_hw(struct mtk_vcodec_dev *dev); diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/drivers/media/platform/mtk-vcodec/venc_drv_if.c index ce0bce811615..6cbdb7e30bb3 100644 --- a/drivers/media/platform/mtk-vcodec/venc_drv_if.c +++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c @@ -32,9 +32,7 @@ int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) } mtk_venc_lock(ctx); - mtk_vcodec_enc_clock_on(&ctx->dev->pm); ret = ctx->enc_if->init(ctx); - mtk_vcodec_enc_clock_off(&ctx->dev->pm); mtk_venc_unlock(ctx); return ret; @@ -46,9 +44,7 @@ int venc_if_set_param(struct mtk_vcodec_ctx *ctx, int ret = 0; mtk_venc_lock(ctx); - mtk_vcodec_enc_clock_on(&ctx->dev->pm); ret = ctx->enc_if->set_param(ctx->drv_handle, type, in); - mtk_vcodec_enc_clock_off(&ctx->dev->pm); mtk_venc_unlock(ctx); return ret; @@ -68,10 +64,10 @@ int venc_if_encode(struct mtk_vcodec_ctx *ctx, ctx->dev->curr_ctx = ctx; spin_unlock_irqrestore(&ctx->dev->irqlock, flags); - mtk_vcodec_enc_clock_on(&ctx->dev->pm); + mtk_vcodec_enc_clock_on(ctx->dev, 0); ret = ctx->enc_if->encode(ctx->drv_handle, opt, frm_buf, bs_buf, result); - mtk_vcodec_enc_clock_off(&ctx->dev->pm); + mtk_vcodec_enc_clock_off(ctx->dev, 0); spin_lock_irqsave(&ctx->dev->irqlock, flags); ctx->dev->curr_ctx = NULL; @@ -89,9 +85,7 @@ int venc_if_deinit(struct mtk_vcodec_ctx *ctx) return 0; mtk_venc_lock(ctx); - mtk_vcodec_enc_clock_on(&ctx->dev->pm); ret = ctx->enc_if->deinit(ctx->drv_handle); - mtk_vcodec_enc_clock_off(&ctx->dev->pm); mtk_venc_unlock(ctx); ctx->drv_handle = NULL; From patchwork Mon Aug 16 10:59:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438235 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CD8AC432BE for ; Mon, 16 Aug 2021 11:00:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0815661BE1 for ; Mon, 16 Aug 2021 11:00:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236222AbhHPLBU (ORCPT ); Mon, 16 Aug 2021 07:01:20 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:53432 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S236188AbhHPLBN (ORCPT ); Mon, 16 Aug 2021 07:01:13 -0400 X-UUID: eac94a34b5254d8185808eeca63fb589-20210816 X-UUID: eac94a34b5254d8185808eeca63fb589-20210816 Received: from mtkexhb02.mediatek.inc [(172.21.101.103)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 391395510; Mon, 16 Aug 2021 19:00:38 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:36 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:35 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , Tiffany Lin , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 6/9] media: mtk-vcodec: Add new venc drv interface for frame_racing mode Date: Mon, 16 Aug 2021 18:59:31 +0800 Message-ID: <20210816105934.28265-7-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Frame-racing mode encoding need more venc working buffers, it will break the compatibility if we just add venc_vsi in AP-Kernel but not in firmware, so add a new venc driver interface to distinguish the sigle_core_mode and frame_racing mode. The new driver interface can be used for different codecs in the future. Signed-off-by: Irui Wang --- drivers/media/platform/mtk-vcodec/Makefile | 1 + .../platform/mtk-vcodec/mtk_vcodec_drv.h | 1 + .../platform/mtk-vcodec/mtk_vcodec_util.c | 19 + .../platform/mtk-vcodec/mtk_vcodec_util.h | 4 + .../platform/mtk-vcodec/venc/venc_common_if.c | 629 ++++++++++++++++++ .../media/platform/mtk-vcodec/venc_drv_if.c | 5 +- .../media/platform/mtk-vcodec/venc_drv_if.h | 1 + 7 files changed, 659 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_common_if.c diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile index 661d4afeb628..a42ce704bf04 100644 --- a/drivers/media/platform/mtk-vcodec/Makefile +++ b/drivers/media/platform/mtk-vcodec/Makefile @@ -15,6 +15,7 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \ mtk-vcodec-enc-y := venc/venc_vp8_if.o \ venc/venc_h264_if.o \ + venc/venc_common_if.o \ mtk_vcodec_enc.o \ mtk_vcodec_enc_drv.o \ mtk_vcodec_enc_pm.o \ diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h index c160b9e505eb..1c6c1eca649f 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h @@ -352,6 +352,7 @@ struct mtk_vcodec_enc_pdata { }; #define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext) +#define MTK_ENC_HW_MODE(ctx) ((ctx)->dev->venc_pdata->hw_mode) /** * struct mtk_vcodec_dev - driver data diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c index ac5973b6735f..5057e2cba627 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c @@ -9,6 +9,7 @@ #include "mtk_vcodec_drv.h" #include "mtk_vcodec_util.h" +#include "mtk_vcodec_enc_hw.h" /* For encoder, this will enable logs in venc/*/ bool mtk_vcodec_dbg; @@ -33,6 +34,24 @@ void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data, } EXPORT_SYMBOL(mtk_vcodec_get_reg_addr); +void __iomem *mtk_get_venc_comp_reg_addr(struct mtk_vcodec_ctx *data, + unsigned int hw_id) +{ + struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data; + struct mtk_venc_comp_dev *venc; + + if (!data || hw_id >= MTK_VENC_HW_MAX) { + mtk_v4l2_err("Invalid arguments, hw_id=%d", hw_id); + return NULL; + } + venc = (struct mtk_venc_comp_dev *)ctx->dev->enc_comp_dev[hw_id]; + if (!venc) + return NULL; + + return venc->reg_base; +} +EXPORT_SYMBOL(mtk_get_venc_comp_reg_addr); + int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data, struct mtk_vcodec_mem *mem) { diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h index b999d7b84ed1..0027747c0a27 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h @@ -75,6 +75,10 @@ extern bool mtk_vcodec_dbg; void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data, unsigned int reg_idx); + +void __iomem *mtk_get_venc_comp_reg_addr(struct mtk_vcodec_ctx *data, + unsigned int hw_id); + int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data, struct mtk_vcodec_mem *mem); void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data, diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c new file mode 100644 index 000000000000..01b7d93241af --- /dev/null +++ b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + */ + +#include "../venc_vpu_if.h" +#include "../venc_drv_base.h" +#include "../mtk_vcodec_intr.h" +#include "../mtk_vcodec_enc.h" +#include "../mtk_vcodec_drv.h" +#include "../mtk_vcodec_util.h" +#include "../mtk_vcodec_enc_hw.h" + +static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc}; + +#define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker) +#define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098 + +enum venc_vpu_work_buf { + VENC_VPU_WORK_BUF_RC_INFO_CORE0, + VENC_VPU_WORK_BUF_RC_INFO_CORE1, + VENC_VPU_WORK_BUF_FR_RC_INFO, + VENC_VPU_WORK_BUF_RC_CODE, + VENC_VPU_WORK_BUF_REC_LUMA, + VENC_VPU_WORK_BUF_REC_CHROMA, + VENC_VPU_WORK_BUF_REF_LUMA, + VENC_VPU_WORK_BUF_REF_CHROMA, + VENC_VPU_WORK_BUF_MV_INFO_1, + VENC_VPU_WORK_BUF_MV_INFO_2, + VENC_VPU_WORK_BUF_SKIP_FRAME, + VENC_VPU_WORK_BUF_MAX, +}; + +enum venc_frame_type { + VENC_IDR_FRM, + VENC_I_FRM, + VENC_P_FRM, + VENC_B_FRM, +}; + +enum venc_bs_mode { + VENC_BS_MODE_SPS, + VENC_BS_MODE_PPS, + VENC_BS_MODE_FRAME, +}; + +struct venc_vpu_buf { + u32 iova; + u32 vpua; + u32 size; +}; + +struct venc_vpu_config { + u32 input_fourcc; + u32 bitrate; + u32 pic_w; + u32 pic_h; + u32 buf_w; + u32 buf_h; + u32 gop_size; + u32 intra_period; + u32 framerate; + u32 profile; + u32 level; + u32 wfd; + u32 max_qp; + u32 min_qp; + u32 reserved[8]; +}; + +struct venc_vsi { + struct venc_vpu_config config; + struct venc_vpu_buf work_bufs[VENC_VPU_WORK_BUF_MAX]; +}; + +struct venc_common_inst { + void __iomem *hw_base[MTK_VENC_HW_MAX]; + struct mtk_vcodec_mem work_bufs[VENC_VPU_WORK_BUF_MAX]; + struct mtk_vcodec_mem pps_buf; + bool work_buf_allocated; + unsigned int frm_cnt; + unsigned int skip_frm_cnt; + unsigned int prepend_hdr; + struct venc_vpu_inst vpu_inst; + struct venc_vsi *vsi; + struct mtk_vcodec_ctx *ctx; +}; + +static inline u32 venc_read_reg(struct venc_common_inst *inst, + u32 addr, int hw_id) +{ + return readl(inst->hw_base[hw_id] + addr); +} + +static unsigned int h264_get_profile(struct venc_common_inst *inst, + unsigned int profile) +{ + switch (profile) { + case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: + return 66; + case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: + return 77; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: + return 100; + case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: + mtk_vcodec_err(inst, "unsupported CONSTRAINED_BASELINE"); + return 0; + case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED: + mtk_vcodec_err(inst, "unsupported EXTENDED"); + return 0; + default: + mtk_vcodec_debug(inst, "unsupported profile %d", profile); + return 100; + } +} + +static unsigned int h264_get_level(struct venc_common_inst *inst, + unsigned int level) +{ + switch (level) { + case V4L2_MPEG_VIDEO_H264_LEVEL_1B: + mtk_vcodec_err(inst, "unsupported 1B"); + return 0; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: + return 10; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: + return 11; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: + return 12; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: + return 13; + case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: + return 20; + case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: + return 21; + case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: + return 22; + case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: + return 30; + case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: + return 31; + case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: + return 32; + case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: + return 40; + case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: + return 41; + case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: + return 42; + case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: + return 50; + case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: + return 51; + default: + mtk_vcodec_debug(inst, "unsupported level %d", level); + return 31; + } +} + +static void venc_free_work_buf(struct venc_common_inst *inst) +{ + int i; + + mtk_vcodec_debug_enter(inst); + + for (i = 0; i < VENC_VPU_WORK_BUF_MAX; i++) { + if (i != VENC_VPU_WORK_BUF_SKIP_FRAME) + mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]); + } + + mtk_vcodec_mem_free(inst->ctx, &inst->pps_buf); + + mtk_vcodec_debug_leave(inst); +} + +static int venc_alloc_work_buf(struct venc_common_inst *inst) +{ + int i; + int ret = 0; + struct venc_vpu_buf *wb = inst->vsi->work_bufs; + + mtk_vcodec_debug_enter(inst); + + for (i = 0; i < VENC_VPU_WORK_BUF_MAX; i++) { + /* + * This 'wb' structure is set by VPU side and shared to AP for + * buffer allocation and IO virtual addr mapping. For most of + * the buffers, AP will allocate the buffer according to 'size' + * field and store the IO virtual addr in 'iova' field. There + * are two exceptions: + * (1) RC_CODE buffer, it's pre-allocated in the VPU side, and + * save the VPU addr in the 'vpua' field. The AP will translate + * the VPU addr to the corresponding IO virtual addr and store + * in 'iova' field for reg setting in VPU side. + * (2) SKIP_FRAME buffer, it's pre-allocated in the VPU side, + * and save the VPU addr in the 'vpua' field. The AP will + * translate the VPU addr to the corresponding AP side virtual + * address and do some memcpy access to move to bitstream buffer + * assigned by v4l2 layer. + */ + inst->work_bufs[i].size = wb[i].size; + if (i == VENC_VPU_WORK_BUF_SKIP_FRAME) { + struct mtk_vcodec_fw *handler; + + handler = inst->vpu_inst.ctx->dev->fw_handler; + inst->work_bufs[i].va = + mtk_vcodec_fw_map_dm_addr(handler, wb[i].vpua); + inst->work_bufs[i].dma_addr = 0; + } else { + ret = mtk_vcodec_mem_alloc(inst->ctx, + &inst->work_bufs[i]); + if (ret) { + mtk_vcodec_err(inst, + "cannot allocate buf %d", i); + goto err_alloc; + } + /* + * This RC_CODE is pre-allocated by VPU and saved in VPU + * addr. So we need use memcpy to copy RC_CODE from VPU + * addr into IO virtual addr in 'iova' field for reg + * setting in VPU side. + */ + if (i == VENC_VPU_WORK_BUF_RC_CODE) { + struct mtk_vcodec_fw *handler; + void *tmp_va; + + handler = inst->vpu_inst.ctx->dev->fw_handler; + tmp_va = mtk_vcodec_fw_map_dm_addr(handler, + wb[i].vpua); + memcpy(inst->work_bufs[i].va, tmp_va, + wb[i].size); + } + } + wb[i].iova = inst->work_bufs[i].dma_addr; + + mtk_vcodec_debug(inst, + "work_buf[%d] va=0x%p iova=%pad size=%zu", + i, inst->work_bufs[i].va, + &inst->work_bufs[i].dma_addr, + inst->work_bufs[i].size); + } + + /* the pps_buf is used by AP side only */ + inst->pps_buf.size = 128; + ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->pps_buf); + if (ret) { + mtk_vcodec_err(inst, "cannot allocate pps_buf"); + goto err_alloc; + } + + mtk_vcodec_debug_leave(inst); + + return ret; + +err_alloc: + venc_free_work_buf(inst); + + return ret; +} + +static unsigned int venc_wait_comp_done(struct venc_common_inst *inst, + unsigned int hw_id) +{ + unsigned int irq_status = 0; + struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)inst->ctx; + + if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS)) { + irq_status = ctx->irq_status; + mtk_vcodec_debug(inst, "irq_status %x <-", irq_status); + } + return irq_status; +} + +static int venc_frame_type(struct venc_common_inst *inst) +{ + if ((inst->vsi->config.gop_size != 0 && + (inst->frm_cnt % inst->vsi->config.gop_size) == 0) || + (inst->frm_cnt == 0 && inst->vsi->config.gop_size == 0)) { + /* IDR frame */ + return VENC_IDR_FRM; + } else if ((inst->vsi->config.intra_period != 0 && + (inst->frm_cnt % inst->vsi->config.intra_period) == 0) || + (inst->frm_cnt == 0 && + inst->vsi->config.intra_period == 0)) { + /* I frame */ + return VENC_I_FRM; + } else { + return VENC_P_FRM; /* Note: B frames are not supported */ + } +} + +static int venc_encode_sps(struct venc_common_inst *inst, + struct mtk_vcodec_mem *bs_buf, + unsigned int *bs_size) +{ + int ret = 0; + unsigned int irq_status; + + mtk_vcodec_debug_enter(inst); + + ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_SPS, NULL, + bs_buf, bs_size, NULL); + if (ret) + return ret; + + irq_status = venc_wait_comp_done(inst, MTK_VENC_CORE0); + if (irq_status != MTK_VENC_IRQ_STATUS_SPS) { + mtk_vcodec_err(inst, "expect irq status %d", + MTK_VENC_IRQ_STATUS_SPS); + return -EINVAL; + } + + *bs_size = venc_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT, + MTK_VENC_CORE0); + mtk_vcodec_debug(inst, "bs size %d <-", *bs_size); + + return ret; +} + +static int venc_encode_pps(struct venc_common_inst *inst, + struct mtk_vcodec_mem *bs_buf, + unsigned int *bs_size) +{ + int ret = 0; + unsigned int irq_status; + + mtk_vcodec_debug_enter(inst); + + ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_PPS, NULL, + bs_buf, bs_size, NULL); + if (ret) + return ret; + + irq_status = venc_wait_comp_done(inst, MTK_VENC_CORE0); + if (irq_status != MTK_VENC_IRQ_STATUS_PPS) { + mtk_vcodec_err(inst, "expect irq status %d", + MTK_VENC_IRQ_STATUS_PPS); + return -EINVAL; + } + + *bs_size = venc_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT, + MTK_VENC_CORE0); + mtk_vcodec_debug(inst, "bs size %d <-", *bs_size); + + return ret; +} + +static int venc_encode_header(struct venc_common_inst *inst, + struct mtk_vcodec_mem *bs_buf, + unsigned int *bs_size) +{ + int ret = 0; + unsigned int bs_size_sps; + unsigned int bs_size_pps; + + ret = venc_encode_sps(inst, bs_buf, &bs_size_sps); + if (ret) + return ret; + + ret = venc_encode_pps(inst, &inst->pps_buf, &bs_size_pps); + if (ret) + return ret; + + memcpy(bs_buf->va + bs_size_sps, inst->pps_buf.va, bs_size_pps); + *bs_size = bs_size_sps + bs_size_pps; + + return ret; +} + +static int venc_encode_frame(struct venc_common_inst *inst, + struct venc_frm_buf *frm_buf, + struct mtk_vcodec_mem *bs_buf, + unsigned int *bs_size, + int hw_id) +{ + int ret = 0; + struct venc_frame_info frame_info; + + mtk_vcodec_debug_enter(inst); + mtk_vcodec_debug(inst, "frm_cnt = %d\n ", inst->frm_cnt); + frame_info.frm_count = inst->frm_cnt; + frame_info.skip_frm_count = inst->skip_frm_cnt; + frame_info.frm_type = venc_frame_type(inst); + mtk_vcodec_debug(inst, "frm_count = %d,skip_frm_count =%d,frm_type=%d.\n", + frame_info.frm_count, frame_info.skip_frm_count, + frame_info.frm_type); + ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_FRAME, frm_buf, + bs_buf, bs_size, &frame_info); + if (ret) + return ret; + + ++inst->frm_cnt; + mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-", + inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm); + + return ret; +} + +static void h264_encode_filler(struct venc_common_inst *inst, void *buf, + int size) +{ + unsigned char *p = buf; + + if (size < H264_FILLER_MARKER_SIZE) { + mtk_vcodec_err(inst, "filler size too small %d", size); + return; + } + + memcpy(p, h264_filler_marker, ARRAY_SIZE(h264_filler_marker)); + size -= H264_FILLER_MARKER_SIZE; + p += H264_FILLER_MARKER_SIZE; + memset(p, 0xff, size); +} + +static int venc_init(struct mtk_vcodec_ctx *ctx) +{ + int i; + int ret = 0; + struct venc_common_inst *inst; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + inst->vpu_inst.ctx = ctx; + inst->vpu_inst.id = SCP_IPI_VENC_H264; + + mtk_vcodec_debug_enter(inst); + + ret = vpu_enc_init(&inst->vpu_inst); + + inst->vsi = (struct venc_vsi *)inst->vpu_inst.vsi; + + for (i = 0; i < MTK_VENC_HW_MAX; i++) + inst->hw_base[i] = mtk_get_venc_comp_reg_addr(ctx, i); + + mtk_vcodec_debug_leave(inst); + + if (ret) + kfree(inst); + else + ctx->drv_handle = inst; + + return ret; +} + +static int venc_encode(void *handle, + enum venc_start_opt opt, + struct venc_frm_buf *frm_buf, + struct mtk_vcodec_mem *bs_buf, + struct venc_done_result *result) +{ + int ret; + struct venc_common_inst *inst = (struct venc_common_inst *)handle; + struct mtk_vcodec_ctx *ctx = inst->ctx; + + switch (opt) { + case VENC_START_OPT_ENCODE_SEQUENCE_HEADER: { + unsigned int bs_size_hdr; + + ret = venc_encode_header(inst, bs_buf, &bs_size_hdr); + if (ret) { + mtk_vcodec_err(inst, "encode header failed: %d", ret); + return ret; + } + + result->bs_size = bs_size_hdr; + result->is_key_frm = false; + + break; + } + + case VENC_START_OPT_ENCODE_FRAME: { + int hdr_sz; + int hdr_sz_ext; + int filler_sz = 0; + const int bs_align = 128; + struct mtk_vcodec_mem tmp_bs_buf; + unsigned int bs_size_hdr; + unsigned int bs_size_frm; + + if (!inst->prepend_hdr) { + ret = venc_encode_frame(inst, frm_buf, bs_buf, + &result->bs_size, ctx->hw_id); + if (ret) { + mtk_vcodec_err(inst, "encode frame failed: %d", + ret); + return ret; + } + + result->is_key_frm = inst->vpu_inst.is_key_frm; + break; + } + + mtk_vcodec_debug(inst, "venc_encode_frame prepend SPS/PPS"); + + ret = venc_encode_header(inst, bs_buf, &bs_size_hdr); + if (ret) { + mtk_vcodec_err(inst, "encode prepend hdr failed: %d", + ret); + return ret; + } + + hdr_sz = bs_size_hdr; + hdr_sz_ext = (hdr_sz & (bs_align - 1)); + if (hdr_sz_ext) { + filler_sz = bs_align - hdr_sz_ext; + if (hdr_sz_ext + H264_FILLER_MARKER_SIZE > bs_align) + filler_sz += bs_align; + h264_encode_filler(inst, bs_buf->va + hdr_sz, + filler_sz); + } + + tmp_bs_buf.va = bs_buf->va + hdr_sz + filler_sz; + tmp_bs_buf.dma_addr = bs_buf->dma_addr + hdr_sz + filler_sz; + tmp_bs_buf.size = bs_buf->size - (hdr_sz + filler_sz); + + ret = venc_encode_frame(inst, frm_buf, &tmp_bs_buf, + &bs_size_frm, ctx->hw_id); + + if (ret) { + mtk_vcodec_err(inst, "encode hdr frame failed: %d", + ret); + return ret; + } + + result->bs_size = hdr_sz + filler_sz + bs_size_frm; + + mtk_vcodec_debug(inst, "hdr %d filler %d frame %d bs %d", + hdr_sz, filler_sz, bs_size_frm, + result->bs_size); + + inst->prepend_hdr = 0; + result->is_key_frm = inst->vpu_inst.is_key_frm; + break; + } + + default: + mtk_vcodec_err(inst, "venc_start_opt %d not supported", opt); + return -EINVAL; + } + + return ret; +} + +static int venc_set_param(void *handle, + enum venc_set_param_type type, + struct venc_enc_param *enc_prm) +{ + int ret = 0; + struct venc_common_inst *inst = (struct venc_common_inst *)handle; + + mtk_vcodec_debug(inst, "->type=%d", type); + + switch (type) { + case VENC_SET_PARAM_ENC: + inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt; + inst->vsi->config.bitrate = enc_prm->bitrate; + inst->vsi->config.pic_w = enc_prm->width; + inst->vsi->config.pic_h = enc_prm->height; + inst->vsi->config.buf_w = enc_prm->buf_width; + inst->vsi->config.buf_h = enc_prm->buf_height; + inst->vsi->config.gop_size = enc_prm->gop_size; + inst->vsi->config.framerate = enc_prm->frm_rate; + inst->vsi->config.intra_period = enc_prm->intra_period; + inst->vsi->config.profile = + h264_get_profile(inst, enc_prm->h264_profile); + inst->vsi->config.level = + h264_get_level(inst, enc_prm->h264_level); + inst->vsi->config.wfd = 0; + + ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm); + if (ret) + break; + if (inst->work_buf_allocated) { + venc_free_work_buf(inst); + inst->work_buf_allocated = false; + } + ret = venc_alloc_work_buf(inst); + if (ret) + break; + inst->work_buf_allocated = true; + break; + + case VENC_SET_PARAM_PREPEND_HEADER: + inst->prepend_hdr = 1; + mtk_vcodec_debug(inst, "set prepend header mode"); + break; + case VENC_SET_PARAM_FORCE_INTRA: + case VENC_SET_PARAM_GOP_SIZE: + case VENC_SET_PARAM_INTRA_PERIOD: + inst->frm_cnt = 0; + inst->skip_frm_cnt = 0; + fallthrough; + default: + ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm); + break; + } + + mtk_vcodec_debug_leave(inst); + return ret; +} + +static int venc_deinit(void *handle) +{ + int ret = 0; + struct venc_common_inst *inst = (struct venc_common_inst *)handle; + + mtk_vcodec_debug_enter(inst); + + ret = vpu_enc_deinit(&inst->vpu_inst); + + if (inst->work_buf_allocated) + venc_free_work_buf(inst); + + mtk_vcodec_debug_leave(inst); + kfree(inst); + + return ret; +} + +const struct venc_common_if venc_if = { + .init = venc_init, + .encode = venc_encode, + .set_param = venc_set_param, + .deinit = venc_deinit, +}; diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/drivers/media/platform/mtk-vcodec/venc_drv_if.c index 6cbdb7e30bb3..93936d002bed 100644 --- a/drivers/media/platform/mtk-vcodec/venc_drv_if.c +++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c @@ -25,7 +25,10 @@ int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) ctx->enc_if = &venc_vp8_if; break; case V4L2_PIX_FMT_H264: - ctx->enc_if = &venc_h264_if; + if (MTK_ENC_HW_MODE(ctx) == VENC_FRAME_RACING_MODE) + ctx->enc_if = &venc_if; + else + ctx->enc_if = &venc_h264_if; break; default: return -EINVAL; diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/drivers/media/platform/mtk-vcodec/venc_drv_if.h index 0b04a1020873..8f384ba24ddf 100644 --- a/drivers/media/platform/mtk-vcodec/venc_drv_if.h +++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.h @@ -125,6 +125,7 @@ struct venc_done_result { extern const struct venc_common_if venc_h264_if; extern const struct venc_common_if venc_vp8_if; +extern const struct venc_common_if venc_if; /* * venc_if_init - Create the driver handle From patchwork Mon Aug 16 10:59:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438239 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11DC6C4338F for ; Mon, 16 Aug 2021 11:01:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ED8C460EFF for ; Mon, 16 Aug 2021 11:00:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236170AbhHPLB3 (ORCPT ); Mon, 16 Aug 2021 07:01:29 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:41878 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S236156AbhHPLBQ (ORCPT ); Mon, 16 Aug 2021 07:01:16 -0400 X-UUID: 2a05ca71d8954faa89a1a0b2865355f6-20210816 X-UUID: 2a05ca71d8954faa89a1a0b2865355f6-20210816 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 904561087; Mon, 16 Aug 2021 19:00:41 +0800 Received: from mtkmbs10n2.mediatek.inc (172.21.101.183) by mtkmbs02n1.mediatek.inc (172.21.101.77) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:40 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs10n2.mediatek.inc (172.21.101.183) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 16 Aug 2021 19:00:39 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:38 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , "Tiffany Lin" , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 7/9] media: mtk-vcodec: Add frame racing mode encode process Date: Mon, 16 Aug 2021 18:59:32 +0800 Message-ID: <20210816105934.28265-8-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The frame_racing mode encoding is try to use the two venc cores: frame#0 use core#0, frame#1 use core#1, frame#2 use core#0..., Lock the device and enabe the clock by used core, for sequence header encoding, it always used core#0. Signed-off-by: Irui Wang --- .../platform/mtk-vcodec/mtk_vcodec_drv.h | 5 +- .../platform/mtk-vcodec/mtk_vcodec_enc.c | 35 ++++---- .../platform/mtk-vcodec/mtk_vcodec_enc.h | 4 +- .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 6 +- .../platform/mtk-vcodec/venc/venc_common_if.c | 6 +- .../platform/mtk-vcodec/venc/venc_h264_if.c | 6 +- .../platform/mtk-vcodec/venc/venc_vp8_if.c | 2 +- .../media/platform/mtk-vcodec/venc_drv_if.c | 85 ++++++++++++++----- .../media/platform/mtk-vcodec/venc_drv_if.h | 4 + .../media/platform/mtk-vcodec/venc_vpu_if.c | 11 ++- .../media/platform/mtk-vcodec/venc_vpu_if.h | 3 +- 11 files changed, 118 insertions(+), 49 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h index 1c6c1eca649f..7a9c2dd52b91 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h @@ -273,6 +273,7 @@ struct vdec_pic_info { * @decoded_frame_cnt: number of decoded frames * @lock: protect variables accessed by V4L2 threads and worker thread such as * mtk_video_dec_buf. + * @enc_idx: used to record encoded frame count */ struct mtk_vcodec_ctx { enum mtk_instance_type type; @@ -313,6 +314,8 @@ struct mtk_vcodec_ctx { int decoded_frame_cnt; struct mutex lock; + int hw_id; + int enc_idx; }; enum mtk_chip { @@ -422,7 +425,7 @@ struct mtk_vcodec_dev { int enc_irq; struct mutex dec_mutex; - struct mutex enc_mutex; + struct mutex enc_mutex[MTK_VENC_HW_MAX]; struct mtk_vcodec_pm pm; unsigned int dec_capability; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index d22f9c8fd063..6b37bd092fdf 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -1090,21 +1090,26 @@ static void mtk_venc_worker(struct work_struct *work) if (enc_result.is_key_frm) dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; - if (ret) { - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); - dst_buf->vb2_buf.planes[0].bytesused = 0; - v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); - mtk_v4l2_err("venc_if_encode failed=%d", ret); - } else { - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); - dst_buf->vb2_buf.planes[0].bytesused = enc_result.bs_size; - v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); - mtk_v4l2_debug(2, "venc_if_encode bs size=%d", - enc_result.bs_size); + if (ctx->dev->venc_pdata->hw_mode == VENC_SINGLE_CORE_MODE) { + if (ret) { + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); + dst_buf->vb2_buf.planes[0].bytesused = 0; + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); + mtk_v4l2_err("venc_if_encode failed=%d", ret); + } else { + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); + dst_buf->vb2_buf.planes[0].bytesused = + enc_result.bs_size; + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); + mtk_v4l2_debug(2, "venc_if_encode bs size=%d", + enc_result.bs_size); + } } v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx); + ctx->enc_idx++; + mtk_v4l2_debug(1, "<=== src_buf[%d] dst_buf[%d] venc_if_encode ret=%d Size=%u===>", src_buf->vb2_buf.index, dst_buf->vb2_buf.index, ret, enc_result.bs_size); @@ -1305,19 +1310,19 @@ int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq, return vb2_queue_init(dst_vq); } -int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx) +int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx, int core_id) { struct mtk_vcodec_dev *dev = ctx->dev; - mutex_unlock(&dev->enc_mutex); + mutex_unlock(&dev->enc_mutex[core_id]); return 0; } -int mtk_venc_lock(struct mtk_vcodec_ctx *ctx) +int mtk_venc_lock(struct mtk_vcodec_ctx *ctx, int core_id) { struct mtk_vcodec_dev *dev = ctx->dev; - mutex_lock(&dev->enc_mutex); + mutex_lock(&dev->enc_mutex[core_id]); return 0; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h index 30b6d7f22ed7..8d486f532025 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h @@ -41,8 +41,8 @@ struct mtk_video_enc_buf { extern const struct v4l2_ioctl_ops mtk_venc_ioctl_ops; extern const struct v4l2_m2m_ops mtk_venc_m2m_ops; -int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx); -int mtk_venc_lock(struct mtk_vcodec_ctx *ctx); +int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx, int core_id); +int mtk_venc_lock(struct mtk_vcodec_ctx *ctx, int core_id); int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq); void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index b78435e8223a..ff1f05a5ca28 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -320,7 +320,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) struct resource *res; phandle rproc_phandle; enum mtk_vcodec_fw_type fw_type; - int ret; + int ret, i; struct component_match *match = NULL; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -384,7 +384,9 @@ static int mtk_vcodec_probe(struct platform_device *pdev) } } - mutex_init(&dev->enc_mutex); + for (i = 0; i < MTK_VENC_HW_MAX; i++) + mutex_init(&dev->enc_mutex[i]); + mutex_init(&dev->dev_mutex); spin_lock_init(&dev->irqlock); diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c index 01b7d93241af..1580bd1beaac 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c @@ -300,7 +300,7 @@ static int venc_encode_sps(struct venc_common_inst *inst, mtk_vcodec_debug_enter(inst); ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_SPS, NULL, - bs_buf, bs_size, NULL); + bs_buf, bs_size, NULL, MTK_VENC_CORE0); if (ret) return ret; @@ -328,7 +328,7 @@ static int venc_encode_pps(struct venc_common_inst *inst, mtk_vcodec_debug_enter(inst); ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_PPS, NULL, - bs_buf, bs_size, NULL); + bs_buf, bs_size, NULL, MTK_VENC_CORE0); if (ret) return ret; @@ -386,7 +386,7 @@ static int venc_encode_frame(struct venc_common_inst *inst, frame_info.frm_count, frame_info.skip_frm_count, frame_info.frm_type); ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_FRAME, frm_buf, - bs_buf, bs_size, &frame_info); + bs_buf, bs_size, &frame_info, hw_id); if (ret) return ret; diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c index b6a4f2074fa5..a90b06a3fe5a 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c @@ -368,7 +368,7 @@ static int h264_encode_sps(struct venc_h264_inst *inst, mtk_vcodec_debug_enter(inst); ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL, - bs_buf, bs_size, NULL); + bs_buf, bs_size, NULL, MTK_VENC_CORE0); if (ret) return ret; @@ -395,7 +395,7 @@ static int h264_encode_pps(struct venc_h264_inst *inst, mtk_vcodec_debug_enter(inst); ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL, - bs_buf, bs_size, NULL); + bs_buf, bs_size, NULL, MTK_VENC_CORE0); if (ret) return ret; @@ -452,7 +452,7 @@ static int h264_encode_frame(struct venc_h264_inst *inst, frame_info.frm_count, frame_info.skip_frm_count, frame_info.frm_type); ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, - bs_buf, bs_size, &frame_info); + bs_buf, bs_size, &frame_info, MTK_VENC_CORE0); if (ret) return ret; diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c index 8267a9c4fd25..a68bf53d7d81 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c @@ -303,7 +303,7 @@ static int vp8_enc_encode_frame(struct venc_vp8_inst *inst, mtk_vcodec_debug(inst, "->frm_cnt=%d", inst->frm_cnt); ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, bs_size, - NULL); + NULL, MTK_VENC_CORE0); if (ret) return ret; diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/drivers/media/platform/mtk-vcodec/venc_drv_if.c index 93936d002bed..09fcec05a655 100644 --- a/drivers/media/platform/mtk-vcodec/venc_drv_if.c +++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c @@ -15,6 +15,7 @@ #include "mtk_vcodec_enc.h" #include "mtk_vcodec_enc_pm.h" +#include "mtk_vcodec_enc_hw.h" int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) { @@ -34,9 +35,9 @@ int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) return -EINVAL; } - mtk_venc_lock(ctx); + mtk_venc_lock(ctx, 0); ret = ctx->enc_if->init(ctx); - mtk_venc_unlock(ctx); + mtk_venc_unlock(ctx, 0); return ret; } @@ -46,9 +47,9 @@ int venc_if_set_param(struct mtk_vcodec_ctx *ctx, { int ret = 0; - mtk_venc_lock(ctx); + mtk_venc_lock(ctx, 0); ret = ctx->enc_if->set_param(ctx->drv_handle, type, in); - mtk_venc_unlock(ctx); + mtk_venc_unlock(ctx, 0); return ret; } @@ -59,24 +60,12 @@ int venc_if_encode(struct mtk_vcodec_ctx *ctx, struct venc_done_result *result) { int ret = 0; - unsigned long flags; - - mtk_venc_lock(ctx); - spin_lock_irqsave(&ctx->dev->irqlock, flags); - ctx->dev->curr_ctx = ctx; - spin_unlock_irqrestore(&ctx->dev->irqlock, flags); - - mtk_vcodec_enc_clock_on(ctx->dev, 0); + venc_encode_prepare(ctx, opt); ret = ctx->enc_if->encode(ctx->drv_handle, opt, frm_buf, bs_buf, result); - mtk_vcodec_enc_clock_off(ctx->dev, 0); - - spin_lock_irqsave(&ctx->dev->irqlock, flags); - ctx->dev->curr_ctx = NULL; - spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + venc_encode_unprepare(ctx, opt); - mtk_venc_unlock(ctx); return ret; } @@ -87,11 +76,67 @@ int venc_if_deinit(struct mtk_vcodec_ctx *ctx) if (!ctx->drv_handle) return 0; - mtk_venc_lock(ctx); + mtk_venc_lock(ctx, 0); ret = ctx->enc_if->deinit(ctx->drv_handle); - mtk_venc_unlock(ctx); + mtk_venc_unlock(ctx, 0); ctx->drv_handle = NULL; return ret; } + +void venc_encode_prepare(struct mtk_vcodec_ctx *ctx, + enum venc_start_opt opt) +{ + unsigned long flags; + struct mtk_venc_comp_dev *venc; + + if (ctx->dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + if (ctx->enc_idx & 0x01) + ctx->hw_id = MTK_VENC_CORE1; + else + ctx->hw_id = MTK_VENC_CORE0; + } else { + ctx->hw_id = MTK_VENC_CORE0; + } + mtk_venc_lock(ctx, ctx->hw_id); + + spin_lock_irqsave(&ctx->dev->irqlock, flags); + + if (ctx->dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + venc = ctx->dev->enc_comp_dev[ctx->hw_id]; + + venc->curr_ctx = ctx; + } else { + ctx->dev->curr_ctx = ctx; + } + + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + + mtk_vcodec_enc_clock_on(ctx->dev, ctx->hw_id); +} + +void venc_encode_unprepare(struct mtk_vcodec_ctx *ctx, + enum venc_start_opt opt) +{ + unsigned long flags; + struct mtk_venc_comp_dev *venc; + + /*clock off and unlock after irq done*/ + if (ctx->dev->venc_pdata->hw_mode == VENC_FRAME_RACING_MODE) { + if (opt == VENC_START_OPT_ENCODE_SEQUENCE_HEADER) { + mtk_vcodec_enc_clock_off(ctx->dev, ctx->hw_id); + spin_lock_irqsave(&ctx->dev->irqlock, flags); + venc = ctx->dev->enc_comp_dev[ctx->hw_id]; + venc->curr_ctx = NULL; + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + mtk_venc_unlock(ctx, ctx->hw_id); + } + } else { + mtk_vcodec_enc_clock_off(ctx->dev, ctx->hw_id); + spin_lock_irqsave(&ctx->dev->irqlock, flags); + ctx->dev->curr_ctx = NULL; + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + mtk_venc_unlock(ctx, ctx->hw_id); + } +} diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/drivers/media/platform/mtk-vcodec/venc_drv_if.h index 8f384ba24ddf..7bd1f437d8e3 100644 --- a/drivers/media/platform/mtk-vcodec/venc_drv_if.h +++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.h @@ -168,4 +168,8 @@ int venc_if_encode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs_buf, struct venc_done_result *result); +void venc_encode_prepare(struct mtk_vcodec_ctx *ctx, + enum venc_start_opt opt); +void venc_encode_unprepare(struct mtk_vcodec_ctx *ctx, + enum venc_start_opt opt); #endif /* _VENC_DRV_IF_H_ */ diff --git a/drivers/media/platform/mtk-vcodec/venc_vpu_if.c b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c index be6d8790a41e..5bee5f1828f1 100644 --- a/drivers/media/platform/mtk-vcodec/venc_vpu_if.c +++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c @@ -226,9 +226,12 @@ int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, struct venc_frm_buf *frm_buf, struct mtk_vcodec_mem *bs_buf, unsigned int *bs_size, - struct venc_frame_info *frame_info) + struct venc_frame_info *frame_info, + int hw_id) { const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx); + const int hw_mode = MTK_ENC_HW_MODE(vpu->ctx); + size_t msg_size = is_ext ? sizeof(struct venc_ap_ipi_msg_enc_ext) : sizeof(struct venc_ap_ipi_msg_enc); @@ -262,6 +265,12 @@ int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, out.data[1] = frame_info->skip_frm_count; out.data[2] = frame_info->frm_type; } + + if (hw_mode == VENC_FRAME_RACING_MODE) { + out.data_item = 4; + out.data[3] = hw_id; + } + if (vpu_enc_send_msg(vpu, &out, msg_size)) { mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_ENCODE %d fail", bs_mode); diff --git a/drivers/media/platform/mtk-vcodec/venc_vpu_if.h b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h index f9be9cab7ff7..e55656781f6e 100644 --- a/drivers/media/platform/mtk-vcodec/venc_vpu_if.h +++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h @@ -46,7 +46,8 @@ int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, struct venc_frm_buf *frm_buf, struct mtk_vcodec_mem *bs_buf, unsigned int *bs_size, - struct venc_frame_info *frame_info); + struct venc_frame_info *frame_info, + int hw_id); int vpu_enc_deinit(struct venc_vpu_inst *vpu); #endif From patchwork Mon Aug 16 10:59:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438237 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68E07C432BE for ; Mon, 16 Aug 2021 11:00:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4DDEF63211 for ; Mon, 16 Aug 2021 11:00:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236280AbhHPLB0 (ORCPT ); Mon, 16 Aug 2021 07:01:26 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:41986 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S236315AbhHPLBT (ORCPT ); Mon, 16 Aug 2021 07:01:19 -0400 X-UUID: 9dce8888aaff44768683aa06e80821c3-20210816 X-UUID: 9dce8888aaff44768683aa06e80821c3-20210816 Received: from mtkmbs10n2.mediatek.inc [(172.21.101.183)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 478976115; Mon, 16 Aug 2021 19:00:44 +0800 Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by mtkmbs05n1.mediatek.inc (172.21.101.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:43 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.15; Mon, 16 Aug 2021 19:00:42 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:41 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , "Tiffany Lin" , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 8/9] media: mtk-vcodec: Return encode result to client Date: Mon, 16 Aug 2021 18:59:33 +0800 Message-ID: <20210816105934.28265-9-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org For frame-racing mode encoding, there will no sync wait IRQ done function, so the encode result can't return to client in device_run. After device_run called to trigger encoding process, finish it, so another scheduled job can be ran. When encoding done, return the encode result to client in IRQ handler. Signed-off-by: Irui Wang --- .../platform/mtk-vcodec/mtk_vcodec_drv.h | 6 ++ .../platform/mtk-vcodec/mtk_vcodec_enc.c | 61 ++++++++++++++++++- .../platform/mtk-vcodec/mtk_vcodec_enc.h | 4 +- .../platform/mtk-vcodec/mtk_vcodec_enc_hw.c | 35 +++++++++++ .../platform/mtk-vcodec/mtk_vcodec_util.h | 1 + .../platform/mtk-vcodec/venc/venc_common_if.c | 9 +++ .../media/platform/mtk-vcodec/venc_drv_if.h | 2 + 7 files changed, 115 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h index 7a9c2dd52b91..c43321362896 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h @@ -274,6 +274,9 @@ struct vdec_pic_info { * @lock: protect variables accessed by V4L2 threads and worker thread such as * mtk_video_dec_buf. * @enc_idx: used to record encoded frame count + * @pfrm_buf: used to store current ctx's frame buffer information + * @pbs_buf: used to store current ctx's bitstream buffer information + * @hdr_size: used to store prepend header size */ struct mtk_vcodec_ctx { enum mtk_instance_type type; @@ -316,6 +319,9 @@ struct mtk_vcodec_ctx { int hw_id; int enc_idx; + struct vb2_v4l2_buffer *pfrm_buf[MTK_VENC_HW_MAX]; + struct vb2_v4l2_buffer *pbs_buf[MTK_VENC_HW_MAX]; + unsigned int hdr_size; }; enum mtk_chip { diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 6b37bd092fdf..de8e012f1b0e 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -867,6 +867,8 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q) mtk_v4l2_debug(2, "[%d]-> type=%d", ctx->id, q->type); + mtk_venc_lock_all(ctx); + if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) { dst_buf->vb2_buf.planes[0].bytesused = 0; @@ -1014,10 +1016,13 @@ static int mtk_venc_param_change(struct mtk_vcodec_ctx *ctx) ctx->id, vb2_v4l2->vb2_buf.index, mtk_buf->enc_params.force_intra); - if (mtk_buf->enc_params.force_intra) + if (mtk_buf->enc_params.force_intra) { ret |= venc_if_set_param(ctx, VENC_SET_PARAM_FORCE_INTRA, NULL); + + ctx->enc_idx = 0; + } } mtk_buf->param_change = MTK_ENCODE_PARAM_NONE; @@ -1068,9 +1073,12 @@ static void mtk_venc_worker(struct work_struct *work) frm_buf.fb_addr[i].size = (size_t)src_buf->vb2_buf.planes[i].length; } + frm_buf.src_addr = src_buf; + bs_buf.va = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); bs_buf.size = (size_t)dst_buf->vb2_buf.planes[0].length; + bs_buf.buf = dst_buf; mtk_v4l2_debug(2, "Framebuf PA=%llx Size=0x%zx;PA=0x%llx Size=0x%zx;PA=0x%llx Size=%zu", @@ -1119,6 +1127,8 @@ static void m2mops_venc_device_run(void *priv) { struct mtk_vcodec_ctx *ctx = priv; + mtk_venc_param_change(ctx); + if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264) && (ctx->state != MTK_STATE_HEADER)) { /* encode h264 sps/pps header */ @@ -1127,7 +1137,6 @@ static void m2mops_venc_device_run(void *priv) return; } - mtk_venc_param_change(ctx); queue_work(ctx->dev->encode_workqueue, &ctx->encode_work); } @@ -1310,6 +1319,33 @@ int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq, return vb2_queue_init(dst_vq); } +void mtk_venc_buf_done(struct mtk_vcodec_ctx *ctx, int core_id, + unsigned int bs_size, bool time_out, bool key_frame) +{ + struct vb2_v4l2_buffer *src_vb2_v4l2 = NULL; + struct vb2_v4l2_buffer *dst_vb2_v4l2 = NULL; + + /* + * the frm_buf(src_buf) and bs_buf(dst_buf) can be obtained from ctx, + * then put them to done list, user can get them by dqbuf call + */ + src_vb2_v4l2 = ctx->pfrm_buf[core_id]; + dst_vb2_v4l2 = ctx->pbs_buf[core_id]; + + if (src_vb2_v4l2 && dst_vb2_v4l2) { + dst_vb2_v4l2->vb2_buf.timestamp = + src_vb2_v4l2->vb2_buf.timestamp; + dst_vb2_v4l2->timecode = src_vb2_v4l2->timecode; + + if (key_frame) + dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_KEYFRAME; + + v4l2_m2m_buf_done(src_vb2_v4l2, VB2_BUF_STATE_DONE); + dst_vb2_v4l2->vb2_buf.planes[0].bytesused = bs_size; + v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_DONE); + } +} + int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx, int core_id) { struct mtk_vcodec_dev *dev = ctx->dev; @@ -1335,3 +1371,24 @@ void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx) ctx->state = MTK_STATE_FREE; } + +void mtk_venc_lock_all(struct mtk_vcodec_ctx *ctx) +{ + unsigned int i; + struct mtk_vcodec_dev *dev = ctx->dev; + + /* + * For frame-racing mode encoding, there are may be bufs being encoded + * when get the empty flush buffer or stop streaming, for example, the + * buffer with LAST flag will return to client before the encoding + * buffers, which will cause frame lost. + * The encoder device mutex will be locked during encoding process, + * when encode done, the mutex unlocked. So if all encoder device mutex + * can be locked, which means there are no bufs being encoded at this + * time, then the buffer with LAST flag can return to client properly. + */ + for (i = 0; i < MTK_VENC_HW_MAX; i++) { + mutex_lock(&dev->enc_mutex[i]); + mutex_unlock(&dev->enc_mutex[i]); + } +} diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h index 8d486f532025..1d603ccb2f3d 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h @@ -48,5 +48,7 @@ int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq, void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx); int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx); void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx); - +void mtk_venc_buf_done(struct mtk_vcodec_ctx *ctx, int core_id, + unsigned int bs_size, bool time_out, bool key_frame); +void mtk_venc_lock_all(struct mtk_vcodec_ctx *ctx); #endif /* _MTK_VCODEC_ENC_H_ */ diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c index 2a9112b0561d..687b255c58e8 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c @@ -12,6 +12,17 @@ #include "mtk_vcodec_enc_hw.h" #include "mtk_vcodec_enc_pm.h" #include "mtk_vcodec_enc.h" +#define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098 +#define VENC_PIC_FRM_TYPE 0x0010 +#define VENC_PIC_KEY_FRM 0x2 + +/* Wake up core context wait_queue */ +static void mtk_venc_comp_wake_up_ctx(struct mtk_vcodec_ctx *ctx, + unsigned int hw_id) +{ + ctx->int_cond = 1; + wake_up_interruptible(&ctx->queue); +} static void clean_irq_status(unsigned int irq_status, void __iomem *addr) { @@ -40,6 +51,9 @@ static irqreturn_t mtk_enc_comp_irq_handler(int irq, void *priv) struct mtk_vcodec_ctx *ctx; unsigned long flags; void __iomem *addr; + unsigned int bs_size; + unsigned int frm_type; + bool is_key_frame = 0; spin_lock_irqsave(&dev->master_dev->irqlock, flags); ctx = dev->curr_ctx; @@ -49,7 +63,28 @@ static irqreturn_t mtk_enc_comp_irq_handler(int irq, void *priv) addr = dev->reg_base + MTK_VENC_IRQ_ACK_OFFSET; ctx->irq_status = readl(dev->reg_base + MTK_VENC_IRQ_STATUS_OFFSET); + bs_size = readl(dev->reg_base + VENC_PIC_BITSTREAM_BYTE_CNT); + frm_type = readl(dev->reg_base + VENC_PIC_FRM_TYPE); clean_irq_status(ctx->irq_status, addr); + if (ctx->irq_status & MTK_VENC_IRQ_STATUS_FRM) { + if (ctx->hdr_size != 0) { + bs_size += ctx->hdr_size; + ctx->hdr_size = 0; + } + if (frm_type & VENC_PIC_KEY_FRM) + is_key_frame = 1; + + mtk_venc_buf_done(ctx, dev->core_id, bs_size, 0, is_key_frame); + mtk_vcodec_enc_clock_off(dev->master_dev, dev->core_id); + + spin_lock_irqsave(&dev->master_dev->irqlock, flags); + dev->curr_ctx = NULL; + spin_unlock_irqrestore(&dev->master_dev->irqlock, flags); + + mtk_venc_unlock(ctx, dev->core_id); + } else { + mtk_venc_comp_wake_up_ctx(ctx, dev->core_id); + } return IRQ_HANDLED; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h index 0027747c0a27..7321b7537f20 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h @@ -15,6 +15,7 @@ struct mtk_vcodec_mem { size_t size; void *va; dma_addr_t dma_addr; + void *buf; }; struct mtk_vcodec_fb { diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c index 1580bd1beaac..75b4e90232ae 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c @@ -481,6 +481,13 @@ static int venc_encode(void *handle, unsigned int bs_size_hdr; unsigned int bs_size_frm; + /* + * the frm_buf and bs_buf need to be recorded into ctx, + * when encoding done, the target buffer can be obtained + */ + ctx->pfrm_buf[ctx->hw_id] = frm_buf->src_addr; + ctx->pbs_buf[ctx->hw_id] = bs_buf->buf; + if (!inst->prepend_hdr) { ret = venc_encode_frame(inst, frm_buf, bs_buf, &result->bs_size, ctx->hw_id); @@ -528,6 +535,8 @@ static int venc_encode(void *handle, result->bs_size = hdr_sz + filler_sz + bs_size_frm; + ctx->hdr_size = hdr_sz + filler_sz; + mtk_vcodec_debug(inst, "hdr %d filler %d frame %d bs %d", hdr_sz, filler_sz, bs_size_frm, result->bs_size); diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/drivers/media/platform/mtk-vcodec/venc_drv_if.h index 7bd1f437d8e3..50824e718c91 100644 --- a/drivers/media/platform/mtk-vcodec/venc_drv_if.h +++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.h @@ -108,9 +108,11 @@ struct venc_frame_info { /* * struct venc_frm_buf - frame buffer information used in venc_if_encode() * @fb_addr: plane frame buffer addresses + * @src_addr: vb2_v4l2_buffer src buffer address */ struct venc_frm_buf { struct mtk_vcodec_fb fb_addr[MTK_VCODEC_MAX_PLANES]; + void *src_addr; }; /* From patchwork Mon Aug 16 10:59:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Irui Wang X-Patchwork-Id: 12438241 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B9CDC4338F for ; Mon, 16 Aug 2021 11:01:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 63D06630EE for ; Mon, 16 Aug 2021 11:01:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236427AbhHPLBg (ORCPT ); Mon, 16 Aug 2021 07:01:36 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:42090 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S236376AbhHPLBW (ORCPT ); Mon, 16 Aug 2021 07:01:22 -0400 X-UUID: 0f203480291e4a2c8795eaf1ead89c8f-20210816 X-UUID: 0f203480291e4a2c8795eaf1ead89c8f-20210816 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1912319955; Mon, 16 Aug 2021 19:00:47 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 16 Aug 2021 19:00:45 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 16 Aug 2021 19:00:44 +0800 From: Irui Wang To: Hans Verkuil , Tzung-Bi Shih , Alexandre Courbot , Tiffany Lin , Andrew-CT Chen , Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Tomasz Figa , Yong Wu CC: Hsin-Yi Wang , Maoguang Meng , Longfei Wang , Yunfei Dong , Fritz Koenig , Irui Wang , , , , , , , Subject: [PATCH 9/9] media: mtk-vcodec: Add delayed worker for encode timeout Date: Mon, 16 Aug 2021 18:59:34 +0800 Message-ID: <20210816105934.28265-10-irui.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210816105934.28265-1-irui.wang@mediatek.com> References: <20210816105934.28265-1-irui.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org When encoding timeout, a delayed timeout worker is needed because of asynchronous encoding process, restore encoding process in timeout worker. Signed-off-by: Irui Wang --- .../platform/mtk-vcodec/mtk_vcodec_enc.c | 12 ++++-- .../platform/mtk-vcodec/mtk_vcodec_enc_hw.c | 26 +++++++++++ .../platform/mtk-vcodec/mtk_vcodec_enc_hw.h | 2 + .../platform/mtk-vcodec/venc/venc_common_if.c | 43 +++++++++++++++++-- 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index de8e012f1b0e..bc635436aa90 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -1340,9 +1340,15 @@ void mtk_venc_buf_done(struct mtk_vcodec_ctx *ctx, int core_id, if (key_frame) dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_KEYFRAME; - v4l2_m2m_buf_done(src_vb2_v4l2, VB2_BUF_STATE_DONE); - dst_vb2_v4l2->vb2_buf.planes[0].bytesused = bs_size; - v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_DONE); + if (time_out) { + v4l2_m2m_buf_done(src_vb2_v4l2, VB2_BUF_STATE_ERROR); + dst_vb2_v4l2->vb2_buf.planes[0].bytesused = 0; + v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_ERROR); + } else { + v4l2_m2m_buf_done(src_vb2_v4l2, VB2_BUF_STATE_DONE); + dst_vb2_v4l2->vb2_buf.planes[0].bytesused = bs_size; + v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_DONE); + } } } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c index 687b255c58e8..f6a5dfa6929f 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.c @@ -16,6 +16,28 @@ #define VENC_PIC_FRM_TYPE 0x0010 #define VENC_PIC_KEY_FRM 0x2 +static void mtk_venc_timeout_worker(struct work_struct *work) +{ + struct mtk_venc_comp_dev *dev = container_of(work, + struct mtk_venc_comp_dev, + enc_timeout_worker.work); + + struct mtk_vcodec_ctx *ctx; + unsigned long flags; + + spin_lock_irqsave(&dev->master_dev->irqlock, flags); + ctx = dev->curr_ctx; + + dev_err(&dev->plat_dev->dev, "core: %d timeout\n", dev->core_id); + + mtk_venc_buf_done(ctx, dev->core_id, 0, 1, 0); + + mtk_vcodec_enc_clock_off(dev->master_dev, dev->core_id); + dev->curr_ctx = NULL; + spin_unlock_irqrestore(&dev->master_dev->irqlock, flags); + + mtk_venc_unlock(ctx, dev->core_id); +} /* Wake up core context wait_queue */ static void mtk_venc_comp_wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int hw_id) @@ -67,6 +89,7 @@ static irqreturn_t mtk_enc_comp_irq_handler(int irq, void *priv) frm_type = readl(dev->reg_base + VENC_PIC_FRM_TYPE); clean_irq_status(ctx->irq_status, addr); if (ctx->irq_status & MTK_VENC_IRQ_STATUS_FRM) { + cancel_delayed_work(&dev->enc_timeout_worker); if (ctx->hdr_size != 0) { bs_size += ctx->hdr_size; ctx->hdr_size = 0; @@ -182,6 +205,9 @@ static int mtk_venc_comp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, comp_dev); + INIT_DELAYED_WORK(&comp_dev->enc_timeout_worker, + mtk_venc_timeout_worker); + ret = component_add(&pdev->dev, &mtk_venc_component_ops); if (ret) { dev_err(&pdev->dev, "Failed to add component: %d\n", ret); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h index f9ae97e252dc..e69344e38ca6 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_hw.h @@ -19,6 +19,7 @@ * @irq_status: venc hw irq status * @enc_irq: venc device irq * @core id: for venc core id: core#0, core#1... + * @enc_timeout_worker: venc timeout worker */ struct mtk_venc_comp_dev { struct platform_device *plat_dev; @@ -31,6 +32,7 @@ struct mtk_venc_comp_dev { unsigned int irq_status; int enc_irq; int core_id; + struct delayed_work enc_timeout_worker; }; #endif /* _MTK_VCODEC_ENC_HW_H_ */ diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c index 75b4e90232ae..1aab84faadf0 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_common_if.c @@ -10,11 +10,13 @@ #include "../mtk_vcodec_drv.h" #include "../mtk_vcodec_util.h" #include "../mtk_vcodec_enc_hw.h" +#include "../mtk_vcodec_enc_pm.h" static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc}; #define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker) #define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098 +#define MTK_VENC_HW_TIMEOUT_MSEC 2000 enum venc_vpu_work_buf { VENC_VPU_WORK_BUF_RC_INFO_CORE0, @@ -413,6 +415,34 @@ static void h264_encode_filler(struct venc_common_inst *inst, void *buf, memset(p, 0xff, size); } +static void init_schedule_work(struct mtk_vcodec_ctx *ctx) +{ + unsigned long timeout; + struct mtk_venc_comp_dev *venc; + + venc = ctx->dev->enc_comp_dev[ctx->hw_id]; + timeout = msecs_to_jiffies(MTK_VENC_HW_TIMEOUT_MSEC); + schedule_delayed_work(&venc->enc_timeout_worker, timeout); +} + +static void cancel_schedule_work(struct mtk_vcodec_ctx *ctx) +{ + struct mtk_venc_comp_dev *venc; + unsigned long flags; + + venc = ctx->dev->enc_comp_dev[ctx->hw_id]; + cancel_delayed_work(&venc->enc_timeout_worker); + + mtk_venc_buf_done(ctx, ctx->hw_id, 0, 1, 0); + mtk_vcodec_enc_clock_off(ctx->dev, ctx->hw_id); + + spin_lock_irqsave(&ctx->dev->irqlock, flags); + venc->curr_ctx = NULL; + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + + mtk_venc_unlock(ctx, ctx->hw_id); +} + static int venc_init(struct mtk_vcodec_ctx *ctx) { int i; @@ -489,12 +519,13 @@ static int venc_encode(void *handle, ctx->pbs_buf[ctx->hw_id] = bs_buf->buf; if (!inst->prepend_hdr) { + init_schedule_work(ctx); ret = venc_encode_frame(inst, frm_buf, bs_buf, &result->bs_size, ctx->hw_id); if (ret) { mtk_vcodec_err(inst, "encode frame failed: %d", ret); - return ret; + goto encode_err; } result->is_key_frm = inst->vpu_inst.is_key_frm; @@ -503,11 +534,13 @@ static int venc_encode(void *handle, mtk_vcodec_debug(inst, "venc_encode_frame prepend SPS/PPS"); + init_schedule_work(ctx); + ret = venc_encode_header(inst, bs_buf, &bs_size_hdr); if (ret) { mtk_vcodec_err(inst, "encode prepend hdr failed: %d", ret); - return ret; + goto encode_err; } hdr_sz = bs_size_hdr; @@ -530,7 +563,7 @@ static int venc_encode(void *handle, if (ret) { mtk_vcodec_err(inst, "encode hdr frame failed: %d", ret); - return ret; + goto encode_err; } result->bs_size = hdr_sz + filler_sz + bs_size_frm; @@ -552,6 +585,10 @@ static int venc_encode(void *handle, } return ret; + +encode_err: + cancel_schedule_work(ctx); + return ret; } static int venc_set_param(void *handle,