2022-01-17 17:16:35

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 00/10] Enable two H264 encoder cores on MT8195

MT8195 has two H264 encoder cores, they have their own power-domains,
clocks, interrupts, register base. The two H264 encoder cores can work
together to achieve higher performance, it's a core mode called
frame-racing, one core has 4K@30fps performance, two cores can achieve
4K@60fps.
The two encoder core encoding process looks like this:

VENC Core0: frm#0....frm#2....frm#4....
VENC Core1: ..frm#1....frm#3....frm#5....

This series of patches are used to enable the two H264 encoder cores,
encoding process will be changed:
As-Is: Synchronous
V4L2_VIDIOC_QBUF#0 --> device_run(triger encoder) --> wait encoder IRQ -->
encoding done with result --> job_finish
V4l2_VIDIOC_QBUF#1 --> device_run(triger encoder) --> wait encoder IRQ -->
encoding done with result --> job_finish
...

To-Be: Asynchronous
V4L2_VIDIOC_QBUF#0 --> device_run(triger encoder) --> job_finish
..V4l2_VIDIOC_QBUF#1 --> device_run(triger encoder) --> job_finish
(venc core0 may encode done here, done the encoding result to client)
V4L2_VIDIOC_QBUF#2 --> device_run(triger encoder) --> job_finish.

There is no "wait encoder IRQ" synchronous call during frame-racing mode
encoding process, it can full use the two encoder cores to achieve higher
performance.

---
This series patches dependent on:
[1]: the latest linux stage tree: https://git.linuxtv.org/media_stage.git

mtk decoder patches
[2]: https://patchwork.linuxtv.org/project/linux-media/list/?series=7105
[3]: https://patchwork.linuxtv.org/project/linux-media/list/?series=7131

new yaml included files
[4]:
https://patchwork.kernel.org/project/linux-mediatek/list/?series=551641
[5]:
https://patchwork.kernel.org/project/linux-mediatek/list/?series=580579

---
---
changes compared with v1:
- of_platform_populate was used in place of the component framework.
- new yaml file for venc cores.
- some modifications for patch v1's review comments.
---

Irui Wang (10):
media: mtk-vcodec: Use core type to indicate h264 and vp8 enc
media: mtk-vcodec: export encoder functions
dt-bindings: media: mtk-vcodec: Adds encoder cores dt-bindings for
mt8195
media: mtk-vcodec: Enable venc dual core usage
media: mtk-vcodec: mtk-vcodec: Rewrite venc power manage interface
media: mtk-vcodec: Add venc power on/off interface
media: mtk-vcodec: Rewrite venc clock interface
media: mtk-vcodec: Add more extra processing for dual-core mode
media: mtk-vcodec: Add dual core mode encode process
media: mtk-vcodec: Done encode result to client

.../media/mediatek,vcodec-encoder-core.yaml | 214 +++++++++++++++++
drivers/media/platform/mtk-vcodec/Makefile | 4 +-
.../platform/mtk-vcodec/mtk_vcodec_drv.h | 44 +++-
.../platform/mtk-vcodec/mtk_vcodec_enc.c | 109 ++++++---
.../platform/mtk-vcodec/mtk_vcodec_enc.h | 7 +-
.../platform/mtk-vcodec/mtk_vcodec_enc_core.c | 187 +++++++++++++++
.../platform/mtk-vcodec/mtk_vcodec_enc_core.h | 36 +++
.../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 118 ++++++----
.../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 187 +++++++++++++--
.../platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 11 +-
.../platform/mtk-vcodec/mtk_vcodec_util.c | 19 ++
.../platform/mtk-vcodec/mtk_vcodec_util.h | 5 +
.../platform/mtk-vcodec/venc/venc_h264_if.c | 216 +++++++++++++++---
.../platform/mtk-vcodec/venc/venc_vp8_if.c | 3 +-
.../media/platform/mtk-vcodec/venc_drv_if.c | 79 +++++--
.../media/platform/mtk-vcodec/venc_drv_if.h | 7 +
.../media/platform/mtk-vcodec/venc_vpu_if.c | 10 +-
.../media/platform/mtk-vcodec/venc_vpu_if.h | 3 +-
18 files changed, 1097 insertions(+), 162 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h

--
2.18.0


2022-01-17 17:16:50

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 02/10] media: mtk-vcodec: export encoder functions

mtk vcodec is built as a module, export some functions to make them
visible by other modules.

Signed-off-by: Irui Wang <[email protected]>
---
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 2 ++
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 3 +++
2 files changed, 5 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
index ffb046eec610..134dc53e4855 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -1432,6 +1432,7 @@ int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx)
mutex_unlock(&dev->enc_mutex);
return 0;
}
+EXPORT_SYMBOL_GPL(mtk_venc_unlock);

int mtk_venc_lock(struct mtk_vcodec_ctx *ctx)
{
@@ -1440,6 +1441,7 @@ int mtk_venc_lock(struct mtk_vcodec_ctx *ctx)
mutex_lock(&dev->enc_mutex);
return 0;
}
+EXPORT_SYMBOL_GPL(mtk_venc_lock);

void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *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 0825c6ec4eb7..7eba1a990ed7 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -85,6 +85,7 @@ int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev)
put_device(pm->larbvenc);
return ret;
}
+EXPORT_SYMBOL_GPL(mtk_vcodec_init_enc_clk);

void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
{
@@ -111,6 +112,7 @@ void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
for (i -= 1; i >= 0; i--)
clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
}
+EXPORT_SYMBOL_GPL(mtk_vcodec_enc_clock_on);

void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
{
@@ -121,3 +123,4 @@ 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);
}
+EXPORT_SYMBOL_GPL(mtk_vcodec_enc_clock_off);
--
2.18.0

2022-01-17 17:16:54

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 03/10] dt-bindings: media: mtk-vcodec: Adds encoder cores dt-bindings for mt8195

Adds encoder cores dt-bindings for mt8195

Signed-off-by: Irui Wang <[email protected]>
---
.../media/mediatek,vcodec-encoder-core.yaml | 214 ++++++++++++++++++
1 file changed, 214 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml

diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
new file mode 100644
index 000000000000..d1e7bfa50bce
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
@@ -0,0 +1,214 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/media/mediatek,vcodec-encoder-core.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Mediatek Video Encoder Accelerator With Multi Core
+
+maintainers:
+ - Irui Wang <[email protected]>
+
+description: |
+ Mediatek Video Encode is the video encode hardware present in Mediatek
+ SoCs which supports high resolution encoding functionalities. Required
+ parent and child device node.
+
+properties:
+ compatible:
+ const: mediatek,mt8195-vcodec-enc
+
+ mediatek,scp:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ maxItems: 1
+ description: |
+ The node of system control processor (SCP), using
+ the remoteproc & rpmsg framework.
+
+ iommus:
+ minItems: 1
+ maxItems: 32
+ description: |
+ List of the hardware port in respective IOMMU block for current Socs.
+ Refer to bindings/iommu/mediatek,iommu.yaml.
+
+ dma-ranges:
+ maxItems: 1
+ description: |
+ Describes the physical address space of IOMMU maps to memory.
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ ranges: true
+
+# Required child node:
+patternProperties:
+ "venc_core0@1a020000":
+ type: object
+
+ properties:
+ compatible:
+ const: mediatek,mtk-venc-core0
+
+ reg:
+ maxItems: 1
+
+ iommus:
+ minItems: 1
+ maxItems: 32
+ description: |
+ List of the hardware port in respective IOMMU block for current Socs.
+ Refer to bindings/iommu/mediatek,iommu.yaml.
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: MT_CG_VENC0
+
+ assigned-clocks:
+ maxItems: 1
+
+ assigned-clock-parents:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ required:
+ - compatible
+ - reg
+ - iommus
+ - interrupts
+ - clocks
+ - clock-names
+ - assigned-clocks
+ - assigned-clock-parents
+ - power-domains
+
+ additionalProperties: false
+
+ "venc_core1@1b020000":
+ type: object
+
+ properties:
+ compatible:
+ const: mediatek,mtk-venc-core1
+
+ reg:
+ maxItems: 1
+
+ iommus:
+ minItems: 1
+ maxItems: 32
+ description: |
+ List of the hardware port in respective IOMMU block for current Socs.
+ Refer to bindings/iommu/mediatek,iommu.yaml.
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: MT_CG_VENC1
+
+ assigned-clocks:
+ maxItems: 1
+
+ assigned-clock-parents:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ required:
+ - compatible
+ - reg
+ - iommus
+ - interrupts
+ - clocks
+ - clock-names
+ - assigned-clocks
+ - assigned-clock-parents
+ - power-domains
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - mediatek,scp
+ - iommus
+ - dma-ranges
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/memory/mt8195-memory-port.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/mt8195-clk.h>
+ #include <dt-bindings/power/mt8195-power.h>
+
+ venc {
+ compatible = "mediatek,mt8195-vcodec-enc";
+ mediatek,scp = <&scp>;
+ iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>;
+ dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ venc_core0@1a020000 {
+ compatible = "mediatek,mtk-venc-core0";
+ reg = <0x1a020000 0x10000>;
+ iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>,
+ <&iommu_vdo M4U_PORT_L19_VENC_REC>,
+ <&iommu_vdo M4U_PORT_L19_VENC_BSDMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_SV_COMV>,
+ <&iommu_vdo M4U_PORT_L19_VENC_RD_COMV>,
+ <&iommu_vdo M4U_PORT_L19_VENC_CUR_LUMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_CUR_CHROMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_REF_LUMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_REF_CHROMA>;
+ interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys CLK_VENC_VENC>;
+ clock-names = "MT_CG_VENC0";
+ assigned-clocks = <&topckgen CLK_TOP_VENC>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_VENC>;
+ };
+
+ venc_core1@1b020000 {
+ compatible = "mediatek,mtk-venc-core1";
+ reg = <0x1b020000 0x10000>;
+ iommus = <&iommu_vpp M4U_PORT_L20_VENC_RCPU>,
+ <&iommu_vpp M4U_PORT_L20_VENC_REC>,
+ <&iommu_vpp M4U_PORT_L20_VENC_BSDMA>,
+ <&iommu_vpp M4U_PORT_L20_VENC_SV_COMV>,
+ <&iommu_vpp M4U_PORT_L20_VENC_RD_COMV>,
+ <&iommu_vpp M4U_PORT_L20_VENC_CUR_LUMA>,
+ <&iommu_vpp M4U_PORT_L20_VENC_CUR_CHROMA>,
+ <&iommu_vpp M4U_PORT_L20_VENC_REF_LUMA>,
+ <&iommu_vpp M4U_PORT_L20_VENC_REF_CHROMA>;
+ interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys_core1 CLK_VENC_CORE1_VENC>;
+ clock-names = "MT_CG_VENC1";
+ assigned-clocks = <&topckgen CLK_TOP_VENC>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_VENC_CORE1>;
+ };
+ };
--
2.18.0

2022-01-17 17:16:55

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 04/10] media: mtk-vcodec: Enable venc dual core usage

Adds new venc core mode to indicate different venc hardware mode:
VENC_SINGLE_CORE_MODE means only one core, the device has its own
power/clk/irq, init_clk/request_irq helper can be used.

VENC_DUAL_CORE_MODE means more than one core inside, the core device
can use the init_clk/request_irq helper to initialize their own
power/clk/irq. And the main device doesn't need use these helper anymore.

MT8195 has two H264 venc cores, enable dual_core_mode for it.

Signed-off-by: Irui Wang <[email protected]>
---
drivers/media/platform/mtk-vcodec/Makefile | 4 +-
.../platform/mtk-vcodec/mtk_vcodec_drv.h | 22 +++
.../platform/mtk-vcodec/mtk_vcodec_enc_core.c | 153 ++++++++++++++++++
.../platform/mtk-vcodec/mtk_vcodec_enc_core.h | 36 +++++
.../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 88 +++++-----
5 files changed, 266 insertions(+), 37 deletions(-)
create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 93e7a343b5b0..c472b221bd6b 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -3,7 +3,8 @@
obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
mtk-vcodec-enc.o \
mtk-vcodec-common.o \
- mtk-vcodec-dec-hw.o
+ mtk-vcodec-dec-hw.o \
+ mtk-vcodec-enc-core.o

mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
vdec/vdec_vp8_if.o \
@@ -32,6 +33,7 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \
venc_drv_if.o \
venc_vpu_if.o \

+mtk-vcodec-enc-core-y := mtk_vcodec_enc_core.o

mtk-vcodec-common-y := mtk_vcodec_intr.o \
mtk_vcodec_util.o \
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index f78463ff4551..9e4e4290a69a 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -117,6 +117,23 @@ enum mtk_vdec_hw_count {
MTK_VDEC_MAX_HW_COUNT,
};

+/*
+ * enum mtk_venc_core_id -- encoder core id
+ */
+enum mtk_venc_core_id {
+ MTK_VENC_CORE0 = 0,
+ MTK_VENC_CORE1 = 1,
+ MTK_VENC_CORE_MAX,
+};
+
+/**
+ * enmu mtk_venc_core_mode - Used to indicate different encode mode
+ */
+enum mtk_venc_core_mode {
+ VENC_SINGLE_CORE_MODE = 0,
+ VENC_DUAL_CORE_MODE = 1,
+};
+
/*
* struct mtk_video_fmt - Structure used to store information about pixelformats
*/
@@ -420,6 +437,7 @@ struct mtk_vcodec_dec_pdata {
* @output_formats: array of supported output formats
* @num_output_formats: number of entries in output_formats
* @core_type: stand for h264 or vp8 encode
+ * @core_mode: indicate encode core mode
*/
struct mtk_vcodec_enc_pdata {
bool uses_ext;
@@ -430,6 +448,7 @@ struct mtk_vcodec_enc_pdata {
const struct mtk_video_fmt *output_formats;
size_t num_output_formats;
int core_type;
+ enum mtk_venc_core_mode core_mode;
};

#define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext)
@@ -479,6 +498,7 @@ struct mtk_vcodec_enc_pdata {
* @subdev_dev: subdev hardware device
* @subdev_prob_done: check whether all used hw device is prob done
* @subdev_bitmap: used to record hardware is ready or not
+ * @enc_core_dev: used to store venc core device
*/
struct mtk_vcodec_dev {
struct v4l2_device v4l2_dev;
@@ -524,6 +544,8 @@ struct mtk_vcodec_dev {
void *subdev_dev[MTK_VDEC_HW_MAX];
int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev);
DECLARE_BITMAP(subdev_bitmap, MTK_VDEC_HW_MAX);
+
+ void *enc_core_dev[MTK_VENC_CORE_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_core.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
new file mode 100644
index 000000000000..d84914f615a5
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_enc.h"
+#include "mtk_vcodec_enc_core.h"
+
+static const struct of_device_id mtk_venc_core_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_core_ids);
+
+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_core_irq_handler(int irq, void *priv)
+{
+ struct mtk_venc_core_dev *core = priv;
+ struct mtk_vcodec_ctx *ctx;
+ unsigned long flags;
+ void __iomem *addr;
+
+ spin_lock_irqsave(&core->main_dev->irqlock, flags);
+ ctx = core->curr_ctx;
+ spin_unlock_irqrestore(&core->main_dev->irqlock, flags);
+ if (!ctx)
+ return IRQ_HANDLED;
+
+ mtk_v4l2_debug(1, "id=%d core :%d", ctx->id, core->core_id);
+
+ addr = core->reg_base + MTK_VENC_IRQ_ACK_OFFSET;
+ ctx->irq_status = readl(core->reg_base + MTK_VENC_IRQ_STATUS_OFFSET);
+ clean_irq_status(ctx->irq_status, addr);
+
+ wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, 0);
+ return IRQ_HANDLED;
+}
+
+static int mtk_venc_core_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_venc_core_dev *core;
+ struct mtk_vcodec_dev *main_dev;
+ int ret;
+
+ if (!dev->parent) {
+ dev_err(dev, "No parent for venc core device\n");
+ return -ENODEV;
+ }
+
+ main_dev = dev_get_drvdata(dev->parent);
+ if (!main_dev) {
+ dev_err(dev, "Failed to get parent driver data");
+ return -EINVAL;
+ }
+
+ core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL);
+ if (!core)
+ return -ENOMEM;
+
+ core->plat_dev = pdev;
+
+ core->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(core->reg_base)) {
+ dev_err(&pdev->dev, "Failed to get reg base");
+ ret = PTR_ERR(core->reg_base);
+ goto err;
+ }
+
+ core->enc_irq = platform_get_irq(pdev, 0);
+ if (core->enc_irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq resource");
+ ret = core->enc_irq;
+ goto err;
+ }
+
+ ret = devm_request_irq(&pdev->dev, core->enc_irq,
+ mtk_enc_core_irq_handler, 0,
+ pdev->name, core);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to install core->enc_irq %d (%d)",
+ core->enc_irq, ret);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ core->core_id =
+ (enum mtk_venc_core_id)of_device_get_match_data(&pdev->dev);
+ if (core->core_id < 0 || core->core_id >= MTK_VENC_CORE_MAX) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ main_dev->enc_core_dev[core->core_id] = core;
+ core->main_dev = main_dev;
+
+ platform_set_drvdata(pdev, core);
+
+ dev_info(dev, "Venc core :%d probe done\n", core->core_id);
+
+ return 0;
+
+err:
+ return ret;
+}
+
+static struct platform_driver mtk_venc_core_driver = {
+ .probe = mtk_venc_core_probe,
+ .driver = {
+ .name = "mtk-venc-core",
+ .of_match_table = mtk_venc_core_ids,
+ },
+};
+module_platform_driver(mtk_venc_core_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek video encoder core driver");
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h
new file mode 100644
index 000000000000..856681989869
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef _MTK_VCODEC_ENC_CORE_H_
+#define _MTK_VCODEC_ENC_CORE_H_
+
+#include <linux/platform_device.h>
+#include "mtk_vcodec_drv.h"
+
+/*
+ * struct mtk_venc_core_dev - driver data
+ * @plat_dev: platform_device
+ * @main_dev: main 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 core irq status
+ * @enc_irq: venc device irq
+ * @core id: for venc core id: core#0, core#1...
+ */
+struct mtk_venc_core_dev {
+ struct platform_device *plat_dev;
+ struct mtk_vcodec_dev *main_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_CORE_H_ */
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 1f950310a3fb..9d48c604bc54 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -231,10 +231,9 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
{
struct mtk_vcodec_dev *dev;
struct video_device *vfd_enc;
- struct resource *res;
phandle rproc_phandle;
enum mtk_vcodec_fw_type fw_type;
- int ret;
+ int ret, core_type;

dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -260,39 +259,37 @@ 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_clk(dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to get mtk vcodec clock source!");
- goto err_enc_pm;
- }
+ core_type = dev->venc_pdata->core_type;

- pm_runtime_enable(&pdev->dev);
+ if (dev->venc_pdata->core_mode == VENC_SINGLE_CORE_MODE) {
+ ret = mtk_vcodec_init_enc_clk(dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Failed to get mtk vcodec clock source!");
+ goto err_enc_pm;
+ }

- dev->reg_base[dev->venc_pdata->core_type] =
- devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(dev->reg_base[dev->venc_pdata->core_type])) {
- ret = PTR_ERR(dev->reg_base[dev->venc_pdata->core_type]);
- goto err_res;
- }
+ pm_runtime_enable(&pdev->dev);

- 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;
- }
+ dev->reg_base[core_type] =
+ devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dev->reg_base[core_type])) {
+ ret = PTR_ERR(dev->reg_base[core_type]);
+ 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_type (%d)",
- dev->enc_irq, ret, dev->venc_pdata->core_type);
- 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 irq %d (%d) core_type (%d)",
+ dev->enc_irq, ret, core_type);
+ ret = -EINVAL;
+ goto err_res;
+ }
}

mutex_init(&dev->enc_mutex);
@@ -358,8 +355,17 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_enc_reg;
}

+ if (dev->venc_pdata->core_mode == VENC_DUAL_CORE_MODE) {
+ ret = of_platform_populate(pdev->dev.of_node,
+ NULL, NULL, &pdev->dev);
+ if (ret) {
+ mtk_v4l2_err("Venc main device populate failed");
+ goto err_enc_reg;
+ }
+ }
+
mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d",
- dev->venc_pdata->core_type, vfd_enc->num);
+ core_type, vfd_enc->num);

return 0;

@@ -372,8 +378,10 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
err_enc_alloc:
v4l2_device_unregister(&dev->v4l2_dev);
err_res:
- pm_runtime_disable(dev->pm.dev);
- put_device(dev->pm.larbvenc);
+ if (dev->venc_pdata->core_mode == VENC_SINGLE_CORE_MODE) {
+ pm_runtime_disable(dev->pm.dev);
+ put_device(dev->pm.larbvenc);
+ }
err_enc_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -387,6 +395,7 @@ static const struct mtk_vcodec_enc_pdata mt8173_avc_pdata = {
.min_bitrate = 64,
.max_bitrate = 60000000,
.core_type = VENC_SYS,
+ .core_mode = VENC_SINGLE_CORE_MODE,
};

static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = {
@@ -397,6 +406,7 @@ static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = {
.min_bitrate = 64,
.max_bitrate = 9000000,
.core_type = VENC_LT_SYS,
+ .core_mode = VENC_SINGLE_CORE_MODE,
};

static const struct mtk_vcodec_enc_pdata mt8183_pdata = {
@@ -408,6 +418,7 @@ static const struct mtk_vcodec_enc_pdata mt8183_pdata = {
.min_bitrate = 64,
.max_bitrate = 40000000,
.core_type = VENC_SYS,
+ .core_mode = VENC_SINGLE_CORE_MODE,
};

static const struct mtk_vcodec_enc_pdata mt8192_pdata = {
@@ -419,6 +430,7 @@ static const struct mtk_vcodec_enc_pdata mt8192_pdata = {
.min_bitrate = 64,
.max_bitrate = 100000000,
.core_type = VENC_SYS,
+ .core_mode = VENC_SINGLE_CORE_MODE,
};

static const struct mtk_vcodec_enc_pdata mt8195_pdata = {
@@ -430,6 +442,7 @@ static const struct mtk_vcodec_enc_pdata mt8195_pdata = {
.min_bitrate = 64,
.max_bitrate = 100000000,
.core_type = VENC_SYS,
+ .core_mode = VENC_DUAL_CORE_MODE,
};

static const struct of_device_id mtk_vcodec_enc_match[] = {
@@ -457,8 +470,11 @@ static int mtk_vcodec_enc_remove(struct platform_device *pdev)
video_unregister_device(dev->vfd_enc);

v4l2_device_unregister(&dev->v4l2_dev);
- pm_runtime_disable(dev->pm.dev);
- put_device(dev->pm.larbvenc);
+
+ if (dev->venc_pdata->core_mode == VENC_SINGLE_CORE_MODE) {
+ pm_runtime_disable(dev->pm.dev);
+ put_device(dev->pm.larbvenc);
+ }
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
}
--
2.18.0

2022-01-17 17:17:00

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 05/10] media: mtk-vcodec: mtk-vcodec: Rewrite venc power manage interface

The args "struct mtk_vcodec_dev *" doesn't appropriate for init_clk
functions because of sub-devices. For main device, it has no "pm/clk"
properties in dtsi, sub-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 <[email protected]>
---
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c | 9 +++++++++
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 2 +-
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 9 ++-------
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 4 ++--
4 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
index d84914f615a5..3835b9f458bf 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
@@ -13,6 +13,7 @@
#include "mtk_vcodec_drv.h"
#include "mtk_vcodec_enc.h"
#include "mtk_vcodec_enc_core.h"
+#include "mtk_vcodec_enc_pm.h"

static const struct of_device_id mtk_venc_core_ids[] = {
{
@@ -95,6 +96,13 @@ static int mtk_venc_core_probe(struct platform_device *pdev)

core->plat_dev = pdev;

+ ret = mtk_vcodec_init_enc_clk(core->plat_dev, &core->pm);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get venc core clock source!");
+ return ret;
+ }
+ pm_runtime_enable(&pdev->dev);
+
core->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(core->reg_base)) {
dev_err(&pdev->dev, "Failed to get reg base");
@@ -137,6 +145,7 @@ static int mtk_venc_core_probe(struct platform_device *pdev)
return 0;

err:
+ pm_runtime_disable(core->pm.dev);
return ret;
}

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 9d48c604bc54..a601d534d26b 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -262,7 +262,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
core_type = dev->venc_pdata->core_type;

if (dev->venc_pdata->core_mode == VENC_SINGLE_CORE_MODE) {
- ret = mtk_vcodec_init_enc_clk(dev);
+ ret = mtk_vcodec_init_enc_clk(dev->plat_dev, &dev->pm);
if (ret < 0) {
dev_err(&pdev->dev,
"Failed to get mtk vcodec clock source!");
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 7eba1a990ed7..c8a7042d7830 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -13,19 +13,15 @@
#include "mtk_vcodec_enc_pm.h"
#include "mtk_vcodec_util.h"

-int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev)
+int mtk_vcodec_init_enc_clk(struct platform_device *pdev,
+ struct mtk_vcodec_pm *pm)
{
struct device_node *node;
- struct platform_device *pdev;
- struct mtk_vcodec_pm *pm;
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->dev = &pdev->dev;
dev = &pdev->dev;
enc_clk = &pm->venc_clk;
@@ -42,7 +38,6 @@ int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev)
return -ENODEV;
}
pm->larbvenc = &pdev->dev;
- pdev = mtkdev->plat_dev;
pm->dev = &pdev->dev;

enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node,
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 bc455cefc0cd..97a394c68f4e 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,8 @@

#include "mtk_vcodec_drv.h"

-int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *dev);
-
+int mtk_vcodec_init_enc_clk(struct platform_device *pdev,
+ 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);

--
2.18.0

2022-01-17 17:17:04

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 07/10] media: mtk-vcodec: Rewrite venc clock interface

Dual core mode need enable the specific core's clk, add an
another param for clock_on/clock_off interface.

Signed-off-by: Irui Wang <[email protected]>
---
.../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 96 ++++++++++++++++---
.../platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 4 +-
.../media/platform/mtk-vcodec/venc_drv_if.c | 10 +-
3 files changed, 86 insertions(+), 24 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 dfaef884e6e3..4e37d68f75dd 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -83,17 +83,42 @@ int mtk_vcodec_init_enc_clk(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(mtk_vcodec_init_enc_clk);

-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;
+ struct mtk_venc_core_dev *core;
+ struct mtk_vcodec_pm *enc_pm;
+ struct mtk_vcodec_clk *enc_clk;
+ struct clk *clk;
int ret, i = 0;

- 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->core_mode == VENC_DUAL_CORE_MODE) {
+ core = (struct mtk_venc_core_dev *)dev->enc_core_dev[core_id];
+ enc_pm = &core->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 core_clk_err;
+ }
+ }
+ } else {
+ enc_pm = &dev->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_prepare_enable(clk);
+ if (ret) {
+ mtk_v4l2_err("clk_prepare %d %s fail %d",
+ i, enc_clk->clk_info[i].clk_name,
+ ret);
+ goto clkerr;
+ }
}
}

@@ -104,27 +129,49 @@ void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
}
return;

+core_clk_err:
+ for (i -= 1; i >= 0; i--)
+ clk_disable(enc_clk->clk_info[i].vcodec_clk);
+
+ return;
+
clkerr:
for (i -= 1; i >= 0; i--)
clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
}
EXPORT_SYMBOL_GPL(mtk_vcodec_enc_clock_on);

-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;
+ struct mtk_venc_core_dev *core;
+ struct mtk_vcodec_pm *enc_pm;
+ struct mtk_vcodec_clk *enc_clk;
int i = 0;

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->core_mode == VENC_DUAL_CORE_MODE) {
+ core = (struct mtk_venc_core_dev *)dev->enc_core_dev[core_id];
+ enc_pm = &core->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);
+ }
}
EXPORT_SYMBOL_GPL(mtk_vcodec_enc_clock_off);

int mtk_venc_core_pw_on(struct mtk_vcodec_dev *dev)
{
- int i, ret;
+ int i, ret, j = 0;
struct mtk_venc_core_dev *core;
+ struct mtk_vcodec_clk *clk;

/* power on all available venc cores */
for (i = 0; i < MTK_VENC_CORE_MAX; i++) {
@@ -137,12 +184,28 @@ int mtk_venc_core_pw_on(struct mtk_vcodec_dev *dev)
mtk_v4l2_err("power on core[%d] fail %d", i, ret);
goto pw_on_fail;
}
+
+ clk = &core->pm.venc_clk;
+ for (j = 0; j < clk->clk_num; j++) {
+ ret = clk_prepare(clk->clk_info[j].vcodec_clk);
+ if (ret) {
+ mtk_v4l2_err("prepare clk [%s] fail %d",
+ clk->clk_info[j].clk_name,
+ ret);
+ goto pw_on_fail;
+ }
+ }
}
return 0;

pw_on_fail:
for (i -= 1; i >= 0; i--) {
core = (struct mtk_venc_core_dev *)dev->enc_core_dev[i];
+
+ clk = &core->pm.venc_clk;
+ for (j -= 1; j >= 0; j--)
+ clk_unprepare(clk->clk_info[j].vcodec_clk);
+
pm_runtime_put_sync(&core->plat_dev->dev);
}
return ret;
@@ -150,8 +213,9 @@ int mtk_venc_core_pw_on(struct mtk_vcodec_dev *dev)

int mtk_venc_core_pw_off(struct mtk_vcodec_dev *dev)
{
- int i, ret;
+ int i, ret, j;
struct mtk_venc_core_dev *core;
+ struct mtk_vcodec_clk *clk;

/* power off all available venc cores */
for (i = 0; i < MTK_VENC_CORE_MAX; i++) {
@@ -159,6 +223,10 @@ int mtk_venc_core_pw_off(struct mtk_vcodec_dev *dev)
if (!core)
return 0;

+ clk = &core->pm.venc_clk;
+ for (j = clk->clk_num - 1; j >= 0; j--)
+ clk_unprepare(clk->clk_info[j].vcodec_clk);
+
ret = pm_runtime_put_sync(&core->plat_dev->dev);
if (ret < 0)
mtk_v4l2_err("power off core[%d] fail %d", i, ret);
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 99b6b6e29e35..5113ed8a869e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
@@ -11,8 +11,8 @@

int mtk_vcodec_init_enc_clk(struct platform_device *pdev,
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_core_pw_on(struct mtk_vcodec_dev *dev);
int mtk_venc_core_pw_off(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;
--
2.18.0

2022-01-17 17:17:22

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 01/10] media: mtk-vcodec: Use core type to indicate h264 and vp8 enc

use core type variables to indicate h264 and vp8 encoder

Signed-off-by: Irui Wang <[email protected]>
---
.../platform/mtk-vcodec/mtk_vcodec_drv.h | 4 +--
.../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 30 ++++++++++---------
2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index cd2939b47790..f78463ff4551 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -419,7 +419,7 @@ struct mtk_vcodec_dec_pdata {
* @num_capture_formats: number of entries in capture_formats
* @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
+ * @core_type: stand for h264 or vp8 encode
*/
struct mtk_vcodec_enc_pdata {
bool uses_ext;
@@ -429,7 +429,7 @@ struct mtk_vcodec_enc_pdata {
size_t num_capture_formats;
const struct mtk_video_fmt *output_formats;
size_t num_output_formats;
- int core_id;
+ int core_type;
};

#define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext)
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 3ac6969c54c0..1f950310a3fb 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -95,11 +95,13 @@ static irqreturn_t mtk_vcodec_enc_irq_handler(int irq, void *priv)
ctx = dev->curr_ctx;
spin_unlock_irqrestore(&dev->irqlock, flags);

- mtk_v4l2_debug(1, "id=%d coreid:%d", ctx->id, dev->venc_pdata->core_id);
- addr = dev->reg_base[dev->venc_pdata->core_id] +
+ mtk_v4l2_debug(1, "id: %d core type: %d",
+ ctx->id, dev->venc_pdata->core_type);
+
+ addr = dev->reg_base[dev->venc_pdata->core_type] +
MTK_VENC_IRQ_ACK_OFFSET;

- ctx->irq_status = readl(dev->reg_base[dev->venc_pdata->core_id] +
+ ctx->irq_status = readl(dev->reg_base[dev->venc_pdata->core_type] +
(MTK_VENC_IRQ_STATUS_OFFSET));

clean_irq_status(ctx->irq_status, addr);
@@ -266,10 +268,10 @@ static int mtk_vcodec_probe(struct platform_device *pdev)

pm_runtime_enable(&pdev->dev);

- dev->reg_base[dev->venc_pdata->core_id] =
+ dev->reg_base[dev->venc_pdata->core_type] =
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]);
+ if (IS_ERR(dev->reg_base[dev->venc_pdata->core_type])) {
+ ret = PTR_ERR(dev->reg_base[dev->venc_pdata->core_type]);
goto err_res;
}

@@ -287,8 +289,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
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);
+ "Failed to install dev->enc_irq %d (%d) core_type (%d)",
+ dev->enc_irq, ret, dev->venc_pdata->core_type);
ret = -EINVAL;
goto err_res;
}
@@ -357,7 +359,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
}

mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d",
- dev->venc_pdata->core_id, vfd_enc->num);
+ dev->venc_pdata->core_type, vfd_enc->num);

return 0;

@@ -384,7 +386,7 @@ static const struct mtk_vcodec_enc_pdata mt8173_avc_pdata = {
.num_output_formats = ARRAY_SIZE(mtk_video_formats_output),
.min_bitrate = 64,
.max_bitrate = 60000000,
- .core_id = VENC_SYS,
+ .core_type = VENC_SYS,
};

static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = {
@@ -394,7 +396,7 @@ static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = {
.num_output_formats = ARRAY_SIZE(mtk_video_formats_output),
.min_bitrate = 64,
.max_bitrate = 9000000,
- .core_id = VENC_LT_SYS,
+ .core_type = VENC_LT_SYS,
};

static const struct mtk_vcodec_enc_pdata mt8183_pdata = {
@@ -405,7 +407,7 @@ static const struct mtk_vcodec_enc_pdata mt8183_pdata = {
.num_output_formats = ARRAY_SIZE(mtk_video_formats_output),
.min_bitrate = 64,
.max_bitrate = 40000000,
- .core_id = VENC_SYS,
+ .core_type = VENC_SYS,
};

static const struct mtk_vcodec_enc_pdata mt8192_pdata = {
@@ -416,7 +418,7 @@ static const struct mtk_vcodec_enc_pdata mt8192_pdata = {
.num_output_formats = ARRAY_SIZE(mtk_video_formats_output),
.min_bitrate = 64,
.max_bitrate = 100000000,
- .core_id = VENC_SYS,
+ .core_type = VENC_SYS,
};

static const struct mtk_vcodec_enc_pdata mt8195_pdata = {
@@ -427,7 +429,7 @@ static const struct mtk_vcodec_enc_pdata mt8195_pdata = {
.num_output_formats = ARRAY_SIZE(mtk_video_formats_output),
.min_bitrate = 64,
.max_bitrate = 100000000,
- .core_id = VENC_SYS,
+ .core_type = VENC_SYS,
};

static const struct of_device_id mtk_vcodec_enc_match[] = {
--
2.18.0

2022-01-17 17:17:22

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 08/10] media: mtk-vcodec: Add more extra processing for dual-core mode

Dual core 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 more struct definition for it.

Signed-off-by: Irui Wang <[email protected]>
---
.../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_h264_if.c | 178 +++++++++++++++---
4 files changed, 177 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 9e4e4290a69a..dc036279c42f 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -452,6 +452,7 @@ struct mtk_vcodec_enc_pdata {
};

#define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext)
+#define MTK_ENC_CORE_MODE(ctx) ((ctx)->dev->venc_pdata->core_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 ace78c4b5b9e..059f665afa96 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -11,6 +11,7 @@

#include "mtk_vcodec_dec_hw.h"
#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_enc_core.h"
#include "mtk_vcodec_util.h"

void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
@@ -26,6 +27,24 @@ void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
}
EXPORT_SYMBOL(mtk_vcodec_get_reg_addr);

+void __iomem *mtk_venc_get_core_reg_addr(struct mtk_vcodec_ctx *ctx,
+ unsigned int core_id)
+{
+ struct mtk_venc_core_dev *core;
+
+ if (core_id >= MTK_VENC_CORE_MAX) {
+ mtk_v4l2_err("Invalid core_id = %d", core_id);
+ return NULL;
+ }
+
+ core = (struct mtk_venc_core_dev *)ctx->dev->enc_core_dev[core_id];
+ if (!core)
+ return NULL;
+
+ return core->reg_base;
+}
+EXPORT_SYMBOL(mtk_venc_get_core_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 71956627a0e2..de9e18688842 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
@@ -50,6 +50,10 @@ struct mtk_vcodec_dev;

void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
unsigned int reg_idx);
+
+void __iomem *mtk_venc_get_core_reg_addr(struct mtk_vcodec_ctx *data,
+ unsigned int core_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_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
index 4d9b8798dffe..023b6eb8b20c 100644
--- a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
@@ -50,6 +50,24 @@ enum venc_h264_vpu_work_buf {
VENC_H264_VPU_WORK_BUF_MAX,
};

+/*
+ * enum venc_dual_core_work_buf - h264 dual core encoder buffer index
+ */
+enum venc_dual_core_work_buf {
+ VENC_DUAL_CORE_WORK_BUF_RC_INFO_CORE0,
+ VENC_DUAL_CORE_WORK_BUF_RC_CODE,
+ VENC_DUAL_CORE_WORK_BUF_REC_LUMA,
+ VENC_DUAL_CORE_WORK_BUF_REC_CHROMA,
+ VENC_DUAL_CORE_WORK_BUF_REF_LUMA,
+ VENC_DUAL_CORE_WORK_BUF_REF_CHROMA,
+ VENC_DUAL_CORE_WORK_BUF_MV_INFO_1,
+ VENC_DUAL_CORE_WORK_BUF_MV_INFO_2,
+ VENC_DUAL_CORE_WORK_BUF_SKIP_FRAME,
+ VENC_DUAL_CORE_WORK_BUF_RC_INFO_CORE1,
+ VENC_DUAL_CORE_WORK_BUF_FR_RC_INFO,
+ VENC_DUAL_CORE_WORK_BUF_MAX,
+};
+
/*
* enum venc_h264_bs_mode - for bs_mode argument in h264_enc_vpu_encode
*/
@@ -94,6 +112,24 @@ struct venc_h264_vpu_config {
u32 wfd;
};

+struct venc_dual_core_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_h264_vpu_buf - Structure for buffer information
* AP-W/R : AP is writer/reader on this item
@@ -127,6 +163,11 @@ struct venc_h264_vsi {
struct venc_h264_vpu_buf work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
};

+struct venc_dual_core_vsi {
+ struct venc_dual_core_config config;
+ struct venc_h264_vpu_buf work_bufs[VENC_DUAL_CORE_WORK_BUF_MAX];
+};
+
/*
* struct venc_h264_inst - h264 encoder AP driver instance
* @hw_base: h264 encoder hardware register base
@@ -143,8 +184,8 @@ struct venc_h264_vsi {
* @ctx: context for v4l2 layer integration
*/
struct venc_h264_inst {
- void __iomem *hw_base;
- struct mtk_vcodec_mem work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
+ void __iomem *hw_base[MTK_VENC_CORE_MAX];
+ struct mtk_vcodec_mem work_bufs[VENC_DUAL_CORE_WORK_BUF_MAX];
struct mtk_vcodec_mem pps_buf;
bool work_buf_allocated;
unsigned int frm_cnt;
@@ -152,12 +193,13 @@ struct venc_h264_inst {
unsigned int prepend_hdr;
struct venc_vpu_inst vpu_inst;
struct venc_h264_vsi *vsi;
+ struct venc_dual_core_vsi *core_vsi;
struct mtk_vcodec_ctx *ctx;
};

static inline u32 h264_read_reg(struct venc_h264_inst *inst, u32 addr)
{
- return readl(inst->hw_base + addr);
+ return readl(inst->hw_base[MTK_VENC_CORE0] + addr);
}

static unsigned int h264_get_profile(struct venc_h264_inst *inst,
@@ -228,13 +270,21 @@ static unsigned int h264_get_level(struct venc_h264_inst *inst,
static void h264_enc_free_work_buf(struct venc_h264_inst *inst)
{
int i;
+ struct mtk_vcodec_ctx *ctx = inst->ctx;
+ int max_work_buf;
+ bool is_dual_core = (MTK_ENC_CORE_MODE(ctx) == VENC_DUAL_CORE_MODE);

mtk_vcodec_debug_enter(inst);

+ if (is_dual_core)
+ max_work_buf = VENC_DUAL_CORE_WORK_BUF_MAX;
+ else
+ max_work_buf = VENC_H264_VPU_WORK_BUF_MAX;
+
/* Except the SKIP_FRAME buffers,
* other buffers need to be freed by AP.
*/
- for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
+ for (i = 0; i < max_work_buf; i++) {
if (i != VENC_H264_VPU_WORK_BUF_SKIP_FRAME)
mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]);
}
@@ -248,11 +298,22 @@ static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst)
{
int i;
int ret = 0;
- struct venc_h264_vpu_buf *wb = inst->vsi->work_bufs;
+ struct mtk_vcodec_ctx *ctx = inst->ctx;
+ struct venc_h264_vpu_buf *wb;
+ int max_work_buf;
+ bool is_dual_core = (MTK_ENC_CORE_MODE(ctx) == VENC_DUAL_CORE_MODE);

mtk_vcodec_debug_enter(inst);

- for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
+ if (is_dual_core) {
+ wb = inst->core_vsi->work_bufs;
+ max_work_buf = VENC_DUAL_CORE_WORK_BUF_MAX;
+ } else {
+ wb = inst->vsi->work_bufs;
+ max_work_buf = VENC_H264_VPU_WORK_BUF_MAX;
+ }
+
+ for (i = 0; i < max_work_buf; i++) {
/*
* This 'wb' structure is set by VPU side and shared to AP for
* buffer allocation and IO virtual addr mapping. For most of
@@ -358,6 +419,26 @@ static int h264_frame_type(struct venc_h264_inst *inst)
return VENC_H264_P_FRM; /* Note: B frames are not supported */
}
}
+
+static int h264_core_frame_type(struct venc_h264_inst *inst)
+{
+ struct venc_dual_core_vsi *vsi = inst->core_vsi;
+
+ if ((vsi->config.gop_size != 0 &&
+ (inst->frm_cnt % vsi->config.gop_size) == 0) ||
+ (inst->frm_cnt == 0 && vsi->config.gop_size == 0)) {
+ /* IDR frame */
+ return VENC_H264_IDR_FRM;
+ } else if ((vsi->config.intra_period != 0 &&
+ (inst->frm_cnt % vsi->config.intra_period) == 0) ||
+ (inst->frm_cnt == 0 && vsi->config.intra_period == 0)) {
+ /* I frame */
+ return VENC_H264_I_FRM;
+ } else {
+ return VENC_H264_P_FRM; /* Note: B frames are not supported */
+ }
+}
+
static int h264_encode_sps(struct venc_h264_inst *inst,
struct mtk_vcodec_mem *bs_buf,
unsigned int *bs_size)
@@ -440,12 +521,18 @@ static int h264_encode_frame(struct venc_h264_inst *inst,
int ret = 0;
unsigned int irq_status;
struct venc_frame_info frame_info;
+ struct mtk_vcodec_ctx *ctx = inst->ctx;
+ bool is_dual_core = (MTK_ENC_CORE_MODE(ctx) == VENC_DUAL_CORE_MODE);

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 = h264_frame_type(inst);
+ if (is_dual_core)
+ frame_info.frm_type = h264_core_frame_type(inst);
+ else
+ frame_info.frm_type = h264_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);
@@ -501,7 +588,8 @@ static void h264_encode_filler(struct venc_h264_inst *inst, void *buf,
static int h264_enc_init(struct mtk_vcodec_ctx *ctx)
{
const bool is_ext = MTK_ENC_CTX_IS_EXT(ctx);
- int ret = 0;
+ bool is_dual_core = (MTK_ENC_CORE_MODE(ctx) == VENC_DUAL_CORE_MODE);
+ int ret, i = 0;
struct venc_h264_inst *inst;

inst = kzalloc(sizeof(*inst), GFP_KERNEL);
@@ -511,13 +599,22 @@ static int h264_enc_init(struct mtk_vcodec_ctx *ctx)
inst->ctx = ctx;
inst->vpu_inst.ctx = ctx;
inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264;
- inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS);

mtk_vcodec_debug_enter(inst);

ret = vpu_enc_init(&inst->vpu_inst);

- inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi;
+ if (is_dual_core) {
+ inst->core_vsi =
+ (struct venc_dual_core_vsi *)inst->vpu_inst.vsi;
+ for (i = 0; i < MTK_VENC_CORE_MAX; i++)
+ inst->hw_base[i] =
+ mtk_venc_get_core_reg_addr(inst->ctx, i);
+
+ } else {
+ inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi;
+ inst->hw_base[0] = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS);
+ }

mtk_vcodec_debug_leave(inst);

@@ -624,31 +721,62 @@ static int h264_enc_encode(void *handle,
return ret;
}

+static void h264_enc_set_configs(struct venc_h264_inst *inst,
+ struct venc_enc_param *enc_prm)
+{
+ 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;
+}
+
+static void h264_enc_set_core_configs(struct venc_h264_inst *inst,
+ struct venc_enc_param *enc_prm)
+{
+ inst->core_vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
+ inst->core_vsi->config.bitrate = enc_prm->bitrate;
+ inst->core_vsi->config.pic_w = enc_prm->width;
+ inst->core_vsi->config.pic_h = enc_prm->height;
+ inst->core_vsi->config.buf_w = enc_prm->buf_width;
+ inst->core_vsi->config.buf_h = enc_prm->buf_height;
+ inst->core_vsi->config.gop_size = enc_prm->gop_size;
+ inst->core_vsi->config.framerate = enc_prm->frm_rate;
+ inst->core_vsi->config.intra_period = enc_prm->intra_period;
+ inst->core_vsi->config.profile =
+ h264_get_profile(inst, enc_prm->h264_profile);
+ inst->core_vsi->config.level =
+ h264_get_level(inst, enc_prm->h264_level);
+ inst->core_vsi->config.wfd = 0;
+}
+
static int h264_enc_set_param(void *handle,
enum venc_set_param_type type,
struct venc_enc_param *enc_prm)
{
int ret = 0;
struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
+ struct mtk_vcodec_ctx *ctx = inst->ctx;
+ bool is_dual_core = (MTK_ENC_CORE_MODE(ctx) == VENC_DUAL_CORE_MODE);

- mtk_vcodec_debug(inst, "->type=%d", type);
+ mtk_vcodec_debug(inst, "->type=%d, dual_core=%d", type, is_dual_core);

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;
+ if (is_dual_core)
+ h264_enc_set_core_configs(inst, enc_prm);
+ else
+ h264_enc_set_configs(inst, enc_prm);
+
ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
if (ret)
break;
--
2.18.0

2022-01-17 17:18:17

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 10/10] media: mtk-vcodec: Done encode result to client

When enable dual core mode encoding, the wait IRQ done synchronous
function should not be called, so the encode result can't return
to client in device_run. device_run called to trigger encoding
process, finish it, so another scheduled job can be ran. When
encoding done, done the encode result to client in IRQ handler.

Signed-off-by: Irui Wang <[email protected]>
---
.../platform/mtk-vcodec/mtk_vcodec_drv.h | 6 ++
.../platform/mtk-vcodec/mtk_vcodec_enc.c | 64 ++++++++++++++++++-
.../platform/mtk-vcodec/mtk_vcodec_enc.h | 3 +
.../platform/mtk-vcodec/mtk_vcodec_enc_core.c | 27 +++++++-
.../platform/mtk-vcodec/mtk_vcodec_util.h | 1 +
.../platform/mtk-vcodec/venc/venc_h264_if.c | 22 ++++++-
.../media/platform/mtk-vcodec/venc_drv_if.h | 2 +
7 files changed, 120 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index c3cf5904b4c6..5faeffd397db 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -311,6 +311,9 @@ struct vdec_pic_info {
* @q_mutex: src & dst vb2_queue mutex
* @enc_idx: used to record encoded frame count
* @core_id: used to reoord used core
+ * @pfrm_buf: used to store current ctx's frame buffer
+ * @pbs_buf: used to store current ctx's bitstream buffer
+ * @hdr_size: used to store prepend header size
*/
struct mtk_vcodec_ctx {
enum mtk_instance_type type;
@@ -363,6 +366,9 @@ struct mtk_vcodec_ctx {
struct mutex q_mutex;
int enc_idx;
int core_id;
+ struct vb2_v4l2_buffer *pfrm_buf[MTK_VENC_CORE_MAX];
+ struct vb2_v4l2_buffer *pbs_buf[MTK_VENC_CORE_MAX];
+ unsigned int hdr_size;
};

/*
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
index dc70d328fcd3..3056cbc4b3a3 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -924,6 +924,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))) {
vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
@@ -1103,10 +1105,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;
@@ -1157,6 +1162,7 @@ static void mtk_venc_worker(struct work_struct *work)
* is dequeued.
*/
if (src_buf == &ctx->empty_flush_buf.vb) {
+ mtk_venc_lock_all(ctx);
vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
dst_buf->flags |= V4L2_BUF_FLAG_LAST;
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
@@ -1171,9 +1177,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",
@@ -1220,6 +1229,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 */
@@ -1228,7 +1239,6 @@ static void m2mops_venc_device_run(void *priv)
return;
}

- mtk_venc_param_change(ctx);
queue_work(ctx->dev->encode_workqueue, &ctx->encode_work);
}

@@ -1414,6 +1424,34 @@ 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);
+ vb2_set_plane_payload(&dst_vb2_v4l2->vb2_buf, 0, bs_size);
+ v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_DONE);
+ }
+}
+EXPORT_SYMBOL_GPL(mtk_venc_buf_done);
+
int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx, int core_id)
{
struct mtk_vcodec_dev *dev = ctx->dev;
@@ -1441,3 +1479,25 @@ 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_CORE_MAX; i++) {
+ mutex_lock(&dev->enc_mutex[i]);
+ mutex_unlock(&dev->enc_mutex[i]);
+ }
+}
+EXPORT_SYMBOL_GPL(mtk_venc_lock_all);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
index 434d91d36158..1e22c77a2760 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
@@ -46,5 +46,8 @@ 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_core.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
index 3835b9f458bf..6140b9bd4dd0 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
@@ -14,6 +14,11 @@
#include "mtk_vcodec_enc.h"
#include "mtk_vcodec_enc_core.h"
#include "mtk_vcodec_enc_pm.h"
+#include "mtk_vcodec_intr.h"
+
+#define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098
+#define VENC_PIC_FRM_TYPE 0x0010
+#define VENC_PIC_KEY_FRM 0x2

static const struct of_device_id mtk_venc_core_ids[] = {
{
@@ -47,6 +52,7 @@ static void clean_irq_status(unsigned int irq_status, void __iomem *addr)

if (irq_status & MTK_VENC_IRQ_STATUS_FRM)
writel(MTK_VENC_IRQ_STATUS_FRM, addr);
+
}

static irqreturn_t mtk_enc_core_irq_handler(int irq, void *priv)
@@ -55,6 +61,9 @@ static irqreturn_t mtk_enc_core_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(&core->main_dev->irqlock, flags);
ctx = core->curr_ctx;
@@ -66,9 +75,25 @@ static irqreturn_t mtk_enc_core_irq_handler(int irq, void *priv)

addr = core->reg_base + MTK_VENC_IRQ_ACK_OFFSET;
ctx->irq_status = readl(core->reg_base + MTK_VENC_IRQ_STATUS_OFFSET);
+ bs_size = readl(core->reg_base + VENC_PIC_BITSTREAM_BYTE_CNT);
+ frm_type = readl(core->reg_base + VENC_PIC_FRM_TYPE);
clean_irq_status(ctx->irq_status, addr);

- wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, 0);
+ 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, core->core_id, bs_size, 0, is_key_frame);
+ mtk_vcodec_enc_clock_off(core->main_dev, core->core_id);
+ mtk_venc_unlock(ctx, core->core_id);
+ } else {
+ wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, 0);
+ }
+
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 de9e18688842..4436d8bc60a0 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_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
index fdecf1d24b25..733dbf431aae 100644
--- a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
@@ -558,6 +558,12 @@ static int h264_encode_frame(struct venc_h264_inst *inst,
return ret;
}

+ if (is_dual_core) {
+ ++inst->frm_cnt;
+ mtk_vcodec_debug(inst, "dual core : frm %d <-", inst->frm_cnt);
+ return ret;
+ }
+
irq_status = h264_enc_wait_venc_done(inst);
if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
@@ -639,10 +645,12 @@ static int h264_enc_encode(void *handle,
int ret = 0;
struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
struct mtk_vcodec_ctx *ctx = inst->ctx;
+ bool is_single_core = (MTK_ENC_CORE_MODE(ctx) == VENC_SINGLE_CORE_MODE);

mtk_vcodec_debug(inst, "opt %d ->", opt);

- enable_irq(ctx->dev->enc_irq);
+ if (is_single_core)
+ enable_irq(ctx->dev->enc_irq);

switch (opt) {
case VENC_START_OPT_ENCODE_SEQUENCE_HEADER: {
@@ -666,6 +674,13 @@ static int h264_enc_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->core_id] = frm_buf->src_addr;
+ ctx->pbs_buf[ctx->core_id] = bs_buf->buf;
+
if (!inst->prepend_hdr) {
ret = h264_encode_frame(inst, frm_buf, bs_buf,
&result->bs_size, ctx->core_id);
@@ -702,6 +717,8 @@ static int h264_enc_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);
@@ -718,8 +735,9 @@ static int h264_enc_encode(void *handle,
}

encode_err:
+ if (is_single_core)
+ disable_irq(ctx->dev->enc_irq);

- disable_irq(ctx->dev->enc_irq);
mtk_vcodec_debug(inst, "opt %d <-", opt);

return ret;
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/drivers/media/platform/mtk-vcodec/venc_drv_if.h
index 15e9a2ab9cda..3ad31abb7290 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;
};

/*
--
2.18.0

2022-01-18 02:23:09

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 06/10] media: mtk-vcodec: Add venc power on/off interface

Dual-core mode 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 <[email protected]>
---
.../platform/mtk-vcodec/mtk_vcodec_enc.c | 20 +----
.../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 7 ++
.../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 83 +++++++++++++++++++
.../platform/mtk-vcodec/mtk_vcodec_enc_pm.h | 5 ++
4 files changed, 98 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 134dc53e4855..df231e67cdb2 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -13,6 +13,7 @@

#include "mtk_vcodec_drv.h"
#include "mtk_vcodec_enc.h"
+#include "mtk_vcodec_enc_pm.h"
#include "mtk_vcodec_intr.h"
#include "mtk_vcodec_util.h"
#include "venc_drv_if.h"
@@ -850,7 +851,7 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
struct venc_enc_param param;
- int ret, pm_ret;
+ int ret;
int i;

/* Once state turn into MTK_STATE_ABORT, we need stop_streaming
@@ -858,7 +859,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 */
@@ -870,12 +871,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, &param);
ret = venc_if_set_param(ctx, VENC_SET_PARAM_ENC, &param);
if (ret) {
@@ -902,11 +897,6 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count)
return 0;

err_set_param:
- pm_ret = pm_runtime_put(&ctx->dev->plat_dev->dev);
- if (pm_ret < 0)
- mtk_v4l2_err("pm_runtime_put fail %d", pm_ret);
-
-err_start_stream:
for (i = 0; i < q->num_buffers; ++i) {
struct vb2_buffer *buf = vb2_get_buffer(q, i);

@@ -989,10 +979,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 a601d534d26b..cef134bb6e83 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -174,6 +174,12 @@ static int fops_vcodec_open(struct file *file)
mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability);
}

+ ret = mtk_vcodec_enc_pw_on(dev);
+ 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);

@@ -208,6 +214,7 @@ static int fops_vcodec_release(struct file *file)

v4l2_m2m_ctx_release(ctx->m2m_ctx);
mtk_vcodec_enc_release(ctx);
+ mtk_vcodec_enc_pw_off(dev);
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
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 c8a7042d7830..dfaef884e6e3 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -10,6 +10,7 @@
#include <linux/pm_runtime.h>
#include <soc/mediatek/smi.h>

+#include "mtk_vcodec_enc_core.h"
#include "mtk_vcodec_enc_pm.h"
#include "mtk_vcodec_util.h"

@@ -119,3 +120,85 @@ void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
}
EXPORT_SYMBOL_GPL(mtk_vcodec_enc_clock_off);
+
+int mtk_venc_core_pw_on(struct mtk_vcodec_dev *dev)
+{
+ int i, ret;
+ struct mtk_venc_core_dev *core;
+
+ /* power on all available venc cores */
+ for (i = 0; i < MTK_VENC_CORE_MAX; i++) {
+ core = (struct mtk_venc_core_dev *)dev->enc_core_dev[i];
+ if (!core)
+ return 0;
+
+ ret = pm_runtime_resume_and_get(&core->plat_dev->dev);
+ if (ret < 0) {
+ mtk_v4l2_err("power on core[%d] fail %d", i, ret);
+ goto pw_on_fail;
+ }
+ }
+ return 0;
+
+pw_on_fail:
+ for (i -= 1; i >= 0; i--) {
+ core = (struct mtk_venc_core_dev *)dev->enc_core_dev[i];
+ pm_runtime_put_sync(&core->plat_dev->dev);
+ }
+ return ret;
+}
+
+int mtk_venc_core_pw_off(struct mtk_vcodec_dev *dev)
+{
+ int i, ret;
+ struct mtk_venc_core_dev *core;
+
+ /* power off all available venc cores */
+ for (i = 0; i < MTK_VENC_CORE_MAX; i++) {
+ core = (struct mtk_venc_core_dev *)dev->enc_core_dev[i];
+ if (!core)
+ return 0;
+
+ ret = pm_runtime_put_sync(&core->plat_dev->dev);
+ if (ret < 0)
+ mtk_v4l2_err("power off core[%d] fail %d", i, ret);
+ }
+ return ret;
+}
+
+int mtk_vcodec_enc_pw_on(struct mtk_vcodec_dev *dev)
+{
+ int ret;
+
+ if (dev->venc_pdata->core_mode == VENC_DUAL_CORE_MODE) {
+ ret = mtk_venc_core_pw_on(dev);
+ if (ret < 0) {
+ mtk_v4l2_err("venc core power on fail: %d", ret);
+ return ret;
+ }
+ } else {
+ ret = pm_runtime_resume_and_get(&dev->plat_dev->dev);
+ if (ret < 0) {
+ mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int mtk_vcodec_enc_pw_off(struct mtk_vcodec_dev *dev)
+{
+ int ret;
+
+ if (dev->venc_pdata->core_mode == VENC_DUAL_CORE_MODE) {
+ ret = mtk_venc_core_pw_off(dev);
+ if (ret < 0)
+ mtk_v4l2_err("venc core power off fail: %d", ret);
+
+ } else {
+ ret = pm_runtime_put_sync(&dev->plat_dev->dev);
+ if (ret < 0)
+ mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
+ }
+ return ret;
+}
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 97a394c68f4e..99b6b6e29e35 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
@@ -14,4 +14,9 @@ int mtk_vcodec_init_enc_clk(struct platform_device *pdev,
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_core_pw_on(struct mtk_vcodec_dev *dev);
+int mtk_venc_core_pw_off(struct mtk_vcodec_dev *dev);
+int mtk_vcodec_enc_pw_on(struct mtk_vcodec_dev *dev);
+int mtk_vcodec_enc_pw_off(struct mtk_vcodec_dev *dev);
+
#endif /* _MTK_VCODEC_ENC_PM_H_ */
--
2.18.0

2022-01-18 02:23:09

by Irui Wang (王瑞)

[permalink] [raw]
Subject: [PATCH v2, 09/10] media: mtk-vcodec: Add dual core mode encode process

The dual core mode encoding is tries to uses the two venc cores:
frame#0 uses core#0, frame#1 uses core#1, frame#2 uses core#0...,

Lock the device and enable the clock by used core, for sequence
header encoding, it always uses core#0.

Signed-off-by: Irui Wang <[email protected]>
---
.../platform/mtk-vcodec/mtk_vcodec_drv.h | 11 ++-
.../platform/mtk-vcodec/mtk_vcodec_enc.c | 23 +++---
.../platform/mtk-vcodec/mtk_vcodec_enc.h | 4 +-
.../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 7 +-
.../platform/mtk-vcodec/venc/venc_h264_if.c | 16 ++--
.../platform/mtk-vcodec/venc/venc_vp8_if.c | 3 +-
.../media/platform/mtk-vcodec/venc_drv_if.c | 73 ++++++++++++++-----
.../media/platform/mtk-vcodec/venc_drv_if.h | 5 ++
.../media/platform/mtk-vcodec/venc_vpu_if.c | 10 ++-
.../media/platform/mtk-vcodec/venc_vpu_if.h | 3 +-
10 files changed, 113 insertions(+), 42 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index dc036279c42f..c3cf5904b4c6 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -308,6 +308,9 @@ struct vdec_pic_info {
* @max_width: hardware supported max width
* @max_height: hardware supported max height
* @msg_queue: msg queue used to store lat buffer information.
+ * @q_mutex: src & dst vb2_queue mutex
+ * @enc_idx: used to record encoded frame count
+ * @core_id: used to reoord used core
*/
struct mtk_vcodec_ctx {
enum mtk_instance_type type;
@@ -356,6 +359,10 @@ struct mtk_vcodec_ctx {
unsigned int max_width;
unsigned int max_height;
struct vdec_msg_queue msg_queue;
+
+ struct mutex q_mutex;
+ int enc_idx;
+ int core_id;
};

/*
@@ -533,7 +540,9 @@ struct mtk_vcodec_dev {

/* decoder hardware mutex lock */
struct mutex dec_mutex[MTK_VDEC_HW_MAX];
- struct mutex enc_mutex;
+
+ /* encoder core mutex lock */
+ struct mutex enc_mutex[MTK_VENC_CORE_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 df231e67cdb2..dc70d328fcd3 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -1198,14 +1198,17 @@ static void mtk_venc_worker(struct work_struct *work)
vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
mtk_v4l2_err("venc_if_encode failed=%d", ret);
- } else {
+ } else if (ctx->dev->venc_pdata->core_mode == VENC_SINGLE_CORE_MODE) {
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, enc_result.bs_size);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
+ 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);
+ enc_result.bs_size);
}

+ ctx->enc_idx++;
+
v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);

mtk_v4l2_debug(1, "<=== src_buf[%d] dst_buf[%d] venc_if_encode ret=%d Size=%u===>",
@@ -1259,7 +1262,7 @@ void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx)
{
struct mtk_q_data *q_data;

- ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
+ ctx->m2m_ctx->q_lock = &ctx->q_mutex;
ctx->fh.m2m_ctx = ctx->m2m_ctx;
ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
INIT_WORK(&ctx->encode_work, mtk_venc_worker);
@@ -1391,7 +1394,7 @@ int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->ops = &mtk_venc_vb2_ops;
src_vq->mem_ops = &vb2_dma_contig_memops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- src_vq->lock = &ctx->dev->dev_mutex;
+ src_vq->lock = &ctx->q_mutex;
src_vq->dev = &ctx->dev->plat_dev->dev;

ret = vb2_queue_init(src_vq);
@@ -1405,26 +1408,26 @@ int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->ops = &mtk_venc_vb2_ops;
dst_vq->mem_ops = &vb2_dma_contig_memops;
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- dst_vq->lock = &ctx->dev->dev_mutex;
+ dst_vq->lock = &ctx->q_mutex;
dst_vq->dev = &ctx->dev->plat_dev->dev;

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;
}
EXPORT_SYMBOL_GPL(mtk_venc_unlock);

-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;
}
EXPORT_SYMBOL_GPL(mtk_venc_lock);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
index 513ee7993e34..434d91d36158 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
@@ -39,8 +39,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 cef134bb6e83..cf42a5930b48 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -133,6 +133,7 @@ static int fops_vcodec_open(struct file *file)
INIT_LIST_HEAD(&ctx->list);
ctx->dev = dev;
init_waitqueue_head(&ctx->queue[0]);
+ mutex_init(&ctx->q_mutex);

ctx->type = MTK_INST_ENCODER;
ret = mtk_vcodec_enc_ctrls_setup(ctx);
@@ -240,7 +241,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
struct video_device *vfd_enc;
phandle rproc_phandle;
enum mtk_vcodec_fw_type fw_type;
- int ret, core_type;
+ int ret, core_type, i;

dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -299,7 +300,9 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
}
}

- mutex_init(&dev->enc_mutex);
+ for (i = 0; i < MTK_VENC_CORE_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_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
index 023b6eb8b20c..fdecf1d24b25 100644
--- a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
@@ -448,7 +448,8 @@ 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, NULL);
+ ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS,
+ NULL, bs_buf, NULL, MTK_VENC_CORE0);
if (ret)
return ret;

@@ -474,7 +475,8 @@ 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, NULL);
+ ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS,
+ NULL, bs_buf, NULL, MTK_VENC_CORE0);
if (ret)
return ret;

@@ -516,7 +518,8 @@ static int h264_encode_header(struct venc_h264_inst *inst,
static int h264_encode_frame(struct venc_h264_inst *inst,
struct venc_frm_buf *frm_buf,
struct mtk_vcodec_mem *bs_buf,
- unsigned int *bs_size)
+ unsigned int *bs_size,
+ int core_id)
{
int ret = 0;
unsigned int irq_status;
@@ -536,7 +539,8 @@ static int h264_encode_frame(struct venc_h264_inst *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, H264_BS_MODE_FRAME, frm_buf, bs_buf, &frame_info);
+ ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME,
+ frm_buf, bs_buf, &frame_info, core_id);
if (ret)
return ret;

@@ -664,7 +668,7 @@ static int h264_enc_encode(void *handle,

if (!inst->prepend_hdr) {
ret = h264_encode_frame(inst, frm_buf, bs_buf,
- &result->bs_size);
+ &result->bs_size, ctx->core_id);
if (ret)
goto encode_err;
result->is_key_frm = inst->vpu_inst.is_key_frm;
@@ -692,7 +696,7 @@ static int h264_enc_encode(void *handle,
tmp_bs_buf.size = bs_buf->size - (hdr_sz + filler_sz);

ret = h264_encode_frame(inst, frm_buf, &tmp_bs_buf,
- &bs_size_frm);
+ &bs_size_frm, ctx->core_id);
if (ret)
goto encode_err;

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 56ce58f761f1..3b3471d90e21 100644
--- a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
@@ -302,7 +302,8 @@ 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, NULL);
+ ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf,
+ 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 6cbdb7e30bb3..5c5013d0f32e 100644
--- a/drivers/media/platform/mtk-vcodec/venc_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
@@ -14,6 +14,7 @@
#include "venc_drv_if.h"

#include "mtk_vcodec_enc.h"
+#include "mtk_vcodec_enc_core.h"
#include "mtk_vcodec_enc_pm.h"

int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
@@ -31,9 +32,9 @@ int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
return -EINVAL;
}

- mtk_venc_lock(ctx);
+ mtk_venc_lock(ctx, ctx->core_id);
ret = ctx->enc_if->init(ctx);
- mtk_venc_unlock(ctx);
+ mtk_venc_unlock(ctx, ctx->core_id);

return ret;
}
@@ -43,9 +44,9 @@ int venc_if_set_param(struct mtk_vcodec_ctx *ctx,
{
int ret = 0;

- mtk_venc_lock(ctx);
+ mtk_venc_lock(ctx, ctx->core_id);
ret = ctx->enc_if->set_param(ctx->drv_handle, type, in);
- mtk_venc_unlock(ctx);
+ mtk_venc_unlock(ctx, ctx->core_id);

return ret;
}
@@ -56,24 +57,14 @@ 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);
+ venc_encode_prepare(ctx, opt);

- 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, 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;
}

@@ -84,11 +75,57 @@ int venc_if_deinit(struct mtk_vcodec_ctx *ctx)
if (!ctx->drv_handle)
return 0;

- mtk_venc_lock(ctx);
+ mtk_venc_lock(ctx, ctx->core_id);
ret = ctx->enc_if->deinit(ctx->drv_handle);
- mtk_venc_unlock(ctx);
+ mtk_venc_unlock(ctx, ctx->core_id);

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_core_dev *core;
+
+ if (ctx->dev->venc_pdata->core_mode == VENC_DUAL_CORE_MODE) {
+ if (ctx->enc_idx & 0x01)
+ ctx->core_id = MTK_VENC_CORE1;
+ else
+ ctx->core_id = MTK_VENC_CORE0;
+ } else {
+ ctx->core_id = MTK_VENC_CORE0;
+ }
+ mtk_venc_lock(ctx, ctx->core_id);
+
+ spin_lock_irqsave(&ctx->dev->irqlock, flags);
+
+ if (ctx->dev->venc_pdata->core_mode == VENC_DUAL_CORE_MODE) {
+ core = ctx->dev->enc_core_dev[ctx->core_id];
+
+ core->curr_ctx = ctx;
+ } else {
+ ctx->dev->curr_ctx = ctx;
+ }
+
+ spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+
+ mtk_vcodec_enc_clock_on(ctx->dev, ctx->core_id);
+}
+
+void venc_encode_unprepare(struct mtk_vcodec_ctx *ctx,
+ enum venc_start_opt opt)
+{
+ unsigned long flags;
+
+ if (ctx->dev->venc_pdata->core_mode == VENC_SINGLE_CORE_MODE ||
+ opt == VENC_START_OPT_ENCODE_SEQUENCE_HEADER) {
+ mtk_vcodec_enc_clock_off(ctx->dev, ctx->core_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->core_id);
+ }
+}
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/drivers/media/platform/mtk-vcodec/venc_drv_if.h
index 0b04a1020873..15e9a2ab9cda 100644
--- a/drivers/media/platform/mtk-vcodec/venc_drv_if.h
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.h
@@ -167,4 +167,9 @@ 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 d3570c4c177d..a7219c10013b 100644
--- a/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
@@ -225,9 +225,11 @@ int vpu_enc_set_param(struct venc_vpu_inst *vpu,
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,
- struct venc_frame_info *frame_info)
+ struct venc_frame_info *frame_info,
+ int core_id)
{
const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx);
+ const int core_mode = MTK_ENC_CORE_MODE(vpu->ctx);
size_t msg_size = is_ext ?
sizeof(struct venc_ap_ipi_msg_enc_ext) :
sizeof(struct venc_ap_ipi_msg_enc);
@@ -261,6 +263,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 (core_mode == VENC_DUAL_CORE_MODE) {
+ out.data_item = 4;
+ out.data[3] = core_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 f83bc1b3f2bf..a8055eb62f7c 100644
--- a/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
+++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
@@ -45,7 +45,8 @@ int vpu_enc_set_param(struct venc_vpu_inst *vpu,
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,
- struct venc_frame_info *frame_info);
+ struct venc_frame_info *frame_info,
+ int core_id);
int vpu_enc_deinit(struct venc_vpu_inst *vpu);

#endif
--
2.18.0

2022-01-18 02:34:31

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v2, 03/10] dt-bindings: media: mtk-vcodec: Adds encoder cores dt-bindings for mt8195

On Mon, 17 Jan 2022 20:06:08 +0800, Irui Wang wrote:
> Adds encoder cores dt-bindings for mt8195
>
> Signed-off-by: Irui Wang <[email protected]>
> ---
> .../media/mediatek,vcodec-encoder-core.yaml | 214 ++++++++++++++++++
> 1 file changed, 214 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
>

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.example.dts:20:18: fatal error: dt-bindings/memory/mt8195-memory-port.h: No such file or directory
20 | #include <dt-bindings/memory/mt8195-memory-port.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.lib:373: Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1413: dt_binding_check] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1580741

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.

2022-01-21 19:16:12

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v2, 03/10] dt-bindings: media: mtk-vcodec: Adds encoder cores dt-bindings for mt8195

On Mon, Jan 17, 2022 at 08:06:08PM +0800, Irui Wang wrote:
> Adds encoder cores dt-bindings for mt8195
>
> Signed-off-by: Irui Wang <[email protected]>
> ---
> .../media/mediatek,vcodec-encoder-core.yaml | 214 ++++++++++++++++++
> 1 file changed, 214 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
> new file mode 100644
> index 000000000000..d1e7bfa50bce
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
> @@ -0,0 +1,214 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/media/mediatek,vcodec-encoder-core.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: Mediatek Video Encoder Accelerator With Multi Core
> +
> +maintainers:
> + - Irui Wang <[email protected]>
> +
> +description: |
> + Mediatek Video Encode is the video encode hardware present in Mediatek
> + SoCs which supports high resolution encoding functionalities. Required
> + parent and child device node.
> +
> +properties:
> + compatible:
> + const: mediatek,mt8195-vcodec-enc
> +
> + mediatek,scp:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1

'phandle' is already 1 item. Drop.

> + description: |
> + The node of system control processor (SCP), using
> + the remoteproc & rpmsg framework.
> +
> + iommus:
> + minItems: 1
> + maxItems: 32
> + description: |
> + List of the hardware port in respective IOMMU block for current Socs.
> + Refer to bindings/iommu/mediatek,iommu.yaml.
> +
> + dma-ranges:
> + maxItems: 1
> + description: |
> + Describes the physical address space of IOMMU maps to memory.
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 1
> +
> + ranges: true
> +
> +# Required child node:
> +patternProperties:
> + "venc_core0@1a020000":

Address should generally not be defined in the node name schema:

'^venc-core0@'

Though I think you should also drop the '0' here. The unit-address is
enough to distinguish each instance. Then the schemas for each child
node can be combined.

> + type: object
> +
> + properties:
> + compatible:
> + const: mediatek,mtk-venc-core0

Is the programming model for each core the same, but just different
codecs implemented? I'd just add a property to indicate which codec if
that's not discoverable.

> +
> + reg:
> + maxItems: 1
> +
> + iommus:
> + minItems: 1
> + maxItems: 32
> + description: |
> + List of the hardware port in respective IOMMU block for current Socs.
> + Refer to bindings/iommu/mediatek,iommu.yaml.
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + clock-names:
> + items:
> + - const: MT_CG_VENC0

The name is supposed to be local to the instance reflecting what the
clock drives rather than a top-level or clock controller name. Lowercase
is also the norm. Given there's only 1 clock, I'd just drop the name.

> +
> + assigned-clocks:
> + maxItems: 1
> +
> + assigned-clock-parents:
> + maxItems: 1

These are always allowed and shouldn't be required.

> +
> + power-domains:
> + maxItems: 1
> +
> + required:
> + - compatible
> + - reg
> + - iommus
> + - interrupts
> + - clocks
> + - clock-names
> + - assigned-clocks
> + - assigned-clock-parents
> + - power-domains
> +
> + additionalProperties: false
> +
> + "venc_core1@1b020000":
> + type: object
> +
> + properties:
> + compatible:
> + const: mediatek,mtk-venc-core1
> +
> + reg:
> + maxItems: 1
> +
> + iommus:
> + minItems: 1
> + maxItems: 32
> + description: |
> + List of the hardware port in respective IOMMU block for current Socs.
> + Refer to bindings/iommu/mediatek,iommu.yaml.
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + clock-names:
> + items:
> + - const: MT_CG_VENC1
> +
> + assigned-clocks:
> + maxItems: 1
> +
> + assigned-clock-parents:
> + maxItems: 1
> +
> + power-domains:
> + maxItems: 1
> +
> + required:
> + - compatible
> + - reg
> + - iommus
> + - interrupts
> + - clocks
> + - clock-names
> + - assigned-clocks
> + - assigned-clock-parents
> + - power-domains
> +
> + additionalProperties: false
> +
> +required:
> + - compatible
> + - mediatek,scp
> + - iommus
> + - dma-ranges
> + - ranges
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/memory/mt8195-memory-port.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> + #include <dt-bindings/clock/mt8195-clk.h>
> + #include <dt-bindings/power/mt8195-power.h>
> +
> + venc {
> + compatible = "mediatek,mt8195-vcodec-enc";
> + mediatek,scp = <&scp>;
> + iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>;
> + dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> +
> + venc_core0@1a020000 {
> + compatible = "mediatek,mtk-venc-core0";
> + reg = <0x1a020000 0x10000>;
> + iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>,
> + <&iommu_vdo M4U_PORT_L19_VENC_REC>,
> + <&iommu_vdo M4U_PORT_L19_VENC_BSDMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_SV_COMV>,
> + <&iommu_vdo M4U_PORT_L19_VENC_RD_COMV>,
> + <&iommu_vdo M4U_PORT_L19_VENC_CUR_LUMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_CUR_CHROMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_REF_LUMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_REF_CHROMA>;
> + interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH 0>;
> + clocks = <&vencsys CLK_VENC_VENC>;
> + clock-names = "MT_CG_VENC0";
> + assigned-clocks = <&topckgen CLK_TOP_VENC>;
> + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
> + power-domains = <&spm MT8195_POWER_DOMAIN_VENC>;
> + };
> +
> + venc_core1@1b020000 {
> + compatible = "mediatek,mtk-venc-core1";
> + reg = <0x1b020000 0x10000>;
> + iommus = <&iommu_vpp M4U_PORT_L20_VENC_RCPU>,
> + <&iommu_vpp M4U_PORT_L20_VENC_REC>,
> + <&iommu_vpp M4U_PORT_L20_VENC_BSDMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_SV_COMV>,
> + <&iommu_vpp M4U_PORT_L20_VENC_RD_COMV>,
> + <&iommu_vpp M4U_PORT_L20_VENC_CUR_LUMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_CUR_CHROMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_REF_LUMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_REF_CHROMA>;
> + interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH 0>;
> + clocks = <&vencsys_core1 CLK_VENC_CORE1_VENC>;
> + clock-names = "MT_CG_VENC1";
> + assigned-clocks = <&topckgen CLK_TOP_VENC>;
> + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
> + power-domains = <&spm MT8195_POWER_DOMAIN_VENC_CORE1>;
> + };
> + };
> --
> 2.18.0
>
>

Subject: Re: [PATCH v2, 04/10] media: mtk-vcodec: Enable venc dual core usage

Il 17/01/22 13:06, Irui Wang ha scritto:
> Adds new venc core mode to indicate different venc hardware mode:
> VENC_SINGLE_CORE_MODE means only one core, the device has its own
> power/clk/irq, init_clk/request_irq helper can be used.
>
> VENC_DUAL_CORE_MODE means more than one core inside, the core device
> can use the init_clk/request_irq helper to initialize their own
> power/clk/irq. And the main device doesn't need use these helper anymore.
>
> MT8195 has two H264 venc cores, enable dual_core_mode for it.
>
> Signed-off-by: Irui Wang <[email protected]>
> ---
> drivers/media/platform/mtk-vcodec/Makefile | 4 +-
> .../platform/mtk-vcodec/mtk_vcodec_drv.h | 22 +++
> .../platform/mtk-vcodec/mtk_vcodec_enc_core.c | 153 ++++++++++++++++++
> .../platform/mtk-vcodec/mtk_vcodec_enc_core.h | 36 +++++
> .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 88 +++++-----
> 5 files changed, 266 insertions(+), 37 deletions(-)
> create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
> create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h
>
> diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
> index 93e7a343b5b0..c472b221bd6b 100644
> --- a/drivers/media/platform/mtk-vcodec/Makefile
> +++ b/drivers/media/platform/mtk-vcodec/Makefile
> @@ -3,7 +3,8 @@
> obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
> mtk-vcodec-enc.o \
> mtk-vcodec-common.o \
> - mtk-vcodec-dec-hw.o
> + mtk-vcodec-dec-hw.o \
> + mtk-vcodec-enc-core.o
>
> mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
> vdec/vdec_vp8_if.o \
> @@ -32,6 +33,7 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \
> venc_drv_if.o \
> venc_vpu_if.o \
>
> +mtk-vcodec-enc-core-y := mtk_vcodec_enc_core.o
>
> mtk-vcodec-common-y := mtk_vcodec_intr.o \
> mtk_vcodec_util.o \
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> index f78463ff4551..9e4e4290a69a 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> @@ -117,6 +117,23 @@ enum mtk_vdec_hw_count {
> MTK_VDEC_MAX_HW_COUNT,
> };
>
> +/*
> + * enum mtk_venc_core_id -- encoder core id
> + */
> +enum mtk_venc_core_id {
> + MTK_VENC_CORE0 = 0,
> + MTK_VENC_CORE1 = 1,

You don't have to say "= 1" for core1, just...

MTK_VENC_CORE0 = 0,
MTK_VENC_CORE1,

...is fine, and better.

> + MTK_VENC_CORE_MAX,
> +};
> +
> +/**
> + * enmu mtk_venc_core_mode - Used to indicate different encode mode
> + */
> +enum mtk_venc_core_mode {
> + VENC_SINGLE_CORE_MODE = 0,
> + VENC_DUAL_CORE_MODE = 1,
> +};
> +
> /*
> * struct mtk_video_fmt - Structure used to store information about pixelformats
> */
> @@ -420,6 +437,7 @@ struct mtk_vcodec_dec_pdata {
> * @output_formats: array of supported output formats
> * @num_output_formats: number of entries in output_formats
> * @core_type: stand for h264 or vp8 encode
> + * @core_mode: indicate encode core mode
> */
> struct mtk_vcodec_enc_pdata {
> bool uses_ext;
> @@ -430,6 +448,7 @@ struct mtk_vcodec_enc_pdata {
> const struct mtk_video_fmt *output_formats;
> size_t num_output_formats;
> int core_type;
> + enum mtk_venc_core_mode core_mode;
> };
>
> #define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext)
> @@ -479,6 +498,7 @@ struct mtk_vcodec_enc_pdata {
> * @subdev_dev: subdev hardware device
> * @subdev_prob_done: check whether all used hw device is prob done
> * @subdev_bitmap: used to record hardware is ready or not
> + * @enc_core_dev: used to store venc core device
> */
> struct mtk_vcodec_dev {
> struct v4l2_device v4l2_dev;
> @@ -524,6 +544,8 @@ struct mtk_vcodec_dev {
> void *subdev_dev[MTK_VDEC_HW_MAX];
> int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev);
> DECLARE_BITMAP(subdev_bitmap, MTK_VDEC_HW_MAX);
> +
> + void *enc_core_dev[MTK_VENC_CORE_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_core.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
> new file mode 100644
> index 000000000000..d84914f615a5
> --- /dev/null
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
> @@ -0,0 +1,153 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +
> +#include "mtk_vcodec_drv.h"
> +#include "mtk_vcodec_enc.h"
> +#include "mtk_vcodec_enc_core.h"
> +
> +static const struct of_device_id mtk_venc_core_ids[] = {
> + {
> + .compatible = "mediatek,mtk-venc-core0",
> + .data = (void *)MTK_VENC_CORE0,
> + },
> + {
> + .compatible = "mediatek,mtk-venc-core1",
> + .data = (void *)MTK_VENC_CORE1,
> + },
> + {},
> +};

Hello Irui,

You don't need a different compatible for the different cores, as in the
declaration, there's nothing special that differentiates them that much.

I understand that there may be a need to differentiate the core number, as
in, CORE0 always has to be the leader, while CORE1 would be the follower,
but this is not a good reason to give them a different compatible string.

I want to make you aware that Kyrie Wu did the same thing as you did here
and in my review on his patch I was able to give an extensive example of
how this should look; the exactly same logic would apply to this patch.

Please have a look here: https://patchwork.kernel.org/comment/24726607/

P.S.: In short, you should have only one "mediatek,mtk-venc-hw" compatible
used for probing both cores.

> +MODULE_DEVICE_TABLE(of, mtk_venc_core_ids);
> +
> +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_core_irq_handler(int irq, void *priv)
> +{
> + struct mtk_venc_core_dev *core = priv;
> + struct mtk_vcodec_ctx *ctx;
> + unsigned long flags;
> + void __iomem *addr;
> +
> + spin_lock_irqsave(&core->main_dev->irqlock, flags);
> + ctx = core->curr_ctx;
> + spin_unlock_irqrestore(&core->main_dev->irqlock, flags);
> + if (!ctx)
> + return IRQ_HANDLED;
> +
> + mtk_v4l2_debug(1, "id=%d core :%d", ctx->id, core->core_id);
> +
> + addr = core->reg_base + MTK_VENC_IRQ_ACK_OFFSET;
> + ctx->irq_status = readl(core->reg_base + MTK_VENC_IRQ_STATUS_OFFSET);
> + clean_irq_status(ctx->irq_status, addr);
> +
> + wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, 0);
> + return IRQ_HANDLED;
> +}
> +
> +static int mtk_venc_core_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct mtk_venc_core_dev *core;
> + struct mtk_vcodec_dev *main_dev;
> + int ret;
> +
> + if (!dev->parent) {
> + dev_err(dev, "No parent for venc core device\n");
> + return -ENODEV;
> + }

Please, use dev_err_probe(), here and everywhere else.

> +
> + main_dev = dev_get_drvdata(dev->parent);
> + if (!main_dev) {
> + dev_err(dev, "Failed to get parent driver data");
> + return -EINVAL;
> + }
> +
> + core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL);
> + if (!core)
> + return -ENOMEM;
> +
> + core->plat_dev = pdev;
> +
> + core->reg_base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(core->reg_base)) {
> + dev_err(&pdev->dev, "Failed to get reg base");
> + ret = PTR_ERR(core->reg_base);
> + goto err;

You don't need the "err" label. Also, you can return dev_err_probe here too.
Example:

return dev_err_probe(&pdev->dev, PTR_ERR(core->reg_base),
"Failed to get reg base\n");

> + }
> +
> + core->enc_irq = platform_get_irq(pdev, 0);
> + if (core->enc_irq < 0) {
> + dev_err(&pdev->dev, "Failed to get irq resource");
> + ret = core->enc_irq;
> + goto err;
> + }
> +
> + ret = devm_request_irq(&pdev->dev, core->enc_irq,
> + mtk_enc_core_irq_handler, 0,
> + pdev->name, core);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "Failed to install core->enc_irq %d (%d)",
> + core->enc_irq, ret);
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + core->core_id =

core_id would be 0 if "mediatek,hw-leader", N if it's not a mediatek,hw-leader.

> + (enum mtk_venc_core_id)of_device_get_match_data(&pdev->dev);
> + if (core->core_id < 0 || core->core_id >= MTK_VENC_CORE_MAX) {
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + main_dev->enc_core_dev[core->core_id] = core;
> + core->main_dev = main_dev;
> +
> + platform_set_drvdata(pdev, core);
> +
> + dev_info(dev, "Venc core :%d probe done\n", core->core_id);

Please change this to dev_dbg().

> +
> + return 0;
> +
> +err:
> + return ret;
> +}
> +
> +static struct platform_driver mtk_venc_core_driver = {
> + .probe = mtk_venc_core_probe,
> + .driver = {
> + .name = "mtk-venc-core",
> + .of_match_table = mtk_venc_core_ids,
> + },
> +};
> +module_platform_driver(mtk_venc_core_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Mediatek video encoder core driver");
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h
> new file mode 100644
> index 000000000000..856681989869
> --- /dev/null
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#ifndef _MTK_VCODEC_ENC_CORE_H_
> +#define _MTK_VCODEC_ENC_CORE_H_
> +
> +#include <linux/platform_device.h>
> +#include "mtk_vcodec_drv.h"
> +
> +/*

I love when developers try to write kerneldoc, this is something that
should really be done *always*, so thank you for this!!!!

....but you missed something here: for this to be parsed by kerneldoc,
you need to do:

/**
^^^ this one :))

* struct mtk_venc_core_dev - driver data

P.S.: https://docs.kernel.org/doc-guide/kernel-doc.html

> + * struct mtk_venc_core_dev - driver data
> + * @plat_dev: platform_device
> + * @main_dev: main 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 core irq status
> + * @enc_irq: venc device irq
> + * @core id: for venc core id: core#0, core#1...
> + */
> +struct mtk_venc_core_dev {
> + struct platform_device *plat_dev;
> + struct mtk_vcodec_dev *main_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_CORE_H_ */


Thanks,
Angelo

Subject: Re: [PATCH v2, 03/10] dt-bindings: media: mtk-vcodec: Adds encoder cores dt-bindings for mt8195

Il 17/01/22 13:06, Irui Wang ha scritto:
> Adds encoder cores dt-bindings for mt8195
>
> Signed-off-by: Irui Wang <[email protected]>
> ---
> .../media/mediatek,vcodec-encoder-core.yaml | 214 ++++++++++++++++++
> 1 file changed, 214 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
> new file mode 100644
> index 000000000000..d1e7bfa50bce
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder-core.yaml
> @@ -0,0 +1,214 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/media/mediatek,vcodec-encoder-core.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: Mediatek Video Encoder Accelerator With Multi Core
> +
> +maintainers:
> + - Irui Wang <[email protected]>
> +
> +description: |
> + Mediatek Video Encode is the video encode hardware present in Mediatek
> + SoCs which supports high resolution encoding functionalities. Required
> + parent and child device node.
> +
> +properties:
> + compatible:
> + const: mediatek,mt8195-vcodec-enc
> +
> + mediatek,scp:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> + description: |
> + The node of system control processor (SCP), using
> + the remoteproc & rpmsg framework.
> +
> + iommus:
> + minItems: 1
> + maxItems: 32
> + description: |
> + List of the hardware port in respective IOMMU block for current Socs.
> + Refer to bindings/iommu/mediatek,iommu.yaml.
> +
> + dma-ranges:
> + maxItems: 1
> + description: |
> + Describes the physical address space of IOMMU maps to memory.
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 1
> +
> + ranges: true
> +
> +# Required child node:
> +patternProperties:
> + "venc_core0@1a020000":

This should be a pattern, venc-coreN where N is a number between 0 and 9,
and any iostart should be allowed, not just 1a020000; doing it that way
allows you to do a spec for all the core subnodes in one.


> + type: object
> +
> + properties:
> + compatible:
> + const: mediatek,mtk-venc-core0
> +

..snip..

> +
> +required:
> + - compatible
> + - mediatek,scp
> + - iommus
> + - dma-ranges
> + - ranges
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/memory/mt8195-memory-port.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> + #include <dt-bindings/clock/mt8195-clk.h>
> + #include <dt-bindings/power/mt8195-power.h>
> +
> + venc {
> + compatible = "mediatek,mt8195-vcodec-enc";
> + mediatek,scp = <&scp>;
> + iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>;
> + dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;

What about doing instead...

#address-cells = <2>;
#size-cells = <2>;
(or fix your dma-ranges property)

and...

ranges = <0 0 0 0x1a020000 0 0x1020000>;
venc-core0@0 {
compatible = "mediatek,mtk-venc-hw";
reg = <0 0 0 0x10000>;
mediatek,hw-leader;
..... other properties .....
};

venc-core1@1000000 {
compatible = "mediatek,mtk-venc-hw";
reg = <0 0x1000000 0 0x10000>;
..... other properties .....
}

Regards,
Angelo

> +
> + venc_core0@1a020000 {
> + compatible = "mediatek,mtk-venc-core0";
> + reg = <0x1a020000 0x10000>;
> + iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>,
> + <&iommu_vdo M4U_PORT_L19_VENC_REC>,
> + <&iommu_vdo M4U_PORT_L19_VENC_BSDMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_SV_COMV>,
> + <&iommu_vdo M4U_PORT_L19_VENC_RD_COMV>,
> + <&iommu_vdo M4U_PORT_L19_VENC_CUR_LUMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_CUR_CHROMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_REF_LUMA>,
> + <&iommu_vdo M4U_PORT_L19_VENC_REF_CHROMA>;
> + interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH 0>;
> + clocks = <&vencsys CLK_VENC_VENC>;
> + clock-names = "MT_CG_VENC0";
> + assigned-clocks = <&topckgen CLK_TOP_VENC>;
> + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
> + power-domains = <&spm MT8195_POWER_DOMAIN_VENC>;
> + };
> +
> + venc_core1@1b020000 {
> + compatible = "mediatek,mtk-venc-core1";
> + reg = <0x1b020000 0x10000>;
> + iommus = <&iommu_vpp M4U_PORT_L20_VENC_RCPU>,
> + <&iommu_vpp M4U_PORT_L20_VENC_REC>,
> + <&iommu_vpp M4U_PORT_L20_VENC_BSDMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_SV_COMV>,
> + <&iommu_vpp M4U_PORT_L20_VENC_RD_COMV>,
> + <&iommu_vpp M4U_PORT_L20_VENC_CUR_LUMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_CUR_CHROMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_REF_LUMA>,
> + <&iommu_vpp M4U_PORT_L20_VENC_REF_CHROMA>;
> + interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH 0>;
> + clocks = <&vencsys_core1 CLK_VENC_CORE1_VENC>;
> + clock-names = "MT_CG_VENC1";
> + assigned-clocks = <&topckgen CLK_TOP_VENC>;
> + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
> + power-domains = <&spm MT8195_POWER_DOMAIN_VENC_CORE1>;
> + };
> + };

Subject: Re: [PATCH v2, 04/10] media: mtk-vcodec: Enable venc dual core usage

Il 04/03/22 03:12, Irui Wang ha scritto:
> Hello, Angelo,
>
> Many thanks for your review.
>
> On Thu, 2022-03-03 at 15:27 +0100, AngeloGioacchino Del Regno wrote:
>> Il 17/01/22 13:06, Irui Wang ha scritto:
>>> Adds new venc core mode to indicate different venc hardware mode:
>>> VENC_SINGLE_CORE_MODE means only one core, the device has its own
>>> power/clk/irq, init_clk/request_irq helper can be used.
>>>
>>> VENC_DUAL_CORE_MODE means more than one core inside, the core
>>> device
>>> can use the init_clk/request_irq helper to initialize their own
>>> power/clk/irq. And the main device doesn't need use these helper
>>> anymore.
>>>
>>> MT8195 has two H264 venc cores, enable dual_core_mode for it.
>>>
>>> Signed-off-by: Irui Wang <[email protected]>
>>> ---
>>> drivers/media/platform/mtk-vcodec/Makefile | 4 +-
>>> .../platform/mtk-vcodec/mtk_vcodec_drv.h | 22 +++
>>> .../platform/mtk-vcodec/mtk_vcodec_enc_core.c | 153
>>> ++++++++++++++++++
>>> .../platform/mtk-vcodec/mtk_vcodec_enc_core.h | 36 +++++
>>> .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 88 +++++-----
>>> 5 files changed, 266 insertions(+), 37 deletions(-)
>>> create mode 100644 drivers/media/platform/mtk-
>>> vcodec/mtk_vcodec_enc_core.c
>>> create mode 100644 drivers/media/platform/mtk-
>>> vcodec/mtk_vcodec_enc_core.h
>>>
>>> diff --git a/drivers/media/platform/mtk-vcodec/Makefile
>>> b/drivers/media/platform/mtk-vcodec/Makefile
>>> index 93e7a343b5b0..c472b221bd6b 100644
>>> --- a/drivers/media/platform/mtk-vcodec/Makefile
>>> +++ b/drivers/media/platform/mtk-vcodec/Makefile
>>> @@ -3,7 +3,8 @@
>>> obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
>>> mtk-vcodec-enc.o \
>>> mtk-vcodec-common.o \
>>> - mtk-vcodec-dec-hw.o
>>> + mtk-vcodec-dec-hw.o \
>>> + mtk-vcodec-enc-core.o
>>>
>>> mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
>>> vdec/vdec_vp8_if.o \
>>> @@ -32,6 +33,7 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \
>>> venc_drv_if.o \
>>> venc_vpu_if.o \
>>>
>>> +mtk-vcodec-enc-core-y := mtk_vcodec_enc_core.o
>>>
>>> mtk-vcodec-common-y := mtk_vcodec_intr.o \
>>> mtk_vcodec_util.o \
>>> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
>>> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
>>> index f78463ff4551..9e4e4290a69a 100644
>>> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
>>> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
>>> @@ -117,6 +117,23 @@ enum mtk_vdec_hw_count {
>>> MTK_VDEC_MAX_HW_COUNT,
>>> };
>>>
>>> +/*
>>> + * enum mtk_venc_core_id -- encoder core id
>>> + */
>>> +enum mtk_venc_core_id {
>>> + MTK_VENC_CORE0 = 0,
>>> + MTK_VENC_CORE1 = 1,
>>
>> You don't have to say "= 1" for core1, just...
>>
>> MTK_VENC_CORE0 = 0,
>> MTK_VENC_CORE1,
>>
>> ...is fine, and better.
>
> I will fix it.
>
>>
>>> + MTK_VENC_CORE_MAX,
>>> +};
>>> +
>>> +/**
>>> + * enmu mtk_venc_core_mode - Used to indicate different encode
>>> mode
>>> + */
>>> +enum mtk_venc_core_mode {
>>> + VENC_SINGLE_CORE_MODE = 0,
>>> + VENC_DUAL_CORE_MODE = 1,
>>> +};
>>> +
>>> /*
>>> * struct mtk_video_fmt - Structure used to store information
>>> about pixelformats
>>> */
>>> @@ -420,6 +437,7 @@ struct mtk_vcodec_dec_pdata {
>>> * @output_formats: array of supported output formats
>>> * @num_output_formats: number of entries in output_formats
>>> * @core_type: stand for h264 or vp8 encode
>>> + * @core_mode: indicate encode core mode
>>> */
>>> struct mtk_vcodec_enc_pdata {
>>> bool uses_ext;
>>> @@ -430,6 +448,7 @@ struct mtk_vcodec_enc_pdata {
>>> const struct mtk_video_fmt *output_formats;
>>> size_t num_output_formats;
>>> int core_type;
>>> + enum mtk_venc_core_mode core_mode;
>>> };
>>>
>>> #define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata-
>>>> uses_ext)
>>> @@ -479,6 +498,7 @@ struct mtk_vcodec_enc_pdata {
>>> * @subdev_dev: subdev hardware device
>>> * @subdev_prob_done: check whether all used hw device is prob
>>> done
>>> * @subdev_bitmap: used to record hardware is ready or not
>>> + * @enc_core_dev: used to store venc core device
>>> */
>>> struct mtk_vcodec_dev {
>>> struct v4l2_device v4l2_dev;
>>> @@ -524,6 +544,8 @@ struct mtk_vcodec_dev {
>>> void *subdev_dev[MTK_VDEC_HW_MAX];
>>> int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev);
>>> DECLARE_BITMAP(subdev_bitmap, MTK_VDEC_HW_MAX);
>>> +
>>> + void *enc_core_dev[MTK_VENC_CORE_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_core.c b/drivers/media/platform/mtk-
>>> vcodec/mtk_vcodec_enc_core.c
>>> new file mode 100644
>>> index 000000000000..d84914f615a5
>>> --- /dev/null
>>> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_core.c
>>> @@ -0,0 +1,153 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Copyright (c) 2021 MediaTek Inc.
>>> + */
>>> +
>>> +#include <linux/interrupt.h>
>>> +#include <linux/irq.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of_platform.h>
>>> +#include <linux/pm_runtime.h>
>>> +#include <linux/slab.h>
>>> +
>>> +#include "mtk_vcodec_drv.h"
>>> +#include "mtk_vcodec_enc.h"
>>> +#include "mtk_vcodec_enc_core.h"
>>> +
>>> +static const struct of_device_id mtk_venc_core_ids[] = {
>>> + {
>>> + .compatible = "mediatek,mtk-venc-core0",
>>> + .data = (void *)MTK_VENC_CORE0,
>>> + },
>>> + {
>>> + .compatible = "mediatek,mtk-venc-core1",
>>> + .data = (void *)MTK_VENC_CORE1,
>>> + },
>>> + {},
>>> +};
>>
>> Hello Irui,
>>
>> You don't need a different compatible for the different cores, as in
>> the
>> declaration, there's nothing special that differentiates them that
>> much.
>>
>> I understand that there may be a need to differentiate the core
>> number, as
>> in, CORE0 always has to be the leader, while CORE1 would be the
>> follower,
>> but this is not a good reason to give them a different compatible
>> string.
>>
>> I want to make you aware that Kyrie Wu did the same thing as you did
>> here
>> and in my review on his patch I was able to give an extensive example
>> of
>> how this should look; the exactly same logic would apply to this
>> patch.
>>
>> Please have a look here:
>> https://patchwork.kernel.org/comment/24726607/
>>
>> P.S.: In short, you should have only one "mediatek,mtk-venc-hw"
>> compatible
>> used for probing both cores.
>
> thanks for your suggestions, with your example, venc can be rewritten
> like this:
> venc {
> compatible = "mediatek,mt8195-vcodec-enc";
> ..... other properties .....
>
> venc_core0 {
> compatible = "mediatek,mtk-venc-hw";
> mediatek,hw-leader;//mediatek,venc-core0;
> ..... other properties .....
> };
>
> venc_core1 {
> compatible = "mediatek,mtk-venc-hw";
> //mediatek,venc-core1;
> ..... other properties .....
> };
> };
> I will rewrite this code if it matches your suggestions.

Yes, exactly. Just one nit, please don't use underscores.

venc_core0: venc-hw@(addr)
this is fine ^

venc_core0: venc_hw@(addr)
this is NOT ok ^^

By the way, one (or more than one) of the commits in this series
is not working correctly, giving a kernel panic on dma mem alloc.

Looking forward to see the new version!

Regards,
Angelo