* [PATCH] [media] platform: constify vb2_ops structures
From: Julia Lawall @ 2016-09-08 23:59 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: kernel-janitors, Fabien Dessenne, linux-samsung-soc,
Krzysztof Kozlowski, Kukjin Kim, Andrzej Hajda, Kamil Debski,
Kyungmin Park, Benoit Parrot, Guennadi Liakhovetski,
Ludovic Desroches, Hyun Kwon, Laurent Pinchart,
Mauro Carvalho Chehab, Michal Simek, Sören Brinkmann,
linux-media, linux-arm-kernel, linux-kernel
Check for vb2_ops structures that are only stored in the ops field of a
vb2_queue structure. That field is declared const, so vb2_ops structures
that have this property can be declared as const also.
The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)
// <smpl>
@r disable optional_qualifier@
identifier i;
position p;
@@
static struct vb2_ops i@p = { ... };
@ok@
identifier r.i;
struct vb2_queue e;
position p;
@@
e.ops = &i@p;
@bad@
position p != {r.p,ok.p};
identifier r.i;
struct vb2_ops e;
@@
e@i@p
@depends on !bad disable optional_qualifier@
identifier r.i;
@@
static
+const
struct vb2_ops i = { ... };
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/media/platform/exynos-gsc/gsc-m2m.c | 2 +-
drivers/media/platform/exynos4-is/fimc-capture.c | 2 +-
drivers/media/platform/exynos4-is/fimc-m2m.c | 2 +-
drivers/media/platform/m2m-deinterlace.c | 2 +-
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 2 +-
drivers/media/platform/mx2_emmaprp.c | 2 +-
drivers/media/platform/rcar-vin/rcar-dma.c | 2 +-
drivers/media/platform/rcar_jpu.c | 2 +-
drivers/media/platform/s5p-g2d/g2d.c | 2 +-
drivers/media/platform/s5p-jpeg/jpeg-core.c | 2 +-
drivers/media/platform/sh_vou.c | 2 +-
drivers/media/platform/soc_camera/atmel-isi.c | 2 +-
drivers/media/platform/soc_camera/rcar_vin.c | 2 +-
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 2 +-
drivers/media/platform/sti/bdisp/bdisp-v4l2.c | 2 +-
drivers/media/platform/ti-vpe/cal.c | 2 +-
drivers/media/platform/ti-vpe/vpe.c | 2 +-
drivers/media/platform/vim2m.c | 2 +-
drivers/media/platform/xilinx/xilinx-dma.c | 2 +-
19 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index 7ae1a13..1d5836c 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -474,7 +474,7 @@ static void xvip_dma_stop_streaming(struct vb2_queue *vq)
spin_unlock_irq(&dma->queued_lock);
}
-static struct vb2_ops xvip_dma_queue_qops = {
+static const struct vb2_ops xvip_dma_queue_qops = {
.queue_setup = xvip_dma_queue_setup,
.buf_prepare = xvip_dma_buffer_prepare,
.buf_queue = xvip_dma_buffer_queue,
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 30211f6..46de657 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -536,7 +536,7 @@ static void stop_streaming(struct vb2_queue *vq)
pm_runtime_put(ici->v4l2_dev.dev);
}
-static struct vb2_ops isi_video_qops = {
+static const struct vb2_ops isi_video_qops = {
.queue_setup = queue_setup,
.buf_init = buffer_init,
.buf_prepare = buffer_prepare,
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 785e693..d9c07b8 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -2538,7 +2538,7 @@ static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
pm_runtime_put(ctx->jpeg->dev);
}
-static struct vb2_ops s5p_jpeg_qops = {
+static const struct vb2_ops s5p_jpeg_qops = {
.queue_setup = s5p_jpeg_queue_setup,
.buf_prepare = s5p_jpeg_buf_prepare,
.buf_queue = s5p_jpeg_buf_queue,
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index e967fcf..44323cb 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1379,7 +1379,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
cal_runtime_put(ctx->dev);
}
-static struct vb2_ops cal_video_qops = {
+static const struct vb2_ops cal_video_qops = {
.queue_setup = cal_queue_setup,
.buf_prepare = cal_buffer_prepare,
.buf_queue = cal_buffer_queue,
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index 55a1458..0189f7f 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -1878,7 +1878,7 @@ static void vpe_stop_streaming(struct vb2_queue *q)
vpdma_dump_regs(ctx->dev->vpdma);
}
-static struct vb2_ops vpe_qops = {
+static const struct vb2_ops vpe_qops = {
.queue_setup = vpe_queue_setup,
.buf_prepare = vpe_buf_prepare,
.buf_queue = vpe_buf_queue,
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 9c13752..0009fc5 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -856,7 +856,7 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq)
spin_unlock_irq(&priv->lock);
}
-static struct vb2_ops rcar_vin_vb2_ops = {
+static const struct vb2_ops rcar_vin_vb2_ops = {
.queue_setup = rcar_vin_videobuf_setup,
.buf_queue = rcar_vin_videobuf_queue,
.stop_streaming = rcar_vin_stop_streaming,
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 02b519d..02c8dc5 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -470,7 +470,7 @@ static void sh_mobile_ceu_stop_streaming(struct vb2_queue *q)
sh_mobile_ceu_soft_reset(pcdev);
}
-static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
+static const struct vb2_ops sh_mobile_ceu_videobuf_ops = {
.queue_setup = sh_mobile_ceu_videobuf_setup,
.buf_prepare = sh_mobile_ceu_videobuf_prepare,
.buf_queue = sh_mobile_ceu_videobuf_queue,
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 391dd7a..62c0dec 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -138,7 +138,7 @@ static void g2d_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
-static struct vb2_ops g2d_qops = {
+static const struct vb2_ops g2d_qops = {
.queue_setup = g2d_queue_setup,
.buf_prepare = g2d_buf_prepare,
.buf_queue = g2d_buf_queue,
diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
index 16782ce..d1746ec 100644
--- a/drivers/media/platform/rcar_jpu.c
+++ b/drivers/media/platform/rcar_jpu.c
@@ -1183,7 +1183,7 @@ static void jpu_stop_streaming(struct vb2_queue *vq)
}
}
-static struct vb2_ops jpu_qops = {
+static const struct vb2_ops jpu_qops = {
.queue_setup = jpu_queue_setup,
.buf_prepare = jpu_buf_prepare,
.buf_queue = jpu_buf_queue,
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index ec6494c..a341a7f 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -261,7 +261,7 @@ static void gsc_m2m_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
}
-static struct vb2_ops gsc_m2m_qops = {
+static const struct vb2_ops gsc_m2m_qops = {
.queue_setup = gsc_m2m_queue_setup,
.buf_prepare = gsc_m2m_buf_prepare,
.buf_queue = gsc_m2m_buf_queue,
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index e1f39b4..1ec9a2e 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -362,7 +362,7 @@ static void sh_vou_stop_streaming(struct vb2_queue *vq)
spin_unlock_irqrestore(&vou_dev->lock, flags);
}
-static struct vb2_ops sh_vou_qops = {
+static const struct vb2_ops sh_vou_qops = {
.queue_setup = sh_vou_queue_setup,
.buf_prepare = sh_vou_buf_prepare,
.buf_queue = sh_vou_buf_queue,
diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
index 3b1ac68..45f82b5 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
@@ -527,7 +527,7 @@ static void bdisp_stop_streaming(struct vb2_queue *q)
pm_runtime_put(ctx->bdisp_dev->dev);
}
-static struct vb2_ops bdisp_qops = {
+static const struct vb2_ops bdisp_qops = {
.queue_setup = bdisp_queue_setup,
.buf_prepare = bdisp_buf_prepare,
.buf_queue = bdisp_buf_queue,
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index 0fcb5c78..0870fad 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -852,7 +852,7 @@ static void deinterlace_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
}
-static struct vb2_ops deinterlace_qops = {
+static const struct vb2_ops deinterlace_qops = {
.queue_setup = deinterlace_queue_setup,
.buf_prepare = deinterlace_buf_prepare,
.buf_queue = deinterlace_buf_queue,
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index c639406..e68d271 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -743,7 +743,7 @@ static void emmaprp_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
}
-static struct vb2_ops emmaprp_qops = {
+static const struct vb2_ops emmaprp_qops = {
.queue_setup = emmaprp_queue_setup,
.buf_prepare = emmaprp_buf_prepare,
.buf_queue = emmaprp_buf_queue,
diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index 496aa97..07c07c1 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -1116,7 +1116,7 @@ static void rvin_stop_streaming(struct vb2_queue *vq)
rvin_disable_interrupts(vin);
}
-static struct vb2_ops rvin_qops = {
+static const struct vb2_ops rvin_qops = {
.queue_setup = rvin_queue_setup,
.buf_prepare = rvin_buffer_prepare,
.buf_queue = rvin_buffer_queue,
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index cd0ff4a..a98f679 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -815,7 +815,7 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
}
}
-static struct vb2_ops vim2m_qops = {
+static const struct vb2_ops vim2m_qops = {
.queue_setup = vim2m_queue_setup,
.buf_prepare = vim2m_buf_prepare,
.buf_queue = vim2m_buf_queue,
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index fdec499..344028e 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -452,7 +452,7 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&fimc->slock, flags);
}
-static struct vb2_ops fimc_capture_qops = {
+static const struct vb2_ops fimc_capture_qops = {
.queue_setup = queue_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index b1309e1..6028e4f 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -219,7 +219,7 @@ static void fimc_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
-static struct vb2_ops fimc_qops = {
+static const struct vb2_ops fimc_qops = {
.queue_setup = fimc_queue_setup,
.buf_prepare = fimc_buf_prepare,
.buf_queue = fimc_buf_queue,
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
index 3ed3f2d..f8e4611 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -864,7 +864,7 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q)
ctx->state = MTK_STATE_FREE;
}
-static struct vb2_ops mtk_venc_vb2_ops = {
+static const struct vb2_ops mtk_venc_vb2_ops = {
.queue_setup = vb2ops_venc_queue_setup,
.buf_prepare = vb2ops_venc_buf_prepare,
.buf_queue = vb2ops_venc_buf_queue,
^ permalink raw reply related
* Re: [PATCH 4/4] clk: mediatek: Add MT6797 clock support
From: Stephen Boyd @ 2016-09-08 19:50 UTC (permalink / raw)
To: Mars Cheng, Matthias Brugger, Rob Herring, Marc Zyngier,
Mark Rutland, Michael Turquette, Erin Lo, James Liao
Cc: linux-clk, CC Hwang, Loda Choui, Miles Chen, Scott Shu,
Jades Shih, Yingjoe Chen, My Chuang, linux-kernel, linux-mediatek,
devicetree, wsd_upstream
In-Reply-To: <1473331794-27542-5-git-send-email-mars.cheng@mediatek.com>
On 09/08/2016 03:49 AM, Mars Cheng wrote:
> Add MT6797 clock support, include topckgen, apmixedsys,
> infracfg and subsystem clocks.
>
> Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
> ---
> arch/arm64/boot/dts/mediatek/mt6797.dtsi | 66 ++-
Please don't combine dts and clk driver changes together. We generally
don't take dts changes through clk tree.
> diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
> index 5aa6204..ce91ecb 100644
> --- a/drivers/clk/mediatek/Kconfig
> +++ b/drivers/clk/mediatek/Kconfig
> @@ -56,6 +56,42 @@ config COMMON_CLK_MT2701_BDPSYS
> ---help---
> This driver supports Mediatek MT2701 bdpsys clocks.
>
What tree is this based on?
> +config COMMON_CLK_MT6797
> + bool "Clock driver for Mediatek MT6797"
> + depends on COMMON_CLK
This sort of depends shouldn't be necessary.
> + select COMMON_CLK_MEDIATEK
> + default ARCH_MEDIATEK
> + ---help---
> + This driver supports Mediatek MT6797 basic clocks.
> +
>
>
> diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c
> new file mode 100644
> index 0000000..4ecd201
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt6797-img.c
> @@ -0,0 +1,87 @@
> +/* Copyright (c) 2016 MediaTek Inc.
> + * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
clk-provider.h?
> +#include <linux/platform_device.h>
> +#include <dt-bindings/clock/mt6797-clk.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +static const struct mtk_gate_regs img_cg_regs = {
> + .set_ofs = 0x0004,
> + .clr_ofs = 0x0008,
> + .sta_ofs = 0x0000,
> +};
> +
> +#define GATE_IMG(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &img_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr, \
> + }
> +
> +static const struct mtk_gate img_clks[] = {
> + GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_sel", 11),
> + GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_sel", 10),
> + GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_sel", 6),
> + GATE_IMG(CLK_IMG_LARB6, "img_larb6", "mm_sel", 0),
> +};
> +
> +static int mtk_imgsys_init(struct device *dev)
> +{
> + struct clk_onecell_data *clk_data;
> + int r;
> +
> + clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
Allocations already print a big error message so this is useless.
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_gates(dev->of_node, img_clks, ARRAY_SIZE(img_clks),
> + clk_data);
> +
> + r = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
> + clk_data);
> + if (r)
> + pr_err("%s: could not register clock provider: %d\n",
> + __func__, r);
> +
> + return r;
> +
> +alloc_err:
> + return -ENOMEM;
> +}
> +
> +static const struct of_device_id of_match_clk_mt6797_img[] = {
> + { .compatible = "mediatek,mt6797-imgsys", },
> + {}
> +};
> +
> +static int clk_mt6797_img_probe(struct platform_device *pdev)
> +{
> + return mtk_imgsys_init(&pdev->dev);
> +}
> +
> +static struct platform_driver clk_mt6797_img_drv = {
> + .probe = clk_mt6797_img_probe,
> + .driver = {
> + .name = "clk-mt6797-img",
> + .of_match_table = of_match_clk_mt6797_img,
> + },
> +};
> +
> +builtin_platform_driver(clk_mt6797_img_drv);
> diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c
> new file mode 100644
> index 0000000..77f0342
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt6797-mm.c
> @@ -0,0 +1,146 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
clk-provider.h?
> +#include <linux/platform_device.h>
> +#include <dt-bindings/clock/mt6797-clk.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +static const struct mtk_gate_regs mm0_cg_regs = {
> + .set_ofs = 0x0104,
> + .clr_ofs = 0x0108,
> + .sta_ofs = 0x0100,
> +};
> +
> +static const struct mtk_gate_regs mm1_cg_regs = {
> + .set_ofs = 0x0114,
> + .clr_ofs = 0x0118,
> + .sta_ofs = 0x0110,
> +};
> +
> +#define GATE_MM0(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &mm0_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr, \
> +}
> +
> +#define GATE_MM1(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &mm1_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr, \
> +}
> +
> +static const struct mtk_gate mm_clks[] = {
> + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
> + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
> + GATE_MM0(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 2),
> + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 3),
> + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 4),
> + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 5),
> + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 6),
> + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 7),
> + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 8),
> + GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
> + GATE_MM0(CLK_MM_MDP_COLOR, "mm_mdp_color", "mm_sel", 10),
> + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
> + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
> + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
> + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
> + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 15),
> + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 16),
> + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 17),
> + GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 18),
> + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 19),
> + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 20),
> + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
> + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
> + GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 23),
> + GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "mm_sel", 24),
> + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
> + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
> + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 27),
> + GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "mm_sel", 28),
> + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 29),
> + GATE_MM0(CLK_MM_DISP_DSC, "mm_disp_dsc", "mm_sel", 30),
> + GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
> + GATE_MM1(CLK_MM_DSI0_MM_CLOCK, "mm_dsi0_mm_clock", "mm_sel", 0),
> + GATE_MM1(CLK_MM_DSI1_MM_CLOCK, "mm_dsi1_mm_clock", "mm_sel", 2),
> + GATE_MM1(CLK_MM_DPI_MM_CLOCK, "mm_dpi_mm_clock", "mm_sel", 4),
> + GATE_MM1(CLK_MM_DPI_INTERFACE_CLOCK, "mm_dpi_interface_clock",
> + "dpi0_sel", 5),
> + GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MM_CLOCK, "mm_larb4_axi_asif_mm_clock",
> + "mm_sel", 6),
> + GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK, "mm_larb4_axi_asif_mjc_clock",
> + "mjc_sel", 7),
> + GATE_MM1(CLK_MM_DISP_OVL0_MOUT_CLOCK, "mm_disp_ovl0_mout_clock",
> + "mm_sel", 8),
> + GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 9),
> + GATE_MM1(CLK_MM_DSI0_INTERFACE_CLOCK, "mm_dsi0_interface_clock",
> + "clk26m", 1),
> + GATE_MM1(CLK_MM_DSI1_INTERFACE_CLOCK, "mm_dsi1_interface_clock",
> + "clk26m", 3),
> +};
> +
> +static void mtk_mmsys_init(struct device *dev)
> +{
> + struct clk_onecell_data *clk_data;
> + int r;
> +
> + clk_data = mtk_alloc_clk_data(CLK_MM_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
Copy pasta!
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_gates(dev->of_node, mm_clks, ARRAY_SIZE(mm_clks),
> + clk_data);
> +
> + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> + if (r)
> + pr_err("%s: could not register clock provider: %d\n",
> + __func__, r);
> +
> + return r;
> +
> +alloc_err:
> + return -ENOMEM;
> +}
> +
> +static const struct of_device_id of_match_clk_mt6797_mm[] = {
> + { .compatible = "mediatek,mt6797-mmsys", },
> + {}
> +};
> +
> +static int clk_mt6797_mm_probe(struct platform_device *pdev)
> +{
> + return mtk_mmsys_init(&pdev->dev);
> +}
> +
> +static struct platform_driver clk_mt6797_mm_drv = {
> + .probe = clk_mt6797_mm_probe,
> + .driver = {
> + .name = "clk-mt6797-mm",
> + .of_match_table = of_match_clk_mt6797_mm,
> + },
> +};
> +
> +builtin_platform_driver(clk_mt6797_mm_drv);
> diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c
> new file mode 100644
> index 0000000..48cba6b
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt6797-vdec.c
> @@ -0,0 +1,102 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + * Author: Kevin-CW Chen <kevin-cw.chen@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
The pattern has emerged.
> +#include <linux/platform_device.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +#include <dt-bindings/clock/mt6797-clk.h>
> +
> +static const struct mtk_gate_regs vdec0_cg_regs = {
> + .set_ofs = 0x0000,
> + .clr_ofs = 0x0004,
> + .sta_ofs = 0x0000,
> +};
> +
> +static const struct mtk_gate_regs vdec1_cg_regs = {
> + .set_ofs = 0x0008,
> + .clr_ofs = 0x000c,
> + .sta_ofs = 0x0008,
> +};
> +
> +#define GATE_VDEC0(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &vdec0_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr_inv, \
> +}
> +
> +#define GATE_VDEC1(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &vdec1_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr_inv, \
> +}
> +
> +static const struct mtk_gate vdec_clks[] = {
> + GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "vdec_sel", 8),
> + GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4),
> + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
> + GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "mm_sel", 0),
> +};
> +
> +static void mtk_vdecsys_init(struct device *dev)
> +{
> + struct clk_onecell_data *clk_data;
> + int r;
> +
> + clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
Can't we consolidate this stuff?
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_gates(dev->of_node, vdec_clks, ARRAY_SIZE(vdec_clks),
> + clk_data);
> +
> + r = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, clk_data);
> + if (r)
> + pr_err("%s: could not register clock provider: %d\n",
> + __func__, r);
> + return r;
> +
> +alloc_err:
> + return -ENOMEM;
> +}
> +
> +static const struct of_device_id of_match_clk_mt6797_vdec[] = {
> + { .compatible = "mediatek,mt6797-vdecsys", },
> + {}
> +};
> +
> +static int clk_mt6797_vdec_probe(struct platform_device *pdev)
> +{
> + return mtk_vdecsys_init(&pdev->dev);
> +}
> +
> +static struct platform_driver clk_mt6797_vdec_drv = {
> + .probe = clk_mt6797_vdec_probe,
> + .driver = {
> + .name = "clk-mt6797-vdec",
> + .of_match_table = of_match_clk_mt6797_vdec,
> + },
> +};
> +
> +builtin_platform_driver(clk_mt6797_vdec_drv);
> diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c
> new file mode 100644
> index 0000000..787e010
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt6797-venc.c
> @@ -0,0 +1,86 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
Sigh.
> +#include <linux/platform_device.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +#include <dt-bindings/clock/mt6797-clk.h>
> +
> +static const struct mtk_gate_regs venc_cg_regs = {
> + .set_ofs = 0x0004,
> + .clr_ofs = 0x0008,
> + .sta_ofs = 0x0000,
> +};
> +
> +#define GATE_VENC(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &venc_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr_inv, \
> + }
> +
> +static const struct mtk_gate venc_clks[] = {
> + GATE_VENC(CLK_VENC_0, "venc_0", "mm_sel", 0),
> + GATE_VENC(CLK_VENC_1, "venc_1", "venc_sel", 4),
> + GATE_VENC(CLK_VENC_2, "venc_2", "venc_sel", 8),
> + GATE_VENC(CLK_VENC_3, "venc_3", "venc_sel", 12),
> +};
> +
> +static void mtk_vencsys_init(struct device_node *node)
> +{
> + struct clk_onecell_data *clk_data;
> + int r;
> +
> + clk_data = mtk_alloc_clk_data(CLK_VENC_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
> + clk_data);
> +
> + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> + if (r)
> + pr_err("%s: could not register clock provider: %d\n",
> + __func__, r);
> + return r;
> +alloc_err:
> + return -ENOMEM;
> +}
> +
> +static const struct of_device_id of_match_clk_mt6797_venc[] = {
> + { .compatible = "mediatek,mt6797-vencsys", },
> + {}
> +};
> +
> +static int clk_mt6797_venc_probe(struct platform_device *pdev)
> +{
> + return mtk_vencsys_init(pdev->dev.of_node);
> +}
> +
> +static struct platform_driver clk_mt6797_venc_drv = {
> + .probe = clk_mt6797_venc_probe,
> + .driver = {
> + .name = "clk-mt6797-venc",
> + .of_match_table = of_match_clk_mt6797_venc,
> + },
> +};
> +
> +builtin_platform_driver(clk_mt6797_venc_drv);
> diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c
> new file mode 100644
> index 0000000..a851d0f
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt6797.c
> @@ -0,0 +1,716 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
Used?
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-gate.h"
> +
> +#include <dt-bindings/clock/mt6797-clk.h>
> +
> +/*
> + * For some clocks, we don't care what their actual rates are. And these
> + * clocks may change their rate on different products or different scenarios.
> + * So we model these clocks' rate as 0, to denote it's not an actual rate.
> + */
> +
> +static DEFINE_SPINLOCK(mt6797_clk_lock);
> +
> +static const struct mtk_fixed_factor top_divs[] = {
> + FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, 1),
> + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
> + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
> + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
> + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
> + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
> + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
> + FACTOR(CLK_TOP_SYSPLL_D3_D3, "syspll_d3_d3", "syspll_d3", 1, 3),
> + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
> + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
> + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
> + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
> + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
> + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
> + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
> + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
> + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
> + FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, 1),
> + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
> + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
> + FACTOR(CLK_TOP_SSUSB_PHY_48M_CK, "ssusb_phy_48m_ck", "univpll", 1, 1),
> + FACTOR(CLK_TOP_USB_PHY48M_CK, "usb_phy48m_ck", "univpll", 1, 1),
> + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
> + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
> + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
> + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
> + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
> + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2),
> + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4),
> + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8),
> + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
> + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
> + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
> + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
> + FACTOR(CLK_TOP_ULPOSC_CK_ORG, "ulposc_ck_org", "ulposc", 1, 1),
> + FACTOR(CLK_TOP_ULPOSC_CK, "ulposc_ck", "ulposc_ck_org", 1, 3),
> + FACTOR(CLK_TOP_ULPOSC_D2, "ulposc_d2", "ulposc_ck", 1, 2),
> + FACTOR(CLK_TOP_ULPOSC_D3, "ulposc_d3", "ulposc_ck", 1, 4),
> + FACTOR(CLK_TOP_ULPOSC_D4, "ulposc_d4", "ulposc_ck", 1, 8),
> + FACTOR(CLK_TOP_ULPOSC_D8, "ulposc_d8", "ulposc_ck", 1, 10),
> + FACTOR(CLK_TOP_ULPOSC_D10, "ulposc_d10", "ulposc_ck_org", 1, 1),
> + FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
> + FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
> + FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1),
> + FACTOR(CLK_TOP_MFGPLL_D2, "mfgpll_d2", "mfgpll_ck", 1, 2),
> + FACTOR(CLK_TOP_IMGPLL_CK, "imgpll_ck", "imgpll", 1, 1),
> + FACTOR(CLK_TOP_IMGPLL_D2, "imgpll_d2", "imgpll_ck", 1, 2),
> + FACTOR(CLK_TOP_IMGPLL_D4, "imgpll_d4", "imgpll_ck", 1, 4),
> + FACTOR(CLK_TOP_CODECPLL_CK, "codecpll_ck", "codecpll", 1, 1),
> + FACTOR(CLK_TOP_CODECPLL_D2, "codecpll_d2", "codecpll_ck", 1, 2),
> + FACTOR(CLK_TOP_VDECPLL_CK, "vdecpll_ck", "vdecpll", 1, 1),
> + FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1),
> + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2),
> + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4),
> + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8),
> + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16),
> + FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
> + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2),
> + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, 4),
> + FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll_ck", 1, 8),
> +};
> +
> +static const char * const axi_parents[] = {
> + "clk26m",
> + "syspll_d7",
> + "ulposc_axi_ck_mux",
> +};
> +
> +static const char * const ulposc_axi_ck_mux_parents[] = {
> + "syspll1_d4",
> + "ulposc_axi_ck_mux_pre",
> +};
> +
> +static const char * const ulposc_axi_ck_mux_pre_parents[] = {
> + "ulposc_d2",
> + "ulposc_d3",
> +};
> +
> +static const char * const ddrphycfg_parents[] = {
> + "clk26m",
> + "syspll3_d2",
> + "syspll2_d4",
> + "syspll1_d8",
> +};
> +
> +static const char * const mm_parents[] = {
> + "clk26m",
> + "imgpll_ck",
> + "univpll1_d2",
> + "syspll1_d2",
> +};
> +
> +static const char * const pwm_parents[] = {
> + "clk26m",
> + "univpll2_d4",
> + "ulposc_d2",
> + "ulposc_d3",
> + "ulposc_d8",
> + "ulposc_d10",
> + "ulposc_d4",
> +};
> +
> +static const char * const vdec_parents[] = {
> + "clk26m",
> + "vdecpll_ck",
> + "imgpll_ck",
> + "syspll_d3",
> + "univpll_d5",
> + "clk26m",
> + "clk26m",
> +};
> +
> +static const char * const venc_parents[] = {
> + "clk26m",
> + "codecpll_ck",
> + "syspll_d3",
> +};
> +
> +static const char * const mfg_parents[] = {
> + "clk26m",
> + "mfgpll_ck",
> + "syspll_d3",
> + "univpll_d3",
> +};
> +
> +static const char * const camtg[] = {
> + "clk26m",
> + "univpll_d26",
> + "univpll2_d2",
> +};
> +
> +static const char * const uart_parents[] = {
> + "clk26m",
> + "univpll2_d8",
> +};
> +
> +static const char * const spi_parents[] = {
> + "clk26m",
> + "syspll3_d2",
> + "syspll2_d4",
> + "ulposc_spi_ck_mux",
> +};
> +
> +static const char * const ulposc_spi_ck_mux_parents[] = {
> + "ulposc_d2",
> + "ulposc_d3",
> +};
> +
> +static const char * const usb20_parents[] = {
> + "clk26m",
> + "univpll1_d8",
> + "syspll4_d2",
> +};
> +
> +static const char * const msdc50_0_hclk_parents[] = {
> + "clk26m",
> + "syspll1_d2",
> + "syspll2_d2",
> + "syspll4_d2",
> +};
> +
> +static const char * const msdc50_0_parents[] = {
> + "clk26m",
> + "msdcpll",
> + "syspll_d3",
> + "univpll1_d4",
> + "syspll2_d2",
> + "syspll_d7",
> + "msdcpll_d2",
> + "univpll1_d2",
> + "univpll_d3",
> +};
> +
> +static const char * const msdc30_1_parents[] = {
> + "clk26m",
> + "univpll2_d2",
> + "msdcpll_d2",
> + "univpll1_d4",
> + "syspll2_d2",
> + "syspll_d7",
> + "univpll_d7",
> +};
> +
> +static const char * const msdc30_2_parents[] = {
> + "clk26m",
> + "univpll2_d8",
> + "syspll2_d8",
> + "syspll1_d8",
> + "msdcpll_d8",
> + "syspll3_d4",
> + "univpll_d26",
> +};
> +
> +static const char * const audio_parents[] = {
> + "clk26m",
> + "syspll3_d4",
> + "syspll4_d4",
> + "syspll1_d16",
> +};
> +
> +static const char * const aud_intbus_parents[] = {
> + "clk26m",
> + "syspll1_d4",
> + "syspll4_d2",
> +};
> +
> +static const char * const pmicspi_parents[] = {
> + "clk26m",
> + "univpll_d26",
> + "syspll3_d4",
> + "syspll1_d8",
> + "ulposc_d4",
> + "ulposc_d8",
> + "syspll2_d8",
> +};
> +
> +static const char * const scp_parents[] = {
> + "clk26m",
> + "syspll_d3",
> + "ulposc_ck",
> + "univpll_d5",
> +};
> +
> +static const char * const atb_parents[] = {
> + "clk26m",
> + "syspll1_d2",
> + "syspll_d5",
> +};
> +
> +static const char * const mjc_parents[] = {
> + "clk26m",
> + "imgpll_ck",
> + "univpll_d5",
> + "syspll1_d2",
> +};
> +
> +static const char * const dpi0_parents[] = {
> + "clk26m",
> + "tvdpll_d2",
> + "tvdpll_d4",
> + "tvdpll_d8",
> + "tvdpll_d16",
> + "clk26m",
> + "clk26m",
> +};
> +
> +static const char * const aud_1_parents[] = {
> + "clk26m",
> + "apll1_ck",
> +};
> +
> +static const char * const aud_2_parents[] = {
> + "clk26m",
> + "apll2_ck",
> +};
> +
> +static const char * const ssusb_top_sys_parents[] = {
> + "clk26m",
> + "univpll3_d2",
> +};
> +
> +static const char * const spm_parents[] = {
> + "clk26m",
> + "syspll1_d8",
> +};
> +
> +static const char * const bsi_spi_parents[] = {
> + "clk26m",
> + "syspll_d3_d3",
> + "syspll1_d4",
> + "syspll_d7",
> +};
> +
> +static const char * const audio_h_parents[] = {
> + "clk26m",
> + "apll2_ck",
> + "apll1_ck",
> + "univpll_d7",
> +};
> +
> +static const char * const mfg_52m_parents[] = {
> + "clk26m",
> + "univpll2_d8",
> + "univpll2_d4",
> + "univpll2_d4",
> +};
> +
> +static const char * const anc_md32_parents[] = {
> + "clk26m",
> + "syspll1_d2",
> + "univpll_d5",
> +};
> +
> +static const struct mtk_composite top_muxes[] = {
> + MUX_GATE(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre",
> + ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1,
> + INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX, "ulposc_axi_ck_mux",
> + ulposc_axi_ck_mux_parents, 0x0040, 2, 1, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_AXI, "axi_sel", axi_parents,
> + 0x0040, 0, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents,
> + 0x0040, 16, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_MM, "mm_sel", mm_parents,
> + 0x0040, 24, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel", pwm_parents, 0x0050, 0, 3, 7),
> + MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel", vdec_parents, 0x0050, 8, 3, 15),
> + MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel", venc_parents, 0x0050, 16, 2, 23),
> + MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel", mfg_parents, 0x0050, 24, 2, 31),
> + MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel", camtg, 0x0060, 0, 2, 7),
> + MUX_GATE(CLK_TOP_MUX_UART, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
> + MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, 0x0060, 16, 2, 23),
> + MUX_GATE(CLK_TOP_MUX_ULPOSC_SPI_CK_MUX, "ulposc_spi_ck_mux",
> + ulposc_spi_ck_mux_parents, 0x0060, 18, 1,
> + INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel", usb20_parents,
> + 0x0060, 24, 2, 31),
> + MUX_GATE(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_0_hclk_sel",
> + msdc50_0_hclk_parents, 0x0070, 8, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", msdc50_0_parents,
> + 0x0070, 16, 4, 23),
> + MUX_GATE(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", msdc30_1_parents,
> + 0x0070, 24, 3, 31),
> + MUX_GATE(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", msdc30_2_parents,
> + 0x0080, 0, 3, 7),
> + MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents,
> + 0x0080, 16, 2, 23),
> + MUX_GATE(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel", aud_intbus_parents,
> + 0x0080, 24, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", pmicspi_parents,
> + 0x0090, 0, 3, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_SCP, "scp_sel", scp_parents,
> + 0x0090, 8, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_ATB, "atb_sel", atb_parents,
> + 0x0090, 16, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_MJC, "mjc_sel", mjc_parents, 0x0090, 24, 2, 31),
> + MUX_GATE(CLK_TOP_MUX_DPI0, "dpi0_sel", dpi0_parents, 0x00A0, 0, 3, 7),
> + MUX_GATE(CLK_TOP_MUX_AUD_1, "aud_1_sel", aud_1_parents,
> + 0x00A0, 16, 1, 23),
> + MUX_GATE(CLK_TOP_MUX_AUD_2, "aud_2_sel", aud_2_parents,
> + 0x00A0, 24, 1, 31),
> + MUX_GATE(CLK_TOP_MUX_SSUSB_TOP_SYS, "ssusb_top_sys_sel",
> + ssusb_top_sys_parents, 0x00B0, 8, 1, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_SPM, "spm_sel", spm_parents,
> + 0x00C0, 0, 1, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_BSI_SPI, "bsi_spi_sel", bsi_spi_parents,
> + 0x00C0, 8, 2, INVALID_MUX_GATE_BIT),
> + MUX_GATE(CLK_TOP_MUX_AUDIO_H, "audio_h_sel", audio_h_parents,
> + 0x00C0, 16, 2, 23),
> + MUX_GATE(CLK_TOP_MUX_ANC_MD32, "anc_md32_sel", anc_md32_parents,
> + 0x00C0, 24, 2, 31),
> + MUX_GATE(CLK_TOP_MUX_MFG_52M, "mfg_52m_sel", mfg_52m_parents,
> + 0x0104, 1, 2, INVALID_MUX_GATE_BIT),
> +};
> +
> +static const struct mtk_gate_regs infra0_cg_regs = {
> + .set_ofs = 0x0080,
> + .clr_ofs = 0x0084,
> + .sta_ofs = 0x0090,
> +};
> +
> +static const struct mtk_gate_regs infra1_cg_regs = {
> + .set_ofs = 0x0088,
> + .clr_ofs = 0x008c,
> + .sta_ofs = 0x0094,
> +};
> +
> +static const struct mtk_gate_regs infra2_cg_regs = {
> + .set_ofs = 0x00a8,
> + .clr_ofs = 0x00ac,
> + .sta_ofs = 0x00b0,
> +};
> +
> +#define GATE_ICG0(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &infra0_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr, \
> +}
> +
> +#define GATE_ICG1(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &infra1_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr, \
> +}
> +
> +#define GATE_ICG2(_id, _name, _parent, _shift) { \
> + .id = _id, \
> + .name = _name, \
> + .parent_name = _parent, \
> + .regs = &infra2_cg_regs, \
> + .shift = _shift, \
> + .ops = &mtk_clk_gate_ops_setclr, \
> +}
> +
> +static const struct mtk_gate infra_gates[] = {
> + GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "ulposc", 0),
> + GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pmicspi_sel", 1),
> + GATE_ICG0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pmicspi_sel", 2),
> + GATE_ICG0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pmicspi_sel", 3),
> + GATE_ICG0(CLK_INFRA_SCP, "infra_scp", "scp_sel", 4),
> + GATE_ICG0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5),
> + GATE_ICG0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6),
> + GATE_ICG0(CLK_INFRA_SEJ_13M, "infra_sej_13m", "clk26m", 7),
> + GATE_ICG0(CLK_INFRA_ICUSB, "infra_icusb", "usb20_sel", 8),
> + GATE_ICG0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 9),
> + GATE_ICG0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10),
> + GATE_ICG0(CLK_INFRA_I2C0, "infra_i2c0", "axi_sel", 11),
> + GATE_ICG0(CLK_INFRA_I2C1, "infra_i2c1", "axi_sel", 12),
> + GATE_ICG0(CLK_INFRA_I2C2, "infra_i2c2", "axi_sel", 13),
> + GATE_ICG0(CLK_INFRA_I2C3, "infra_i2c3", "axi_sel", 14),
> + GATE_ICG0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", "axi_sel", 15),
> + GATE_ICG0(CLK_INFRA_PWM1, "infra_pwm1", "axi_sel", 16),
> + GATE_ICG0(CLK_INFRA_PWM2, "infra_pwm2", "axi_sel", 17),
> + GATE_ICG0(CLK_INFRA_PWM3, "infra_pwm3", "axi_sel", 18),
> + GATE_ICG0(CLK_INFRA_PWM4, "infra_pwm4", "axi_sel", 19),
> + GATE_ICG0(CLK_INFRA_PWM, "infra_pwm", "axi_sel", 21),
> + GATE_ICG0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22),
> + GATE_ICG0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23),
> + GATE_ICG0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24),
> + GATE_ICG0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25),
> + GATE_ICG0(CLK_INFRA_MD2MD_CCIF_0, "infra_md2md_ccif_0", "axi_sel", 27),
> + GATE_ICG0(CLK_INFRA_MD2MD_CCIF_1, "infra_md2md_ccif_1", "axi_sel", 28),
> + GATE_ICG0(CLK_INFRA_MD2MD_CCIF_2, "infra_md2md_ccif_2", "axi_sel", 29),
> + GATE_ICG0(CLK_INFRA_FHCTL, "infra_fhctl", "clk26m", 30),
> + GATE_ICG0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31),
> + GATE_ICG1(CLK_INFRA_MD2MD_CCIF_3, "infra_md2md_ccif_3", "axi_sel", 0),
> + GATE_ICG1(CLK_INFRA_SPI, "infra_spi", "spi_sel", 1),
> + GATE_ICG1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_sel", 2),
> + GATE_ICG1(CLK_INFRA_MD2MD_CCIF_4, "infra_md2md_ccif_4", "axi_sel", 3),
> + GATE_ICG1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc30_1_sel", 4),
> + GATE_ICG1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc30_2_sel", 5),
> + GATE_ICG1(CLK_INFRA_MD2MD_CCIF_5, "infra_md2md_ccif_5", "axi_sel", 7),
> + GATE_ICG1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8),
> + GATE_ICG1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9),
> + GATE_ICG1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10),
> + GATE_ICG1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11),
> + GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_0, "infra_ap_c2k_ccif_0",
> + "axi_sel", 12),
> + GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_1, "infra_ap_c2k_ccif_1",
> + "axi_sel", 13),
> + GATE_ICG1(CLK_INFRA_CLDMA, "infra_cldma", "axi_sel", 16),
> + GATE_ICG1(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "pwm_sel", 17),
> + GATE_ICG1(CLK_INFRA_AP_DMA, "infra_ap_dma", "axi_sel", 18),
> + GATE_ICG1(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20),
> + GATE_ICG1(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "mm_sel", 22),
> + GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23),
> + GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25),
> + GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26),
> + GATE_ICG1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31),
> + GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4", "axi_sel", 0),
> + GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm", "axi_sel", 1),
> + GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm", "axi_sel", 2),
> + GATE_ICG2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "axi_sel", 3),
> + GATE_ICG2(CLK_INFRA_I2C2_ARB, "infra_i2c2_arb", "axi_sel", 4),
> + GATE_ICG2(CLK_INFRA_I2C3_IMM, "infra_i2c3_imm", "axi_sel", 5),
> + GATE_ICG2(CLK_INFRA_I2C3_ARB, "infra_i2c3_arb", "axi_sel", 6),
> + GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5", "axi_sel", 7),
> + GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq", "axi_sel", 8),
> + GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 10),
> + GATE_ICG2(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m", "clk26m", 11),
> + GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32", "anc_md32_sel", 12),
> + GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k", "clk26m", 13),
> + GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1", "axi_sel", 15),
> + GATE_ICG2(CLK_INFRA_AES_TOP0, "infra_aes_top0", "axi_sel", 16),
> + GATE_ICG2(CLK_INFRA_AES_TOP1, "infra_aes_top1", "axi_sel", 17),
> + GATE_ICG2(CLK_INFRA_SSUSB_BUS, "infra_ssusb_bus", "axi_sel", 18),
> + GATE_ICG2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 19),
> + GATE_ICG2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 20),
> + GATE_ICG2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 21),
> + GATE_ICG2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 22),
> + GATE_ICG2(CLK_INFRA_IRTX, "infra_irtx", "spi_sel", 23),
> + GATE_ICG2(CLK_INFRA_SSUSB_SYS, "infra_ssusb_sys",
> + "ssusb_top_sys_sel", 24),
> + GATE_ICG2(CLK_INFRA_SSUSB_REF, "infra_ssusb_ref", "clk26m", 9),
> + GATE_ICG2(CLK_INFRA_AUDIO_26M, "infra_audio_26m", "clk26m", 26),
> + GATE_ICG2(CLK_INFRA_AUDIO_26M_PAD_TOP, "infra_audio_26m_pad_top",
> + "clk26m", 27),
> + GATE_ICG2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share",
> + "axi_sel", 28),
> + GATE_ICG2(CLK_INFRA_VAD_WRAP_SOC, "infra_vad_wrap_soc", "axi_sel", 29),
> + GATE_ICG2(CLK_INFRA_DRAMC_CONF, "infra_dramc_conf", "axi_sel", 30),
> + GATE_ICG2(CLK_INFRA_DRAMC_B_CONF, "infra_dramc_b_conf", "axi_sel", 31),
> + GATE_ICG1(CLK_INFRA_MFG_VCG, "infra_mfg_vcg", "mfg_52m_sel", 14),
> +};
> +
> +static const struct mtk_fixed_factor infra_divs[] = {
> + FACTOR(CLK_INFRA_13M, "clk13m", "clk26m", 1, 2),
> +};
> +
> +#define MT6797_PLL_FMAX (3000UL * MHZ)
> +
> +#define CON0_MT6797_RST_BAR BIT(24)
> +
> +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
> + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
> + _pcw_shift, _div_table) { \
> + .id = _id, \
> + .name = _name, \
> + .reg = _reg, \
> + .pwr_reg = _pwr_reg, \
> + .en_mask = _en_mask, \
> + .flags = _flags, \
> + .rst_bar_mask = CON0_MT6797_RST_BAR, \
> + .fmax = MT6797_PLL_FMAX, \
> + .pcwbits = _pcwbits, \
> + .pd_reg = _pd_reg, \
> + .pd_shift = _pd_shift, \
> + .tuner_reg = _tuner_reg, \
> + .pcw_reg = _pcw_reg, \
> + .pcw_shift = _pcw_shift, \
> + .div_table = _div_table, \
> +}
> +
> +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
> + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
> + _pcw_shift) \
> + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
> + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
> + NULL)
> +
> +static const struct mtk_pll_data plls[] = {
> + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000101, 0, 21,
> + 0x220, 4, 0x0, 0x224, 0),
> + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000011, 0, 7,
> + 0x230, 4, 0x0, 0x234, 14),
> + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000101, 0, 21,
> + 0x244, 24, 0x0, 0x244, 0),
> + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000121, 0, 21,
> + 0x250, 4, 0x0, 0x254, 0),
> + PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000121, 0, 21,
> + 0x260, 4, 0x0, 0x264, 0),
> + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000121, 0, 21,
> + 0x270, 4, 0x0, 0x274, 0),
> + PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000121, 0, 21,
> + 0x290, 4, 0x0, 0x294, 0),
> + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000121, 0, 21,
> + 0x2E4, 4, 0x0, 0x2E8, 0),
> + PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000131, 0, 31,
> + 0x2A0, 4, 0x2A8, 0x2A4, 0),
> + PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000131, 0, 31,
> + 0x2B4, 4, 0x2BC, 0x2B8, 0),
> +};
> +
> +static struct clk_onecell_data * __init mtk_topckgen_init(struct device *dev)
> +{
> + struct clk_onecell_data *clk_data;
> + struct resource mem;
> + void __iomem *base;
> +
> + if (of_address_to_resource(dev->of_node, 0, &mem)) {
Please use platform APIs instead of OF APIs.
> + pr_err("%s: get resource failed\n", __func__);
> + goto res_err;
> + }
> +
> + base = devm_ioremap(dev, mem.start, resource_size(&mem));
> + if (!base) {
> + pr_err("%s: ioremap failed\n", __func__);
> + goto ioremap_err;
> + }
> +
> + clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
> + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
> + &mt6797_clk_lock, clk_data);
> +
> + return clk_data;
> +
> +alloc_err:
> + devm_iounmap(dev, base);
> +res_err:
> +ioremap_err:
> + return NULL;
> +}
> +
> +static struct clk_onecell_data * __init mtk_infrasys_init(struct device *dev)
> +{
> + struct clk_onecell_data *clk_data;
> +
> + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_gates(dev->of_node, infra_gates,
> + ARRAY_SIZE(infra_gates), clk_data);
> + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
> +
> + return clk_data;
> +
> +alloc_err:
> + return NULL;
> +}
> +
> +static struct clk_onecell_data * __init mtk_apmixedsys_init(struct device *dev)
> +{
> + struct clk_onecell_data *clk_data;
> +
> + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
> + if (!clk_data) {
> + pr_err("%s: alloc failed\n", __func__);
> + goto alloc_err;
> + }
> +
> + mtk_clk_register_plls(dev->of_node, plls, ARRAY_SIZE(plls), clk_data);
> +
> + return clk_data;
> +
> +alloc_err:
> + return NULL;
> +}
> +
> +static const struct of_device_id of_match_clk_mt6797[] = {
> + {
> + .compatible = "mediatek,mt6797-topckgen",
> + .data = mtk_topckgen_init,
> + }, {
> + .compatible = "mediatek,mt6797-infracfg",
> + .data = mtk_infrasys_init,
> + }, {
> + .compatible = "mediatek,mt6797-apmixedsys",
> + .data = mtk_apmixedsys_init,
> + }, {
> + /* sentinel */
> + }
> +};
> +
> +static int clk_mt6797_probe(struct platform_device *pdev)
> +{
> + struct clk_onecell_data * (*clk_init)(struct device *);
> + struct clk_onecell_data *clk_data;
> + int r;
> +
> + clk_init = of_device_get_match_data(&pdev->dev);
> + if (!clk_init) {
> + pr_err("%s: matched clk not found\n", __func__);
> + return -EINVAL;
> + }
> +
> + clk_data = clk_init(&pdev->dev);
> + if (!clk_data) {
> + pr_err("%s: clk init failed\n", __func__);
> + return -EINVAL;
> + }
> +
> + r = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
> + clk_data);
> + if (r) {
> + pr_err("%s: could not register clock provider: %d\n",
> + __func__, r);
> + return r;
> + }
> +
> + return 0;
> +}
> +
> +static struct platform_driver clk_mt6797_drv = {
> + .probe = clk_mt6797_probe,
> + .driver = {
> + .name = "clk-mt6797",
> + .owner = THIS_MODULE,
> + .of_match_table = of_match_clk_mt6797,
> + },
> +};
> +
> +static int __init clk_mt6797_init(void)
> +{
> + return platform_driver_register(&clk_mt6797_drv);
> +}
> +
> +arch_initcall(clk_mt6797_init);
> diff --git a/include/dt-bindings/clock/mt6797-clk.h b/include/dt-bindings/clock/mt6797-clk.h
> new file mode 100644
> index 0000000..6f32e6b
> --- /dev/null
> +++ b/include/dt-bindings/clock/mt6797-clk.h
> @@ -0,0 +1,281 @@
> +/*
> +* Copyright (c) 2016 MediaTek Inc.
> +* Author: Kevin Chen <kevin-cw.chen@mediatek.com>
> +*
> +* This program is free software; you can redistribute it and/or modify
> +* it under the terms of the GNU General Public License version 2 as
> +* published by the Free Software Foundation.
> +*
> +* This program is distributed in the hope that it will be useful,
> +* but WITHOUT ANY WARRANTY; without even the implied warranty of
> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +* GNU General Public License for more details.
> +*/
> +
> +#ifndef _DT_BINDINGS_CLK_MT6797_H
> +#define _DT_BINDINGS_CLK_MT6797_H
> +
> +/* TOPCKGEN */
> +#define CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE 1
> +#define CLK_TOP_MUX_ULPOSC_AXI_CK_MUX 2
> +#define CLK_TOP_MUX_AXI 3
> +#define CLK_TOP_MUX_MEM 4
> +#define CLK_TOP_MUX_DDRPHYCFG 5
> +#define CLK_TOP_MUX_MM 6
> +#define CLK_TOP_MUX_PWM 7
> +#define CLK_TOP_MUX_VDEC 8
> +#define CLK_TOP_MUX_VENC 9
> +#define CLK_TOP_MUX_MFG 10
> +#define CLK_TOP_MUX_CAMTG 11
> +#define CLK_TOP_MUX_UART 12
> +#define CLK_TOP_MUX_SPI 13
> +#define CLK_TOP_MUX_ULPOSC_SPI_CK_MUX 14
> +#define CLK_TOP_MUX_USB20 15
> +#define CLK_TOP_MUX_MSDC50_0_HCLK 16
> +#define CLK_TOP_MUX_MSDC50_0 17
> +#define CLK_TOP_MUX_MSDC30_1 18
> +#define CLK_TOP_MUX_MSDC30_2 19
> +#define CLK_TOP_MUX_AUDIO 20
> +#define CLK_TOP_MUX_AUD_INTBUS 21
> +#define CLK_TOP_MUX_PMICSPI 22
> +#define CLK_TOP_MUX_SCP 23
> +#define CLK_TOP_MUX_ATB 24
> +#define CLK_TOP_MUX_MJC 25
> +#define CLK_TOP_MUX_DPI0 26
> +#define CLK_TOP_MUX_AUD_1 27
> +#define CLK_TOP_MUX_AUD_2 28
> +#define CLK_TOP_MUX_SSUSB_TOP_SYS 29
> +#define CLK_TOP_MUX_SPM 30
> +#define CLK_TOP_MUX_BSI_SPI 31
> +#define CLK_TOP_MUX_AUDIO_H 32
> +#define CLK_TOP_MUX_ANC_MD32 33
> +#define CLK_TOP_MUX_MFG_52M 34
> +#define CLK_TOP_SYSPLL_CK 35
> +#define CLK_TOP_SYSPLL_D2 36
> +#define CLK_TOP_SYSPLL1_D2 37
> +#define CLK_TOP_SYSPLL1_D4 38
> +#define CLK_TOP_SYSPLL1_D8 39
> +#define CLK_TOP_SYSPLL1_D16 40
> +#define CLK_TOP_SYSPLL_D3 41
> +#define CLK_TOP_SYSPLL_D3_D3 42
> +#define CLK_TOP_SYSPLL2_D2 43
> +#define CLK_TOP_SYSPLL2_D4 44
> +#define CLK_TOP_SYSPLL2_D8 45
> +#define CLK_TOP_SYSPLL_D5 46
> +#define CLK_TOP_SYSPLL3_D2 47
> +#define CLK_TOP_SYSPLL3_D4 48
> +#define CLK_TOP_SYSPLL_D7 49
> +#define CLK_TOP_SYSPLL4_D2 50
> +#define CLK_TOP_SYSPLL4_D4 51
> +#define CLK_TOP_UNIVPLL_CK 52
> +#define CLK_TOP_UNIVPLL_D7 53
> +#define CLK_TOP_UNIVPLL_D26 54
> +#define CLK_TOP_SSUSB_PHY_48M_CK 55
> +#define CLK_TOP_USB_PHY48M_CK 56
> +#define CLK_TOP_UNIVPLL_D2 57
> +#define CLK_TOP_UNIVPLL1_D2 58
> +#define CLK_TOP_UNIVPLL1_D4 59
> +#define CLK_TOP_UNIVPLL1_D8 60
> +#define CLK_TOP_UNIVPLL_D3 61
> +#define CLK_TOP_UNIVPLL2_D2 62
> +#define CLK_TOP_UNIVPLL2_D4 63
> +#define CLK_TOP_UNIVPLL2_D8 64
> +#define CLK_TOP_UNIVPLL_D5 65
> +#define CLK_TOP_UNIVPLL3_D2 66
> +#define CLK_TOP_UNIVPLL3_D4 67
> +#define CLK_TOP_UNIVPLL3_D8 68Groundhog day?
> +#define CLK_TOP_ULPOSC_CK_ORG 69
> +#define CLK_TOP_ULPOSC_CK 70
> +#define CLK_TOP_ULPOSC_D2 71
> +#define CLK_TOP_ULPOSC_D3 72
> +#define CLK_TOP_ULPOSC_D4 73
> +#define CLK_TOP_ULPOSC_D8 74
> +#define CLK_TOP_ULPOSC_D10 75
> +#define CLK_TOP_APLL1_CK 76
> +#define CLK_TOP_APLL2_CK 77
> +#define CLK_TOP_MFGPLL_CK 78
> +#define CLK_TOP_MFGPLL_D2 79
> +#define CLK_TOP_IMGPLL_CK 80
> +#define CLK_TOP_IMGPLL_D2 81
> +#define CLK_TOP_IMGPLL_D4 82
> +#define CLK_TOP_CODECPLL_CK 83
> +#define CLK_TOP_CODECPLL_D2 84
> +#define CLK_TOP_VDECPLL_CK 85
> +#define CLK_TOP_TVDPLL_CK 86
> +#define CLK_TOP_TVDPLL_D2 87
> +#define CLK_TOP_TVDPLL_D4 88
> +#define CLK_TOP_TVDPLL_D8 89
> +#define CLK_TOP_TVDPLL_D16 90
> +#define CLK_TOP_MSDCPLL_CK 91
> +#define CLK_TOP_MSDCPLL_D2 92
> +#define CLK_TOP_MSDCPLL_D4 93
> +#define CLK_TOP_MSDCPLL_D8 94
> +#define CLK_TOP_NR 95
> +
> +/* APMIXED_SYS */
> +#define CLK_APMIXED_MAINPLL 1
> +#define CLK_APMIXED_UNIVPLL 2
> +#define CLK_APMIXED_MFGPLL 3
> +#define CLK_APMIXED_MSDCPLL 4
> +#define CLK_APMIXED_IMGPLL 5
> +#define CLK_APMIXED_TVDPLL 6
> +#define CLK_APMIXED_CODECPLL 7
> +#define CLK_APMIXED_VDECPLL 8
> +#define CLK_APMIXED_APLL1 9
> +#define CLK_APMIXED_APLL2 10
> +#define CLK_APMIXED_NR 11
> +
> +/* INFRA_SYS */
> +#define CLK_INFRA_PMIC_TMR 1
> +#define CLK_INFRA_PMIC_AP 2
> +#define CLK_INFRA_PMIC_MD 3
> +#define CLK_INFRA_PMIC_CONN 4
> +#define CLK_INFRA_SCP 5
> +#define CLK_INFRA_SEJ 6
> +#define CLK_INFRA_APXGPT 7
> +#define CLK_INFRA_SEJ_13M 8
> +#define CLK_INFRA_ICUSB 9
> +#define CLK_INFRA_GCE 10
> +#define CLK_INFRA_THERM 11
> +#define CLK_INFRA_I2C0 12
> +#define CLK_INFRA_I2C1 13
> +#define CLK_INFRA_I2C2 14
> +#define CLK_INFRA_I2C3 15
> +#define CLK_INFRA_PWM_HCLK 16
> +#define CLK_INFRA_PWM1 17
> +#define CLK_INFRA_PWM2 18
> +#define CLK_INFRA_PWM3 19
> +#define CLK_INFRA_PWM4 20
> +#define CLK_INFRA_PWM 21
> +#define CLK_INFRA_UART0 22
> +#define CLK_INFRA_UART1 23
> +#define CLK_INFRA_UART2 24
> +#define CLK_INFRA_UART3 25
> +#define CLK_INFRA_MD2MD_CCIF_0 26
> +#define CLK_INFRA_MD2MD_CCIF_1 27
> +#define CLK_INFRA_MD2MD_CCIF_2 28
> +#define CLK_INFRA_FHCTL 29
> +#define CLK_INFRA_BTIF 30
> +#define CLK_INFRA_MD2MD_CCIF_3 31
> +#define CLK_INFRA_SPI 32
> +#define CLK_INFRA_MSDC0 33
> +#define CLK_INFRA_MD2MD_CCIF_4 34
> +#define CLK_INFRA_MSDC1 35
> +#define CLK_INFRA_MSDC2 36
> +#define CLK_INFRA_MD2MD_CCIF_5 37
> +#define CLK_INFRA_GCPU 38
> +#define CLK_INFRA_TRNG 39
> +#define CLK_INFRA_AUXADC 40
> +#define CLK_INFRA_CPUM 41
> +#define CLK_INFRA_AP_C2K_CCIF_0 42
> +#define CLK_INFRA_AP_C2K_CCIF_1 43
> +#define CLK_INFRA_CLDMA 44
> +#define CLK_INFRA_DISP_PWM 45
> +#define CLK_INFRA_AP_DMA 46
> +#define CLK_INFRA_DEVICE_APC 47
> +#define CLK_INFRA_L2C_SRAM 48
> +#define CLK_INFRA_CCIF_AP 49
> +#define CLK_INFRA_AUDIO 50
> +#define CLK_INFRA_CCIF_MD 51
> +#define CLK_INFRA_DRAMC_F26M 52
> +#define CLK_INFRA_I2C4 53
> +#define CLK_INFRA_I2C_APPM 54
> +#define CLK_INFRA_I2C_GPUPM 55
> +#define CLK_INFRA_I2C2_IMM 56
> +#define CLK_INFRA_I2C2_ARB 57
> +#define CLK_INFRA_I2C3_IMM 58
> +#define CLK_INFRA_I2C3_ARB 59
> +#define CLK_INFRA_I2C5 60
> +#define CLK_INFRA_SYS_CIRQ 61
> +#define CLK_INFRA_SPI1 62
> +#define CLK_INFRA_DRAMC_B_F26M 63
> +#define CLK_INFRA_ANC_MD32 64
> +#define CLK_INFRA_ANC_MD32_32K 65
> +#define CLK_INFRA_DVFS_SPM1 66
> +#define CLK_INFRA_AES_TOP0 67
> +#define CLK_INFRA_AES_TOP1 68
> +#define CLK_INFRA_SSUSB_BUS 69
> +#define CLK_INFRA_SPI2 70
> +#define CLK_INFRA_SPI3 71
> +#define CLK_INFRA_SPI4 72
> +#define CLK_INFRA_SPI5 73
> +#define CLK_INFRA_IRTX 74
> +#define CLK_INFRA_SSUSB_SYS 75
> +#define CLK_INFRA_SSUSB_REF 76
> +#define CLK_INFRA_AUDIO_26M 77
> +#define CLK_INFRA_AUDIO_26M_PAD_TOP 78
> +#define CLK_INFRA_MODEM_TEMP_SHARE 79
> +#define CLK_INFRA_VAD_WRAP_SOC 80
> +#define CLK_INFRA_DRAMC_CONF 81
> +#define CLK_INFRA_DRAMC_B_CONF 82
> +#define CLK_INFRA_MFG_VCG 83
> +#define CLK_INFRA_13M 84
> +#define CLK_INFRA_NR 85
Weird spacing here?
> +
> +/* IMG_SYS */
> +#define CLK_IMG_FDVT 1
> +#define CLK_IMG_DPE 2
> +#define CLK_IMG_DIP 3
> +#define CLK_IMG_LARB6 4
> +#define CLK_IMG_NR 5
Same here.
> +
> +/* MM_SYS */
> +#define CLK_MM_SMI_COMMON 1
> +#define CLK_MM_SMI_LARB0 2
> +#define CLK_MM_SMI_LARB5 3
> +#define CLK_MM_CAM_MDP 4
> +#define CLK_MM_MDP_RDMA0 5
> +#define CLK_MM_MDP_RDMA1 6
> +#define CLK_MM_MDP_RSZ0 7
> +#define CLK_MM_MDP_RSZ1 8
> +#define CLK_MM_MDP_RSZ2 9
> +#define CLK_MM_MDP_TDSHP 10
> +#define CLK_MM_MDP_COLOR 11
> +#define CLK_MM_MDP_WDMA 12
> +#define CLK_MM_MDP_WROT0 13
> +#define CLK_MM_MDP_WROT1 14
> +#define CLK_MM_FAKE_ENG 15
> +#define CLK_MM_DISP_OVL0 16
> +#define CLK_MM_DISP_OVL1 17
> +#define CLK_MM_DISP_OVL0_2L 18
> +#define CLK_MM_DISP_OVL1_2L 19
> +#define CLK_MM_DISP_RDMA0 20
> +#define CLK_MM_DISP_RDMA1 21
> +#define CLK_MM_DISP_WDMA0 22
> +#define CLK_MM_DISP_WDMA1 23
> +#define CLK_MM_DISP_COLOR 24
> +#define CLK_MM_DISP_CCORR 25
> +#define CLK_MM_DISP_AAL 26
> +#define CLK_MM_DISP_GAMMA 27Groundhog day?
> +#define CLK_MM_DISP_OD 28
> +#define CLK_MM_DISP_DITHER 29
> +#define CLK_MM_DISP_UFOE 30
> +#define CLK_MM_DISP_DSC 31
> +#define CLK_MM_DISP_SPLIT 32
> +#define CLK_MM_DSI0_MM_CLOCK 33
> +#define CLK_MM_DSI1_MM_CLOCK 34
> +#define CLK_MM_DPI_MM_CLOCK 35
> +#define CLK_MM_DPI_INTERFACE_CLOCK 36
> +#define CLK_MM_LARB4_AXI_ASIF_MM_CLOCK 37
> +#define CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK 38
> +#define CLK_MM_DISP_OVL0_MOUT_CLOCK 39
> +#define CLK_MM_FAKE_ENG2 40
> +#define CLK_MM_DSI0_INTERFACE_CLOCK 41
> +#define CLK_MM_DSI1_INTERFACE_CLOCK 42
> +#define CLK_MM_NR 43
Ditto.
> +
> +/* VDEC_SYS */
> +#define CLK_VDEC_CKEN_ENG 1
> +#define CLK_VDEC_ACTIVE 2
> +#define CLK_VDEC_CKEN 3
> +#define CLK_VDEC_LARB1_CKEN 4
> +#define CLK_VDEC_NR 5
Another one
> +
> +/* VENC_SYS */
> +#define CLK_VENC_0 1
> +#define CLK_VENC_1 2
> +#define CLK_VENC_2 3
> +#define CLK_VENC_3 4
> +#define CLK_VENC_NR 5
>
Again.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH 1/4] Document: DT: Add bindings for mediatek MT6797 SoC Platform
From: Marc Zyngier @ 2016-09-08 14:32 UTC (permalink / raw)
To: Mars Cheng
Cc: Matthias Brugger, Rob Herring, Mark Rutland, Michael Turquette,
Stephen Boyd, Erin Lo, James Liao, linux-clk, CC Hwang,
Loda Choui, Miles Chen, Scott Shu, Jades Shih, Yingjoe Chen,
My Chuang, linux-kernel, linux-mediatek, devicetree, wsd_upstream
In-Reply-To: <1473343735.1896.15.camel@mtkswgap22>
On 08/09/16 15:08, Mars Cheng wrote:
> Hi Marc
>
> Thanks for your review. the response inlined.
>
> On Thu, 2016-09-08 at 13:37 +0100, Marc Zyngier wrote:
>> On 08/09/16 11:49, Mars Cheng wrote:
>>> This adds DT binding documentation for Mediatek MT6797.
>>>
>>> Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
>>> ---
> [...]
>>
>>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
>>> index 9d1d72c..3d97eb4 100644
>>> --- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
>>> +++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
>>> @@ -8,6 +8,7 @@ Required properties:
>>> "mediatek,mt8173-sysirq"
>>> "mediatek,mt8135-sysirq"
>>> "mediatek,mt8127-sysirq"
>>> + "mediatek,mt6797-sysirq"
>>> "mediatek,mt6795-sysirq"
>>> "mediatek,mt6755-sysirq"
>>> "mediatek,mt6592-sysirq"
>>> @@ -21,7 +22,8 @@ Required properties:
>>> - interrupt-parent: phandle of irq parent for sysirq. The parent must
>>> use the same interrupt-cells format as GIC.
>>> - reg: Physical base address of the intpol registers and length of memory
>>> - mapped region.
>>> + mapped region. Could be up to 2 registers here at max. Ex: 6797 needs 2 reg,
>>> + others need 1.
>>
>> Two things:
>>
>> - Please make this a separate patch that can be reviewed independently
>> of the rest of the changes, which are just adding new compatible
>> identifiers.
>
> Will fix this in the next patch set.
>
>>
>> - Why can't you simply expose it as a separate controller? Looking at
>> the way you're changing the corresponding driver, it looks like you're
>> simply adding an extra base/size. If you simply had a base for the
>> corresponding GIC interrupts, you could handle as many region as you
>> want, and have a more generic driver.
>>
>
> May I know the meaning of "simply expose it as a separate controller"?
At the moment, you have something like this:
sysirq: intpol-controller@10200620 {
compatible = "mediatek,mt6755-sysirq",
"mediatek,mt6577-sysirq";
interrupt-controller;
#interrupt-cells = <3>;
interrupt-parent = <&gic>;
reg = <0 0x10200620 0 0x20>;
};
I suggest that, when you have a second base (which is effectively
another controller), you add:
sysirq2: intpol-controller@10201620 {
compatible = "mediatek,mt6755-sysirq",
"mediatek,mt6577-sysirq";
interrupt-controller;
#interrupt-cells = <3>;
interrupt-parent = <&gic>;
irq-base = <32>;
reg = <0 0x10201620 0 0x20>;
};
Where irq-base is the first SPI this is connected to (the lack of
property indicates implies that irq-base is 0). This becomes a very
simple change in the driver.
> Or you might like to suggest me any similar driver as a reference? I
> will examine it. Current design is based on the fact: We expect
> irq-mtk-sysirq needs the optional second base but the third one will not
> happen.
>
> If we really need more than 2 bases, we can figure out a more generic
> driver at the time, right?
I'd rather fix the driver and the binding to do the right thing once and
for all. In my experience, you will need to add a third base in six
months, and a fourth soon after. I'd rather either support an arbitrary
number of bases, or a single one per controller (and have multiple
controllers).
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: mediatek: add mt6797 support
From: Mars Cheng @ 2016-09-08 14:10 UTC (permalink / raw)
To: Marc Zyngier
Cc: Matthias Brugger, Rob Herring, Mark Rutland, Michael Turquette,
Stephen Boyd, Erin Lo, James Liao, linux-clk, CC Hwang,
Loda Choui, Miles Chen, Scott Shu, Jades Shih, Yingjoe Chen,
My Chuang, linux-kernel, linux-mediatek, devicetree, wsd_upstream
In-Reply-To: <57D16470.6050100@arm.com>
On Thu, 2016-09-08 at 14:15 +0100, Marc Zyngier wrote:
> On 08/09/16 11:49, Mars Cheng wrote:
> > This adds basic chip support for MT6797 SoC.
> >
> > Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
> > ---
[...]
>
> > + gic: interrupt-controller@19000000 {
> > + compatible = "arm,gic-v3";
> > + #interrupt-cells = <3>;
> > + interrupt-parent = <&gic>;
> > + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
> > + interrupt-controller;
> > + reg = <0 0x19000000 0 0x10000>, /* GICD */
> > + <0 0x19200000 0 0x200000>, /* GICR */
> > + <0 0x10240000 0 0x2000>; /* GICC */
>
> Where are the GICV and GICH regions? No ITS?
Have confirmed with our HW guys, there is no GICV, GICH, nor ITS in our
GIC design.
Thanks.
>
> Thanks,
>
> M.
^ permalink raw reply
* Re: [PATCH 1/4] Document: DT: Add bindings for mediatek MT6797 SoC Platform
From: Mars Cheng @ 2016-09-08 14:08 UTC (permalink / raw)
To: Marc Zyngier
Cc: Matthias Brugger, Rob Herring, Mark Rutland, Michael Turquette,
Stephen Boyd, Erin Lo, James Liao, linux-clk, CC Hwang,
Loda Choui, Miles Chen, Scott Shu, Jades Shih, Yingjoe Chen,
My Chuang, linux-kernel, linux-mediatek, devicetree, wsd_upstream
In-Reply-To: <57D15B6C.6080305@arm.com>
Hi Marc
Thanks for your review. the response inlined.
On Thu, 2016-09-08 at 13:37 +0100, Marc Zyngier wrote:
> On 08/09/16 11:49, Mars Cheng wrote:
> > This adds DT binding documentation for Mediatek MT6797.
> >
> > Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
> > ---
[...]
>
> > diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
> > index 9d1d72c..3d97eb4 100644
> > --- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
> > @@ -8,6 +8,7 @@ Required properties:
> > "mediatek,mt8173-sysirq"
> > "mediatek,mt8135-sysirq"
> > "mediatek,mt8127-sysirq"
> > + "mediatek,mt6797-sysirq"
> > "mediatek,mt6795-sysirq"
> > "mediatek,mt6755-sysirq"
> > "mediatek,mt6592-sysirq"
> > @@ -21,7 +22,8 @@ Required properties:
> > - interrupt-parent: phandle of irq parent for sysirq. The parent must
> > use the same interrupt-cells format as GIC.
> > - reg: Physical base address of the intpol registers and length of memory
> > - mapped region.
> > + mapped region. Could be up to 2 registers here at max. Ex: 6797 needs 2 reg,
> > + others need 1.
>
> Two things:
>
> - Please make this a separate patch that can be reviewed independently
> of the rest of the changes, which are just adding new compatible
> identifiers.
Will fix this in the next patch set.
>
> - Why can't you simply expose it as a separate controller? Looking at
> the way you're changing the corresponding driver, it looks like you're
> simply adding an extra base/size. If you simply had a base for the
> corresponding GIC interrupts, you could handle as many region as you
> want, and have a more generic driver.
>
May I know the meaning of "simply expose it as a separate controller"?
Or you might like to suggest me any similar driver as a reference? I
will examine it. Current design is based on the fact: We expect
irq-mtk-sysirq needs the optional second base but the third one will not
happen.
If we really need more than 2 bases, we can figure out a more generic
driver at the time, right?
Thanks.
> Thanks,
>
> M.
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: mediatek: add mt6797 support
From: Marc Zyngier @ 2016-09-08 13:15 UTC (permalink / raw)
To: Mars Cheng, Matthias Brugger, Rob Herring, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA, CC Hwang, Loda Choui,
Miles Chen, Scott Shu, Jades Shih, Yingjoe Chen, My Chuang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
wsd_upstream-NuS5LvNUpcJWk0Htik3J/w
In-Reply-To: <1473331794-27542-4-git-send-email-mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
On 08/09/16 11:49, Mars Cheng wrote:
> This adds basic chip support for MT6797 SoC.
>
> Signed-off-by: Mars Cheng <mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> ---
> arch/arm64/boot/dts/mediatek/Makefile | 1 +
> arch/arm64/boot/dts/mediatek/mt6797-evb.dts | 36 +++++
> arch/arm64/boot/dts/mediatek/mt6797.dtsi | 193 +++++++++++++++++++++++++++
> 3 files changed, 230 insertions(+)
> create mode 100644 arch/arm64/boot/dts/mediatek/mt6797-evb.dts
> create mode 100644 arch/arm64/boot/dts/mediatek/mt6797.dtsi
>
> diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
> index 9fbfd32..015eb07 100644
> --- a/arch/arm64/boot/dts/mediatek/Makefile
> +++ b/arch/arm64/boot/dts/mediatek/Makefile
> @@ -1,5 +1,6 @@
> dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
> dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
> +dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
> dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
>
> always := $(dtb-y)
[...]
> diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
> new file mode 100644
> index 0000000..66f6442
> --- /dev/null
> +++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
> @@ -0,0 +1,193 @@
[...]
> + gic: interrupt-controller@19000000 {
> + compatible = "arm,gic-v3";
> + #interrupt-cells = <3>;
> + interrupt-parent = <&gic>;
> + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-controller;
> + reg = <0 0x19000000 0 0x10000>, /* GICD */
> + <0 0x19200000 0 0x200000>, /* GICR */
> + <0 0x10240000 0 0x2000>; /* GICC */
Where are the GICV and GICH regions? No ITS?
Thanks,
M.
--
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v6 6/6] media: mtk-mdp: add Maintainers entry for Mediatek MDP driver
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson, Rob Herring, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak
Cc: srv_heupstream, Eddie Huang, Yingjoe Chen, devicetree,
linux-kernel, linux-arm-kernel, linux-media, linux-mediatek,
Minghsiu Tsai, Houlong Wei, Andrew-CT Chen
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>
Add Minghsiu Tsai, Houlong Wei and Andrew-CT Chen as
maintainers for Mediatek MDP driver
Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
Signed-off-by: Houlong Wei <houlong.wei@mediatek.com>
Signed-off-by: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
---
MAINTAINERS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 20bb1d0..e17e681 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7605,6 +7605,15 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/mediatek/
+MEDIATEK MDP DRIVER
+M: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
+M: Houlong Wei <houlong.wei@mediatek.com>
+M: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
+S: Supported
+F: drivers/media/platform/mtk-mdp/
+F: drivers/media/platform/mtk-vpu/
+F: Documentation/devicetree/bindings/media/mediatek-mdp.txt
+
MEDIATEK MT7601U WIRELESS LAN DRIVER
M: Jakub Kicinski <kubakici@wp.pl>
L: linux-wireless@vger.kernel.org
--
1.7.9.5
^ permalink raw reply related
* [PATCH v6 5/6] media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson, Rob Herring, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak
Cc: srv_heupstream, Eddie Huang, Yingjoe Chen, devicetree,
linux-kernel, linux-arm-kernel, linux-media, linux-mediatek,
Minghsiu Tsai
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>
Add V4L2_PIX_FMT_MT21C in format list.
Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
---
drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 8 ++++++++
drivers/media/platform/mtk-mdp/mtk_mdp_regs.c | 4 ++++
2 files changed, 12 insertions(+)
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
index 0655027..a90972e 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
@@ -54,6 +54,14 @@ static struct mtk_mdp_pix_align mtk_mdp_size_align = {
static const struct mtk_mdp_fmt mtk_mdp_formats[] = {
{
+ .pixelformat = V4L2_PIX_FMT_MT21C,
+ .depth = { 8, 4 },
+ .row_depth = { 8, 8 },
+ .num_planes = 2,
+ .num_comp = 2,
+ .align = &mtk_mdp_size_align,
+ .flags = MTK_MDP_FMT_FLAG_OUTPUT,
+ }, {
.pixelformat = V4L2_PIX_FMT_NV12M,
.depth = { 8, 4 },
.row_depth = { 8, 8 },
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c b/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
index a5601e1..86d57f3 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
@@ -29,6 +29,8 @@ enum MDP_COLOR_ENUM {
MDP_COLOR_NV12 = MDP_COLORFMT_PACK(0, 2, 1, 1, 1, 8, 1, 0, 12),
MDP_COLOR_I420 = MDP_COLORFMT_PACK(0, 3, 0, 1, 1, 8, 1, 0, 8),
MDP_COLOR_YV12 = MDP_COLORFMT_PACK(0, 3, 0, 1, 1, 8, 1, 1, 8),
+ /* Mediatek proprietary format */
+ MDP_COLOR_420_MT21 = MDP_COLORFMT_PACK(5, 2, 1, 1, 1, 256, 1, 0, 12),
};
static int32_t mtk_mdp_map_color_format(int v4l2_format)
@@ -37,6 +39,8 @@ static int32_t mtk_mdp_map_color_format(int v4l2_format)
case V4L2_PIX_FMT_NV12M:
case V4L2_PIX_FMT_NV12:
return MDP_COLOR_NV12;
+ case V4L2_PIX_FMT_MT21C:
+ return MDP_COLOR_420_MT21;
case V4L2_PIX_FMT_YUV420M:
case V4L2_PIX_FMT_YUV420:
return MDP_COLOR_I420;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v6 4/6] arm64: dts: mediatek: Add MDP for MT8173
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson, Rob Herring, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak
Cc: devicetree, Minghsiu Tsai, srv_heupstream, linux-kernel,
linux-mediatek, Yingjoe Chen, Eddie Huang, linux-arm-kernel,
linux-media
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>
Add MDP node for MT8173
Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 84 ++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 10f638f..cd93228 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -41,6 +41,14 @@
dpi0 = &dpi0;
dsi0 = &dsi0;
dsi1 = &dsi1;
+ mdp_rdma0 = &mdp_rdma0;
+ mdp_rdma1 = &mdp_rdma1;
+ mdp_rsz0 = &mdp_rsz0;
+ mdp_rsz1 = &mdp_rsz1;
+ mdp_rsz2 = &mdp_rsz2;
+ mdp_wdma0 = &mdp_wdma0;
+ mdp_wrot0 = &mdp_wrot0;
+ mdp_wrot1 = &mdp_wrot1;
};
cpus {
@@ -716,6 +724,82 @@
#clock-cells = <1>;
};
+ mdp {
+ compatible = "mediatek,mt8173-mdp";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ mediatek,vpu = <&vpu>;
+
+ mdp_rdma0: rdma@14001000 {
+ compatible = "mediatek,mt8173-mdp-rdma";
+ reg = <0 0x14001000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RDMA0>,
+ <&mmsys CLK_MM_MUTEX_32K>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_RDMA0>;
+ mediatek,larb = <&larb0>;
+ };
+
+ mdp_rdma1: rdma@14002000 {
+ compatible = "mediatek,mt8173-mdp-rdma";
+ reg = <0 0x14002000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RDMA1>,
+ <&mmsys CLK_MM_MUTEX_32K>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_RDMA1>;
+ mediatek,larb = <&larb4>;
+ };
+
+ mdp_rsz0: rsz@14003000 {
+ compatible = "mediatek,mt8173-mdp-rsz";
+ reg = <0 0x14003000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RSZ0>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ };
+
+ mdp_rsz1: rsz@14004000 {
+ compatible = "mediatek,mt8173-mdp-rsz";
+ reg = <0 0x14004000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RSZ1>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ };
+
+ mdp_rsz2: rsz@14005000 {
+ compatible = "mediatek,mt8173-mdp-rsz";
+ reg = <0 0x14005000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RSZ2>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ };
+
+ mdp_wdma0: wdma@14006000 {
+ compatible = "mediatek,mt8173-mdp-wdma";
+ reg = <0 0x14006000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_WDMA>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_WDMA>;
+ mediatek,larb = <&larb0>;
+ };
+
+ mdp_wrot0: wrot@14007000 {
+ compatible = "mediatek,mt8173-mdp-wrot";
+ reg = <0 0x14007000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_WROT0>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_WROT0>;
+ mediatek,larb = <&larb0>;
+ };
+
+ mdp_wrot1: wrot@14008000 {
+ compatible = "mediatek,mt8173-mdp-wrot";
+ reg = <0 0x14008000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_WROT1>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_WROT1>;
+ mediatek,larb = <&larb4>;
+ };
+ };
+
ovl0: ovl@1400c000 {
compatible = "mediatek,mt8173-disp-ovl";
reg = <0 0x1400c000 0 0x1000>;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v6 3/6] media: Add Mediatek MDP Driver
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson, Rob Herring, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak
Cc: srv_heupstream, Eddie Huang, Yingjoe Chen, devicetree,
linux-kernel, linux-arm-kernel, linux-media, linux-mediatek,
Minghsiu Tsai
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>
Add MDP driver for MT8173
Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
---
drivers/media/platform/Kconfig | 17 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/mtk-mdp/Makefile | 9 +
drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 159 ++++
drivers/media/platform/mtk-mdp/mtk_mdp_comp.h | 72 ++
drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 294 ++++++
drivers/media/platform/mtk-mdp/mtk_mdp_core.h | 260 +++++
drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h | 126 +++
drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 1270 +++++++++++++++++++++++++
drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h | 22 +
drivers/media/platform/mtk-mdp/mtk_mdp_regs.c | 152 +++
drivers/media/platform/mtk-mdp/mtk_mdp_regs.h | 31 +
drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c | 145 +++
drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h | 41 +
14 files changed, 2600 insertions(+)
create mode 100644 drivers/media/platform/mtk-mdp/Makefile
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index f25344b..0c88532 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -166,6 +166,23 @@ config VIDEO_MEDIATEK_VPU
To compile this driver as a module, choose M here: the
module will be called mtk-vpu.
+config VIDEO_MEDIATEK_MDP
+ tristate "Mediatek MDP driver"
+ depends on MTK_IOMMU || COMPILE_TEST
+ depends on VIDEO_DEV && VIDEO_V4L2
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on HAS_DMA
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_MEM2MEM_DEV
+ select VIDEO_MEDIATEK_VPU
+ default n
+ ---help---
+ It is a v4l2 driver and present in Mediatek MT8173 SoCs.
+ The driver supports for scaling and color space conversion.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mtk-mdp.
+
config VIDEO_MEDIATEK_VCODEC
tristate "Mediatek Video Codec driver"
depends on MTK_IOMMU || COMPILE_TEST
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 21771c1..221aace 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -63,3 +63,5 @@ ccflags-y += -I$(srctree)/drivers/media/i2c
obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/
obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec/
+
+obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp/
diff --git a/drivers/media/platform/mtk-mdp/Makefile b/drivers/media/platform/mtk-mdp/Makefile
new file mode 100644
index 0000000..f802569
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/Makefile
@@ -0,0 +1,9 @@
+mtk-mdp-y += mtk_mdp_core.o
+mtk-mdp-y += mtk_mdp_comp.o
+mtk-mdp-y += mtk_mdp_m2m.o
+mtk-mdp-y += mtk_mdp_regs.o
+mtk-mdp-y += mtk_mdp_vpu.o
+
+obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp.o
+
+ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vpu
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
new file mode 100644
index 0000000..aa8f9fd
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_mdp_comp.h"
+
+
+static const char * const mtk_mdp_comp_stem[MTK_MDP_COMP_TYPE_MAX] = {
+ "mdp_rdma",
+ "mdp_rsz",
+ "mdp_wdma",
+ "mdp_wrot",
+};
+
+struct mtk_mdp_comp_match {
+ enum mtk_mdp_comp_type type;
+ int alias_id;
+};
+
+static const struct mtk_mdp_comp_match mtk_mdp_matches[MTK_MDP_COMP_ID_MAX] = {
+ { MTK_MDP_RDMA, 0 },
+ { MTK_MDP_RDMA, 1 },
+ { MTK_MDP_RSZ, 0 },
+ { MTK_MDP_RSZ, 1 },
+ { MTK_MDP_RSZ, 2 },
+ { MTK_MDP_WDMA, 0 },
+ { MTK_MDP_WROT, 0 },
+ { MTK_MDP_WROT, 1 },
+};
+
+int mtk_mdp_comp_get_id(struct device *dev, struct device_node *node,
+ enum mtk_mdp_comp_type comp_type)
+{
+ int id = of_alias_get_id(node, mtk_mdp_comp_stem[comp_type]);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mtk_mdp_matches); i++) {
+ if (comp_type == mtk_mdp_matches[i].type &&
+ id == mtk_mdp_matches[i].alias_id)
+ return i;
+ }
+
+ dev_err(dev, "Failed to get id. type: %d, id: %d\n", comp_type, id);
+
+ return -EINVAL;
+}
+
+void mtk_mdp_comp_clock_on(struct device *dev, struct mtk_mdp_comp *comp)
+{
+ int i, err;
+
+ if (comp->larb_dev) {
+ err = mtk_smi_larb_get(comp->larb_dev);
+ if (err)
+ dev_err(dev,
+ "failed to get larb, err %d. type:%d id:%d\n",
+ err, comp->type, comp->id);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+ if (!comp->clk[i])
+ continue;
+ err = clk_prepare_enable(comp->clk[i]);
+ if (err)
+ dev_err(dev,
+ "failed to enable clock, err %d. type:%d id:%d i:%d\n",
+ err, comp->type, comp->id, i);
+ }
+}
+
+void mtk_mdp_comp_clock_off(struct device *dev, struct mtk_mdp_comp *comp)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+ if (!comp->clk[i])
+ continue;
+ clk_disable_unprepare(comp->clk[i]);
+ }
+
+ if (comp->larb_dev)
+ mtk_smi_larb_put(comp->larb_dev);
+}
+
+int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
+ struct mtk_mdp_comp *comp, enum mtk_mdp_comp_id comp_id)
+{
+ struct device_node *larb_node;
+ struct platform_device *larb_pdev;
+ int i;
+
+ if (comp_id < 0 || comp_id >= MTK_MDP_COMP_ID_MAX) {
+ dev_err(dev, "Invalid comp_id %d\n", comp_id);
+ return -EINVAL;
+ }
+
+ comp->dev_node = of_node_get(node);
+ comp->id = comp_id;
+ comp->type = mtk_mdp_matches[comp_id].type;
+ comp->regs = of_iomap(node, 0);
+
+ for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+ comp->clk[i] = of_clk_get(node, i);
+
+ /* Only RDMA needs two clocks */
+ if (comp->type != MTK_MDP_RDMA)
+ break;
+ }
+
+ /* Only DMA capable components need the LARB property */
+ comp->larb_dev = NULL;
+ if (comp->type != MTK_MDP_RDMA &&
+ comp->type != MTK_MDP_WDMA &&
+ comp->type != MTK_MDP_WROT)
+ return 0;
+
+ larb_node = of_parse_phandle(node, "mediatek,larb", 0);
+ if (!larb_node) {
+ dev_err(dev,
+ "Missing mediadek,larb phandle in %s node\n",
+ node->full_name);
+ return -EINVAL;
+ }
+
+ larb_pdev = of_find_device_by_node(larb_node);
+ if (!larb_pdev) {
+ dev_warn(dev, "Waiting for larb device %s\n",
+ larb_node->full_name);
+ of_node_put(larb_node);
+ return -EPROBE_DEFER;
+ }
+ of_node_put(larb_node);
+
+ comp->larb_dev = &larb_pdev->dev;
+
+ return 0;
+}
+
+void mtk_mdp_comp_deinit(struct device *dev, struct mtk_mdp_comp *comp)
+{
+ of_node_put(comp->dev_node);
+}
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
new file mode 100644
index 0000000..63b3983
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_COMP_H__
+#define __MTK_MDP_COMP_H__
+
+/**
+ * enum mtk_mdp_comp_type - the MDP component
+ * @MTK_MDP_RDMA: Read DMA
+ * @MTK_MDP_RSZ: Riszer
+ * @MTK_MDP_WDMA: Write DMA
+ * @MTK_MDP_WROT: Write DMA with rotation
+ */
+enum mtk_mdp_comp_type {
+ MTK_MDP_RDMA,
+ MTK_MDP_RSZ,
+ MTK_MDP_WDMA,
+ MTK_MDP_WROT,
+ MTK_MDP_COMP_TYPE_MAX,
+};
+
+enum mtk_mdp_comp_id {
+ MTK_MDP_COMP_RDMA0,
+ MTK_MDP_COMP_RDMA1,
+ MTK_MDP_COMP_RSZ0,
+ MTK_MDP_COMP_RSZ1,
+ MTK_MDP_COMP_RSZ2,
+ MTK_MDP_COMP_WDMA,
+ MTK_MDP_COMP_WROT0,
+ MTK_MDP_COMP_WROT1,
+ MTK_MDP_COMP_ID_MAX,
+};
+
+/**
+ * struct mtk_mdp_comp - the MDP's function component data
+ * @dev_node: component device node
+ * @clk: clocks required for component
+ * @regs: Mapped address of component registers.
+ * @larb_dev: SMI device required for component
+ * @type: component type
+ * @id: component ID
+ */
+struct mtk_mdp_comp {
+ struct device_node *dev_node;
+ struct clk *clk[2];
+ void __iomem *regs;
+ struct device *larb_dev;
+ enum mtk_mdp_comp_type type;
+ enum mtk_mdp_comp_id id;
+};
+
+int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
+ struct mtk_mdp_comp *comp, enum mtk_mdp_comp_id comp_id);
+void mtk_mdp_comp_deinit(struct device *dev, struct mtk_mdp_comp *comp);
+int mtk_mdp_comp_get_id(struct device *dev, struct device_node *node,
+ enum mtk_mdp_comp_type comp_type);
+void mtk_mdp_comp_clock_on(struct device *dev, struct mtk_mdp_comp *comp);
+void mtk_mdp_comp_clock_off(struct device *dev, struct mtk_mdp_comp *comp);
+
+
+#endif /* __MTK_MDP_COMP_H__ */
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
new file mode 100644
index 0000000..b0c421e
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_m2m.h"
+#include "mtk_vpu.h"
+
+/* MDP debug log level (0-3). 3 shows all the logs. */
+int mtk_mdp_dbg_level;
+EXPORT_SYMBOL(mtk_mdp_dbg_level);
+
+module_param(mtk_mdp_dbg_level, int, S_IRUGO | S_IWUSR);
+
+static const struct of_device_id mtk_mdp_comp_dt_ids[] = {
+ {
+ .compatible = "mediatek,mt8173-mdp-rdma",
+ .data = (void *)MTK_MDP_RDMA
+ }, {
+ .compatible = "mediatek,mt8173-mdp-rsz",
+ .data = (void *)MTK_MDP_RSZ
+ }, {
+ .compatible = "mediatek,mt8173-mdp-wdma",
+ .data = (void *)MTK_MDP_WDMA
+ }, {
+ .compatible = "mediatek,mt8173-mdp-wrot",
+ .data = (void *)MTK_MDP_WROT
+ }
+};
+
+static const struct of_device_id mtk_mdp_of_ids[] = {
+ { .compatible = "mediatek,mt8173-mdp", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, mtk_mdp_of_ids);
+
+static void mtk_mdp_clock_on(struct mtk_mdp_dev *mdp)
+{
+ struct device *dev = &mdp->pdev->dev;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+ mtk_mdp_comp_clock_on(dev, mdp->comp[i]);
+}
+
+static void mtk_mdp_clock_off(struct mtk_mdp_dev *mdp)
+{
+ struct device *dev = &mdp->pdev->dev;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+ mtk_mdp_comp_clock_off(dev, mdp->comp[i]);
+}
+
+static void mtk_mdp_wdt_worker(struct work_struct *work)
+{
+ struct mtk_mdp_dev *mdp =
+ container_of(work, struct mtk_mdp_dev, wdt_work);
+ struct mtk_mdp_ctx *ctx;
+
+ mtk_mdp_err("Watchdog timeout");
+
+ list_for_each_entry(ctx, &mdp->ctx_list, list) {
+ mtk_mdp_dbg(0, "[%d] Change as state error", ctx->id);
+ mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_CTX_ERROR);
+ }
+}
+
+static void mtk_mdp_reset_handler(void *priv)
+{
+ struct mtk_mdp_dev *mdp = priv;
+
+ queue_work(mdp->wdt_wq, &mdp->wdt_work);
+}
+
+static int mtk_mdp_probe(struct platform_device *pdev)
+{
+ struct mtk_mdp_dev *mdp;
+ struct device *dev = &pdev->dev;
+ struct device_node *node;
+ int i, ret = 0;
+
+ mdp = devm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL);
+ if (!mdp)
+ return -ENOMEM;
+
+ mdp->id = pdev->id;
+ mdp->pdev = pdev;
+ INIT_LIST_HEAD(&mdp->ctx_list);
+
+ mutex_init(&mdp->lock);
+ mutex_init(&mdp->vpulock);
+
+ /* Iterate over sibling MDP function blocks */
+ for_each_child_of_node(dev->of_node, node) {
+ const struct of_device_id *of_id;
+ enum mtk_mdp_comp_type comp_type;
+ int comp_id;
+ struct mtk_mdp_comp *comp;
+
+ of_id = of_match_node(mtk_mdp_comp_dt_ids, node);
+ if (!of_id)
+ continue;
+
+ if (!of_device_is_available(node)) {
+ dev_err(dev, "Skipping disabled component %s\n",
+ node->full_name);
+ continue;
+ }
+
+ comp_type = (enum mtk_mdp_comp_type)of_id->data;
+ comp_id = mtk_mdp_comp_get_id(dev, node, comp_type);
+ if (comp_id < 0) {
+ dev_warn(dev, "Skipping unknown component %s\n",
+ node->full_name);
+ continue;
+ }
+
+ comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
+ if (!comp) {
+ ret = -ENOMEM;
+ goto err_comp;
+ }
+ mdp->comp[comp_id] = comp;
+
+ ret = mtk_mdp_comp_init(dev, node, comp, comp_id);
+ if (ret)
+ goto err_comp;
+ }
+
+ mdp->job_wq = create_singlethread_workqueue(MTK_MDP_MODULE_NAME);
+ if (!mdp->job_wq) {
+ dev_err(&pdev->dev, "unable to alloc job workqueue\n");
+ ret = -ENOMEM;
+ goto err_alloc_job_wq;
+ }
+
+ mdp->wdt_wq = create_singlethread_workqueue("mdp_wdt_wq");
+ if (!mdp->wdt_wq) {
+ dev_err(&pdev->dev, "unable to alloc wdt workqueue\n");
+ ret = -ENOMEM;
+ goto err_alloc_wdt_wq;
+ }
+ INIT_WORK(&mdp->wdt_work, mtk_mdp_wdt_worker);
+
+ ret = v4l2_device_register(dev, &mdp->v4l2_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register v4l2 device\n");
+ ret = -EINVAL;
+ goto err_dev_register;
+ }
+
+ ret = mtk_mdp_register_m2m_device(mdp);
+ if (ret) {
+ v4l2_err(&mdp->v4l2_dev, "Failed to init mem2mem device\n");
+ goto err_m2m_register;
+ }
+
+ mdp->vpu_dev = vpu_get_plat_device(pdev);
+ vpu_wdt_reg_handler(mdp->vpu_dev, mtk_mdp_reset_handler, mdp,
+ VPU_RST_MDP);
+
+ platform_set_drvdata(pdev, mdp);
+
+ vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
+
+ pm_runtime_enable(dev);
+ dev_dbg(dev, "mdp-%d registered successfully\n", mdp->id);
+
+ return 0;
+
+err_m2m_register:
+ v4l2_device_unregister(&mdp->v4l2_dev);
+
+err_dev_register:
+ destroy_workqueue(mdp->wdt_wq);
+
+err_alloc_wdt_wq:
+ destroy_workqueue(mdp->job_wq);
+
+err_alloc_job_wq:
+
+err_comp:
+ for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+ mtk_mdp_comp_deinit(dev, mdp->comp[i]);
+
+ dev_dbg(dev, "err %d\n", ret);
+ return ret;
+}
+
+static int mtk_mdp_remove(struct platform_device *pdev)
+{
+ struct mtk_mdp_dev *mdp = platform_get_drvdata(pdev);
+ int i;
+
+ pm_runtime_disable(&pdev->dev);
+ vb2_dma_contig_clear_max_seg_size(&pdev->dev);
+ mtk_mdp_unregister_m2m_device(mdp);
+ v4l2_device_unregister(&mdp->v4l2_dev);
+
+ flush_workqueue(mdp->job_wq);
+ destroy_workqueue(mdp->job_wq);
+
+ for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+ mtk_mdp_comp_deinit(&pdev->dev, mdp->comp[i]);
+
+ dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
+ return 0;
+}
+
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
+static int mtk_mdp_pm_suspend(struct device *dev)
+{
+ struct mtk_mdp_dev *mdp = dev_get_drvdata(dev);
+
+ mtk_mdp_clock_off(mdp);
+
+ return 0;
+}
+
+static int mtk_mdp_pm_resume(struct device *dev)
+{
+ struct mtk_mdp_dev *mdp = dev_get_drvdata(dev);
+
+ mtk_mdp_clock_on(mdp);
+
+ return 0;
+}
+#endif /* CONFIG_PM_RUNTIME || CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_SLEEP
+static int mtk_mdp_suspend(struct device *dev)
+{
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ return mtk_mdp_pm_suspend(dev);
+}
+
+static int mtk_mdp_resume(struct device *dev)
+{
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ return mtk_mdp_pm_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops mtk_mdp_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mtk_mdp_suspend, mtk_mdp_resume)
+ SET_RUNTIME_PM_OPS(mtk_mdp_pm_suspend, mtk_mdp_pm_resume, NULL)
+};
+
+static struct platform_driver mtk_mdp_driver = {
+ .probe = mtk_mdp_probe,
+ .remove = mtk_mdp_remove,
+ .driver = {
+ .name = MTK_MDP_MODULE_NAME,
+ .owner = THIS_MODULE,
+ .pm = &mtk_mdp_pm_ops,
+ .of_match_table = mtk_mdp_of_ids,
+ }
+};
+
+module_platform_driver(mtk_mdp_driver);
+
+MODULE_AUTHOR("Houlong Wei <houlong.wei@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek image processor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.h b/drivers/media/platform/mtk-mdp/mtk_mdp_core.h
new file mode 100644
index 0000000..2e979f9
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_CORE_H__
+#define __MTK_MDP_CORE_H__
+
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_mdp_vpu.h"
+#include "mtk_mdp_comp.h"
+
+
+#define MTK_MDP_MODULE_NAME "mtk-mdp"
+
+#define MTK_MDP_SHUTDOWN_TIMEOUT ((100*HZ)/1000) /* 100ms */
+#define MTK_MDP_MAX_CTRL_NUM 10
+
+#define MTK_MDP_FMT_FLAG_OUTPUT BIT(0)
+#define MTK_MDP_FMT_FLAG_CAPTURE BIT(1)
+
+#define MTK_MDP_VPU_INIT BIT(0)
+#define MTK_MDP_SRC_FMT BIT(1)
+#define MTK_MDP_DST_FMT BIT(2)
+#define MTK_MDP_CTX_ERROR BIT(5)
+
+/**
+ * struct mtk_mdp_pix_align - alignement of image
+ * @org_w: source alignment of width
+ * @org_h: source alignment of height
+ * @target_w: dst alignment of width
+ * @target_h: dst alignment of height
+ */
+struct mtk_mdp_pix_align {
+ u16 org_w;
+ u16 org_h;
+ u16 target_w;
+ u16 target_h;
+};
+
+/**
+ * struct mtk_mdp_fmt - the driver's internal color format data
+ * @pixelformat: the fourcc code for this format, 0 if not applicable
+ * @num_planes: number of physically non-contiguous data planes
+ * @num_comp: number of logical data planes
+ * @depth: per plane driver's private 'number of bits per pixel'
+ * @row_depth: per plane driver's private 'number of bits per pixel per row'
+ * @flags: flags indicating which operation mode format applies to
+ MTK_MDP_FMT_FLAG_OUTPUT is used in OUTPUT stream
+ MTK_MDP_FMT_FLAG_CAPTURE is used in CAPTURE stream
+ * @align: pointer to a pixel alignment struct, NULL if using default value
+ */
+struct mtk_mdp_fmt {
+ u32 pixelformat;
+ u16 num_planes;
+ u16 num_comp;
+ u8 depth[VIDEO_MAX_PLANES];
+ u8 row_depth[VIDEO_MAX_PLANES];
+ u32 flags;
+ struct mtk_mdp_pix_align *align;
+};
+
+/**
+ * struct mtk_mdp_addr - the image processor physical address set
+ * @addr: address of planes
+ */
+struct mtk_mdp_addr {
+ dma_addr_t addr[MTK_MDP_MAX_NUM_PLANE];
+};
+
+/* struct mtk_mdp_ctrls - the image processor control set
+ * @rotate: rotation degree
+ * @hflip: horizontal flip
+ * @vflip: vertical flip
+ * @global_alpha: the alpha value of current frame
+ */
+struct mtk_mdp_ctrls {
+ struct v4l2_ctrl *rotate;
+ struct v4l2_ctrl *hflip;
+ struct v4l2_ctrl *vflip;
+ struct v4l2_ctrl *global_alpha;
+};
+
+/**
+ * struct mtk_mdp_frame - source/target frame properties
+ * @width: SRC : SRCIMG_WIDTH, DST : OUTPUTDMA_WHOLE_IMG_WIDTH
+ * @height: SRC : SRCIMG_HEIGHT, DST : OUTPUTDMA_WHOLE_IMG_HEIGHT
+ * @crop: cropped(source)/scaled(destination) size
+ * @payload: image size in bytes (w x h x bpp)
+ * @pitch: bytes per line of image in memory
+ * @addr: image frame buffer physical addresses
+ * @fmt: color format pointer
+ * @alpha: frame's alpha value
+ */
+struct mtk_mdp_frame {
+ u32 width;
+ u32 height;
+ struct v4l2_rect crop;
+ unsigned long payload[VIDEO_MAX_PLANES];
+ unsigned int pitch[VIDEO_MAX_PLANES];
+ struct mtk_mdp_addr addr;
+ const struct mtk_mdp_fmt *fmt;
+ u8 alpha;
+};
+
+/**
+ * struct mtk_mdp_variant - image processor variant information
+ * @pix_max: maximum limit of image size
+ * @pix_min: minimun limit of image size
+ * @pix_align: alignement of image
+ * @h_scale_up_max: maximum scale-up in horizontal
+ * @v_scale_up_max: maximum scale-up in vertical
+ * @h_scale_down_max: maximum scale-down in horizontal
+ * @v_scale_down_max: maximum scale-down in vertical
+ */
+struct mtk_mdp_variant {
+ struct mtk_mdp_pix_limit *pix_max;
+ struct mtk_mdp_pix_limit *pix_min;
+ struct mtk_mdp_pix_align *pix_align;
+ u16 h_scale_up_max;
+ u16 v_scale_up_max;
+ u16 h_scale_down_max;
+ u16 v_scale_down_max;
+};
+
+/**
+ * struct mtk_mdp_dev - abstraction for image processor entity
+ * @lock: the mutex protecting this data structure
+ * @vpulock: the mutex protecting the communication with VPU
+ * @pdev: pointer to the image processor platform device
+ * @variant: the IP variant information
+ * @id: image processor device index (0..MTK_MDP_MAX_DEVS)
+ * @comp: MDP function components
+ * @m2m_dev: v4l2 memory-to-memory device data
+ * @ctx_list: list of struct mtk_mdp_ctx
+ * @vdev: video device for image processor driver
+ * @v4l2_dev: V4L2 device to register video devices for.
+ * @job_wq: processor work queue
+ * @vpu_dev: VPU platform device
+ * @ctx_num: counter of active MTK MDP context
+ * @id_counter: An integer id given to the next opened context
+ * @wdt_wq: work queue for VPU watchdog
+ * @wdt_work: worker for VPU watchdog
+ */
+struct mtk_mdp_dev {
+ struct mutex lock;
+ struct mutex vpulock;
+ struct platform_device *pdev;
+ struct mtk_mdp_variant *variant;
+ u16 id;
+ struct mtk_mdp_comp *comp[MTK_MDP_COMP_ID_MAX];
+ struct v4l2_m2m_dev *m2m_dev;
+ struct list_head ctx_list;
+ struct video_device vdev;
+ struct v4l2_device v4l2_dev;
+ struct workqueue_struct *job_wq;
+ struct platform_device *vpu_dev;
+ int ctx_num;
+ unsigned long id_counter;
+ struct workqueue_struct *wdt_wq;
+ struct work_struct wdt_work;
+};
+
+/**
+ * mtk_mdp_ctx - the device context data
+ * @list: link to ctx_list of mtk_mdp_dev
+ * @s_frame: source frame properties
+ * @d_frame: destination frame properties
+ * @id: index of the context that this structure describes
+ * @flags: additional flags for image conversion
+ * @state: flags to keep track of user configuration
+ Protected by slock
+ * @rotation: rotates the image by specified angle
+ * @hflip: mirror the picture horizontally
+ * @vflip: mirror the picture vertically
+ * @mdp_dev: the image processor device this context applies to
+ * @m2m_ctx: memory-to-memory device context
+ * @fh: v4l2 file handle
+ * @ctrl_handler: v4l2 controls handler
+ * @ctrls image processor control set
+ * @ctrls_rdy: true if the control handler is initialized
+ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
+ * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
+ * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
+ * @quant: enum v4l2_quantization, colorspace quantization
+ * @vpu: VPU instance
+ * @slock: the mutex protecting mtp_mdp_ctx.state
+ * @work: worker for image processing
+ */
+struct mtk_mdp_ctx {
+ struct list_head list;
+ struct mtk_mdp_frame s_frame;
+ struct mtk_mdp_frame d_frame;
+ u32 flags;
+ u32 state;
+ int id;
+ int rotation;
+ u32 hflip:1;
+ u32 vflip:1;
+ struct mtk_mdp_dev *mdp_dev;
+ struct v4l2_m2m_ctx *m2m_ctx;
+ struct v4l2_fh fh;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct mtk_mdp_ctrls ctrls;
+ bool ctrls_rdy;
+ enum v4l2_colorspace colorspace;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_xfer_func xfer_func;
+ enum v4l2_quantization quant;
+
+ struct mtk_mdp_vpu vpu;
+ struct mutex slock;
+ struct work_struct work;
+};
+
+extern int mtk_mdp_dbg_level;
+
+#if defined(DEBUG)
+
+#define mtk_mdp_dbg(level, fmt, args...) \
+ do { \
+ if (mtk_mdp_dbg_level >= level) \
+ pr_info("[MTK_MDP] level=%d %s(),%d: " fmt "\n", \
+ level, __func__, __LINE__, ##args); \
+ } while (0)
+
+#define mtk_mdp_err(fmt, args...) \
+ pr_err("[MTK_MDP][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \
+ ##args)
+
+
+#define mtk_mdp_dbg_enter() mtk_mdp_dbg(3, "+")
+#define mtk_mdp_dbg_leave() mtk_mdp_dbg(3, "-")
+
+#else
+
+#define mtk_mdp_dbg(level, fmt, args...)
+#define mtk_mdp_err(fmt, args...)
+#define mtk_mdp_dbg_enter()
+#define mtk_mdp_dbg_leave()
+
+#endif
+
+#endif /* __MTK_MDP_CORE_H__ */
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h b/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
new file mode 100644
index 0000000..78e2cc0
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_IPI_H__
+#define __MTK_MDP_IPI_H__
+
+#define MTK_MDP_MAX_NUM_PLANE 3
+
+enum mdp_ipi_msgid {
+ AP_MDP_INIT = 0xd000,
+ AP_MDP_DEINIT = 0xd001,
+ AP_MDP_PROCESS = 0xd002,
+
+ VPU_MDP_INIT_ACK = 0xe000,
+ VPU_MDP_DEINIT_ACK = 0xe001,
+ VPU_MDP_PROCESS_ACK = 0xe002
+};
+
+#pragma pack(push, 4)
+
+/**
+ * struct mdp_ipi_init - for AP_MDP_INIT
+ * @msg_id : AP_MDP_INIT
+ * @ipi_id : IPI_MDP
+ * @ap_inst : AP mtk_mdp_vpu address
+ */
+struct mdp_ipi_init {
+ uint32_t msg_id;
+ uint32_t ipi_id;
+ uint64_t ap_inst;
+};
+
+/**
+ * struct mdp_ipi_comm - for AP_MDP_PROCESS, AP_MDP_DEINIT
+ * @msg_id : AP_MDP_PROCESS, AP_MDP_DEINIT
+ * @ipi_id : IPI_MDP
+ * @ap_inst : AP mtk_mdp_vpu address
+ * @vpu_inst_addr : VPU MDP instance address
+ */
+struct mdp_ipi_comm {
+ uint32_t msg_id;
+ uint32_t ipi_id;
+ uint64_t ap_inst;
+ uint32_t vpu_inst_addr;
+};
+
+/**
+ * struct mdp_ipi_comm_ack - for VPU_MDP_DEINIT_ACK, VPU_MDP_PROCESS_ACK
+ * @msg_id : VPU_MDP_DEINIT_ACK, VPU_MDP_PROCESS_ACK
+ * @ipi_id : IPI_MDP
+ * @ap_inst : AP mtk_mdp_vpu address
+ * @vpu_inst_addr : VPU MDP instance address
+ * @status : VPU exeuction result
+ */
+struct mdp_ipi_comm_ack {
+ uint32_t msg_id;
+ uint32_t ipi_id;
+ uint64_t ap_inst;
+ uint32_t vpu_inst_addr;
+ int32_t status;
+};
+
+/**
+ * struct mdp_config - configured for source/destination image
+ * @x : left
+ * @y : top
+ * @w : width
+ * @h : height
+ * @w_stride : bytes in horizontal
+ * @h_stride : bytes in vertical
+ * @crop_x : cropped left
+ * @crop_y : cropped top
+ * @crop_w : cropped width
+ * @crop_h : cropped height
+ * @format : color format
+ */
+struct mdp_config {
+ int32_t x;
+ int32_t y;
+ int32_t w;
+ int32_t h;
+ int32_t w_stride;
+ int32_t h_stride;
+ int32_t crop_x;
+ int32_t crop_y;
+ int32_t crop_w;
+ int32_t crop_h;
+ int32_t format;
+};
+
+struct mdp_buffer {
+ uint64_t addr_mva[MTK_MDP_MAX_NUM_PLANE];
+ int32_t plane_size[MTK_MDP_MAX_NUM_PLANE];
+ int32_t plane_num;
+};
+
+struct mdp_config_misc {
+ int32_t orientation; /* 0, 90, 180, 270 */
+ int32_t hflip; /* 1 will enable the flip */
+ int32_t vflip; /* 1 will enable the flip */
+ int32_t alpha; /* global alpha */
+};
+
+struct mdp_process_vsi {
+ struct mdp_config src_config;
+ struct mdp_buffer src_buffer;
+ struct mdp_config dst_config;
+ struct mdp_buffer dst_buffer;
+ struct mdp_config_misc misc;
+};
+
+#pragma pack(pop)
+
+#endif /* __MTK_MDP_IPI_H__ */
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
new file mode 100644
index 0000000..0655027
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
@@ -0,0 +1,1270 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_m2m.h"
+#include "mtk_mdp_regs.h"
+#include "mtk_vpu.h"
+
+
+/**
+ * struct mtk_mdp_pix_limit - image pixel size limits
+ * @org_w: source pixel width
+ * @org_h: source pixel height
+ * @target_rot_dis_w: pixel dst scaled width with the rotator is off
+ * @target_rot_dis_h: pixel dst scaled height with the rotator is off
+ * @target_rot_en_w: pixel dst scaled width with the rotator is on
+ * @target_rot_en_h: pixel dst scaled height with the rotator is on
+ */
+struct mtk_mdp_pix_limit {
+ u16 org_w;
+ u16 org_h;
+ u16 target_rot_dis_w;
+ u16 target_rot_dis_h;
+ u16 target_rot_en_w;
+ u16 target_rot_en_h;
+};
+
+static struct mtk_mdp_pix_align mtk_mdp_size_align = {
+ .org_w = 16,
+ .org_h = 16,
+ .target_w = 2,
+ .target_h = 2,
+};
+
+static const struct mtk_mdp_fmt mtk_mdp_formats[] = {
+ {
+ .pixelformat = V4L2_PIX_FMT_NV12M,
+ .depth = { 8, 4 },
+ .row_depth = { 8, 8 },
+ .num_planes = 2,
+ .num_comp = 2,
+ .flags = MTK_MDP_FMT_FLAG_OUTPUT |
+ MTK_MDP_FMT_FLAG_CAPTURE,
+ }, {
+ .pixelformat = V4L2_PIX_FMT_YUV420M,
+ .depth = { 8, 2, 2 },
+ .row_depth = { 8, 4, 4 },
+ .num_planes = 3,
+ .num_comp = 3,
+ .flags = MTK_MDP_FMT_FLAG_OUTPUT |
+ MTK_MDP_FMT_FLAG_CAPTURE,
+ }, {
+ .pixelformat = V4L2_PIX_FMT_YVU420,
+ .depth = { 12 },
+ .row_depth = { 8 },
+ .num_planes = 1,
+ .num_comp = 3,
+ .flags = MTK_MDP_FMT_FLAG_OUTPUT |
+ MTK_MDP_FMT_FLAG_CAPTURE,
+ }
+};
+
+static struct mtk_mdp_pix_limit mtk_mdp_size_max = {
+ .target_rot_dis_w = 4096,
+ .target_rot_dis_h = 4096,
+ .target_rot_en_w = 4096,
+ .target_rot_en_h = 4096,
+};
+
+static struct mtk_mdp_pix_limit mtk_mdp_size_min = {
+ .org_w = 16,
+ .org_h = 16,
+ .target_rot_dis_w = 16,
+ .target_rot_dis_h = 16,
+ .target_rot_en_w = 16,
+ .target_rot_en_h = 16,
+};
+
+/* align size for normal raster scan pixel format */
+static struct mtk_mdp_pix_align mtk_mdp_rs_align = {
+ .org_w = 2,
+ .org_h = 2,
+ .target_w = 2,
+ .target_h = 2,
+};
+
+static struct mtk_mdp_variant mtk_mdp_default_variant = {
+ .pix_max = &mtk_mdp_size_max,
+ .pix_min = &mtk_mdp_size_min,
+ .pix_align = &mtk_mdp_rs_align,
+ .h_scale_up_max = 32,
+ .v_scale_up_max = 32,
+ .h_scale_down_max = 32,
+ .v_scale_down_max = 128,
+};
+
+static const struct mtk_mdp_fmt *mtk_mdp_find_fmt(u32 pixelformat, u32 type)
+{
+ u32 i, flag;
+
+ flag = V4L2_TYPE_IS_OUTPUT(type) ? MTK_MDP_FMT_FLAG_OUTPUT :
+ MTK_MDP_FMT_FLAG_CAPTURE;
+
+ for (i = 0; i < ARRAY_SIZE(mtk_mdp_formats); ++i) {
+ if (!(mtk_mdp_formats[i].flags & flag))
+ continue;
+ if (mtk_mdp_formats[i].pixelformat == pixelformat)
+ return &mtk_mdp_formats[i];
+ }
+ return NULL;
+}
+
+static const struct mtk_mdp_fmt *mtk_mdp_find_fmt_by_index(u32 index, u32 type)
+{
+ u32 i, flag, num = 0;
+
+ flag = V4L2_TYPE_IS_OUTPUT(type) ? MTK_MDP_FMT_FLAG_OUTPUT :
+ MTK_MDP_FMT_FLAG_CAPTURE;
+
+ for (i = 0; i < ARRAY_SIZE(mtk_mdp_formats); ++i) {
+ if (!(mtk_mdp_formats[i].flags & flag))
+ continue;
+ if (index == num)
+ return &mtk_mdp_formats[i];
+ num++;
+ }
+ return NULL;
+}
+
+static void mtk_mdp_bound_align_image(u32 *w, unsigned int wmin,
+ unsigned int wmax, unsigned int align_w,
+ u32 *h, unsigned int hmin,
+ unsigned int hmax, unsigned int align_h)
+{
+ int org_w, org_h, step_w, step_h;
+ int walign, halign;
+
+ org_w = *w;
+ org_h = *h;
+ walign = ffs(align_w) - 1;
+ halign = ffs(align_h) - 1;
+ v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
+
+ step_w = 1 << walign;
+ step_h = 1 << halign;
+ if (*w < org_w && (*w + step_w) <= wmax)
+ *w += step_w;
+ if (*h < org_h && (*h + step_h) <= hmax)
+ *h += step_h;
+}
+
+static const struct mtk_mdp_fmt *mtk_mdp_try_fmt_mplane(struct mtk_mdp_ctx *ctx,
+ struct v4l2_format *f)
+{
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+ struct mtk_mdp_variant *variant = mdp->variant;
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+ const struct mtk_mdp_fmt *fmt;
+ u32 max_w, max_h, align_w, align_h;
+ u32 min_w, min_h, org_w, org_h;
+ int i;
+
+ fmt = mtk_mdp_find_fmt(pix_mp->pixelformat, f->type);
+ if (!fmt)
+ fmt = mtk_mdp_find_fmt_by_index(0, f->type);
+ if (!fmt) {
+ dev_dbg(&ctx->mdp_dev->pdev->dev,
+ "pixelformat format 0x%X invalid\n",
+ pix_mp->pixelformat);
+ return NULL;
+ }
+
+ pix_mp->field = V4L2_FIELD_NONE;
+ pix_mp->pixelformat = fmt->pixelformat;
+ if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
+ pix_mp->colorspace = ctx->colorspace;
+ pix_mp->xfer_func = ctx->xfer_func;
+ pix_mp->ycbcr_enc = ctx->ycbcr_enc;
+ pix_mp->quantization = ctx->quant;
+ }
+ memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+
+ max_w = variant->pix_max->target_rot_dis_w;
+ max_h = variant->pix_max->target_rot_dis_h;
+
+ if (fmt->align == NULL) {
+ /* use default alignment */
+ align_w = variant->pix_align->org_w;
+ align_h = variant->pix_align->org_h;
+ } else {
+ align_w = fmt->align->org_w;
+ align_h = fmt->align->org_h;
+ }
+
+ if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+ min_w = variant->pix_min->org_w;
+ min_h = variant->pix_min->org_h;
+ } else {
+ min_w = variant->pix_min->target_rot_dis_w;
+ min_h = variant->pix_min->target_rot_dis_h;
+ }
+
+ mtk_mdp_dbg(2, "[%d] type:%d, wxh:%ux%u, align:%ux%u, max:%ux%u",
+ ctx->id, f->type, pix_mp->width, pix_mp->height,
+ align_w, align_h, max_w, max_h);
+ /*
+ * To check if image size is modified to adjust parameter against
+ * hardware abilities
+ */
+ org_w = pix_mp->width;
+ org_h = pix_mp->height;
+
+ mtk_mdp_bound_align_image(&pix_mp->width, min_w, max_w, align_w,
+ &pix_mp->height, min_h, max_h, align_h);
+
+ if (org_w != pix_mp->width || org_h != pix_mp->height)
+ mtk_mdp_dbg(1, "[%d] size change:%ux%u to %ux%u", ctx->id,
+ org_w, org_h, pix_mp->width, pix_mp->height);
+ pix_mp->num_planes = fmt->num_planes;
+
+ for (i = 0; i < pix_mp->num_planes; ++i) {
+ int bpl = (pix_mp->width * fmt->row_depth[i]) / 8;
+ int sizeimage = (pix_mp->width * pix_mp->height *
+ fmt->depth[i]) / 8;
+
+ pix_mp->plane_fmt[i].bytesperline = bpl;
+ if (pix_mp->plane_fmt[i].sizeimage < sizeimage)
+ pix_mp->plane_fmt[i].sizeimage = sizeimage;
+ memset(pix_mp->plane_fmt[i].reserved, 0,
+ sizeof(pix_mp->plane_fmt[i].reserved));
+ mtk_mdp_dbg(2, "[%d] p%d, bpl:%d, sizeimage:%u (%u)", ctx->id,
+ i, bpl, pix_mp->plane_fmt[i].sizeimage, sizeimage);
+ }
+
+ return fmt;
+}
+
+static struct mtk_mdp_frame *mtk_mdp_ctx_get_frame(struct mtk_mdp_ctx *ctx,
+ enum v4l2_buf_type type)
+{
+ if (V4L2_TYPE_IS_OUTPUT(type))
+ return &ctx->s_frame;
+ return &ctx->d_frame;
+}
+
+static void mtk_mdp_check_crop_change(u32 new_w, u32 new_h, u32 *w, u32 *h)
+{
+ if (new_w != *w || new_h != *h) {
+ mtk_mdp_dbg(1, "size change:%dx%d to %dx%d",
+ *w, *h, new_w, new_h);
+
+ *w = new_w;
+ *h = new_h;
+ }
+}
+
+static int mtk_mdp_try_crop(struct mtk_mdp_ctx *ctx, u32 type,
+ struct v4l2_rect *r)
+{
+ struct mtk_mdp_frame *frame;
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+ struct mtk_mdp_variant *variant = mdp->variant;
+ u32 align_w, align_h, new_w, new_h;
+ u32 min_w, min_h, max_w, max_h;
+
+ if (r->top < 0 || r->left < 0) {
+ dev_err(&ctx->mdp_dev->pdev->dev,
+ "doesn't support negative values for top & left\n");
+ return -EINVAL;
+ }
+
+ mtk_mdp_dbg(2, "[%d] type:%d, set wxh:%dx%d", ctx->id, type,
+ r->width, r->height);
+
+ frame = mtk_mdp_ctx_get_frame(ctx, type);
+ max_w = frame->width;
+ max_h = frame->height;
+ new_w = r->width;
+ new_h = r->height;
+
+ if (V4L2_TYPE_IS_OUTPUT(type)) {
+ align_w = 1;
+ align_h = 1;
+ min_w = 64;
+ min_h = 32;
+ } else {
+ align_w = variant->pix_align->target_w;
+ align_h = variant->pix_align->target_h;
+ if (ctx->ctrls.rotate->val == 90 ||
+ ctx->ctrls.rotate->val == 270) {
+ max_w = frame->height;
+ max_h = frame->width;
+ min_w = variant->pix_min->target_rot_en_w;
+ min_h = variant->pix_min->target_rot_en_h;
+ new_w = r->height;
+ new_h = r->width;
+ } else {
+ min_w = variant->pix_min->target_rot_dis_w;
+ min_h = variant->pix_min->target_rot_dis_h;
+ }
+ }
+
+ mtk_mdp_dbg(2, "[%d] align:%dx%d, min:%dx%d, new:%dx%d", ctx->id,
+ align_w, align_h, min_w, min_h, new_w, new_h);
+
+ mtk_mdp_bound_align_image(&new_w, min_w, max_w, align_w,
+ &new_h, min_h, max_h, align_h);
+
+ if (!V4L2_TYPE_IS_OUTPUT(type) &&
+ (ctx->ctrls.rotate->val == 90 ||
+ ctx->ctrls.rotate->val == 270))
+ mtk_mdp_check_crop_change(new_h, new_w,
+ &r->width, &r->height);
+ else
+ mtk_mdp_check_crop_change(new_w, new_h,
+ &r->width, &r->height);
+
+ /* adjust left/top if cropping rectangle is out of bounds */
+ /* Need to add code to algin left value with 2's multiple */
+ if (r->left + new_w > max_w)
+ r->left = max_w - new_w;
+ if (r->top + new_h > max_h)
+ r->top = max_h - new_h;
+
+ if (r->left & 1)
+ r->left -= 1;
+
+ mtk_mdp_dbg(2, "[%d] crop l,t,w,h:%d,%d,%d,%d, max:%dx%d", ctx->id,
+ r->left, r->top, r->width,
+ r->height, max_w, max_h);
+ return 0;
+}
+
+static inline struct mtk_mdp_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+ return container_of(fh, struct mtk_mdp_ctx, fh);
+}
+
+static inline struct mtk_mdp_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
+{
+ return container_of(ctrl->handler, struct mtk_mdp_ctx, ctrl_handler);
+}
+
+void mtk_mdp_ctx_state_lock_set(struct mtk_mdp_ctx *ctx, u32 state)
+{
+ mutex_lock(&ctx->slock);
+ ctx->state |= state;
+ mutex_unlock(&ctx->slock);
+}
+
+static void mtk_mdp_ctx_state_lock_clear(struct mtk_mdp_ctx *ctx, u32 state)
+{
+ mutex_lock(&ctx->slock);
+ ctx->state &= ~state;
+ mutex_unlock(&ctx->slock);
+}
+
+static bool mtk_mdp_ctx_state_is_set(struct mtk_mdp_ctx *ctx, u32 mask)
+{
+ bool ret;
+
+ mutex_lock(&ctx->slock);
+ ret = (ctx->state & mask) == mask;
+ mutex_unlock(&ctx->slock);
+ return ret;
+}
+
+static void mtk_mdp_ctx_lock(struct vb2_queue *vq)
+{
+ struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vq);
+
+ mutex_lock(&ctx->mdp_dev->lock);
+}
+
+static void mtk_mdp_ctx_unlock(struct vb2_queue *vq)
+{
+ struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vq);
+
+ mutex_unlock(&ctx->mdp_dev->lock);
+}
+
+static void mtk_mdp_set_frame_size(struct mtk_mdp_frame *frame, int width,
+ int height)
+{
+ frame->width = width;
+ frame->height = height;
+ frame->crop.width = width;
+ frame->crop.height = height;
+ frame->crop.left = 0;
+ frame->crop.top = 0;
+}
+
+static int mtk_mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct mtk_mdp_ctx *ctx = q->drv_priv;
+ int ret;
+
+ ret = pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev);
+ if (ret < 0)
+ mtk_mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d",
+ ctx->id, ret);
+
+ return 0;
+}
+
+static void *mtk_mdp_m2m_buf_remove(struct mtk_mdp_ctx *ctx,
+ enum v4l2_buf_type type)
+{
+ if (V4L2_TYPE_IS_OUTPUT(type))
+ return v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ else
+ return v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+}
+
+static void mtk_mdp_m2m_stop_streaming(struct vb2_queue *q)
+{
+ struct mtk_mdp_ctx *ctx = q->drv_priv;
+ struct vb2_buffer *vb;
+
+ vb = mtk_mdp_m2m_buf_remove(ctx, q->type);
+ while (vb != NULL) {
+ v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_ERROR);
+ vb = mtk_mdp_m2m_buf_remove(ctx, q->type);
+ }
+
+ pm_runtime_put(&ctx->mdp_dev->pdev->dev);
+}
+
+static void mtk_mdp_m2m_job_abort(void *priv)
+{
+}
+
+/* The color format (num_planes) must be already configured. */
+static void mtk_mdp_prepare_addr(struct mtk_mdp_ctx *ctx,
+ struct vb2_buffer *vb,
+ struct mtk_mdp_frame *frame,
+ struct mtk_mdp_addr *addr)
+{
+ u32 pix_size, planes, i;
+
+ pix_size = frame->width * frame->height;
+ planes = min_t(u32, frame->fmt->num_planes, ARRAY_SIZE(addr->addr));
+ for (i = 0; i < planes; i++)
+ addr->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+
+ if (planes == 1) {
+ if (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) {
+ addr->addr[1] = (dma_addr_t)(addr->addr[0] + pix_size);
+ addr->addr[2] = (dma_addr_t)(addr->addr[1] +
+ (pix_size >> 2));
+ } else {
+ dev_err(&ctx->mdp_dev->pdev->dev,
+ "Invalid pixelformat:0x%x\n",
+ frame->fmt->pixelformat);
+ }
+ }
+ mtk_mdp_dbg(3, "[%d] planes:%d, size:%d, addr:%p,%p,%p",
+ ctx->id, planes, pix_size, (void *)addr->addr[0],
+ (void *)addr->addr[1], (void *)addr->addr[2]);
+}
+
+static void mtk_mdp_m2m_get_bufs(struct mtk_mdp_ctx *ctx)
+{
+ struct mtk_mdp_frame *s_frame, *d_frame;
+ struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
+
+ s_frame = &ctx->s_frame;
+ d_frame = &ctx->d_frame;
+
+ src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ mtk_mdp_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
+
+ dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ mtk_mdp_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
+
+ src_vbuf = to_vb2_v4l2_buffer(src_vb);
+ dst_vbuf = to_vb2_v4l2_buffer(dst_vb);
+ dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp;
+}
+
+static void mtk_mdp_process_done(void *priv, int vb_state)
+{
+ struct mtk_mdp_dev *mdp = priv;
+ struct mtk_mdp_ctx *ctx;
+ struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vbuf = NULL, *dst_vbuf = NULL;
+
+ ctx = v4l2_m2m_get_curr_priv(mdp->m2m_dev);
+ if (!ctx)
+ return;
+
+ src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ src_vbuf = to_vb2_v4l2_buffer(src_vb);
+ dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+ dst_vbuf = to_vb2_v4l2_buffer(dst_vb);
+
+ dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp;
+ dst_vbuf->timecode = src_vbuf->timecode;
+ dst_vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vbuf->flags |= src_vbuf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+
+ v4l2_m2m_buf_done(src_vbuf, vb_state);
+ v4l2_m2m_buf_done(dst_vbuf, vb_state);
+ v4l2_m2m_job_finish(ctx->mdp_dev->m2m_dev, ctx->m2m_ctx);
+}
+
+static void mtk_mdp_m2m_worker(struct work_struct *work)
+{
+ struct mtk_mdp_ctx *ctx =
+ container_of(work, struct mtk_mdp_ctx, work);
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ int ret;
+
+ if (mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_CTX_ERROR)) {
+ dev_err(&mdp->pdev->dev, "ctx is in error state");
+ goto worker_end;
+ }
+
+ mtk_mdp_m2m_get_bufs(ctx);
+
+ mtk_mdp_hw_set_input_addr(ctx, &ctx->s_frame.addr);
+ mtk_mdp_hw_set_output_addr(ctx, &ctx->d_frame.addr);
+
+ mtk_mdp_hw_set_in_size(ctx);
+ mtk_mdp_hw_set_in_image_format(ctx);
+
+ mtk_mdp_hw_set_out_size(ctx);
+ mtk_mdp_hw_set_out_image_format(ctx);
+
+ mtk_mdp_hw_set_rotation(ctx);
+ mtk_mdp_hw_set_global_alpha(ctx);
+
+ ret = mtk_mdp_vpu_process(&ctx->vpu);
+ if (ret) {
+ dev_err(&mdp->pdev->dev, "processing failed: %d", ret);
+ goto worker_end;
+ }
+
+ buf_state = VB2_BUF_STATE_DONE;
+
+worker_end:
+ mtk_mdp_process_done(mdp, buf_state);
+}
+
+static void mtk_mdp_m2m_device_run(void *priv)
+{
+ struct mtk_mdp_ctx *ctx = priv;
+
+ queue_work(ctx->mdp_dev->job_wq, &ctx->work);
+}
+
+static int mtk_mdp_m2m_queue_setup(struct vb2_queue *vq,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], struct device *alloc_devs[])
+{
+ struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vq);
+ struct mtk_mdp_frame *frame;
+ int i;
+
+ frame = mtk_mdp_ctx_get_frame(ctx, vq->type);
+ *num_planes = frame->fmt->num_planes;
+ for (i = 0; i < frame->fmt->num_planes; i++)
+ sizes[i] = frame->payload[i];
+ mtk_mdp_dbg(2, "[%d] type:%d, planes:%d, buffers:%d, size:%u,%u",
+ ctx->id, vq->type, *num_planes, *num_buffers,
+ sizes[0], sizes[1]);
+ return 0;
+}
+
+static int mtk_mdp_m2m_buf_prepare(struct vb2_buffer *vb)
+{
+ struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct mtk_mdp_frame *frame;
+ int i;
+
+ frame = mtk_mdp_ctx_get_frame(ctx, vb->vb2_queue->type);
+
+ if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+ for (i = 0; i < frame->fmt->num_planes; i++)
+ vb2_set_plane_payload(vb, i, frame->payload[i]);
+ }
+
+ return 0;
+}
+
+static void mtk_mdp_m2m_buf_queue(struct vb2_buffer *vb)
+{
+ struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb));
+}
+
+static struct vb2_ops mtk_mdp_m2m_qops = {
+ .queue_setup = mtk_mdp_m2m_queue_setup,
+ .buf_prepare = mtk_mdp_m2m_buf_prepare,
+ .buf_queue = mtk_mdp_m2m_buf_queue,
+ .wait_prepare = mtk_mdp_ctx_unlock,
+ .wait_finish = mtk_mdp_ctx_lock,
+ .stop_streaming = mtk_mdp_m2m_stop_streaming,
+ .start_streaming = mtk_mdp_m2m_start_streaming,
+};
+
+static int mtk_mdp_m2m_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+
+ strlcpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver));
+ strlcpy(cap->card, mdp->pdev->name, sizeof(cap->card));
+ strlcpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info));
+
+ return 0;
+}
+
+static int mtk_mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f, u32 type)
+{
+ const struct mtk_mdp_fmt *fmt;
+
+ fmt = mtk_mdp_find_fmt_by_index(f->index, type);
+ if (!fmt)
+ return -EINVAL;
+
+ f->pixelformat = fmt->pixelformat;
+
+ return 0;
+}
+
+static int mtk_mdp_m2m_enum_fmt_mplane_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ return mtk_mdp_enum_fmt_mplane(f, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+}
+
+static int mtk_mdp_m2m_enum_fmt_mplane_vid_out(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ return mtk_mdp_enum_fmt_mplane(f, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+}
+
+static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+ struct mtk_mdp_frame *frame;
+ struct v4l2_pix_format_mplane *pix_mp;
+ int i;
+
+ mtk_mdp_dbg(2, "[%d] type:%d", ctx->id, f->type);
+
+ frame = mtk_mdp_ctx_get_frame(ctx, f->type);
+ pix_mp = &f->fmt.pix_mp;
+
+ pix_mp->width = frame->width;
+ pix_mp->height = frame->height;
+ pix_mp->field = V4L2_FIELD_NONE;
+ pix_mp->pixelformat = frame->fmt->pixelformat;
+ pix_mp->num_planes = frame->fmt->num_planes;
+ pix_mp->colorspace = ctx->colorspace;
+ pix_mp->xfer_func = ctx->xfer_func;
+ pix_mp->ycbcr_enc = ctx->ycbcr_enc;
+ pix_mp->quantization = ctx->quant;
+ mtk_mdp_dbg(2, "[%d] wxh:%dx%d", ctx->id,
+ pix_mp->width, pix_mp->height);
+
+ for (i = 0; i < pix_mp->num_planes; ++i) {
+ pix_mp->plane_fmt[i].bytesperline = (frame->width *
+ frame->fmt->row_depth[i]) / 8;
+ pix_mp->plane_fmt[i].sizeimage = (frame->width *
+ frame->height * frame->fmt->depth[i]) / 8;
+
+ mtk_mdp_dbg(2, "[%d] p%d, bpl:%d, sizeimage:%d", ctx->id, i,
+ pix_mp->plane_fmt[i].bytesperline,
+ pix_mp->plane_fmt[i].sizeimage);
+ }
+
+ return 0;
+}
+
+static int mtk_mdp_m2m_try_fmt_mplane(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+
+ if (!mtk_mdp_try_fmt_mplane(ctx, f))
+ return -EINVAL;
+ return 0;
+}
+
+static int mtk_mdp_m2m_s_fmt_mplane(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+ struct vb2_queue *vq;
+ struct mtk_mdp_frame *frame;
+ struct v4l2_pix_format_mplane *pix_mp;
+ const struct mtk_mdp_fmt *fmt;
+ int i;
+
+ mtk_mdp_dbg(2, "[%d] type:%d", ctx->id, f->type);
+
+ frame = mtk_mdp_ctx_get_frame(ctx, f->type);
+ fmt = mtk_mdp_try_fmt_mplane(ctx, f);
+ if (!fmt) {
+ mtk_mdp_err("[%d] try_fmt failed, type:%d", ctx->id, f->type);
+ return -EINVAL;
+ }
+ frame->fmt = fmt;
+
+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+ if (vb2_is_streaming(vq)) {
+ dev_info(&ctx->mdp_dev->pdev->dev, "queue %d busy", f->type);
+ return -EBUSY;
+ }
+
+ pix_mp = &f->fmt.pix_mp;
+ for (i = 0; i < frame->fmt->num_planes; i++) {
+ frame->payload[i] = pix_mp->plane_fmt[i].sizeimage;
+ frame->pitch[i] = pix_mp->plane_fmt[i].bytesperline;
+ }
+
+ mtk_mdp_set_frame_size(frame, pix_mp->width, pix_mp->height);
+ if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+ ctx->colorspace = pix_mp->colorspace;
+ ctx->xfer_func = pix_mp->xfer_func;
+ ctx->ycbcr_enc = pix_mp->ycbcr_enc;
+ ctx->quant = pix_mp->quantization;
+ }
+
+ if (V4L2_TYPE_IS_OUTPUT(f->type))
+ mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_SRC_FMT);
+ else
+ mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_DST_FMT);
+
+ mtk_mdp_dbg(2, "[%d] type:%d, frame:%dx%d", ctx->id, f->type,
+ frame->width, frame->height);
+
+ return 0;
+}
+
+static int mtk_mdp_m2m_reqbufs(struct file *file, void *fh,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+
+ if (reqbufs->count == 0) {
+ if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ mtk_mdp_ctx_state_lock_clear(ctx, MTK_MDP_SRC_FMT);
+ else
+ mtk_mdp_ctx_state_lock_clear(ctx, MTK_MDP_DST_FMT);
+ }
+
+ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int mtk_mdp_m2m_streamon(struct file *file, void *fh,
+ enum v4l2_buf_type type)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+ int ret;
+
+ /* The source and target color format need to be set */
+ if (V4L2_TYPE_IS_OUTPUT(type)) {
+ if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_SRC_FMT))
+ return -EINVAL;
+ } else if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT)) {
+ return -EINVAL;
+ }
+
+ if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_VPU_INIT)) {
+ ret = mtk_mdp_vpu_init(&ctx->vpu);
+ if (ret < 0) {
+ dev_err(&ctx->mdp_dev->pdev->dev,
+ "vpu init failed %d\n",
+ ret);
+ return -EINVAL;
+ }
+ mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_VPU_INIT);
+ }
+
+ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static inline bool mtk_mdp_is_target_compose(u32 target)
+{
+ if (target == V4L2_SEL_TGT_COMPOSE_DEFAULT
+ || target == V4L2_SEL_TGT_COMPOSE_BOUNDS
+ || target == V4L2_SEL_TGT_COMPOSE)
+ return true;
+ return false;
+}
+
+static inline bool mtk_mdp_is_target_crop(u32 target)
+{
+ if (target == V4L2_SEL_TGT_CROP_DEFAULT
+ || target == V4L2_SEL_TGT_CROP_BOUNDS
+ || target == V4L2_SEL_TGT_CROP)
+ return true;
+ return false;
+}
+
+static int mtk_mdp_m2m_g_selection(struct file *file, void *fh,
+ struct v4l2_selection *s)
+{
+ struct mtk_mdp_frame *frame;
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+ bool valid = false;
+
+ if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ if (mtk_mdp_is_target_compose(s->target))
+ valid = true;
+ } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ if (mtk_mdp_is_target_crop(s->target))
+ valid = true;
+ }
+ if (!valid) {
+ mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
+ s->target);
+ return -EINVAL;
+ }
+
+ frame = mtk_mdp_ctx_get_frame(ctx, s->type);
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ s->r.left = 0;
+ s->r.top = 0;
+ s->r.width = frame->width;
+ s->r.height = frame->height;
+ return 0;
+
+ case V4L2_SEL_TGT_COMPOSE:
+ case V4L2_SEL_TGT_CROP:
+ s->r.left = frame->crop.left;
+ s->r.top = frame->crop.top;
+ s->r.width = frame->crop.width;
+ s->r.height = frame->crop.height;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int mtk_mdp_check_scaler_ratio(struct mtk_mdp_variant *var, int src_w,
+ int src_h, int dst_w, int dst_h, int rot)
+{
+ int tmp_w, tmp_h;
+
+ if (rot == 90 || rot == 270) {
+ tmp_w = dst_h;
+ tmp_h = dst_w;
+ } else {
+ tmp_w = dst_w;
+ tmp_h = dst_h;
+ }
+
+ if ((src_w / tmp_w) > var->h_scale_down_max ||
+ (src_h / tmp_h) > var->v_scale_down_max ||
+ (tmp_w / src_w) > var->h_scale_up_max ||
+ (tmp_h / src_h) > var->v_scale_up_max)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int mtk_mdp_m2m_s_selection(struct file *file, void *fh,
+ struct v4l2_selection *s)
+{
+ struct mtk_mdp_frame *frame;
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+ struct v4l2_rect new_r;
+ struct mtk_mdp_variant *variant = ctx->mdp_dev->variant;
+ int ret;
+ bool valid = false;
+
+ if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ if (s->target == V4L2_SEL_TGT_COMPOSE)
+ valid = true;
+ } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ if (s->target == V4L2_SEL_TGT_CROP)
+ valid = true;
+ }
+ if (!valid) {
+ mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
+ s->target);
+ return -EINVAL;
+ }
+
+ new_r = s->r;
+ ret = mtk_mdp_try_crop(ctx, s->type, &new_r);
+ if (ret)
+ return ret;
+
+ if (mtk_mdp_is_target_crop(s->target))
+ frame = &ctx->s_frame;
+ else
+ frame = &ctx->d_frame;
+
+ /* Check to see if scaling ratio is within supported range */
+ if (mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT)) {
+ if (V4L2_TYPE_IS_OUTPUT(s->type)) {
+ ret = mtk_mdp_check_scaler_ratio(variant, new_r.width,
+ new_r.height, ctx->d_frame.crop.width,
+ ctx->d_frame.crop.height,
+ ctx->ctrls.rotate->val);
+ } else {
+ ret = mtk_mdp_check_scaler_ratio(variant,
+ ctx->s_frame.crop.width,
+ ctx->s_frame.crop.height, new_r.width,
+ new_r.height, ctx->ctrls.rotate->val);
+ }
+
+ if (ret) {
+ dev_info(&ctx->mdp_dev->pdev->dev,
+ "Out of scaler range");
+ return -EINVAL;
+ }
+ }
+
+ s->r = new_r;
+ frame->crop = new_r;
+
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops mtk_mdp_m2m_ioctl_ops = {
+ .vidioc_querycap = mtk_mdp_m2m_querycap,
+ .vidioc_enum_fmt_vid_cap_mplane = mtk_mdp_m2m_enum_fmt_mplane_vid_cap,
+ .vidioc_enum_fmt_vid_out_mplane = mtk_mdp_m2m_enum_fmt_mplane_vid_out,
+ .vidioc_g_fmt_vid_cap_mplane = mtk_mdp_m2m_g_fmt_mplane,
+ .vidioc_g_fmt_vid_out_mplane = mtk_mdp_m2m_g_fmt_mplane,
+ .vidioc_try_fmt_vid_cap_mplane = mtk_mdp_m2m_try_fmt_mplane,
+ .vidioc_try_fmt_vid_out_mplane = mtk_mdp_m2m_try_fmt_mplane,
+ .vidioc_s_fmt_vid_cap_mplane = mtk_mdp_m2m_s_fmt_mplane,
+ .vidioc_s_fmt_vid_out_mplane = mtk_mdp_m2m_s_fmt_mplane,
+ .vidioc_reqbufs = mtk_mdp_m2m_reqbufs,
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_streamon = mtk_mdp_m2m_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+ .vidioc_g_selection = mtk_mdp_m2m_g_selection,
+ .vidioc_s_selection = mtk_mdp_m2m_s_selection
+};
+
+static int mtk_mdp_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
+{
+ struct mtk_mdp_ctx *ctx = priv;
+ int ret;
+
+ memset(src_vq, 0, sizeof(*src_vq));
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->drv_priv = ctx;
+ src_vq->ops = &mtk_mdp_m2m_qops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->dev = &ctx->mdp_dev->pdev->dev;
+
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+ return ret;
+
+ memset(dst_vq, 0, sizeof(*dst_vq));
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ dst_vq->drv_priv = ctx;
+ dst_vq->ops = &mtk_mdp_m2m_qops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->dev = &ctx->mdp_dev->pdev->dev;
+
+ return vb2_queue_init(dst_vq);
+}
+
+static int mtk_mdp_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct mtk_mdp_ctx *ctx = ctrl_to_ctx(ctrl);
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+ struct mtk_mdp_variant *variant = mdp->variant;
+ u32 state = MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT;
+ int ret = 0;
+
+ if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_HFLIP:
+ ctx->hflip = ctrl->val;
+ break;
+ case V4L2_CID_VFLIP:
+ ctx->vflip = ctrl->val;
+ break;
+ case V4L2_CID_ROTATE:
+ if (mtk_mdp_ctx_state_is_set(ctx, state)) {
+ ret = mtk_mdp_check_scaler_ratio(variant,
+ ctx->s_frame.crop.width,
+ ctx->s_frame.crop.height,
+ ctx->d_frame.crop.width,
+ ctx->d_frame.crop.height,
+ ctx->ctrls.rotate->val);
+
+ if (ret)
+ return -EINVAL;
+ }
+
+ ctx->rotation = ctrl->val;
+ break;
+ case V4L2_CID_ALPHA_COMPONENT:
+ ctx->d_frame.alpha = ctrl->val;
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops mtk_mdp_ctrl_ops = {
+ .s_ctrl = mtk_mdp_s_ctrl,
+};
+
+static int mtk_mdp_ctrls_create(struct mtk_mdp_ctx *ctx)
+{
+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, MTK_MDP_MAX_CTRL_NUM);
+
+ ctx->ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+ &mtk_mdp_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
+ ctx->ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+ &mtk_mdp_ctrl_ops,
+ V4L2_CID_HFLIP,
+ 0, 1, 1, 0);
+ ctx->ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+ &mtk_mdp_ctrl_ops,
+ V4L2_CID_VFLIP,
+ 0, 1, 1, 0);
+ ctx->ctrls.global_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+ &mtk_mdp_ctrl_ops,
+ V4L2_CID_ALPHA_COMPONENT,
+ 0, 255, 1, 0);
+ ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
+
+ if (ctx->ctrl_handler.error) {
+ int err = ctx->ctrl_handler.error;
+
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+ dev_err(&ctx->mdp_dev->pdev->dev,
+ "Failed to create control handlers\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void mtk_mdp_set_default_params(struct mtk_mdp_ctx *ctx)
+{
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+ struct mtk_mdp_frame *frame;
+
+ frame = mtk_mdp_ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ frame->fmt = mtk_mdp_find_fmt_by_index(0,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ frame->width = mdp->variant->pix_min->org_w;
+ frame->height = mdp->variant->pix_min->org_h;
+ frame->payload[0] = frame->width * frame->height;
+ frame->payload[1] = frame->payload[0] / 2;
+
+ frame = mtk_mdp_ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ frame->fmt = mtk_mdp_find_fmt_by_index(0,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ frame->width = mdp->variant->pix_min->target_rot_dis_w;
+ frame->height = mdp->variant->pix_min->target_rot_dis_h;
+ frame->payload[0] = frame->width * frame->height;
+ frame->payload[1] = frame->payload[0] / 2;
+
+}
+
+static int mtk_mdp_m2m_open(struct file *file)
+{
+ struct mtk_mdp_dev *mdp = video_drvdata(file);
+ struct video_device *vfd = video_devdata(file);
+ struct mtk_mdp_ctx *ctx = NULL;
+ int ret;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ if (mutex_lock_interruptible(&mdp->lock)) {
+ ret = -ERESTARTSYS;
+ goto err_lock;
+ }
+
+ mutex_init(&ctx->slock);
+ ctx->id = mdp->id_counter++;
+ v4l2_fh_init(&ctx->fh, vfd);
+ file->private_data = &ctx->fh;
+ ret = mtk_mdp_ctrls_create(ctx);
+ if (ret)
+ goto error_ctrls;
+
+ /* Use separate control handler per file handle */
+ ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+ v4l2_fh_add(&ctx->fh);
+ INIT_LIST_HEAD(&ctx->list);
+
+ ctx->mdp_dev = mdp;
+ mtk_mdp_set_default_params(ctx);
+
+ INIT_WORK(&ctx->work, mtk_mdp_m2m_worker);
+ ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx,
+ mtk_mdp_m2m_queue_init);
+ if (IS_ERR(ctx->m2m_ctx)) {
+ dev_err(&mdp->pdev->dev, "Failed to initialize m2m context");
+ ret = PTR_ERR(ctx->m2m_ctx);
+ goto error_m2m_ctx;
+ }
+ ctx->fh.m2m_ctx = ctx->m2m_ctx;
+ if (mdp->ctx_num++ == 0) {
+ ret = vpu_load_firmware(mdp->vpu_dev);
+ if (ret < 0) {
+ dev_err(&mdp->pdev->dev,
+ "vpu_load_firmware failed %d\n", ret);
+ goto err_load_vpu;
+ }
+
+ ret = mtk_mdp_vpu_register(mdp->pdev);
+ if (ret < 0) {
+ dev_err(&mdp->pdev->dev,
+ "mdp_vpu register failed %d\n", ret);
+ goto err_load_vpu;
+ }
+ }
+
+ list_add(&ctx->list, &mdp->ctx_list);
+ mutex_unlock(&mdp->lock);
+
+ mtk_mdp_dbg(0, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id);
+
+ return 0;
+
+err_load_vpu:
+ mdp->ctx_num--;
+ v4l2_m2m_ctx_release(ctx->m2m_ctx);
+error_m2m_ctx:
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+error_ctrls:
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ mutex_unlock(&mdp->lock);
+err_lock:
+ kfree(ctx);
+
+ return ret;
+}
+
+static int mtk_mdp_m2m_release(struct file *file)
+{
+ struct mtk_mdp_ctx *ctx = fh_to_ctx(file->private_data);
+ struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+
+ flush_workqueue(mdp->job_wq);
+ mutex_lock(&mdp->lock);
+ v4l2_m2m_ctx_release(ctx->m2m_ctx);
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ mtk_mdp_vpu_deinit(&ctx->vpu);
+ mdp->ctx_num--;
+ list_del_init(&ctx->list);
+
+ mtk_mdp_dbg(0, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id);
+
+ mutex_unlock(&mdp->lock);
+ kfree(ctx);
+
+ return 0;
+}
+
+static const struct v4l2_file_operations mtk_mdp_m2m_fops = {
+ .owner = THIS_MODULE,
+ .open = mtk_mdp_m2m_open,
+ .release = mtk_mdp_m2m_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
+};
+
+static struct v4l2_m2m_ops mtk_mdp_m2m_ops = {
+ .device_run = mtk_mdp_m2m_device_run,
+ .job_abort = mtk_mdp_m2m_job_abort,
+};
+
+int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp)
+{
+ struct device *dev = &mdp->pdev->dev;
+ int ret;
+
+ mdp->variant = &mtk_mdp_default_variant;
+ mdp->vdev.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+ mdp->vdev.fops = &mtk_mdp_m2m_fops;
+ mdp->vdev.ioctl_ops = &mtk_mdp_m2m_ioctl_ops;
+ mdp->vdev.release = video_device_release_empty;
+ mdp->vdev.lock = &mdp->lock;
+ mdp->vdev.vfl_dir = VFL_DIR_M2M;
+ mdp->vdev.v4l2_dev = &mdp->v4l2_dev;
+ snprintf(mdp->vdev.name, sizeof(mdp->vdev.name), "%s:m2m",
+ MTK_MDP_MODULE_NAME);
+ video_set_drvdata(&mdp->vdev, mdp);
+
+ mdp->m2m_dev = v4l2_m2m_init(&mtk_mdp_m2m_ops);
+ if (IS_ERR(mdp->m2m_dev)) {
+ dev_err(dev, "failed to initialize v4l2-m2m device\n");
+ ret = PTR_ERR(mdp->m2m_dev);
+ goto err_m2m_init;
+ }
+
+ ret = video_register_device(&mdp->vdev, VFL_TYPE_GRABBER, 2);
+ if (ret) {
+ dev_err(dev, "failed to register video device\n");
+ goto err_vdev_register;
+ }
+
+ v4l2_info(&mdp->v4l2_dev, "driver registered as /dev/video%d",
+ mdp->vdev.num);
+ return 0;
+
+err_vdev_register:
+ v4l2_m2m_release(mdp->m2m_dev);
+err_m2m_init:
+ video_device_release(&mdp->vdev);
+
+ return ret;
+}
+
+void mtk_mdp_unregister_m2m_device(struct mtk_mdp_dev *mdp)
+{
+ video_device_release(&mdp->vdev);
+ v4l2_m2m_release(mdp->m2m_dev);
+}
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
new file mode 100644
index 0000000..45afd36
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_M2M_H__
+#define __MTK_MDP_M2M_H__
+
+void mtk_mdp_ctx_state_lock_set(struct mtk_mdp_ctx *ctx, u32 state);
+int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp);
+void mtk_mdp_unregister_m2m_device(struct mtk_mdp_dev *mdp);
+
+#endif /* __MTK_MDP_M2M_H__ */
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c b/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
new file mode 100644
index 0000000..a5601e1
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_regs.h"
+
+
+#define MDP_COLORFMT_PACK(VIDEO, PLANE, COPLANE, HF, VF, BITS, GROUP, SWAP, ID)\
+ (((VIDEO) << 27) | ((PLANE) << 24) | ((COPLANE) << 22) |\
+ ((HF) << 20) | ((VF) << 18) | ((BITS) << 8) | ((GROUP) << 6) |\
+ ((SWAP) << 5) | ((ID) << 0))
+
+enum MDP_COLOR_ENUM {
+ MDP_COLOR_UNKNOWN = 0,
+ MDP_COLOR_NV12 = MDP_COLORFMT_PACK(0, 2, 1, 1, 1, 8, 1, 0, 12),
+ MDP_COLOR_I420 = MDP_COLORFMT_PACK(0, 3, 0, 1, 1, 8, 1, 0, 8),
+ MDP_COLOR_YV12 = MDP_COLORFMT_PACK(0, 3, 0, 1, 1, 8, 1, 1, 8),
+};
+
+static int32_t mtk_mdp_map_color_format(int v4l2_format)
+{
+ switch (v4l2_format) {
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12:
+ return MDP_COLOR_NV12;
+ case V4L2_PIX_FMT_YUV420M:
+ case V4L2_PIX_FMT_YUV420:
+ return MDP_COLOR_I420;
+ case V4L2_PIX_FMT_YVU420:
+ return MDP_COLOR_YV12;
+ }
+
+ mtk_mdp_err("Unknown format 0x%x", v4l2_format);
+
+ return MDP_COLOR_UNKNOWN;
+}
+
+void mtk_mdp_hw_set_input_addr(struct mtk_mdp_ctx *ctx,
+ struct mtk_mdp_addr *addr)
+{
+ struct mdp_buffer *src_buf = &ctx->vpu.vsi->src_buffer;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(addr->addr); i++)
+ src_buf->addr_mva[i] = (uint64_t)addr->addr[i];
+}
+
+void mtk_mdp_hw_set_output_addr(struct mtk_mdp_ctx *ctx,
+ struct mtk_mdp_addr *addr)
+{
+ struct mdp_buffer *dst_buf = &ctx->vpu.vsi->dst_buffer;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(addr->addr); i++)
+ dst_buf->addr_mva[i] = (uint64_t)addr->addr[i];
+}
+
+void mtk_mdp_hw_set_in_size(struct mtk_mdp_ctx *ctx)
+{
+ struct mtk_mdp_frame *frame = &ctx->s_frame;
+ struct mdp_config *config = &ctx->vpu.vsi->src_config;
+
+ /* Set input pixel offset */
+ config->crop_x = frame->crop.left;
+ config->crop_y = frame->crop.top;
+
+ /* Set input cropped size */
+ config->crop_w = frame->crop.width;
+ config->crop_h = frame->crop.height;
+
+ /* Set input original size */
+ config->x = 0;
+ config->y = 0;
+ config->w = frame->width;
+ config->h = frame->height;
+}
+
+void mtk_mdp_hw_set_in_image_format(struct mtk_mdp_ctx *ctx)
+{
+ unsigned int i;
+ struct mtk_mdp_frame *frame = &ctx->s_frame;
+ struct mdp_config *config = &ctx->vpu.vsi->src_config;
+ struct mdp_buffer *src_buf = &ctx->vpu.vsi->src_buffer;
+
+ src_buf->plane_num = frame->fmt->num_comp;
+ config->format = mtk_mdp_map_color_format(frame->fmt->pixelformat);
+ config->w_stride = 0; /* MDP will calculate it by color format. */
+ config->h_stride = 0; /* MDP will calculate it by color format. */
+
+ for (i = 0; i < src_buf->plane_num; i++)
+ src_buf->plane_size[i] = frame->payload[i];
+}
+
+void mtk_mdp_hw_set_out_size(struct mtk_mdp_ctx *ctx)
+{
+ struct mtk_mdp_frame *frame = &ctx->d_frame;
+ struct mdp_config *config = &ctx->vpu.vsi->dst_config;
+
+ config->crop_x = frame->crop.left;
+ config->crop_y = frame->crop.top;
+ config->crop_w = frame->crop.width;
+ config->crop_h = frame->crop.height;
+ config->x = 0;
+ config->y = 0;
+ config->w = frame->width;
+ config->h = frame->height;
+}
+
+void mtk_mdp_hw_set_out_image_format(struct mtk_mdp_ctx *ctx)
+{
+ unsigned int i;
+ struct mtk_mdp_frame *frame = &ctx->d_frame;
+ struct mdp_config *config = &ctx->vpu.vsi->dst_config;
+ struct mdp_buffer *dst_buf = &ctx->vpu.vsi->dst_buffer;
+
+ dst_buf->plane_num = frame->fmt->num_comp;
+ config->format = mtk_mdp_map_color_format(frame->fmt->pixelformat);
+ config->w_stride = 0; /* MDP will calculate it by color format. */
+ config->h_stride = 0; /* MDP will calculate it by color format. */
+ for (i = 0; i < dst_buf->plane_num; i++)
+ dst_buf->plane_size[i] = frame->payload[i];
+}
+
+void mtk_mdp_hw_set_rotation(struct mtk_mdp_ctx *ctx)
+{
+ struct mdp_config_misc *misc = &ctx->vpu.vsi->misc;
+
+ misc->orientation = ctx->ctrls.rotate->val;
+ misc->hflip = ctx->ctrls.hflip->val;
+ misc->vflip = ctx->ctrls.vflip->val;
+}
+
+void mtk_mdp_hw_set_global_alpha(struct mtk_mdp_ctx *ctx)
+{
+ struct mdp_config_misc *misc = &ctx->vpu.vsi->misc;
+
+ misc->alpha = ctx->ctrls.global_alpha->val;
+}
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h b/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
new file mode 100644
index 0000000..42bd057
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_REGS_H__
+#define __MTK_MDP_REGS_H__
+
+
+void mtk_mdp_hw_set_input_addr(struct mtk_mdp_ctx *ctx,
+ struct mtk_mdp_addr *addr);
+void mtk_mdp_hw_set_output_addr(struct mtk_mdp_ctx *ctx,
+ struct mtk_mdp_addr *addr);
+void mtk_mdp_hw_set_in_size(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_in_image_format(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_out_size(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_out_image_format(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_rotation(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_global_alpha(struct mtk_mdp_ctx *ctx);
+
+
+#endif /* __MTK_MDP_REGS_H__ */
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c b/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
new file mode 100644
index 0000000..fb07bf3
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_vpu.h"
+#include "mtk_vpu.h"
+
+
+static inline struct mtk_mdp_ctx *vpu_to_ctx(struct mtk_mdp_vpu *vpu)
+{
+ return container_of(vpu, struct mtk_mdp_ctx, vpu);
+}
+
+static void mtk_mdp_vpu_handle_init_ack(struct mdp_ipi_comm_ack *msg)
+{
+ struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)msg->ap_inst;
+
+ /* mapping VPU address to kernel virtual address */
+ vpu->vsi = (struct mdp_process_vsi *)
+ vpu_mapping_dm_addr(vpu->pdev, msg->vpu_inst_addr);
+ vpu->inst_addr = msg->vpu_inst_addr;
+}
+
+static void mtk_mdp_vpu_ipi_handler(void *data, unsigned int len, void *priv)
+{
+ unsigned int msg_id = *(unsigned int *)data;
+ struct mdp_ipi_comm_ack *msg = (struct mdp_ipi_comm_ack *)data;
+ struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)msg->ap_inst;
+ struct mtk_mdp_ctx *ctx;
+
+ vpu->failure = msg->status;
+ if (!vpu->failure) {
+ switch (msg_id) {
+ case VPU_MDP_INIT_ACK:
+ mtk_mdp_vpu_handle_init_ack(data);
+ break;
+ case VPU_MDP_DEINIT_ACK:
+ case VPU_MDP_PROCESS_ACK:
+ break;
+ default:
+ ctx = vpu_to_ctx(vpu);
+ dev_err(&ctx->mdp_dev->pdev->dev,
+ "handle unknown ipi msg:0x%x\n",
+ msg_id);
+ break;
+ }
+ } else {
+ ctx = vpu_to_ctx(vpu);
+ mtk_mdp_dbg(0, "[%d]:msg 0x%x, failure:%d", ctx->id,
+ msg_id, vpu->failure);
+ }
+}
+
+int mtk_mdp_vpu_register(struct platform_device *pdev)
+{
+ struct mtk_mdp_dev *mdp = platform_get_drvdata(pdev);
+ int err;
+
+ err = vpu_ipi_register(mdp->vpu_dev, IPI_MDP,
+ mtk_mdp_vpu_ipi_handler, "mdp_vpu", NULL);
+ if (err)
+ dev_err(&mdp->pdev->dev,
+ "vpu_ipi_registration fail status=%d\n", err);
+
+ return err;
+}
+
+static int mtk_mdp_vpu_send_msg(void *msg, int len, struct mtk_mdp_vpu *vpu,
+ int id)
+{
+ struct mtk_mdp_ctx *ctx = vpu_to_ctx(vpu);
+ int err;
+
+ if (!vpu->pdev) {
+ mtk_mdp_dbg(1, "[%d]:vpu pdev is NULL", ctx->id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctx->mdp_dev->vpulock);
+ err = vpu_ipi_send(vpu->pdev, (enum ipi_id)id, msg, len);
+ if (err) {
+ mutex_unlock(&ctx->mdp_dev->vpulock);
+ dev_err(&ctx->mdp_dev->pdev->dev,
+ "vpu_ipi_send fail status %d\n", err);
+ }
+ mutex_unlock(&ctx->mdp_dev->vpulock);
+
+ return err;
+}
+
+static int mtk_mdp_vpu_send_ap_ipi(struct mtk_mdp_vpu *vpu, uint32_t msg_id)
+{
+ int err;
+ struct mdp_ipi_comm msg;
+
+ msg.msg_id = msg_id;
+ msg.ipi_id = IPI_MDP;
+ msg.vpu_inst_addr = vpu->inst_addr;
+ msg.ap_inst = (uint64_t)vpu;
+ err = mtk_mdp_vpu_send_msg((void *)&msg, sizeof(msg), vpu, IPI_MDP);
+ if (!err && vpu->failure)
+ err = -EINVAL;
+
+ return err;
+}
+
+int mtk_mdp_vpu_init(struct mtk_mdp_vpu *vpu)
+{
+ int err;
+ struct mdp_ipi_init msg;
+ struct mtk_mdp_ctx *ctx = vpu_to_ctx(vpu);
+
+ vpu->pdev = ctx->mdp_dev->vpu_dev;
+
+ msg.msg_id = AP_MDP_INIT;
+ msg.ipi_id = IPI_MDP;
+ msg.ap_inst = (uint64_t)vpu;
+ err = mtk_mdp_vpu_send_msg((void *)&msg, sizeof(msg), vpu, IPI_MDP);
+ if (!err && vpu->failure)
+ err = -EINVAL;
+
+ return err;
+}
+
+int mtk_mdp_vpu_deinit(struct mtk_mdp_vpu *vpu)
+{
+ return mtk_mdp_vpu_send_ap_ipi(vpu, AP_MDP_DEINIT);
+}
+
+int mtk_mdp_vpu_process(struct mtk_mdp_vpu *vpu)
+{
+ return mtk_mdp_vpu_send_ap_ipi(vpu, AP_MDP_PROCESS);
+}
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h b/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
new file mode 100644
index 0000000..df4bdda
--- /dev/null
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_VPU_H__
+#define __MTK_MDP_VPU_H__
+
+#include "mtk_mdp_ipi.h"
+
+
+/**
+ * struct mtk_mdp_vpu - VPU instance for MDP
+ * @pdev : pointer to the VPU platform device
+ * @inst_addr : VPU MDP instance address
+ * @failure : VPU execution result status
+ * @vsi : VPU shared information
+ */
+struct mtk_mdp_vpu {
+ struct platform_device *pdev;
+ uint32_t inst_addr;
+ int32_t failure;
+ struct mdp_process_vsi *vsi;
+};
+
+int mtk_mdp_vpu_register(struct platform_device *pdev);
+int mtk_mdp_vpu_init(struct mtk_mdp_vpu *vpu);
+int mtk_mdp_vpu_deinit(struct mtk_mdp_vpu *vpu);
+int mtk_mdp_vpu_process(struct mtk_mdp_vpu *vpu);
+
+#endif /* __MTK_MDP_VPU_H__ */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v6 2/6] dt-bindings: Add a binding for Mediatek MDP
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Minghsiu Tsai,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yingjoe Chen,
Eddie Huang, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Add a DT binding documentation of MDP for the MT8173 SoC
from Mediatek
Signed-off-by: Minghsiu Tsai <minghsiu.tsai-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/media/mediatek-mdp.txt | 109 ++++++++++++++++++++
1 file changed, 109 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek-mdp.txt
diff --git a/Documentation/devicetree/bindings/media/mediatek-mdp.txt b/Documentation/devicetree/bindings/media/mediatek-mdp.txt
new file mode 100644
index 0000000..4182063
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek-mdp.txt
@@ -0,0 +1,109 @@
+* Mediatek Media Data Path
+
+Media Data Path is used for scaling and color space conversion.
+
+Required properties (controller (parent) node):
+- compatible: "mediatek,mt8173-mdp"
+- mediatek,vpu: the node of video processor unit, see
+ Documentation/devicetree/bindings/media/mediatek-vpu.txt for details.
+
+Required properties (all function blocks, child node):
+- compatible: Should be one of
+ "mediatek,mt8173-mdp-rdma" - read DMA
+ "mediatek,mt8173-mdp-rsz" - resizer
+ "mediatek,mt8173-mdp-wdma" - write DMA
+ "mediatek,mt8173-mdp-wrot" - write DMA with rotation
+- reg: Physical base address and length of the function block register space
+- clocks: device clocks, see
+ Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
+- power-domains: a phandle to the power domain, see
+ Documentation/devicetree/bindings/power/power_domain.txt for details.
+
+Required properties (DMA function blocks, child node):
+- compatible: Should be one of
+ "mediatek,mt8173-mdp-rdma"
+ "mediatek,mt8173-mdp-wdma"
+ "mediatek,mt8173-mdp-wrot"
+- iommus: should point to the respective IOMMU block with master port as
+ argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+ for details.
+- mediatek,larb: must contain the local arbiters in the current Socs, see
+ Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+ for details.
+
+Example:
+mdp {
+ compatible = "mediatek,mt8173-mdp";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ mediatek,vpu = <&vpu>;
+
+ mdp_rdma0: rdma@14001000 {
+ compatible = "mediatek,mt8173-mdp-rdma";
+ reg = <0 0x14001000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RDMA0>,
+ <&mmsys CLK_MM_MUTEX_32K>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_RDMA0>;
+ mediatek,larb = <&larb0>;
+ };
+
+ mdp_rdma1: rdma@14002000 {
+ compatible = "mediatek,mt8173-mdp-rdma";
+ reg = <0 0x14002000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RDMA1>,
+ <&mmsys CLK_MM_MUTEX_32K>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_RDMA1>;
+ mediatek,larb = <&larb4>;
+ };
+
+ mdp_rsz0: rsz@14003000 {
+ compatible = "mediatek,mt8173-mdp-rsz";
+ reg = <0 0x14003000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RSZ0>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ };
+
+ mdp_rsz1: rsz@14004000 {
+ compatible = "mediatek,mt8173-mdp-rsz";
+ reg = <0 0x14004000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RSZ1>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ };
+
+ mdp_rsz2: rsz@14005000 {
+ compatible = "mediatek,mt8173-mdp-rsz";
+ reg = <0 0x14005000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_RSZ2>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ };
+
+ mdp_wdma0: wdma@14006000 {
+ compatible = "mediatek,mt8173-mdp-wdma";
+ reg = <0 0x14006000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_WDMA>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_WDMA>;
+ mediatek,larb = <&larb0>;
+ };
+
+ mdp_wrot0: wrot@14007000 {
+ compatible = "mediatek,mt8173-mdp-wrot";
+ reg = <0 0x14007000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_WROT0>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_WROT0>;
+ mediatek,larb = <&larb0>;
+ };
+
+ mdp_wrot1: wrot@14008000 {
+ compatible = "mediatek,mt8173-mdp-wrot";
+ reg = <0 0x14008000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MDP_WROT1>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ iommus = <&iommu M4U_PORT_MDP_WROT1>;
+ mediatek,larb = <&larb4>;
+ };
+};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v6 1/6] VPU: mediatek: Add mdp support
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson, Rob Herring, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak
Cc: devicetree, Minghsiu Tsai, srv_heupstream, linux-kernel,
linux-mediatek, Yingjoe Chen, Eddie Huang, linux-arm-kernel,
linux-media
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>
VPU driver add mdp support
Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
---
drivers/media/platform/mtk-vpu/mtk_vpu.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.h b/drivers/media/platform/mtk-vpu/mtk_vpu.h
index f457479..291ae46 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.h
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.h
@@ -53,6 +53,8 @@ typedef void (*ipi_handler_t) (void *data,
handle H264 video encoder job, and vice versa.
* @IPI_VENC_VP8: The interrupt fro vpu is to notify kernel to
handle VP8 video encoder job,, and vice versa.
+ * @IPI_MDP: The interrupt from vpu is to notify kernel to
+ handle MDP (Media Data Path) job, and vice versa.
* @IPI_MAX: The maximum IPI number
*/
@@ -63,6 +65,7 @@ enum ipi_id {
IPI_VDEC_VP9,
IPI_VENC_H264,
IPI_VENC_VP8,
+ IPI_MDP,
IPI_MAX,
};
@@ -71,11 +74,13 @@ enum ipi_id {
*
* @VPU_RST_ENC: encoder reset id
* @VPU_RST_DEC: decoder reset id
+ * @VPU_RST_MDP: MDP (Media Data Path) reset id
* @VPU_RST_MAX: maximum reset id
*/
enum rst_id {
VPU_RST_ENC,
VPU_RST_DEC,
+ VPU_RST_MDP,
VPU_RST_MAX,
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v6 0/6] Add MT8173 MDP Driver
From: Minghsiu Tsai @ 2016-09-08 13:09 UTC (permalink / raw)
To: Hans Verkuil, daniel.thompson, Rob Herring, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak
Cc: srv_heupstream, Eddie Huang, Yingjoe Chen, devicetree,
linux-kernel, linux-arm-kernel, linux-media, linux-mediatek
Changes in v6:
- s_selection() can't set the _DEFAULT and _BOUNDS targets
- Add Maintainers entry
Changes in v5:
- Add ack in the comment of dts patch
- Fix s/g_selection()
- Separate format V4L2_PIX_FMT_MT21C into new patch
Changes in v4:
- Add "depends on HAS_DMA" in Kconfig.
- Fix s/g_selection()
- Replace struct v4l2_crop with u32 and struct v4l2_rect
- Remove VB2_USERPTR
- Move mutex lock after ctx allocation in mtk_mdp_m2m_open()
- Add new format V4L2_PIX_FMT_YVU420 to support software on Android platform.
- Only width/height of image in format V4L2_PIX_FMT_MT21 is aligned to 16/16,
other ones are aligned to 2/2 by default
Changes in v3:
- Modify device ndoe as structured one.
- Fix conflict in dts on Linux 4.8-rc1
Changes in v2:
- Add section to describe blocks function in dts-bindings
- Remove the assignment of device_caps in querycap()
- Remove format's name assignment
- Copy colorspace-related parameters from OUTPUT to CAPTURE
- Use m2m helper functions
- Fix DMA allocation failure
- Initialize lazily vpu instance in streamon()
==============
Introduction
==============
The purpose of this series is to add the driver for Media Data Path HW embedded in the Mediatek's MT8173 SoC.
MDP is used for scaling and color space conversion.
It could convert V4L2_PIX_FMT_MT21 to V4L2_PIX_FMT_NV12M or V4L2_PIX_FMT_YUV420M.
NV12M/YUV420M/MT21 -> MDP -> NV12M/YUV420M
This patch series rely on MTK VPU driver in patch series "Add MT8173 Video Encoder Driver and VPU Driver"[1] and "Add MT8173 Video Decoder Driver"[2].
MDP driver rely on VPU driver to load, communicate with VPU.
Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
[1]https://patchwork.kernel.org/patch/9002171/
[2]https://patchwork.kernel.org/patch/9141245/
==================
Device interface
==================
In principle the driver bases on v4l2 memory-to-memory framework:
it provides a single video node and each opened file handle gets its own private context with separate buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers) and CAPTURE (for destination buffers).
OUTPUT and CAPTURE buffer could be MMAP or DMABUF memory type.
v4l2-compliance test output:
v4l2-compliance SHA : abc1453dfe89f244dccd3460d8e1a2e3091cbadb
Driver Info:
Driver name : mtk-mdp
Card type : soc:mdp
Bus info : platform:mt8173
Driver version: 4.8.0
Capabilities : 0x84204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04204000
Video Memory-to-Memory Multiplanar
Streaming
Extended Pix Format
Compliance test for device /dev/image-proc0 (not using libv4l2):
Required ioctls:
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second video open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 5 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK
test Composing: OK
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
Test input 0:
Total: 43, Succeeded: 43, Failed: 0, Warnings: 0
Minghsiu Tsai (6):
VPU: mediatek: Add mdp support
dt-bindings: Add a binding for Mediatek MDP
media: Add Mediatek MDP Driver
arm64: dts: mediatek: Add MDP for MT8173
media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C
media: mtk-mdp: add Maintainers entry for Mediatek MDP driver
.../devicetree/bindings/media/mediatek-mdp.txt | 109 ++
MAINTAINERS | 9 +
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 84 ++
drivers/media/platform/Kconfig | 17 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/mtk-mdp/Makefile | 9 +
drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 159 +++
drivers/media/platform/mtk-mdp/mtk_mdp_comp.h | 72 ++
drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 294 +++++
drivers/media/platform/mtk-mdp/mtk_mdp_core.h | 260 ++++
drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h | 126 ++
drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 1278 ++++++++++++++++++++
drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h | 22 +
drivers/media/platform/mtk-mdp/mtk_mdp_regs.c | 156 +++
drivers/media/platform/mtk-mdp/mtk_mdp_regs.h | 31 +
drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c | 145 +++
drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h | 41 +
drivers/media/platform/mtk-vpu/mtk_vpu.h | 5 +
18 files changed, 2819 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek-mdp.txt
create mode 100644 drivers/media/platform/mtk-mdp/Makefile
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH 1/4] Document: DT: Add bindings for mediatek MT6797 SoC Platform
From: Marc Zyngier @ 2016-09-08 12:37 UTC (permalink / raw)
To: Mars Cheng, Matthias Brugger, Rob Herring, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: linux-clk, CC Hwang, Loda Choui, Miles Chen, Scott Shu,
Jades Shih, Yingjoe Chen, My Chuang, linux-kernel, linux-mediatek,
devicetree, wsd_upstream
In-Reply-To: <1473331794-27542-2-git-send-email-mars.cheng@mediatek.com>
On 08/09/16 11:49, Mars Cheng wrote:
> This adds DT binding documentation for Mediatek MT6797.
>
> Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
> ---
> Documentation/devicetree/bindings/arm/mediatek.txt | 4 ++++
> .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
> .../bindings/arm/mediatek/mediatek,mmsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,topckgen.txt | 1 +
> .../bindings/arm/mediatek/mediatek,vdecsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,vencsys.txt | 3 ++-
> .../interrupt-controller/mediatek,sysirq.txt | 4 +++-
> .../devicetree/bindings/serial/mtk-uart.txt | 1 +
> 10 files changed, 16 insertions(+), 2 deletions(-)
[...]
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
> index 9d1d72c..3d97eb4 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
> @@ -8,6 +8,7 @@ Required properties:
> "mediatek,mt8173-sysirq"
> "mediatek,mt8135-sysirq"
> "mediatek,mt8127-sysirq"
> + "mediatek,mt6797-sysirq"
> "mediatek,mt6795-sysirq"
> "mediatek,mt6755-sysirq"
> "mediatek,mt6592-sysirq"
> @@ -21,7 +22,8 @@ Required properties:
> - interrupt-parent: phandle of irq parent for sysirq. The parent must
> use the same interrupt-cells format as GIC.
> - reg: Physical base address of the intpol registers and length of memory
> - mapped region.
> + mapped region. Could be up to 2 registers here at max. Ex: 6797 needs 2 reg,
> + others need 1.
Two things:
- Please make this a separate patch that can be reviewed independently
of the rest of the changes, which are just adding new compatible
identifiers.
- Why can't you simply expose it as a separate controller? Looking at
the way you're changing the corresponding driver, it looks like you're
simply adding an extra base/size. If you simply had a base for the
corresponding GIC interrupts, you could handle as many region as you
want, and have a more generic driver.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* Re: [PATCH v5 3/5] media: Add Mediatek MDP Driver
From: Minghsiu Tsai @ 2016-09-08 12:21 UTC (permalink / raw)
To: Hans Verkuil
Cc: Hans Verkuil, daniel.thompson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Eddie Huang,
Yingjoe Chen, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <cb59f743-66b9-15cd-0281-54510d7f93ca-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
On Mon, 2016-09-05 at 12:17 +0200, Hans Verkuil wrote:
> On 08/30/2016 02:25 PM, Minghsiu Tsai wrote:
> > Add MDP driver for MT8173
> >
> > Signed-off-by: Minghsiu Tsai <minghsiu.tsai-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > ---
> > drivers/media/platform/Kconfig | 17 +
> > drivers/media/platform/Makefile | 2 +
> > drivers/media/platform/mtk-mdp/Makefile | 9 +
> > drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 159 ++++
> > drivers/media/platform/mtk-mdp/mtk_mdp_comp.h | 72 ++
> > drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 294 ++++++
> > drivers/media/platform/mtk-mdp/mtk_mdp_core.h | 260 +++++
> > drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h | 126 +++
> > drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 1270 +++++++++++++++++++++++++
> > drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h | 22 +
> > drivers/media/platform/mtk-mdp/mtk_mdp_regs.c | 152 +++
> > drivers/media/platform/mtk-mdp/mtk_mdp_regs.h | 31 +
> > drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c | 145 +++
> > drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h | 41 +
> > 14 files changed, 2600 insertions(+)
> > create mode 100644 drivers/media/platform/mtk-mdp/Makefile
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.c
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.h
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
> > create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
> >
>
> <snip>
>
> > +static inline bool mtk_mdp_is_target_compose(u32 target)
> > +{
> > + if (target == V4L2_SEL_TGT_COMPOSE_DEFAULT
> > + || target == V4L2_SEL_TGT_COMPOSE_BOUNDS
> > + || target == V4L2_SEL_TGT_COMPOSE)
> > + return true;
> > + return false;
> > +}
> > +
> > +static inline bool mtk_mdp_is_target_crop(u32 target)
> > +{
> > + if (target == V4L2_SEL_TGT_CROP_DEFAULT
> > + || target == V4L2_SEL_TGT_CROP_BOUNDS
> > + || target == V4L2_SEL_TGT_CROP)
> > + return true;
> > + return false;
> > +}
> > +
> > +static int mtk_mdp_m2m_g_selection(struct file *file, void *fh,
> > + struct v4l2_selection *s)
> > +{
> > + struct mtk_mdp_frame *frame;
> > + struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
> > + bool valid = false;
> > +
> > + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> > + if (mtk_mdp_is_target_compose(s->target))
> > + valid = true;
> > + } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> > + if (mtk_mdp_is_target_crop(s->target))
> > + valid = true;
> > + }
> > + if (!valid) {
> > + mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
> > + s->target);
> > + return -EINVAL;
> > + }
> > +
> > + frame = mtk_mdp_ctx_get_frame(ctx, s->type);
> > +
> > + switch (s->target) {
> > + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> > + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> > + case V4L2_SEL_TGT_CROP_BOUNDS:
> > + case V4L2_SEL_TGT_CROP_DEFAULT:
> > + s->r.left = 0;
> > + s->r.top = 0;
> > + s->r.width = frame->width;
> > + s->r.height = frame->height;
> > + return 0;
> > +
> > + case V4L2_SEL_TGT_COMPOSE:
> > + case V4L2_SEL_TGT_CROP:
> > + s->r.left = frame->crop.left;
> > + s->r.top = frame->crop.top;
> > + s->r.width = frame->crop.width;
> > + s->r.height = frame->crop.height;
> > + return 0;
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +static int mtk_mdp_check_scaler_ratio(struct mtk_mdp_variant *var, int src_w,
> > + int src_h, int dst_w, int dst_h, int rot)
> > +{
> > + int tmp_w, tmp_h;
> > +
> > + if (rot == 90 || rot == 270) {
> > + tmp_w = dst_h;
> > + tmp_h = dst_w;
> > + } else {
> > + tmp_w = dst_w;
> > + tmp_h = dst_h;
> > + }
> > +
> > + if ((src_w / tmp_w) > var->h_scale_down_max ||
> > + (src_h / tmp_h) > var->v_scale_down_max ||
> > + (tmp_w / src_w) > var->h_scale_up_max ||
> > + (tmp_h / src_h) > var->v_scale_up_max)
> > + return -EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_mdp_m2m_s_selection(struct file *file, void *fh,
> > + struct v4l2_selection *s)
> > +{
> > + struct mtk_mdp_frame *frame;
> > + struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
> > + struct v4l2_rect new_r;
> > + struct mtk_mdp_variant *variant = ctx->mdp_dev->variant;
> > + int ret;
> > + bool valid = false;
> > +
> > + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> > + if (mtk_mdp_is_target_compose(s->target))
> > + valid = true;
> > + } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> > + if (mtk_mdp_is_target_crop(s->target))
> > + valid = true;
> > + }
>
> These tests are wrong: you can't set the _DEFAULT and _BOUNDS targets.
> Those are read-only. It's easiest to just explicitly check for _CROP or
> _COMPOSE here.
>
> I've added a check to v4l2-compliance to test for this.
>
I will fix it in v6 and test with the latest v4l2-compliance. Thanks.
> > + if (!valid) {
> > + mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
> > + s->target);
> > + return -EINVAL;
> > + }
> > +
> > + new_r = s->r;
> > + ret = mtk_mdp_try_crop(ctx, s->type, &new_r);
> > + if (ret)
> > + return ret;
> > +
> > + if (mtk_mdp_is_target_crop(s->target))
> > + frame = &ctx->s_frame;
> > + else
> > + frame = &ctx->d_frame;
> > +
> > + /* Check to see if scaling ratio is within supported range */
> > + if (mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT)) {
> > + if (V4L2_TYPE_IS_OUTPUT(s->type)) {
> > + ret = mtk_mdp_check_scaler_ratio(variant, new_r.width,
> > + new_r.height, ctx->d_frame.crop.width,
> > + ctx->d_frame.crop.height,
> > + ctx->ctrls.rotate->val);
> > + } else {
> > + ret = mtk_mdp_check_scaler_ratio(variant,
> > + ctx->s_frame.crop.width,
> > + ctx->s_frame.crop.height, new_r.width,
> > + new_r.height, ctx->ctrls.rotate->val);
> > + }
> > +
> > + if (ret) {
> > + dev_info(&ctx->mdp_dev->pdev->dev,
> > + "Out of scaler range");
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + s->r = new_r;
> > + frame->crop = new_r;
> > +
> > + return 0;
> > +}
>
>
> Regards,
>
> Hans
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 4/4] clk: mediatek: Add MT6797 clock support
From: Mars Cheng @ 2016-09-08 10:49 UTC (permalink / raw)
To: Matthias Brugger, Rob Herring, Marc Zyngier, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: linux-clk, CC Hwang, Loda Choui, Miles Chen, Scott Shu,
Jades Shih, Yingjoe Chen, My Chuang, linux-kernel, linux-mediatek,
devicetree, wsd_upstream, Mars Cheng
In-Reply-To: <1473331794-27542-1-git-send-email-mars.cheng@mediatek.com>
Add MT6797 clock support, include topckgen, apmixedsys,
infracfg and subsystem clocks.
Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt6797.dtsi | 66 ++-
drivers/clk/mediatek/Kconfig | 36 ++
drivers/clk/mediatek/Makefile | 5 +
drivers/clk/mediatek/clk-mt6797-img.c | 87 ++++
drivers/clk/mediatek/clk-mt6797-mm.c | 146 ++++++
drivers/clk/mediatek/clk-mt6797-vdec.c | 102 +++++
drivers/clk/mediatek/clk-mt6797-venc.c | 86 ++++
drivers/clk/mediatek/clk-mt6797.c | 716 ++++++++++++++++++++++++++++++
include/dt-bindings/clock/mt6797-clk.h | 281 ++++++++++++
9 files changed, 1514 insertions(+), 11 deletions(-)
create mode 100644 drivers/clk/mediatek/clk-mt6797-img.c
create mode 100644 drivers/clk/mediatek/clk-mt6797-mm.c
create mode 100644 drivers/clk/mediatek/clk-mt6797-vdec.c
create mode 100644 drivers/clk/mediatek/clk-mt6797-venc.c
create mode 100644 drivers/clk/mediatek/clk-mt6797.c
create mode 100644 include/dt-bindings/clock/mt6797-clk.h
diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
index 66f6442..75d3877 100644
--- a/arch/arm64/boot/dts/mediatek/mt6797.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/clock/mt6797-clk.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -113,12 +114,6 @@
clock-output-names = "clk32k";
};
- uart_clk: dummy26m {
- compatible = "fixed-clock";
- clock-frequency = <26000000>;
- #clock-cells = <0>;
- };
-
timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&gic>;
@@ -132,6 +127,24 @@
(GIC_CPU_MASK_SIMPLE(10) | IRQ_TYPE_LEVEL_LOW)>;
};
+ topckgen: topckgen@10000000 {
+ compatible = "mediatek,mt6797-topckgen";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ infrasys: infracfg_ao@10001000 {
+ compatible = "mediatek,mt6797-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ apmixedsys: apmixed@1000c000 {
+ compatible = "mediatek,mt6797-apmixedsys";
+ reg = <0 0x1000c000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
sysirq: intpol-controller@10200620 {
compatible = "mediatek,mt6797-sysirq",
"mediatek,mt6577-sysirq";
@@ -148,7 +161,9 @@
"mediatek,mt6577-uart";
reg = <0 0x11002000 0 0x400>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&uart_clk>;
+ clocks = <&infrasys CLK_INFRA_UART0>,
+ <&infrasys CLK_INFRA_AP_DMA>;
+ clock-names = "baud", "bus";
status = "disabled";
};
@@ -157,7 +172,9 @@
"mediatek,mt6577-uart";
reg = <0 0x11003000 0 0x400>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&uart_clk>;
+ clocks = <&infrasys CLK_INFRA_UART1>,
+ <&infrasys CLK_INFRA_AP_DMA>;
+ clock-names = "baud", "bus";
status = "disabled";
};
@@ -166,7 +183,9 @@
"mediatek,mt6577-uart";
reg = <0 0x11004000 0 0x400>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&uart_clk>;
+ clocks = <&infrasys CLK_INFRA_UART2>,
+ <&infrasys CLK_INFRA_AP_DMA>;
+ clock-names = "baud", "bus";
status = "disabled";
};
@@ -175,10 +194,36 @@
"mediatek,mt6577-uart";
reg = <0 0x11005000 0 0x400>;
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&uart_clk>;
+ clocks = <&infrasys CLK_INFRA_UART3>,
+ <&infrasys CLK_INFRA_AP_DMA>;
+ clock-names = "baud", "bus";
status = "disabled";
};
+ mmsys: mmsys_config@14000000 {
+ compatible = "mediatek,mt6797-mmsys", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ imgsys: imgsys_config@15000000 {
+ compatible = "mediatek,mt6797-imgsys", "syscon";
+ reg = <0 0x15000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ vdecsys: vdec_gcon@16000000 {
+ compatible = "mediatek,mt6797-vdecsys", "syscon";
+ reg = <0 0x16000000 0 0x10000>;
+ #clock-cells = <1>;
+ };
+
+ vencsys: venc_gcon@17000000 {
+ compatible = "mediatek,mt6797-vencsys", "syscon";
+ reg = <0 0x17000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
gic: interrupt-controller@19000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
@@ -189,5 +234,4 @@
<0 0x19200000 0 0x200000>, /* GICR */
<0 0x10240000 0 0x2000>; /* GICC */
};
-
};
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 5aa6204..ce91ecb 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -56,6 +56,42 @@ config COMMON_CLK_MT2701_BDPSYS
---help---
This driver supports Mediatek MT2701 bdpsys clocks.
+config COMMON_CLK_MT6797
+ bool "Clock driver for Mediatek MT6797"
+ depends on COMMON_CLK
+ select COMMON_CLK_MEDIATEK
+ default ARCH_MEDIATEK
+ ---help---
+ This driver supports Mediatek MT6797 basic clocks.
+
+config COMMON_CLK_MT6797_MMSYS
+ bool "Clock driver for Mediatek MT6797 mmsys"
+ depends on COMMON_CLK
+ select COMMON_CLK_MT6797
+ ---help---
+ This driver supports Mediatek MT6797 mmsys clocks.
+
+config COMMON_CLK_MT6797_IMGSYS
+ bool "Clock driver for Mediatek MT6797 imgsys"
+ depends on COMMON_CLK
+ select COMMON_CLK_MT6797
+ ---help---
+ This driver supports Mediatek MT6797 imgsys clocks.
+
+config COMMON_CLK_MT6797_VDECSYS
+ bool "Clock driver for Mediatek MT6797 vdecsys"
+ depends on COMMON_CLK
+ select COMMON_CLK_MT6797
+ ---help---
+ This driver supports Mediatek MT6797 vdecsys clocks.
+
+config COMMON_CLK_MT6797_VENCSYS
+ bool "Clock driver for Mediatek MT6797 vencsys"
+ depends on COMMON_CLK
+ select COMMON_CLK_MT6797
+ ---help---
+ This driver supports Mediatek MT6797 vencsys clocks.
+
config COMMON_CLK_MT8135
bool "Clock driver for Mediatek MT8135"
depends on COMMON_CLK
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 19ae7ef..a5bae28d 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -7,5 +7,10 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
+obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
+obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
+obj-$(CONFIG_COMMON_CLK_MT6797_VDECSYS) += clk-mt6797-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT6797_VENCSYS) += clk-mt6797-venc.o
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c
new file mode 100644
index 0000000..4ecd201
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6797-img.c
@@ -0,0 +1,87 @@
+/* Copyright (c) 2016 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/mt6797-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static const struct mtk_gate_regs img_cg_regs = {
+ .set_ofs = 0x0004,
+ .clr_ofs = 0x0008,
+ .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &img_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate img_clks[] = {
+ GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_sel", 11),
+ GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_sel", 10),
+ GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_sel", 6),
+ GATE_IMG(CLK_IMG_LARB6, "img_larb6", "mm_sel", 0),
+};
+
+static int mtk_imgsys_init(struct device *dev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_gates(dev->of_node, img_clks, ARRAY_SIZE(img_clks),
+ clk_data);
+
+ r = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ clk_data);
+ if (r)
+ pr_err("%s: could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+
+alloc_err:
+ return -ENOMEM;
+}
+
+static const struct of_device_id of_match_clk_mt6797_img[] = {
+ { .compatible = "mediatek,mt6797-imgsys", },
+ {}
+};
+
+static int clk_mt6797_img_probe(struct platform_device *pdev)
+{
+ return mtk_imgsys_init(&pdev->dev);
+}
+
+static struct platform_driver clk_mt6797_img_drv = {
+ .probe = clk_mt6797_img_probe,
+ .driver = {
+ .name = "clk-mt6797-img",
+ .of_match_table = of_match_clk_mt6797_img,
+ },
+};
+
+builtin_platform_driver(clk_mt6797_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c
new file mode 100644
index 0000000..77f0342
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6797-mm.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/mt6797-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+}
+
+#define GATE_MM1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+}
+
+static const struct mtk_gate mm_clks[] = {
+ GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
+ GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+ GATE_MM0(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 2),
+ GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 3),
+ GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 4),
+ GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 5),
+ GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 6),
+ GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 7),
+ GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 8),
+ GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+ GATE_MM0(CLK_MM_MDP_COLOR, "mm_mdp_color", "mm_sel", 10),
+ GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+ GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
+ GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
+ GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
+ GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 15),
+ GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 16),
+ GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 17),
+ GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 18),
+ GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 19),
+ GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 20),
+ GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
+ GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
+ GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 23),
+ GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "mm_sel", 24),
+ GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
+ GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
+ GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 27),
+ GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "mm_sel", 28),
+ GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 29),
+ GATE_MM0(CLK_MM_DISP_DSC, "mm_disp_dsc", "mm_sel", 30),
+ GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
+ GATE_MM1(CLK_MM_DSI0_MM_CLOCK, "mm_dsi0_mm_clock", "mm_sel", 0),
+ GATE_MM1(CLK_MM_DSI1_MM_CLOCK, "mm_dsi1_mm_clock", "mm_sel", 2),
+ GATE_MM1(CLK_MM_DPI_MM_CLOCK, "mm_dpi_mm_clock", "mm_sel", 4),
+ GATE_MM1(CLK_MM_DPI_INTERFACE_CLOCK, "mm_dpi_interface_clock",
+ "dpi0_sel", 5),
+ GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MM_CLOCK, "mm_larb4_axi_asif_mm_clock",
+ "mm_sel", 6),
+ GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK, "mm_larb4_axi_asif_mjc_clock",
+ "mjc_sel", 7),
+ GATE_MM1(CLK_MM_DISP_OVL0_MOUT_CLOCK, "mm_disp_ovl0_mout_clock",
+ "mm_sel", 8),
+ GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 9),
+ GATE_MM1(CLK_MM_DSI0_INTERFACE_CLOCK, "mm_dsi0_interface_clock",
+ "clk26m", 1),
+ GATE_MM1(CLK_MM_DSI1_INTERFACE_CLOCK, "mm_dsi1_interface_clock",
+ "clk26m", 3),
+};
+
+static void mtk_mmsys_init(struct device *dev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_gates(dev->of_node, mm_clks, ARRAY_SIZE(mm_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s: could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+
+alloc_err:
+ return -ENOMEM;
+}
+
+static const struct of_device_id of_match_clk_mt6797_mm[] = {
+ { .compatible = "mediatek,mt6797-mmsys", },
+ {}
+};
+
+static int clk_mt6797_mm_probe(struct platform_device *pdev)
+{
+ return mtk_mmsys_init(&pdev->dev);
+}
+
+static struct platform_driver clk_mt6797_mm_drv = {
+ .probe = clk_mt6797_mm_probe,
+ .driver = {
+ .name = "clk-mt6797-mm",
+ .of_match_table = of_match_clk_mt6797_mm,
+ },
+};
+
+builtin_platform_driver(clk_mt6797_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c
new file mode 100644
index 0000000..48cba6b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6797-vdec.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Kevin-CW Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6797-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+ .set_ofs = 0x0000,
+ .clr_ofs = 0x0004,
+ .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x000c,
+ .sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+}
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+}
+
+static const struct mtk_gate vdec_clks[] = {
+ GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "vdec_sel", 8),
+ GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4),
+ GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "mm_sel", 0),
+};
+
+static void mtk_vdecsys_init(struct device *dev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_gates(dev->of_node, vdec_clks, ARRAY_SIZE(vdec_clks),
+ clk_data);
+
+ r = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s: could not register clock provider: %d\n",
+ __func__, r);
+ return r;
+
+alloc_err:
+ return -ENOMEM;
+}
+
+static const struct of_device_id of_match_clk_mt6797_vdec[] = {
+ { .compatible = "mediatek,mt6797-vdecsys", },
+ {}
+};
+
+static int clk_mt6797_vdec_probe(struct platform_device *pdev)
+{
+ return mtk_vdecsys_init(&pdev->dev);
+}
+
+static struct platform_driver clk_mt6797_vdec_drv = {
+ .probe = clk_mt6797_vdec_probe,
+ .driver = {
+ .name = "clk-mt6797-vdec",
+ .of_match_table = of_match_clk_mt6797_vdec,
+ },
+};
+
+builtin_platform_driver(clk_mt6797_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c
new file mode 100644
index 0000000..787e010
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6797-venc.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6797-clk.h>
+
+static const struct mtk_gate_regs venc_cg_regs = {
+ .set_ofs = 0x0004,
+ .clr_ofs = 0x0008,
+ .sta_ofs = 0x0000,
+};
+
+#define GATE_VENC(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &venc_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate venc_clks[] = {
+ GATE_VENC(CLK_VENC_0, "venc_0", "mm_sel", 0),
+ GATE_VENC(CLK_VENC_1, "venc_1", "venc_sel", 4),
+ GATE_VENC(CLK_VENC_2, "venc_2", "venc_sel", 8),
+ GATE_VENC(CLK_VENC_3, "venc_3", "venc_sel", 12),
+};
+
+static void mtk_vencsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VENC_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s: could not register clock provider: %d\n",
+ __func__, r);
+ return r;
+alloc_err:
+ return -ENOMEM;
+}
+
+static const struct of_device_id of_match_clk_mt6797_venc[] = {
+ { .compatible = "mediatek,mt6797-vencsys", },
+ {}
+};
+
+static int clk_mt6797_venc_probe(struct platform_device *pdev)
+{
+ return mtk_vencsys_init(pdev->dev.of_node);
+}
+
+static struct platform_driver clk_mt6797_venc_drv = {
+ .probe = clk_mt6797_venc_probe,
+ .driver = {
+ .name = "clk-mt6797-venc",
+ .of_match_table = of_match_clk_mt6797_venc,
+ },
+};
+
+builtin_platform_driver(clk_mt6797_venc_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c
new file mode 100644
index 0000000..a851d0f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6797.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6797-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+
+static DEFINE_SPINLOCK(mt6797_clk_lock);
+
+static const struct mtk_fixed_factor top_divs[] = {
+ FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_SYSPLL_D3_D3, "syspll_d3_d3", "syspll_d3", 1, 3),
+ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+ FACTOR(CLK_TOP_SSUSB_PHY_48M_CK, "ssusb_phy_48m_ck", "univpll", 1, 1),
+ FACTOR(CLK_TOP_USB_PHY48M_CK, "usb_phy48m_ck", "univpll", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+ FACTOR(CLK_TOP_ULPOSC_CK_ORG, "ulposc_ck_org", "ulposc", 1, 1),
+ FACTOR(CLK_TOP_ULPOSC_CK, "ulposc_ck", "ulposc_ck_org", 1, 3),
+ FACTOR(CLK_TOP_ULPOSC_D2, "ulposc_d2", "ulposc_ck", 1, 2),
+ FACTOR(CLK_TOP_ULPOSC_D3, "ulposc_d3", "ulposc_ck", 1, 4),
+ FACTOR(CLK_TOP_ULPOSC_D4, "ulposc_d4", "ulposc_ck", 1, 8),
+ FACTOR(CLK_TOP_ULPOSC_D8, "ulposc_d8", "ulposc_ck", 1, 10),
+ FACTOR(CLK_TOP_ULPOSC_D10, "ulposc_d10", "ulposc_ck_org", 1, 1),
+ FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
+ FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
+ FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1),
+ FACTOR(CLK_TOP_MFGPLL_D2, "mfgpll_d2", "mfgpll_ck", 1, 2),
+ FACTOR(CLK_TOP_IMGPLL_CK, "imgpll_ck", "imgpll", 1, 1),
+ FACTOR(CLK_TOP_IMGPLL_D2, "imgpll_d2", "imgpll_ck", 1, 2),
+ FACTOR(CLK_TOP_IMGPLL_D4, "imgpll_d4", "imgpll_ck", 1, 4),
+ FACTOR(CLK_TOP_CODECPLL_CK, "codecpll_ck", "codecpll", 1, 1),
+ FACTOR(CLK_TOP_CODECPLL_D2, "codecpll_d2", "codecpll_ck", 1, 2),
+ FACTOR(CLK_TOP_VDECPLL_CK, "vdecpll_ck", "vdecpll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16),
+ FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, 4),
+ FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll_ck", 1, 8),
+};
+
+static const char * const axi_parents[] = {
+ "clk26m",
+ "syspll_d7",
+ "ulposc_axi_ck_mux",
+};
+
+static const char * const ulposc_axi_ck_mux_parents[] = {
+ "syspll1_d4",
+ "ulposc_axi_ck_mux_pre",
+};
+
+static const char * const ulposc_axi_ck_mux_pre_parents[] = {
+ "ulposc_d2",
+ "ulposc_d3",
+};
+
+static const char * const ddrphycfg_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "syspll2_d4",
+ "syspll1_d8",
+};
+
+static const char * const mm_parents[] = {
+ "clk26m",
+ "imgpll_ck",
+ "univpll1_d2",
+ "syspll1_d2",
+};
+
+static const char * const pwm_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "ulposc_d2",
+ "ulposc_d3",
+ "ulposc_d8",
+ "ulposc_d10",
+ "ulposc_d4",
+};
+
+static const char * const vdec_parents[] = {
+ "clk26m",
+ "vdecpll_ck",
+ "imgpll_ck",
+ "syspll_d3",
+ "univpll_d5",
+ "clk26m",
+ "clk26m",
+};
+
+static const char * const venc_parents[] = {
+ "clk26m",
+ "codecpll_ck",
+ "syspll_d3",
+};
+
+static const char * const mfg_parents[] = {
+ "clk26m",
+ "mfgpll_ck",
+ "syspll_d3",
+ "univpll_d3",
+};
+
+static const char * const camtg[] = {
+ "clk26m",
+ "univpll_d26",
+ "univpll2_d2",
+};
+
+static const char * const uart_parents[] = {
+ "clk26m",
+ "univpll2_d8",
+};
+
+static const char * const spi_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "syspll2_d4",
+ "ulposc_spi_ck_mux",
+};
+
+static const char * const ulposc_spi_ck_mux_parents[] = {
+ "ulposc_d2",
+ "ulposc_d3",
+};
+
+static const char * const usb20_parents[] = {
+ "clk26m",
+ "univpll1_d8",
+ "syspll4_d2",
+};
+
+static const char * const msdc50_0_hclk_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll2_d2",
+ "syspll4_d2",
+};
+
+static const char * const msdc50_0_parents[] = {
+ "clk26m",
+ "msdcpll",
+ "syspll_d3",
+ "univpll1_d4",
+ "syspll2_d2",
+ "syspll_d7",
+ "msdcpll_d2",
+ "univpll1_d2",
+ "univpll_d3",
+};
+
+static const char * const msdc30_1_parents[] = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d2",
+ "univpll1_d4",
+ "syspll2_d2",
+ "syspll_d7",
+ "univpll_d7",
+};
+
+static const char * const msdc30_2_parents[] = {
+ "clk26m",
+ "univpll2_d8",
+ "syspll2_d8",
+ "syspll1_d8",
+ "msdcpll_d8",
+ "syspll3_d4",
+ "univpll_d26",
+};
+
+static const char * const audio_parents[] = {
+ "clk26m",
+ "syspll3_d4",
+ "syspll4_d4",
+ "syspll1_d16",
+};
+
+static const char * const aud_intbus_parents[] = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll4_d2",
+};
+
+static const char * const pmicspi_parents[] = {
+ "clk26m",
+ "univpll_d26",
+ "syspll3_d4",
+ "syspll1_d8",
+ "ulposc_d4",
+ "ulposc_d8",
+ "syspll2_d8",
+};
+
+static const char * const scp_parents[] = {
+ "clk26m",
+ "syspll_d3",
+ "ulposc_ck",
+ "univpll_d5",
+};
+
+static const char * const atb_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+};
+
+static const char * const mjc_parents[] = {
+ "clk26m",
+ "imgpll_ck",
+ "univpll_d5",
+ "syspll1_d2",
+};
+
+static const char * const dpi0_parents[] = {
+ "clk26m",
+ "tvdpll_d2",
+ "tvdpll_d4",
+ "tvdpll_d8",
+ "tvdpll_d16",
+ "clk26m",
+ "clk26m",
+};
+
+static const char * const aud_1_parents[] = {
+ "clk26m",
+ "apll1_ck",
+};
+
+static const char * const aud_2_parents[] = {
+ "clk26m",
+ "apll2_ck",
+};
+
+static const char * const ssusb_top_sys_parents[] = {
+ "clk26m",
+ "univpll3_d2",
+};
+
+static const char * const spm_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+};
+
+static const char * const bsi_spi_parents[] = {
+ "clk26m",
+ "syspll_d3_d3",
+ "syspll1_d4",
+ "syspll_d7",
+};
+
+static const char * const audio_h_parents[] = {
+ "clk26m",
+ "apll2_ck",
+ "apll1_ck",
+ "univpll_d7",
+};
+
+static const char * const mfg_52m_parents[] = {
+ "clk26m",
+ "univpll2_d8",
+ "univpll2_d4",
+ "univpll2_d4",
+};
+
+static const char * const anc_md32_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "univpll_d5",
+};
+
+static const struct mtk_composite top_muxes[] = {
+ MUX_GATE(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre",
+ ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1,
+ INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX, "ulposc_axi_ck_mux",
+ ulposc_axi_ck_mux_parents, 0x0040, 2, 1, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_AXI, "axi_sel", axi_parents,
+ 0x0040, 0, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents,
+ 0x0040, 16, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_MM, "mm_sel", mm_parents,
+ 0x0040, 24, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel", pwm_parents, 0x0050, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel", vdec_parents, 0x0050, 8, 3, 15),
+ MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel", venc_parents, 0x0050, 16, 2, 23),
+ MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel", mfg_parents, 0x0050, 24, 2, 31),
+ MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel", camtg, 0x0060, 0, 2, 7),
+ MUX_GATE(CLK_TOP_MUX_UART, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+ MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, 0x0060, 16, 2, 23),
+ MUX_GATE(CLK_TOP_MUX_ULPOSC_SPI_CK_MUX, "ulposc_spi_ck_mux",
+ ulposc_spi_ck_mux_parents, 0x0060, 18, 1,
+ INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel", usb20_parents,
+ 0x0060, 24, 2, 31),
+ MUX_GATE(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_0_hclk_sel",
+ msdc50_0_hclk_parents, 0x0070, 8, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", msdc50_0_parents,
+ 0x0070, 16, 4, 23),
+ MUX_GATE(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", msdc30_1_parents,
+ 0x0070, 24, 3, 31),
+ MUX_GATE(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", msdc30_2_parents,
+ 0x0080, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents,
+ 0x0080, 16, 2, 23),
+ MUX_GATE(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel", aud_intbus_parents,
+ 0x0080, 24, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", pmicspi_parents,
+ 0x0090, 0, 3, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_SCP, "scp_sel", scp_parents,
+ 0x0090, 8, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_ATB, "atb_sel", atb_parents,
+ 0x0090, 16, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_MJC, "mjc_sel", mjc_parents, 0x0090, 24, 2, 31),
+ MUX_GATE(CLK_TOP_MUX_DPI0, "dpi0_sel", dpi0_parents, 0x00A0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MUX_AUD_1, "aud_1_sel", aud_1_parents,
+ 0x00A0, 16, 1, 23),
+ MUX_GATE(CLK_TOP_MUX_AUD_2, "aud_2_sel", aud_2_parents,
+ 0x00A0, 24, 1, 31),
+ MUX_GATE(CLK_TOP_MUX_SSUSB_TOP_SYS, "ssusb_top_sys_sel",
+ ssusb_top_sys_parents, 0x00B0, 8, 1, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_SPM, "spm_sel", spm_parents,
+ 0x00C0, 0, 1, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_BSI_SPI, "bsi_spi_sel", bsi_spi_parents,
+ 0x00C0, 8, 2, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MUX_AUDIO_H, "audio_h_sel", audio_h_parents,
+ 0x00C0, 16, 2, 23),
+ MUX_GATE(CLK_TOP_MUX_ANC_MD32, "anc_md32_sel", anc_md32_parents,
+ 0x00C0, 24, 2, 31),
+ MUX_GATE(CLK_TOP_MUX_MFG_52M, "mfg_52m_sel", mfg_52m_parents,
+ 0x0104, 1, 2, INVALID_MUX_GATE_BIT),
+};
+
+static const struct mtk_gate_regs infra0_cg_regs = {
+ .set_ofs = 0x0080,
+ .clr_ofs = 0x0084,
+ .sta_ofs = 0x0090,
+};
+
+static const struct mtk_gate_regs infra1_cg_regs = {
+ .set_ofs = 0x0088,
+ .clr_ofs = 0x008c,
+ .sta_ofs = 0x0094,
+};
+
+static const struct mtk_gate_regs infra2_cg_regs = {
+ .set_ofs = 0x00a8,
+ .clr_ofs = 0x00ac,
+ .sta_ofs = 0x00b0,
+};
+
+#define GATE_ICG0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+}
+
+#define GATE_ICG1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+}
+
+#define GATE_ICG2(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra2_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+}
+
+static const struct mtk_gate infra_gates[] = {
+ GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "ulposc", 0),
+ GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pmicspi_sel", 1),
+ GATE_ICG0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pmicspi_sel", 2),
+ GATE_ICG0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pmicspi_sel", 3),
+ GATE_ICG0(CLK_INFRA_SCP, "infra_scp", "scp_sel", 4),
+ GATE_ICG0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5),
+ GATE_ICG0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6),
+ GATE_ICG0(CLK_INFRA_SEJ_13M, "infra_sej_13m", "clk26m", 7),
+ GATE_ICG0(CLK_INFRA_ICUSB, "infra_icusb", "usb20_sel", 8),
+ GATE_ICG0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 9),
+ GATE_ICG0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10),
+ GATE_ICG0(CLK_INFRA_I2C0, "infra_i2c0", "axi_sel", 11),
+ GATE_ICG0(CLK_INFRA_I2C1, "infra_i2c1", "axi_sel", 12),
+ GATE_ICG0(CLK_INFRA_I2C2, "infra_i2c2", "axi_sel", 13),
+ GATE_ICG0(CLK_INFRA_I2C3, "infra_i2c3", "axi_sel", 14),
+ GATE_ICG0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", "axi_sel", 15),
+ GATE_ICG0(CLK_INFRA_PWM1, "infra_pwm1", "axi_sel", 16),
+ GATE_ICG0(CLK_INFRA_PWM2, "infra_pwm2", "axi_sel", 17),
+ GATE_ICG0(CLK_INFRA_PWM3, "infra_pwm3", "axi_sel", 18),
+ GATE_ICG0(CLK_INFRA_PWM4, "infra_pwm4", "axi_sel", 19),
+ GATE_ICG0(CLK_INFRA_PWM, "infra_pwm", "axi_sel", 21),
+ GATE_ICG0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22),
+ GATE_ICG0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23),
+ GATE_ICG0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24),
+ GATE_ICG0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25),
+ GATE_ICG0(CLK_INFRA_MD2MD_CCIF_0, "infra_md2md_ccif_0", "axi_sel", 27),
+ GATE_ICG0(CLK_INFRA_MD2MD_CCIF_1, "infra_md2md_ccif_1", "axi_sel", 28),
+ GATE_ICG0(CLK_INFRA_MD2MD_CCIF_2, "infra_md2md_ccif_2", "axi_sel", 29),
+ GATE_ICG0(CLK_INFRA_FHCTL, "infra_fhctl", "clk26m", 30),
+ GATE_ICG0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31),
+ GATE_ICG1(CLK_INFRA_MD2MD_CCIF_3, "infra_md2md_ccif_3", "axi_sel", 0),
+ GATE_ICG1(CLK_INFRA_SPI, "infra_spi", "spi_sel", 1),
+ GATE_ICG1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_sel", 2),
+ GATE_ICG1(CLK_INFRA_MD2MD_CCIF_4, "infra_md2md_ccif_4", "axi_sel", 3),
+ GATE_ICG1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc30_1_sel", 4),
+ GATE_ICG1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc30_2_sel", 5),
+ GATE_ICG1(CLK_INFRA_MD2MD_CCIF_5, "infra_md2md_ccif_5", "axi_sel", 7),
+ GATE_ICG1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8),
+ GATE_ICG1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9),
+ GATE_ICG1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10),
+ GATE_ICG1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11),
+ GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_0, "infra_ap_c2k_ccif_0",
+ "axi_sel", 12),
+ GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_1, "infra_ap_c2k_ccif_1",
+ "axi_sel", 13),
+ GATE_ICG1(CLK_INFRA_CLDMA, "infra_cldma", "axi_sel", 16),
+ GATE_ICG1(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "pwm_sel", 17),
+ GATE_ICG1(CLK_INFRA_AP_DMA, "infra_ap_dma", "axi_sel", 18),
+ GATE_ICG1(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20),
+ GATE_ICG1(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "mm_sel", 22),
+ GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23),
+ GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25),
+ GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26),
+ GATE_ICG1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31),
+ GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4", "axi_sel", 0),
+ GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm", "axi_sel", 1),
+ GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm", "axi_sel", 2),
+ GATE_ICG2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "axi_sel", 3),
+ GATE_ICG2(CLK_INFRA_I2C2_ARB, "infra_i2c2_arb", "axi_sel", 4),
+ GATE_ICG2(CLK_INFRA_I2C3_IMM, "infra_i2c3_imm", "axi_sel", 5),
+ GATE_ICG2(CLK_INFRA_I2C3_ARB, "infra_i2c3_arb", "axi_sel", 6),
+ GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5", "axi_sel", 7),
+ GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq", "axi_sel", 8),
+ GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 10),
+ GATE_ICG2(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m", "clk26m", 11),
+ GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32", "anc_md32_sel", 12),
+ GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k", "clk26m", 13),
+ GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1", "axi_sel", 15),
+ GATE_ICG2(CLK_INFRA_AES_TOP0, "infra_aes_top0", "axi_sel", 16),
+ GATE_ICG2(CLK_INFRA_AES_TOP1, "infra_aes_top1", "axi_sel", 17),
+ GATE_ICG2(CLK_INFRA_SSUSB_BUS, "infra_ssusb_bus", "axi_sel", 18),
+ GATE_ICG2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 19),
+ GATE_ICG2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 20),
+ GATE_ICG2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 21),
+ GATE_ICG2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 22),
+ GATE_ICG2(CLK_INFRA_IRTX, "infra_irtx", "spi_sel", 23),
+ GATE_ICG2(CLK_INFRA_SSUSB_SYS, "infra_ssusb_sys",
+ "ssusb_top_sys_sel", 24),
+ GATE_ICG2(CLK_INFRA_SSUSB_REF, "infra_ssusb_ref", "clk26m", 9),
+ GATE_ICG2(CLK_INFRA_AUDIO_26M, "infra_audio_26m", "clk26m", 26),
+ GATE_ICG2(CLK_INFRA_AUDIO_26M_PAD_TOP, "infra_audio_26m_pad_top",
+ "clk26m", 27),
+ GATE_ICG2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share",
+ "axi_sel", 28),
+ GATE_ICG2(CLK_INFRA_VAD_WRAP_SOC, "infra_vad_wrap_soc", "axi_sel", 29),
+ GATE_ICG2(CLK_INFRA_DRAMC_CONF, "infra_dramc_conf", "axi_sel", 30),
+ GATE_ICG2(CLK_INFRA_DRAMC_B_CONF, "infra_dramc_b_conf", "axi_sel", 31),
+ GATE_ICG1(CLK_INFRA_MFG_VCG, "infra_mfg_vcg", "mfg_52m_sel", 14),
+};
+
+static const struct mtk_fixed_factor infra_divs[] = {
+ FACTOR(CLK_INFRA_13M, "clk13m", "clk26m", 1, 2),
+};
+
+#define MT6797_PLL_FMAX (3000UL * MHZ)
+
+#define CON0_MT6797_RST_BAR BIT(24)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
+ _pcw_shift, _div_table) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT6797_RST_BAR, \
+ .fmax = MT6797_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ .div_table = _div_table, \
+}
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
+ _pcw_shift) \
+ PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
+ NULL)
+
+static const struct mtk_pll_data plls[] = {
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000101, 0, 21,
+ 0x220, 4, 0x0, 0x224, 0),
+ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000011, 0, 7,
+ 0x230, 4, 0x0, 0x234, 14),
+ PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000101, 0, 21,
+ 0x244, 24, 0x0, 0x244, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000121, 0, 21,
+ 0x250, 4, 0x0, 0x254, 0),
+ PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000121, 0, 21,
+ 0x260, 4, 0x0, 0x264, 0),
+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000121, 0, 21,
+ 0x270, 4, 0x0, 0x274, 0),
+ PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000121, 0, 21,
+ 0x290, 4, 0x0, 0x294, 0),
+ PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000121, 0, 21,
+ 0x2E4, 4, 0x0, 0x2E8, 0),
+ PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000131, 0, 31,
+ 0x2A0, 4, 0x2A8, 0x2A4, 0),
+ PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000131, 0, 31,
+ 0x2B4, 4, 0x2BC, 0x2B8, 0),
+};
+
+static struct clk_onecell_data * __init mtk_topckgen_init(struct device *dev)
+{
+ struct clk_onecell_data *clk_data;
+ struct resource mem;
+ void __iomem *base;
+
+ if (of_address_to_resource(dev->of_node, 0, &mem)) {
+ pr_err("%s: get resource failed\n", __func__);
+ goto res_err;
+ }
+
+ base = devm_ioremap(dev, mem.start, resource_size(&mem));
+ if (!base) {
+ pr_err("%s: ioremap failed\n", __func__);
+ goto ioremap_err;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+ &mt6797_clk_lock, clk_data);
+
+ return clk_data;
+
+alloc_err:
+ devm_iounmap(dev, base);
+res_err:
+ioremap_err:
+ return NULL;
+}
+
+static struct clk_onecell_data * __init mtk_infrasys_init(struct device *dev)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_gates(dev->of_node, infra_gates,
+ ARRAY_SIZE(infra_gates), clk_data);
+ mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
+
+ return clk_data;
+
+alloc_err:
+ return NULL;
+}
+
+static struct clk_onecell_data * __init mtk_apmixedsys_init(struct device *dev)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+ if (!clk_data) {
+ pr_err("%s: alloc failed\n", __func__);
+ goto alloc_err;
+ }
+
+ mtk_clk_register_plls(dev->of_node, plls, ARRAY_SIZE(plls), clk_data);
+
+ return clk_data;
+
+alloc_err:
+ return NULL;
+}
+
+static const struct of_device_id of_match_clk_mt6797[] = {
+ {
+ .compatible = "mediatek,mt6797-topckgen",
+ .data = mtk_topckgen_init,
+ }, {
+ .compatible = "mediatek,mt6797-infracfg",
+ .data = mtk_infrasys_init,
+ }, {
+ .compatible = "mediatek,mt6797-apmixedsys",
+ .data = mtk_apmixedsys_init,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int clk_mt6797_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data * (*clk_init)(struct device *);
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_init = of_device_get_match_data(&pdev->dev);
+ if (!clk_init) {
+ pr_err("%s: matched clk not found\n", __func__);
+ return -EINVAL;
+ }
+
+ clk_data = clk_init(&pdev->dev);
+ if (!clk_data) {
+ pr_err("%s: clk init failed\n", __func__);
+ return -EINVAL;
+ }
+
+ r = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+ clk_data);
+ if (r) {
+ pr_err("%s: could not register clock provider: %d\n",
+ __func__, r);
+ return r;
+ }
+
+ return 0;
+}
+
+static struct platform_driver clk_mt6797_drv = {
+ .probe = clk_mt6797_probe,
+ .driver = {
+ .name = "clk-mt6797",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_clk_mt6797,
+ },
+};
+
+static int __init clk_mt6797_init(void)
+{
+ return platform_driver_register(&clk_mt6797_drv);
+}
+
+arch_initcall(clk_mt6797_init);
diff --git a/include/dt-bindings/clock/mt6797-clk.h b/include/dt-bindings/clock/mt6797-clk.h
new file mode 100644
index 0000000..6f32e6b
--- /dev/null
+++ b/include/dt-bindings/clock/mt6797-clk.h
@@ -0,0 +1,281 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _DT_BINDINGS_CLK_MT6797_H
+#define _DT_BINDINGS_CLK_MT6797_H
+
+/* TOPCKGEN */
+#define CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE 1
+#define CLK_TOP_MUX_ULPOSC_AXI_CK_MUX 2
+#define CLK_TOP_MUX_AXI 3
+#define CLK_TOP_MUX_MEM 4
+#define CLK_TOP_MUX_DDRPHYCFG 5
+#define CLK_TOP_MUX_MM 6
+#define CLK_TOP_MUX_PWM 7
+#define CLK_TOP_MUX_VDEC 8
+#define CLK_TOP_MUX_VENC 9
+#define CLK_TOP_MUX_MFG 10
+#define CLK_TOP_MUX_CAMTG 11
+#define CLK_TOP_MUX_UART 12
+#define CLK_TOP_MUX_SPI 13
+#define CLK_TOP_MUX_ULPOSC_SPI_CK_MUX 14
+#define CLK_TOP_MUX_USB20 15
+#define CLK_TOP_MUX_MSDC50_0_HCLK 16
+#define CLK_TOP_MUX_MSDC50_0 17
+#define CLK_TOP_MUX_MSDC30_1 18
+#define CLK_TOP_MUX_MSDC30_2 19
+#define CLK_TOP_MUX_AUDIO 20
+#define CLK_TOP_MUX_AUD_INTBUS 21
+#define CLK_TOP_MUX_PMICSPI 22
+#define CLK_TOP_MUX_SCP 23
+#define CLK_TOP_MUX_ATB 24
+#define CLK_TOP_MUX_MJC 25
+#define CLK_TOP_MUX_DPI0 26
+#define CLK_TOP_MUX_AUD_1 27
+#define CLK_TOP_MUX_AUD_2 28
+#define CLK_TOP_MUX_SSUSB_TOP_SYS 29
+#define CLK_TOP_MUX_SPM 30
+#define CLK_TOP_MUX_BSI_SPI 31
+#define CLK_TOP_MUX_AUDIO_H 32
+#define CLK_TOP_MUX_ANC_MD32 33
+#define CLK_TOP_MUX_MFG_52M 34
+#define CLK_TOP_SYSPLL_CK 35
+#define CLK_TOP_SYSPLL_D2 36
+#define CLK_TOP_SYSPLL1_D2 37
+#define CLK_TOP_SYSPLL1_D4 38
+#define CLK_TOP_SYSPLL1_D8 39
+#define CLK_TOP_SYSPLL1_D16 40
+#define CLK_TOP_SYSPLL_D3 41
+#define CLK_TOP_SYSPLL_D3_D3 42
+#define CLK_TOP_SYSPLL2_D2 43
+#define CLK_TOP_SYSPLL2_D4 44
+#define CLK_TOP_SYSPLL2_D8 45
+#define CLK_TOP_SYSPLL_D5 46
+#define CLK_TOP_SYSPLL3_D2 47
+#define CLK_TOP_SYSPLL3_D4 48
+#define CLK_TOP_SYSPLL_D7 49
+#define CLK_TOP_SYSPLL4_D2 50
+#define CLK_TOP_SYSPLL4_D4 51
+#define CLK_TOP_UNIVPLL_CK 52
+#define CLK_TOP_UNIVPLL_D7 53
+#define CLK_TOP_UNIVPLL_D26 54
+#define CLK_TOP_SSUSB_PHY_48M_CK 55
+#define CLK_TOP_USB_PHY48M_CK 56
+#define CLK_TOP_UNIVPLL_D2 57
+#define CLK_TOP_UNIVPLL1_D2 58
+#define CLK_TOP_UNIVPLL1_D4 59
+#define CLK_TOP_UNIVPLL1_D8 60
+#define CLK_TOP_UNIVPLL_D3 61
+#define CLK_TOP_UNIVPLL2_D2 62
+#define CLK_TOP_UNIVPLL2_D4 63
+#define CLK_TOP_UNIVPLL2_D8 64
+#define CLK_TOP_UNIVPLL_D5 65
+#define CLK_TOP_UNIVPLL3_D2 66
+#define CLK_TOP_UNIVPLL3_D4 67
+#define CLK_TOP_UNIVPLL3_D8 68
+#define CLK_TOP_ULPOSC_CK_ORG 69
+#define CLK_TOP_ULPOSC_CK 70
+#define CLK_TOP_ULPOSC_D2 71
+#define CLK_TOP_ULPOSC_D3 72
+#define CLK_TOP_ULPOSC_D4 73
+#define CLK_TOP_ULPOSC_D8 74
+#define CLK_TOP_ULPOSC_D10 75
+#define CLK_TOP_APLL1_CK 76
+#define CLK_TOP_APLL2_CK 77
+#define CLK_TOP_MFGPLL_CK 78
+#define CLK_TOP_MFGPLL_D2 79
+#define CLK_TOP_IMGPLL_CK 80
+#define CLK_TOP_IMGPLL_D2 81
+#define CLK_TOP_IMGPLL_D4 82
+#define CLK_TOP_CODECPLL_CK 83
+#define CLK_TOP_CODECPLL_D2 84
+#define CLK_TOP_VDECPLL_CK 85
+#define CLK_TOP_TVDPLL_CK 86
+#define CLK_TOP_TVDPLL_D2 87
+#define CLK_TOP_TVDPLL_D4 88
+#define CLK_TOP_TVDPLL_D8 89
+#define CLK_TOP_TVDPLL_D16 90
+#define CLK_TOP_MSDCPLL_CK 91
+#define CLK_TOP_MSDCPLL_D2 92
+#define CLK_TOP_MSDCPLL_D4 93
+#define CLK_TOP_MSDCPLL_D8 94
+#define CLK_TOP_NR 95
+
+/* APMIXED_SYS */
+#define CLK_APMIXED_MAINPLL 1
+#define CLK_APMIXED_UNIVPLL 2
+#define CLK_APMIXED_MFGPLL 3
+#define CLK_APMIXED_MSDCPLL 4
+#define CLK_APMIXED_IMGPLL 5
+#define CLK_APMIXED_TVDPLL 6
+#define CLK_APMIXED_CODECPLL 7
+#define CLK_APMIXED_VDECPLL 8
+#define CLK_APMIXED_APLL1 9
+#define CLK_APMIXED_APLL2 10
+#define CLK_APMIXED_NR 11
+
+/* INFRA_SYS */
+#define CLK_INFRA_PMIC_TMR 1
+#define CLK_INFRA_PMIC_AP 2
+#define CLK_INFRA_PMIC_MD 3
+#define CLK_INFRA_PMIC_CONN 4
+#define CLK_INFRA_SCP 5
+#define CLK_INFRA_SEJ 6
+#define CLK_INFRA_APXGPT 7
+#define CLK_INFRA_SEJ_13M 8
+#define CLK_INFRA_ICUSB 9
+#define CLK_INFRA_GCE 10
+#define CLK_INFRA_THERM 11
+#define CLK_INFRA_I2C0 12
+#define CLK_INFRA_I2C1 13
+#define CLK_INFRA_I2C2 14
+#define CLK_INFRA_I2C3 15
+#define CLK_INFRA_PWM_HCLK 16
+#define CLK_INFRA_PWM1 17
+#define CLK_INFRA_PWM2 18
+#define CLK_INFRA_PWM3 19
+#define CLK_INFRA_PWM4 20
+#define CLK_INFRA_PWM 21
+#define CLK_INFRA_UART0 22
+#define CLK_INFRA_UART1 23
+#define CLK_INFRA_UART2 24
+#define CLK_INFRA_UART3 25
+#define CLK_INFRA_MD2MD_CCIF_0 26
+#define CLK_INFRA_MD2MD_CCIF_1 27
+#define CLK_INFRA_MD2MD_CCIF_2 28
+#define CLK_INFRA_FHCTL 29
+#define CLK_INFRA_BTIF 30
+#define CLK_INFRA_MD2MD_CCIF_3 31
+#define CLK_INFRA_SPI 32
+#define CLK_INFRA_MSDC0 33
+#define CLK_INFRA_MD2MD_CCIF_4 34
+#define CLK_INFRA_MSDC1 35
+#define CLK_INFRA_MSDC2 36
+#define CLK_INFRA_MD2MD_CCIF_5 37
+#define CLK_INFRA_GCPU 38
+#define CLK_INFRA_TRNG 39
+#define CLK_INFRA_AUXADC 40
+#define CLK_INFRA_CPUM 41
+#define CLK_INFRA_AP_C2K_CCIF_0 42
+#define CLK_INFRA_AP_C2K_CCIF_1 43
+#define CLK_INFRA_CLDMA 44
+#define CLK_INFRA_DISP_PWM 45
+#define CLK_INFRA_AP_DMA 46
+#define CLK_INFRA_DEVICE_APC 47
+#define CLK_INFRA_L2C_SRAM 48
+#define CLK_INFRA_CCIF_AP 49
+#define CLK_INFRA_AUDIO 50
+#define CLK_INFRA_CCIF_MD 51
+#define CLK_INFRA_DRAMC_F26M 52
+#define CLK_INFRA_I2C4 53
+#define CLK_INFRA_I2C_APPM 54
+#define CLK_INFRA_I2C_GPUPM 55
+#define CLK_INFRA_I2C2_IMM 56
+#define CLK_INFRA_I2C2_ARB 57
+#define CLK_INFRA_I2C3_IMM 58
+#define CLK_INFRA_I2C3_ARB 59
+#define CLK_INFRA_I2C5 60
+#define CLK_INFRA_SYS_CIRQ 61
+#define CLK_INFRA_SPI1 62
+#define CLK_INFRA_DRAMC_B_F26M 63
+#define CLK_INFRA_ANC_MD32 64
+#define CLK_INFRA_ANC_MD32_32K 65
+#define CLK_INFRA_DVFS_SPM1 66
+#define CLK_INFRA_AES_TOP0 67
+#define CLK_INFRA_AES_TOP1 68
+#define CLK_INFRA_SSUSB_BUS 69
+#define CLK_INFRA_SPI2 70
+#define CLK_INFRA_SPI3 71
+#define CLK_INFRA_SPI4 72
+#define CLK_INFRA_SPI5 73
+#define CLK_INFRA_IRTX 74
+#define CLK_INFRA_SSUSB_SYS 75
+#define CLK_INFRA_SSUSB_REF 76
+#define CLK_INFRA_AUDIO_26M 77
+#define CLK_INFRA_AUDIO_26M_PAD_TOP 78
+#define CLK_INFRA_MODEM_TEMP_SHARE 79
+#define CLK_INFRA_VAD_WRAP_SOC 80
+#define CLK_INFRA_DRAMC_CONF 81
+#define CLK_INFRA_DRAMC_B_CONF 82
+#define CLK_INFRA_MFG_VCG 83
+#define CLK_INFRA_13M 84
+#define CLK_INFRA_NR 85
+
+/* IMG_SYS */
+#define CLK_IMG_FDVT 1
+#define CLK_IMG_DPE 2
+#define CLK_IMG_DIP 3
+#define CLK_IMG_LARB6 4
+#define CLK_IMG_NR 5
+
+/* MM_SYS */
+#define CLK_MM_SMI_COMMON 1
+#define CLK_MM_SMI_LARB0 2
+#define CLK_MM_SMI_LARB5 3
+#define CLK_MM_CAM_MDP 4
+#define CLK_MM_MDP_RDMA0 5
+#define CLK_MM_MDP_RDMA1 6
+#define CLK_MM_MDP_RSZ0 7
+#define CLK_MM_MDP_RSZ1 8
+#define CLK_MM_MDP_RSZ2 9
+#define CLK_MM_MDP_TDSHP 10
+#define CLK_MM_MDP_COLOR 11
+#define CLK_MM_MDP_WDMA 12
+#define CLK_MM_MDP_WROT0 13
+#define CLK_MM_MDP_WROT1 14
+#define CLK_MM_FAKE_ENG 15
+#define CLK_MM_DISP_OVL0 16
+#define CLK_MM_DISP_OVL1 17
+#define CLK_MM_DISP_OVL0_2L 18
+#define CLK_MM_DISP_OVL1_2L 19
+#define CLK_MM_DISP_RDMA0 20
+#define CLK_MM_DISP_RDMA1 21
+#define CLK_MM_DISP_WDMA0 22
+#define CLK_MM_DISP_WDMA1 23
+#define CLK_MM_DISP_COLOR 24
+#define CLK_MM_DISP_CCORR 25
+#define CLK_MM_DISP_AAL 26
+#define CLK_MM_DISP_GAMMA 27
+#define CLK_MM_DISP_OD 28
+#define CLK_MM_DISP_DITHER 29
+#define CLK_MM_DISP_UFOE 30
+#define CLK_MM_DISP_DSC 31
+#define CLK_MM_DISP_SPLIT 32
+#define CLK_MM_DSI0_MM_CLOCK 33
+#define CLK_MM_DSI1_MM_CLOCK 34
+#define CLK_MM_DPI_MM_CLOCK 35
+#define CLK_MM_DPI_INTERFACE_CLOCK 36
+#define CLK_MM_LARB4_AXI_ASIF_MM_CLOCK 37
+#define CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK 38
+#define CLK_MM_DISP_OVL0_MOUT_CLOCK 39
+#define CLK_MM_FAKE_ENG2 40
+#define CLK_MM_DSI0_INTERFACE_CLOCK 41
+#define CLK_MM_DSI1_INTERFACE_CLOCK 42
+#define CLK_MM_NR 43
+
+/* VDEC_SYS */
+#define CLK_VDEC_CKEN_ENG 1
+#define CLK_VDEC_ACTIVE 2
+#define CLK_VDEC_CKEN 3
+#define CLK_VDEC_LARB1_CKEN 4
+#define CLK_VDEC_NR 5
+
+/* VENC_SYS */
+#define CLK_VENC_0 1
+#define CLK_VENC_1 2
+#define CLK_VENC_2 3
+#define CLK_VENC_3 4
+#define CLK_VENC_NR 5
+
+#endif /* _DT_BINDINGS_CLK_MT6797_H */
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/4] arm64: dts: mediatek: add mt6797 support
From: Mars Cheng @ 2016-09-08 10:49 UTC (permalink / raw)
To: Matthias Brugger, Rob Herring, Marc Zyngier, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, CC Hwang,
wsd_upstream-NuS5LvNUpcJWk0Htik3J/w, Mars Cheng, Loda Choui,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jades Shih, Scott Shu,
Miles Chen, linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
My Chuang, Yingjoe Chen, linux-clk-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1473331794-27542-1-git-send-email-mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
This adds basic chip support for MT6797 SoC.
Signed-off-by: Mars Cheng <mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
arch/arm64/boot/dts/mediatek/Makefile | 1 +
arch/arm64/boot/dts/mediatek/mt6797-evb.dts | 36 +++++
arch/arm64/boot/dts/mediatek/mt6797.dtsi | 193 +++++++++++++++++++++++++++
3 files changed, 230 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6797-evb.dts
create mode 100644 arch/arm64/boot/dts/mediatek/mt6797.dtsi
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 9fbfd32..015eb07 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -1,5 +1,6 @@
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
always := $(dtb-y)
diff --git a/arch/arm64/boot/dts/mediatek/mt6797-evb.dts b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts
new file mode 100644
index 0000000..7314a14
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Mars.C <mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "mt6797.dtsi"
+
+/ {
+ model = "MediaTek MT6797 Evaluation Board";
+ compatible = "mediatek,mt6797-evb", "mediatek,mt6797";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x1e800000>;
+ };
+
+ chosen {};
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
new file mode 100644
index 0000000..66f6442
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
@@ -0,0 +1,193 @@
+/* Copyright (c) 2016 MediaTek Inc.
+ * Author: Mars.C <mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "mediatek,mt6797";
+ interrupt-parent = <&sysirq>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x000>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x001>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x002>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x003>;
+ };
+
+ cpu4: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x100>;
+ };
+
+ cpu5: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x101>;
+ };
+
+ cpu6: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x102>;
+ };
+
+ cpu7: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x103>;
+ };
+
+ cpu8: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ enable-method = "psci";
+ reg = <0x200>;
+ };
+
+ cpu9: cpu@201 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ enable-method = "psci";
+ reg = <0x201>;
+ };
+ };
+
+ clk26m: oscillator@0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "clk26m";
+ };
+
+ clk32k: oscillator@1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32000>;
+ clock-output-names = "clk32k";
+ };
+
+ uart_clk: dummy26m {
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ #clock-cells = <0>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 13
+ (GIC_CPU_MASK_SIMPLE(10) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14
+ (GIC_CPU_MASK_SIMPLE(10) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11
+ (GIC_CPU_MASK_SIMPLE(10) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10
+ (GIC_CPU_MASK_SIMPLE(10) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ sysirq: intpol-controller@10200620 {
+ compatible = "mediatek,mt6797-sysirq",
+ "mediatek,mt6577-sysirq";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #intpol-bases = <2>;
+ interrupt-parent = <&gic>;
+ reg = <0 0x10220620 0 0x20>,
+ <0 0x10220690 0 0x10>;
+ };
+
+ uart0: serial@11002000 {
+ compatible = "mediatek,mt6797-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11002000 0 0x400>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart1: serial@11003000 {
+ compatible = "mediatek,mt6797-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11003000 0 0x400>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart2: serial@11004000 {
+ compatible = "mediatek,mt6797-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11004000 0 0x400>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart3: serial@11005000 {
+ compatible = "mediatek,mt6797-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11005000 0 0x400>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@19000000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ reg = <0 0x19000000 0 0x10000>, /* GICD */
+ <0 0x19200000 0 0x200000>, /* GICR */
+ <0 0x10240000 0 0x2000>; /* GICC */
+ };
+
+};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/4] irqchip: mtk-sysirq: support second intpol base
From: Mars Cheng @ 2016-09-08 10:49 UTC (permalink / raw)
To: Matthias Brugger, Rob Herring, Marc Zyngier, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA, CC Hwang, Loda Choui,
Miles Chen, Scott Shu, Jades Shih, Yingjoe Chen, My Chuang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
wsd_upstream-NuS5LvNUpcJWk0Htik3J/w, Mars Cheng
In-Reply-To: <1473331794-27542-1-git-send-email-mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Original mtk-sysirq does not support multiple intpol bases. However,
there are some mtk chips need it.
Signed-off-by: Mars Cheng <mars.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
drivers/irqchip/irq-mtk-sysirq.c | 42 +++++++++++++++++++++++++++++++-------
1 file changed, 35 insertions(+), 7 deletions(-)
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index 63ac73b..20f488a 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -24,7 +24,10 @@
struct mtk_sysirq_chip_data {
spinlock_t lock;
+ unsigned int intpol_num;
+ unsigned int intpol_num_ex;
void __iomem *intpol_base;
+ void __iomem *intpol_base_ex;
};
static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type)
@@ -32,14 +35,22 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type)
irq_hw_number_t hwirq = data->hwirq;
struct mtk_sysirq_chip_data *chip_data = data->chip_data;
u32 offset, reg_index, value;
+ void __iomem *intpol_base;
unsigned long flags;
int ret;
+ if (hwirq >= (chip_data->intpol_num)) {
+ intpol_base = chip_data->intpol_base_ex;
+ reg_index = (hwirq - chip_data->intpol_num) >> 5;
+ } else {
+ intpol_base = chip_data->intpol_base;
+ reg_index = hwirq >> 5;
+ }
+
offset = hwirq & 0x1f;
- reg_index = hwirq >> 5;
spin_lock_irqsave(&chip_data->lock, flags);
- value = readl_relaxed(chip_data->intpol_base + reg_index * 4);
+ value = readl_relaxed(intpol_base + reg_index * 4);
if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) {
if (type == IRQ_TYPE_LEVEL_LOW)
type = IRQ_TYPE_LEVEL_HIGH;
@@ -49,7 +60,7 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type)
} else {
value &= ~(1 << offset);
}
- writel(value, chip_data->intpol_base + reg_index * 4);
+ writel(value, intpol_base + reg_index * 4);
data = data->parent_data;
ret = data->chip->irq_set_type(data, type);
@@ -124,7 +135,7 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
{
struct irq_domain *domain, *domain_parent;
struct mtk_sysirq_chip_data *chip_data;
- int ret, size, intpol_num;
+ int ret, size, total_intpol_num;
struct resource res;
domain_parent = irq_find_host(parent);
@@ -142,7 +153,8 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
return -ENOMEM;
size = resource_size(&res);
- intpol_num = size * 8;
+ chip_data->intpol_num = size * 8;
+ total_intpol_num = chip_data->intpol_num;
chip_data->intpol_base = ioremap(res.start, size);
if (!chip_data->intpol_base) {
pr_err("mtk_sysirq: unable to map sysirq register\n");
@@ -150,8 +162,22 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
goto out_free;
}
- domain = irq_domain_add_hierarchy(domain_parent, 0, intpol_num, node,
- &sysirq_domain_ops, chip_data);
+ /* if we get the second base, handle it, or just go on */
+ ret = of_address_to_resource(node, 1, &res);
+ if (!ret) { /* if we get the second base, handle it */
+ size = resource_size(&res);
+ chip_data->intpol_num_ex = size * 8;
+ total_intpol_num += chip_data->intpol_num_ex;
+ chip_data->intpol_base_ex = ioremap(res.start, size);
+ if (!chip_data->intpol_base_ex) {
+ pr_err("mtk_sysirq: unable to map sysirq register\n");
+ ret = -ENXIO;
+ goto out_free_ex;
+ }
+ }
+
+ domain = irq_domain_add_hierarchy(domain_parent, 0, total_intpol_num,
+ node, &sysirq_domain_ops, chip_data);
if (!domain) {
ret = -ENOMEM;
goto out_unmap;
@@ -161,6 +187,8 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
return 0;
out_unmap:
+ iounmap(chip_data->intpol_base_ex);
+out_free_ex:
iounmap(chip_data->intpol_base);
out_free:
kfree(chip_data);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/4] Document: DT: Add bindings for mediatek MT6797 SoC Platform
From: Mars Cheng @ 2016-09-08 10:49 UTC (permalink / raw)
To: Matthias Brugger, Rob Herring, Marc Zyngier, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: linux-clk, CC Hwang, Loda Choui, Miles Chen, Scott Shu,
Jades Shih, Yingjoe Chen, My Chuang, linux-kernel, linux-mediatek,
devicetree, wsd_upstream, Mars Cheng
In-Reply-To: <1473331794-27542-1-git-send-email-mars.cheng@mediatek.com>
This adds DT binding documentation for Mediatek MT6797.
Signed-off-by: Mars Cheng <mars.cheng@mediatek.com>
---
Documentation/devicetree/bindings/arm/mediatek.txt | 4 ++++
.../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
.../bindings/arm/mediatek/mediatek,mmsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,topckgen.txt | 1 +
.../bindings/arm/mediatek/mediatek,vdecsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,vencsys.txt | 3 ++-
.../interrupt-controller/mediatek,sysirq.txt | 4 +++-
.../devicetree/bindings/serial/mtk-uart.txt | 1 +
10 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/mediatek.txt b/Documentation/devicetree/bindings/arm/mediatek.txt
index c860b24..2d3344d 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek.txt
@@ -12,6 +12,7 @@ compatible: Must contain one of
"mediatek,mt6592"
"mediatek,mt6755"
"mediatek,mt6795"
+ "mediatek,mt6797"
"mediatek,mt7623"
"mediatek,mt8127"
"mediatek,mt8135"
@@ -38,6 +39,9 @@ Supported boards:
- Evaluation board for MT6795(Helio X10):
Required root node properties:
- compatible = "mediatek,mt6795-evb", "mediatek,mt6795";
+- Evaluation board for MT6797(Helio X20):
+ Required root node properties:
+ - compatible = "mediatek,mt6797-evb", "mediatek,mt6797";
- Evaluation board for MT7623:
Required root node properties:
- compatible = "mediatek,mt7623-evb", "mediatek,mt7623";
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
index cb0054a..cd977db 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-apmixedsys"
+ - "mediatek,mt6797-apmixedsys"
- "mediatek,mt8135-apmixedsys"
- "mediatek,mt8173-apmixedsys"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
index f6a9166..047b11a 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-imgsys", "syscon"
+ - "mediatek,mt6797-imgsys", "syscon"
- "mediatek,mt8173-imgsys", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
index 1620ec2..58d58e2 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-infracfg", "syscon"
+ - "mediatek,mt6797-infracfg", "syscon"
- "mediatek,mt8135-infracfg", "syscon"
- "mediatek,mt8173-infracfg", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
index 67dd2e4..70529e0 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-mmsys", "syscon"
+ - "mediatek,mt6797-mmsys", "syscon"
- "mediatek,mt8173-mmsys", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
index 9f2fe78..ec93ecb 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-topckgen"
+ - "mediatek,mt6797-topckgen"
- "mediatek,mt8135-topckgen"
- "mediatek,mt8173-topckgen"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
index 2440f73..d150104 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-vdecsys", "syscon"
+ - "mediatek,mt6797-vdecsys", "syscon"
- "mediatek,mt8173-vdecsys", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
index 5bb2866..8a93be6 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
@@ -5,7 +5,8 @@ The Mediatek vencsys controller provides various clocks to the system.
Required Properties:
-- compatible: Should be:
+- compatible: Should be one of:
+ - "mediatek,mt6797-vencsys", "syscon"
- "mediatek,mt8173-vencsys", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
index 9d1d72c..3d97eb4 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
@@ -8,6 +8,7 @@ Required properties:
"mediatek,mt8173-sysirq"
"mediatek,mt8135-sysirq"
"mediatek,mt8127-sysirq"
+ "mediatek,mt6797-sysirq"
"mediatek,mt6795-sysirq"
"mediatek,mt6755-sysirq"
"mediatek,mt6592-sysirq"
@@ -21,7 +22,8 @@ Required properties:
- interrupt-parent: phandle of irq parent for sysirq. The parent must
use the same interrupt-cells format as GIC.
- reg: Physical base address of the intpol registers and length of memory
- mapped region.
+ mapped region. Could be up to 2 registers here at max. Ex: 6797 needs 2 reg,
+ others need 1.
Example:
sysirq: interrupt-controller@10200100 {
diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index 0015c72..a1dbb62 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -8,6 +8,7 @@ Required properties:
* "mediatek,mt6589-uart" for MT6589 compatible UARTS
* "mediatek,mt6755-uart" for MT6755 compatible UARTS
* "mediatek,mt6795-uart" for MT6795 compatible UARTS
+ * "mediatek,mt6797-uart" for MT6795 compatible UARTS
* "mediatek,mt7623-uart" for MT7623 compatible UARTS
* "mediatek,mt8127-uart" for MT8127 compatible UARTS
* "mediatek,mt8135-uart" for MT8135 compatible UARTS
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/4] Add MT6797 SoC basic support
From: Mars Cheng @ 2016-09-08 10:49 UTC (permalink / raw)
To: Matthias Brugger, Rob Herring, Marc Zyngier, Mark Rutland,
Michael Turquette, Stephen Boyd, Erin Lo, James Liao
Cc: linux-clk, CC Hwang, Loda Choui, Miles Chen, Scott Shu,
Jades Shih, Yingjoe Chen, My Chuang, linux-kernel, linux-mediatek,
devicetree, wsd_upstream
This patch set adds basic chip support for mediatek's first 10-core
chip, X20, also known as MT6797.
- Based on 4.8-rc1
- Based on the MT2701 patch by Erin Lo[1]
- Modify irq-mtk-sysirq to support 2 base address
[1] https://lkml.org/lkml/2016/8/22/128
Mars Cheng (4):
Document: DT: Add bindings for mediatek MT6797 SoC Platform
irqchip: mtk-sysirq: support second intpol base
arm64: dts: mediatek: add mt6797 support
clk: mediatek: Add MT6797 clock support
Documentation/devicetree/bindings/arm/mediatek.txt | 4 +
.../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
.../bindings/arm/mediatek/mediatek,mmsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,topckgen.txt | 1 +
.../bindings/arm/mediatek/mediatek,vdecsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,vencsys.txt | 3 +-
.../interrupt-controller/mediatek,sysirq.txt | 4 +-
.../devicetree/bindings/serial/mtk-uart.txt | 1 +
arch/arm64/boot/dts/mediatek/Makefile | 1 +
arch/arm64/boot/dts/mediatek/mt6797-evb.dts | 36 +
arch/arm64/boot/dts/mediatek/mt6797.dtsi | 237 +++++++
drivers/clk/mediatek/Kconfig | 36 +
drivers/clk/mediatek/Makefile | 5 +
drivers/clk/mediatek/clk-mt6797-img.c | 87 +++
drivers/clk/mediatek/clk-mt6797-mm.c | 146 ++++
drivers/clk/mediatek/clk-mt6797-vdec.c | 102 +++
drivers/clk/mediatek/clk-mt6797-venc.c | 86 +++
drivers/clk/mediatek/clk-mt6797.c | 716 ++++++++++++++++++++
drivers/irqchip/irq-mtk-sysirq.c | 42 +-
include/dt-bindings/clock/mt6797-clk.h | 281 ++++++++
22 files changed, 1784 insertions(+), 9 deletions(-)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6797-evb.dts
create mode 100644 arch/arm64/boot/dts/mediatek/mt6797.dtsi
create mode 100644 drivers/clk/mediatek/clk-mt6797-img.c
create mode 100644 drivers/clk/mediatek/clk-mt6797-mm.c
create mode 100644 drivers/clk/mediatek/clk-mt6797-vdec.c
create mode 100644 drivers/clk/mediatek/clk-mt6797-venc.c
create mode 100644 drivers/clk/mediatek/clk-mt6797.c
create mode 100644 include/dt-bindings/clock/mt6797-clk.h
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH 0/4] Add V4L2_PIX_FMT_MT21C format for MT8173 codec driver
From: Hans Verkuil @ 2016-09-08 9:27 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen
Cc: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak, Eddie Huang,
Yingjoe Chen, linux-kernel, linux-media, linux-mediatek
In-Reply-To: <1473325879.26612.2.camel@mtksdaap41>
On 09/08/16 11:11, Tiffany Lin wrote:
> Hi Hans,
>
> On Thu, 2016-09-08 at 09:21 +0200, Hans Verkuil wrote:
>> Hi Tiffany,
>>
>> On 09/07/2016 08:56 AM, Tiffany Lin wrote:
>>> This patch series add Mediatek compressed block format V4L2_PIX_FMT_MT21C, the
>>> decoder driver will decoded bitstream to V4L2_PIX_FMT_MT21C format.
>>>
>>> User space applications could use MT8173 MDP driver to convert V4L2_PIX_FMT_MT21C to
>>> V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M and V4L2_PIX_FMT_YVU420.
>>>
>>> MDP driver[1] is stand alone driver.
>>>
>>> Usage:
>>> MT21C -> MT8173 MDP -> NV12M/YUV420M/YVU420
>>> NV12M/NV21M/YUV420M/YVU420M -> mt8173 Encoder -> H264/VP8
>>> H264/VP8/VP9 -> mtk8173 Decoder -> MT21C
>>>
>>> When encode with MT21 source, the pipeline will be:
>>> MT21C -> MDP driver-> NV12M/NV21M/YUV420M/YVU420M -> Encoder -> H264/VP8
>>>
>>> When playback, the pipeline will be:
>>> H264/VP8/VP9 -> Decoder driver -> MT21C -> MDP Driver -> DRM
>>>
>>> [1]https://patchwork.kernel.org/patch/9305329/
>>>
>>> Tiffany Lin (4):
>>> v4l: add Mediatek compressed video block format
>>> docs-rst: Add compressed video formats used on MT8173 codec driver
>>> vcodec: mediatek: Add V4L2_PIX_FMT_MT21C support for v4l2 decoder
>>> arm64: dts: mediatek: Add Video Decoder for MT8173
>>>
>>> Documentation/media/uapi/v4l/pixfmt-reserved.rst | 6 +++
>>> arch/arm64/boot/dts/mediatek/mt8173.dtsi | 44 ++++++++++++++++++++
>>> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 7 +++-
>>> drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
>>> include/uapi/linux/videodev2.h | 1 +
>>> 5 files changed, 58 insertions(+), 1 deletion(-)
>>>
>>
>> So basically the video decoder is useless without support for this format and
>> without the MDP driver, right?
>>
> Yes. It also require new vpu firmware.
> Andrew will help release new vpu firmware include encode/decode/mdp
> capability.
OK, then I'll park this until:
- the MT21C patch series is OK
- the MDP patch series is OK
- the new firmware is released
For the record: the decoder patch series is OK as far as I am concerned.
It's in my mtkdec branch.
Regards,
Hans
^ permalink raw reply
* Re: [PATCH 0/4] Add V4L2_PIX_FMT_MT21C format for MT8173 codec driver
From: Tiffany Lin @ 2016-09-08 9:11 UTC (permalink / raw)
To: Hans Verkuil, Andrew-CT Chen
Cc: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak, Eddie Huang,
Yingjoe Chen, linux-kernel, linux-media, linux-mediatek
In-Reply-To: <e4d91e67-0b36-3675-575a-c5f38a68dbdb@xs4all.nl>
Hi Hans,
On Thu, 2016-09-08 at 09:21 +0200, Hans Verkuil wrote:
> Hi Tiffany,
>
> On 09/07/2016 08:56 AM, Tiffany Lin wrote:
> > This patch series add Mediatek compressed block format V4L2_PIX_FMT_MT21C, the
> > decoder driver will decoded bitstream to V4L2_PIX_FMT_MT21C format.
> >
> > User space applications could use MT8173 MDP driver to convert V4L2_PIX_FMT_MT21C to
> > V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M and V4L2_PIX_FMT_YVU420.
> >
> > MDP driver[1] is stand alone driver.
> >
> > Usage:
> > MT21C -> MT8173 MDP -> NV12M/YUV420M/YVU420
> > NV12M/NV21M/YUV420M/YVU420M -> mt8173 Encoder -> H264/VP8
> > H264/VP8/VP9 -> mtk8173 Decoder -> MT21C
> >
> > When encode with MT21 source, the pipeline will be:
> > MT21C -> MDP driver-> NV12M/NV21M/YUV420M/YVU420M -> Encoder -> H264/VP8
> >
> > When playback, the pipeline will be:
> > H264/VP8/VP9 -> Decoder driver -> MT21C -> MDP Driver -> DRM
> >
> > [1]https://patchwork.kernel.org/patch/9305329/
> >
> > Tiffany Lin (4):
> > v4l: add Mediatek compressed video block format
> > docs-rst: Add compressed video formats used on MT8173 codec driver
> > vcodec: mediatek: Add V4L2_PIX_FMT_MT21C support for v4l2 decoder
> > arm64: dts: mediatek: Add Video Decoder for MT8173
> >
> > Documentation/media/uapi/v4l/pixfmt-reserved.rst | 6 +++
> > arch/arm64/boot/dts/mediatek/mt8173.dtsi | 44 ++++++++++++++++++++
> > drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 7 +++-
> > drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
> > include/uapi/linux/videodev2.h | 1 +
> > 5 files changed, 58 insertions(+), 1 deletion(-)
> >
>
> So basically the video decoder is useless without support for this format and
> without the MDP driver, right?
>
Yes. It also require new vpu firmware.
Andrew will help release new vpu firmware include encode/decode/mdp
capability.
best regards,
Tiffany
> I'm wondering if I should hold off on merging the decoder driver until these two
> are in. What is the timeline for v6 of the MDP driver?
>
> If a v6 is posted early next week, then I have time to review and (assuming it is
> OK) I can make a pull request for both this driver and the MDP driver.
>
> If it takes longer, then there is a good chance that it will slip to 4.10. I will
> have very little time in the period September 20 - October 14.
>
> Regards,
>
> Hans
^ permalink raw reply
* Re: [PATCH 0/4] Add V4L2_PIX_FMT_MT21C format for MT8173 codec driver
From: Hans Verkuil @ 2016-09-08 7:21 UTC (permalink / raw)
To: Tiffany Lin, Hans Verkuil, Laurent Pinchart,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak
Cc: Eddie Huang, Yingjoe Chen, linux-kernel, linux-media,
linux-mediatek
In-Reply-To: <1473231403-14900-1-git-send-email-tiffany.lin@mediatek.com>
Hi Tiffany,
On 09/07/2016 08:56 AM, Tiffany Lin wrote:
> This patch series add Mediatek compressed block format V4L2_PIX_FMT_MT21C, the
> decoder driver will decoded bitstream to V4L2_PIX_FMT_MT21C format.
>
> User space applications could use MT8173 MDP driver to convert V4L2_PIX_FMT_MT21C to
> V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M and V4L2_PIX_FMT_YVU420.
>
> MDP driver[1] is stand alone driver.
>
> Usage:
> MT21C -> MT8173 MDP -> NV12M/YUV420M/YVU420
> NV12M/NV21M/YUV420M/YVU420M -> mt8173 Encoder -> H264/VP8
> H264/VP8/VP9 -> mtk8173 Decoder -> MT21C
>
> When encode with MT21 source, the pipeline will be:
> MT21C -> MDP driver-> NV12M/NV21M/YUV420M/YVU420M -> Encoder -> H264/VP8
>
> When playback, the pipeline will be:
> H264/VP8/VP9 -> Decoder driver -> MT21C -> MDP Driver -> DRM
>
> [1]https://patchwork.kernel.org/patch/9305329/
>
> Tiffany Lin (4):
> v4l: add Mediatek compressed video block format
> docs-rst: Add compressed video formats used on MT8173 codec driver
> vcodec: mediatek: Add V4L2_PIX_FMT_MT21C support for v4l2 decoder
> arm64: dts: mediatek: Add Video Decoder for MT8173
>
> Documentation/media/uapi/v4l/pixfmt-reserved.rst | 6 +++
> arch/arm64/boot/dts/mediatek/mt8173.dtsi | 44 ++++++++++++++++++++
> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 7 +++-
> drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
> include/uapi/linux/videodev2.h | 1 +
> 5 files changed, 58 insertions(+), 1 deletion(-)
>
So basically the video decoder is useless without support for this format and
without the MDP driver, right?
I'm wondering if I should hold off on merging the decoder driver until these two
are in. What is the timeline for v6 of the MDP driver?
If a v6 is posted early next week, then I have time to review and (assuming it is
OK) I can make a pull request for both this driver and the MDP driver.
If it takes longer, then there is a good chance that it will slip to 4.10. I will
have very little time in the period September 20 - October 14.
Regards,
Hans
^ permalink raw reply
* Re: [PATCH v5 0/5] Add MT8173 MDP Driver
From: Hans Verkuil @ 2016-09-08 6:49 UTC (permalink / raw)
To: Minghsiu Tsai, Hans Verkuil, daniel.thompson, Rob Herring,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak
Cc: srv_heupstream, Eddie Huang, Yingjoe Chen, devicetree,
linux-kernel, linux-arm-kernel, linux-media, linux-mediatek
In-Reply-To: <1472559944-55114-1-git-send-email-minghsiu.tsai@mediatek.com>
FYI: I'm missing a MAINTAINERS entry for this driver.
Please add one when you post v6.
Thanks!
Hans
On 08/30/2016 02:25 PM, Minghsiu Tsai wrote:
> Changes in v5:
> - Add ack in the comment of dts patch
> - Fix s/g_selection()
> - Separate format V4L2_PIX_FMT_MT21C into new patch
>
> Changes in v4:
> - Add "depends on HAS_DMA" in Kconfig.
> - Fix s/g_selection()
> - Replace struct v4l2_crop with u32 and struct v4l2_rect
> - Remove VB2_USERPTR
> - Move mutex lock after ctx allocation in mtk_mdp_m2m_open()
> - Add new format V4L2_PIX_FMT_YVU420 to support software on Android platform.
> - Only width/height of image in format V4L2_PIX_FMT_MT21 is aligned to 16/16,
> other ones are aligned to 2/2 by default
>
> Changes in v3:
> - Modify device ndoe as structured one.
> - Fix conflict in dts on Linux 4.8-rc1
>
> Changes in v2:
> - Add section to describe blocks function in dts-bindings
> - Remove the assignment of device_caps in querycap()
> - Remove format's name assignment
> - Copy colorspace-related parameters from OUTPUT to CAPTURE
> - Use m2m helper functions
> - Fix DMA allocation failure
> - Initialize lazily vpu instance in streamon()
>
> ==============
> Introduction
> ==============
>
> The purpose of this series is to add the driver for Media Data Path HW embedded in the Mediatek's MT8173 SoC.
> MDP is used for scaling and color space conversion.
>
> It could convert V4L2_PIX_FMT_MT21 to V4L2_PIX_FMT_NV12M or V4L2_PIX_FMT_YUV420M.
>
> NV12M/YUV420M/MT21 -> MDP -> NV12M/YUV420M
>
> This patch series rely on MTK VPU driver in patch series "Add MT8173 Video Encoder Driver and VPU Driver"[1] and "Add MT8173 Video Decoder Driver"[2].
> MDP driver rely on VPU driver to load, communicate with VPU.
>
> Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
>
> [1]https://patchwork.kernel.org/patch/9002171/
> [2]https://patchwork.kernel.org/patch/9141245/
>
> ==================
> Device interface
> ==================
>
> In principle the driver bases on v4l2 memory-to-memory framework:
> it provides a single video node and each opened file handle gets its own private context with separate buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers) and CAPTURE (for destination buffers).
> OUTPUT and CAPTURE buffer could be MMAP or DMABUF memory type.
>
> v4l2-compliance test output:
> # v4l2-compliance -d /dev/image-proc0
> v4l2-compliance SHA : a737a6161485fffb70bf51e4fd7f6e2d910174c1
>
> Driver Info:
> Driver name : mtk-mdp
> Card type : soc:mdp
> Bus info : platform:mt8173
> Driver version: 4.8.0
> Capabilities : 0x84204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps : 0x04204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
>
> Compliance test for device /dev/image-proc0 (not using libv4l2):
>
> Required ioctls:
> test VIDIOC_QUERYCAP: OK
>
> Allow for multiple opens:
> test second video open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
>
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
>
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 0 Audio Inputs: 0 Tuners: 0
>
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
>
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test VIDIOC_G/S_EDID: OK (Not Supported)
>
> Control ioctls:
> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
> test VIDIOC_QUERYCTRL: OK
> test VIDIOC_G/S_CTRL: OK
> test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 5 Private Controls: 0
>
> Format ioctls:
> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> test VIDIOC_G/S_PARM: OK (Not Supported)
> test VIDIOC_G_FBUF: OK (Not Supported)
> test VIDIOC_G_FMT: OK
> test VIDIOC_TRY_FMT: OK
> test VIDIOC_S_FMT: OK
> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> test Cropping: OK
> test Composing: OK
> test Scaling: OK
>
> Codec ioctls:
> test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>
> Buffer ioctls:
> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> test VIDIOC_EXPBUF: OK
>
> Test input 0:
>
>
> Total: 43, Succeeded: 43, Failed: 0, Warnings: 0
>
>
> Minghsiu Tsai (5):
> VPU: mediatek: Add mdp support
> dt-bindings: Add a binding for Mediatek MDP
> media: Add Mediatek MDP Driver
> arm64: dts: mediatek: Add MDP for MT8173
> media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C
>
> .../devicetree/bindings/media/mediatek-mdp.txt | 109 ++
> arch/arm64/boot/dts/mediatek/mt8173.dtsi | 84 ++
> drivers/media/platform/Kconfig | 17 +
> drivers/media/platform/Makefile | 2 +
> drivers/media/platform/mtk-mdp/Makefile | 9 +
> drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 159 +++
> drivers/media/platform/mtk-mdp/mtk_mdp_comp.h | 72 ++
> drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 294 +++++
> drivers/media/platform/mtk-mdp/mtk_mdp_core.h | 260 ++++
> drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h | 126 ++
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 1278 ++++++++++++++++++++
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h | 22 +
> drivers/media/platform/mtk-mdp/mtk_mdp_regs.c | 156 +++
> drivers/media/platform/mtk-mdp/mtk_mdp_regs.h | 31 +
> drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c | 145 +++
> drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h | 41 +
> drivers/media/platform/mtk-vpu/mtk_vpu.h | 5 +
> 17 files changed, 2810 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/mediatek-mdp.txt
> create mode 100644 drivers/media/platform/mtk-mdp/Makefile
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
>
^ permalink raw reply
* Re: [PATCH 2/4] docs-rst: Add compressed video formats used on MT8173 codec driver
From: Tiffany Lin @ 2016-09-08 6:44 UTC (permalink / raw)
To: Hans Verkuil
Cc: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab,
Matthias Brugger, Daniel Kurtz, Pawel Osciak, Eddie Huang,
Yingjoe Chen, linux-kernel, linux-media, linux-mediatek
In-Reply-To: <246f1aca-0b46-b2f1-edd0-158a2a07b1d9@xs4all.nl>
Hi Hans,
On Wed, 2016-09-07 at 11:23 +0200, Hans Verkuil wrote:
> On 09/07/16 08:56, Tiffany Lin wrote:
> > Add V4L2_PIX_FMT_MT21C documentation
> >
> > Signed-off-by: Tiffany Lin <tiffany.lin@mediatek.com>
> > ---
> > Documentation/media/uapi/v4l/pixfmt-reserved.rst | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/Documentation/media/uapi/v4l/pixfmt-reserved.rst b/Documentation/media/uapi/v4l/pixfmt-reserved.rst
> > index 0dd2f7f..2e21fbc 100644
> > --- a/Documentation/media/uapi/v4l/pixfmt-reserved.rst
> > +++ b/Documentation/media/uapi/v4l/pixfmt-reserved.rst
> > @@ -339,7 +339,13 @@ please make a proposal on the linux-media mailing list.
> > array. Anything what's in between the UYVY lines is JPEG data and
> > should be concatenated to form the JPEG stream.
> >
> > + - .. _V4L2-PIX-FMT-MT21C:
> >
> > + - ``V4L2_PIX_FMT_MT21C``
> > +
> > + - 'MT21C'
> > +
> > + - Compressed two-planar YVU420 format used by Mediatek MT8173.
>
> This really needs to be expanded.
>
> Ideally this should reference the precise specification of this format if
> available.
>
> It certainly should explain which HW blocks of the mediatek SoC use this
> format, it should explain that is it meant as an opaque intermediate format
> between those blocks.
>
Yes. it is an opaque intermediate format.
VDEC HW only output MT21C format, and it need MDP HW to convert to other
standard format.
At first, we plan to put "convert MT21C to other standard format" in our
v4l2 decoder driver, actually in VPU firmware.
In this case, there is no need to expose MT21C format to user space.
But consider that MDP is a stand alone HW (interrupt, power, clk),
combine decode and format convert in one decode step impact performance.
VDEC HW and MDP HW could process different frame at same time.
MDP may also used by other modules to do format convert, not only VDEC.
That's why we need to expose MT21C to user space.
When user space application enumerate VDEC and display HW and found that
the format is not match.
It need to use MDP driver to do format convert.
> If you have some characteristics (i.e. is it lossy or lossless
> compression, I
> presume it's lossless), then that will be useful to add as well.
>
I will update this in next version.
best regards,
Tiffany
> We like to have as much information about formats as possible.
>
> Regards,
>
> Hans
>
> >
> > .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
> >
> >
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox