This series enables the hardware decoder present on mt8183. At first
glance, the only missing piece is the devicetree node for it, however,
simply adding it as is would cause an address collision between the
first register iospace and the clock-controller node, so a rework of the
dt-binding and driver, as well as addition of a new syscon phandle
property, were needed first.
Tested that H264 decoding works with the hardware decoder on
mt8183-kukui-jacuzzi-juniper-sku16, giving a fluster score of 98/135 on
the JVT-AVC_V1 test suite. And ensured other SoCs (MT8192 and MT8195)
still work as usual.
Changes in v4:
- Removed VDEC_SYS reg from mt8173 as well
- Made driver handling cleaner
Changes in v3:
- Switched the handling of the VDEC_HW_ACTIVE bit to use a syscon
instead of the 'active' clock
Changes in v2:
- Merged commit 1 (media: dt-bindings: mediatek,vcodec: Allow single
clock for mt8183) into commit 3 (media: dt-bindings: mediatek,vcodec:
Remove VDEC_SYS for mt8183)
- Further constrained properties in dt-binding
- Added CLK_IGNORE_UNUSED flag to active clock
- Reformatted reg-names in DT node
Nícolas F. R. A. Prado (6):
media: dt-bindings: mediatek,vcodec: Allow single clock for mt8183
media: dt-bindings: mediatek,vcodec: Don't require assigned-clocks
media: dt-bindings: mediatek,vcodec: Remove VDEC_SYS register space
media: mediatek: vcodec: Define address for VDEC_HW_ACTIVE
media: mediatek: vcodec: Read HW active status from syscon
arm64: dts: mediatek: mt8173: Drop VDEC_SYS reg from decoder
Yunfei Dong (1):
arm64: dts: mediatek: mt8183: Add decoder
.../media/mediatek,vcodec-decoder.yaml | 67 ++++++++++++----
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 8 +-
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 30 ++++++++
.../mediatek/vcodec/mtk_vcodec_dec_drv.c | 76 ++++++++++++++++---
.../mediatek/vcodec/mtk_vcodec_dec_hw.c | 4 +-
.../mediatek/vcodec/mtk_vcodec_dec_hw.h | 3 +-
.../platform/mediatek/vcodec/mtk_vcodec_drv.h | 1 +
.../mediatek/vcodec/mtk_vcodec_util.c | 15 ++++
.../mediatek/vcodec/mtk_vcodec_util.h | 2 +
.../mediatek/vcodec/vdec/vdec_vp8_if.c | 10 +--
10 files changed, 177 insertions(+), 39 deletions(-)
--
2.41.0
Remove the requirement of a VDEC_SYS reg iospace for both MT8173 and
MT8183. To achieve that, rely on a vdecsys syscon to be passed through
the DT, and use it to directly read the VDEC_HW_ACTIVE bit during IRQ
handling to check whether the HW is active. Also update the VP8 stateful
decoder to use the syscon, if present, for writes to VDEC_SYS.
The old behavior is still present when reg-names aren't supplied, as
to keep backward compatibility.
Signed-off-by: Nícolas F. R. A. Prado <[email protected]>
---
Changes in v4:
- Added new helper and updated VP8 stateful decoder to use it, so the
syscon can also be used by mt8173
- Made handling cleaner
- Reworded commit
Changes in v3:
- Switched handling of VDEC_HW_ACTIVE to use a syscon instead of the
'active' clock
- Reworded commit
- Removed changes to subdev part of driver, since they aren't used by
MT8183
.../mediatek/vcodec/mtk_vcodec_dec_drv.c | 76 ++++++++++++++++---
.../platform/mediatek/vcodec/mtk_vcodec_drv.h | 1 +
.../mediatek/vcodec/mtk_vcodec_util.c | 15 ++++
.../mediatek/vcodec/mtk_vcodec_util.h | 2 +
.../mediatek/vcodec/vdec/vdec_vp8_if.c | 10 +--
5 files changed, 86 insertions(+), 18 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
index 83780d29a9cf..d83c2eb6f118 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
@@ -8,10 +8,12 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>
@@ -38,22 +40,30 @@ static int mtk_vcodec_get_hw_count(struct mtk_vcodec_dev *dev)
}
}
+static bool mtk_vcodec_is_hw_active(struct mtk_vcodec_dev *dev)
+{
+ u32 cg_status;
+
+ if (dev->vdecsys_regmap)
+ return !regmap_test_bits(dev->vdecsys_regmap, VDEC_HW_ACTIVE_ADDR,
+ VDEC_HW_ACTIVE_MASK);
+
+ cg_status = readl(dev->reg_base[VDEC_SYS] + VDEC_HW_ACTIVE_ADDR);
+ return !FIELD_GET(VDEC_HW_ACTIVE_MASK, cg_status);
+}
+
static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
{
struct mtk_vcodec_dev *dev = priv;
struct mtk_vcodec_ctx *ctx;
- u32 cg_status = 0;
unsigned int dec_done_status = 0;
void __iomem *vdec_misc_addr = dev->reg_base[VDEC_MISC] +
VDEC_IRQ_CFG_REG;
ctx = mtk_vcodec_get_curr_ctx(dev, MTK_VDEC_CORE);
- /* check if HW active or not */
- cg_status = readl(dev->reg_base[0] + VDEC_HW_ACTIVE_ADDR);
- if ((cg_status & VDEC_HW_ACTIVE_MASK) != 0) {
- mtk_v4l2_err("DEC ISR, VDEC active is not 0x0 (0x%08x)",
- cg_status);
+ if (!mtk_vcodec_is_hw_active(dev)) {
+ mtk_v4l2_err("DEC ISR, VDEC active is not 0x0");
return IRQ_HANDLED;
}
@@ -82,6 +92,33 @@ static int mtk_vcodec_get_reg_bases(struct mtk_vcodec_dev *dev)
{
struct platform_device *pdev = dev->plat_dev;
int reg_num, i;
+ struct resource *res;
+ bool has_vdecsys_reg;
+ static const char * const mtk_dec_reg_names[] = {
+ "misc",
+ "ld",
+ "top",
+ "cm",
+ "ad",
+ "av",
+ "pp",
+ "hwd",
+ "hwq",
+ "hwb",
+ "hwg"
+ };
+
+ /*
+ * If we have reg-names in devicetree, this means that we're on a new
+ * register organization, which implies that the VDEC_SYS iospace gets
+ * R/W through a syscon (regmap).
+ * Here we try to get the "misc" iostart only to check if we have reg-names
+ */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "misc");
+ if (res)
+ has_vdecsys_reg = false;
+ else
+ has_vdecsys_reg = true;
/* Sizeof(u32) * 4 bytes for each register base. */
reg_num = of_property_count_elems_of_size(pdev->dev.of_node, "reg",
@@ -91,12 +128,29 @@ static int mtk_vcodec_get_reg_bases(struct mtk_vcodec_dev *dev)
return -EINVAL;
}
- for (i = 0; i < reg_num; i++) {
- dev->reg_base[i] = devm_platform_ioremap_resource(pdev, i);
- if (IS_ERR(dev->reg_base[i]))
- return PTR_ERR(dev->reg_base[i]);
+ if (has_vdecsys_reg) {
+ for (i = 0; i < reg_num; i++) {
+ dev->reg_base[i] = devm_platform_ioremap_resource(pdev, i);
+ if (IS_ERR(dev->reg_base[i]))
+ return PTR_ERR(dev->reg_base[i]);
+
+ mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
+ }
+ } else {
+ for (i = 0; i < reg_num; i++) {
+ dev->reg_base[i+1] = devm_platform_ioremap_resource_byname(pdev, mtk_dec_reg_names[i]);
+ if (IS_ERR(dev->reg_base[i+1]))
+ return PTR_ERR(dev->reg_base[i+1]);
- mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
+ mtk_v4l2_debug(2, "reg[%d] base=%p", i+1, dev->reg_base[i+1]);
+ }
+
+ dev->vdecsys_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "mediatek,vdecsys");
+ if (IS_ERR(dev->vdecsys_regmap)) {
+ dev_err(&pdev->dev, "Missing mediatek,vdecsys property");
+ return PTR_ERR(dev->vdecsys_regmap);
+ }
}
return 0;
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
index f17d67e781c9..0b430936f67d 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
@@ -489,6 +489,7 @@ struct mtk_vcodec_dev {
void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE];
const struct mtk_vcodec_dec_pdata *vdec_pdata;
const struct mtk_vcodec_enc_pdata *venc_pdata;
+ struct regmap *vdecsys_regmap;
struct mtk_vcodec_fw *fw_handler;
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c
index f214e6f67005..8aaa5eb45444 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/regmap.h>
#include "mtk_vcodec_dec_hw.h"
#include "mtk_vcodec_drv.h"
@@ -34,6 +35,20 @@ void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
}
EXPORT_SYMBOL(mtk_vcodec_get_reg_addr);
+int mtk_vcodec_write_vdecsys(struct mtk_vcodec_ctx *ctx, unsigned int reg,
+ unsigned int val)
+{
+ struct mtk_vcodec_dev *dev = ctx->dev;
+
+ if (dev->vdecsys_regmap)
+ return regmap_write(dev->vdecsys_regmap, reg, val);
+
+ writel(val, dev->reg_base[VDEC_SYS] + reg);
+
+ return 0;
+}
+EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
+
int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
struct mtk_vcodec_mem *mem)
{
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h
index 88d389b65f13..c8bb4fc5153f 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h
@@ -70,6 +70,8 @@ extern int mtk_vcodec_dbg;
void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
unsigned int reg_idx);
+int mtk_vcodec_write_vdecsys(struct mtk_vcodec_ctx *ctx, unsigned int reg,
+ unsigned int val);
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/mediatek/vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_if.c
index 88c046731754..2592fa37b4c8 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_if.c
@@ -91,7 +91,6 @@ struct vdec_vp8_vsi {
/**
* struct vdec_vp8_hw_reg_base - HW register base
- * @sys : base address for sys
* @misc : base address for misc
* @ld : base address for ld
* @top : base address for top
@@ -100,7 +99,6 @@ struct vdec_vp8_vsi {
* @hwb : base address for hwb
*/
struct vdec_vp8_hw_reg_base {
- void __iomem *sys;
void __iomem *misc;
void __iomem *ld;
void __iomem *top;
@@ -170,7 +168,6 @@ static void get_hw_reg_base(struct vdec_vp8_inst *inst)
inst->reg_base.top = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_TOP);
inst->reg_base.cm = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_CM);
inst->reg_base.hwd = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWD);
- inst->reg_base.sys = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_SYS);
inst->reg_base.misc = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_MISC);
inst->reg_base.ld = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_LD);
inst->reg_base.hwb = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWB);
@@ -222,17 +219,16 @@ static void read_hw_segmentation_data(struct vdec_vp8_inst *inst)
static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
{
u32 val = 0;
- void __iomem *sys = inst->reg_base.sys;
void __iomem *misc = inst->reg_base.misc;
void __iomem *ld = inst->reg_base.ld;
void __iomem *hwb = inst->reg_base.hwb;
void __iomem *hwd = inst->reg_base.hwd;
- writel(0x1, sys + VP8_RW_CKEN_SET);
+ mtk_vcodec_write_vdecsys(inst->ctx, VP8_RW_CKEN_SET, 0x1);
writel(0x101, ld + VP8_WO_VLD_SRST);
writel(0x101, hwb + VP8_WO_VLD_SRST);
- writel(1, sys);
+ mtk_vcodec_write_vdecsys(inst->ctx, 0, 0x1);
val = readl(misc + VP8_RW_MISC_SRST);
writel((val & 0xFFFFFFFE), misc + VP8_RW_MISC_SRST);
@@ -241,7 +237,7 @@ static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
writel(0x71201100, misc + VP8_RW_MISC_FUNC_CON);
writel(0x0, ld + VP8_WO_VLD_SRST);
writel(0x0, hwb + VP8_WO_VLD_SRST);
- writel(0x1, sys + VP8_RW_DCM_CON);
+ mtk_vcodec_write_vdecsys(inst->ctx, VP8_RW_DCM_CON, 0x1);
writel(0x1, misc + VP8_RW_MISC_DCM_CON);
writel(0x1, hwd + VP8_RW_VP8_CTRL);
}
--
2.41.0
From: Yunfei Dong <[email protected]>
Add node for the hardware decoder present on the MT8183 SoC.
Signed-off-by: Yunfei Dong <[email protected]>
Signed-off-by: Qianqian Yan <[email protected]>
Signed-off-by: Frederic Chen <[email protected]>
Signed-off-by: Alexandre Courbot <[email protected]>
Signed-off-by: Nícolas F. R. A. Prado <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
---
(no changes since v3)
Changes in v3:
- Dropped 'active' clock and added the 'mediatek,vdecsys' syscon phandle
property instead
Changes in v2:
- Reformatted reg-names to fit in fewer lines
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 30 ++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 5169779d01df..4144f1ed3ff0 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -2019,6 +2019,36 @@ vdecsys: syscon@16000000 {
#clock-cells = <1>;
};
+ vcodec_dec: video-codec@16020000 {
+ compatible = "mediatek,mt8183-vcodec-dec";
+ reg = <0 0x16020000 0 0x1000>, /* VDEC_MISC */
+ <0 0x16021000 0 0x800>, /* VDEC_VLD */
+ <0 0x16021800 0 0x800>, /* VDEC_TOP */
+ <0 0x16022000 0 0x1000>, /* VDEC_MC */
+ <0 0x16023000 0 0x1000>, /* VDEC_AVCVLD */
+ <0 0x16024000 0 0x1000>, /* VDEC_AVCMV */
+ <0 0x16025000 0 0x1000>, /* VDEC_PP */
+ <0 0x16026800 0 0x800>, /* VP8_VD */
+ <0 0x16027000 0 0x800>, /* VP6_VD */
+ <0 0x16027800 0 0x800>, /* VP8_VL */
+ <0 0x16028400 0 0x400>; /* VP9_VD */
+ reg-names = "misc", "ld", "top", "cm", "ad", "av", "pp",
+ "hwd", "hwq", "hwb", "hwg";
+ interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_LOW>;
+ iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+ <&iommu M4U_PORT_HW_VDEC_PPWRAP_EXT>;
+ mediatek,scp = <&scp>;
+ mediatek,vdecsys = <&vdecsys>;
+ power-domains = <&spm MT8183_POWER_DOMAIN_VDEC>;
+ clocks = <&vdecsys CLK_VDEC_VDEC>;
+ clock-names = "vdec";
+ };
+
larb1: larb@16010000 {
compatible = "mediatek,mt8183-smi-larb";
reg = <0 0x16010000 0 0x1000>;
--
2.41.0
Hi N?colas,
kernel test robot noticed the following build errors:
[auto build test ERROR on media-tree/master]
[also build test ERROR on robh/for-next]
[cannot apply to mbgg-mediatek/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/N-colas-F-R-A-Prado/media-dt-bindings-mediatek-vcodec-Allow-single-clock-for-mt8183/20230628-054734
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20230627214615.1503901-6-nfraprado%40collabora.com
patch subject: [PATCH v4 5/7] media: mediatek: vcodec: Read HW active status from syscon
config: arm-allmodconfig (https://download.01.org/0day-ci/archive/20230628/[email protected]/config)
compiler: arm-linux-gnueabi-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230628/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c: In function 'mtk_vcodec_is_hw_active':
>> drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c:52:17: error: implicit declaration of function 'FIELD_GET' [-Werror=implicit-function-declaration]
52 | return !FIELD_GET(VDEC_HW_ACTIVE_MASK, cg_status);
| ^~~~~~~~~
cc1: some warnings being treated as errors
vim +/FIELD_GET +52 drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
42
43 static bool mtk_vcodec_is_hw_active(struct mtk_vcodec_dev *dev)
44 {
45 u32 cg_status;
46
47 if (dev->vdecsys_regmap)
48 return !regmap_test_bits(dev->vdecsys_regmap, VDEC_HW_ACTIVE_ADDR,
49 VDEC_HW_ACTIVE_MASK);
50
51 cg_status = readl(dev->reg_base[VDEC_SYS] + VDEC_HW_ACTIVE_ADDR);
> 52 return !FIELD_GET(VDEC_HW_ACTIVE_MASK, cg_status);
53 }
54
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki