Skip to content

Commit

Permalink
Add linux patches for V4L2 M2M driver
Browse files Browse the repository at this point in the history
  • Loading branch information
superna9999 committed Apr 3, 2018
1 parent f7311d1 commit b3b60c3
Show file tree
Hide file tree
Showing 20 changed files with 8,662 additions and 115 deletions.
@@ -0,0 +1,136 @@
From f7c84635cccaeeefae003012611f26d6a85f342e Mon Sep 17 00:00:00 2001
From: Maxime Jourdan <raptorteak@gmail.com>
Date: Thu, 15 Mar 2018 13:32:33 +0100
Subject: [PATCH] clock: meson8b: add clocks necessary for VDEC1

---
drivers/clk/meson/meson8b.c | 55 ++++++++++++++++++++++++++++++++
drivers/clk/meson/meson8b.h | 6 +++-
include/dt-bindings/clock/meson8b-clkc.h | 3 ++
3 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 3ffea80..d323749 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -418,6 +418,55 @@ struct clk_gate meson8b_clk81 = {
},
};

+/* VDEC clocks */
+
+static u32 mux_table_vdec[] = {0, 1, 2, 3};
+static const char * const meson8b_vdec_parent_names[] = {
+ "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+};
+
+static struct clk_mux meson8b_vdec_1_sel = {
+ .reg = (void *)HHI_VDEC_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 9,
+ .lock = &meson_clk_lock,
+ .table = mux_table_vdec,
+ .hw.init = &(struct clk_init_data){
+ .name = "vdec_1_sel",
+ .ops = &clk_mux_ops,
+ .parent_names = meson8b_vdec_parent_names,
+ .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+ .flags = CLK_SET_RATE_NO_REPARENT,
+ },
+};
+
+static struct clk_divider meson8b_vdec_1_div = {
+ .reg = (void *)HHI_VDEC_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ .lock = &meson_clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "vdec_1_div",
+ .ops = &clk_divider_ops,
+ .parent_names = (const char *[]){ "vdec_1_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_gate meson8b_vdec_1 = {
+ .reg = (void *)HHI_VDEC_CLK_CNTL,
+ .bit_idx = 8,
+ .lock = &meson_clk_lock,
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdec_1",
+ .ops = &clk_gate_ops,
+ .parent_names = (const char *[]){ "vdec_1_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ },
+};
+
/* Everything Else (EE) domain gates */

static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
@@ -599,6 +648,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_MPLL0] = &meson8b_mpll0.hw,
[CLKID_MPLL1] = &meson8b_mpll1.hw,
[CLKID_MPLL2] = &meson8b_mpll2.hw,
+ [CLKID_VDEC_1_SEL] = &meson8b_vdec_1_sel.hw,
+ [CLKID_VDEC_1_DIV] = &meson8b_vdec_1_div.hw,
+ [CLKID_VDEC_1] = &meson8b_vdec_1.hw,
[CLK_NR_CLKS] = NULL,
},
.num = CLK_NR_CLKS,
@@ -695,14 +747,17 @@ static struct clk_gate *const meson8b_clk_gates[] = {
&meson8b_ao_ahb_sram,
&meson8b_ao_ahb_bus,
&meson8b_ao_iface,
+ &meson8b_vdec_1,
};

static struct clk_mux *const meson8b_clk_muxes[] = {
&meson8b_mpeg_clk_sel,
+ &meson8b_vdec_1_sel,
};

static struct clk_divider *const meson8b_clk_dividers[] = {
&meson8b_mpeg_clk_div,
+ &meson8b_vdec_1_div,
};

static const struct meson8b_clk_reset_line {
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 2eaf8a5..aa5f97f 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -40,6 +40,10 @@
#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
#define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */
#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */
+#define HHI_VDEC_CLK_CNTL 0x1e0
+#define HHI_VDEC2_CLK_CNTL 0x1e4
+#define HHI_VDEC3_CLK_CNTL 0x1e8
+#define HHI_VDEC4_CLK_CNTL 0x1ec
#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */
#define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
@@ -69,7 +73,7 @@
* will remain defined here.
*/

-#define CLK_NR_CLKS 96
+#define CLK_NR_CLKS 99

/*
* include the CLKID and RESETID that have
diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h
index dea9d46..49bcf5f 100644
--- a/include/dt-bindings/clock/meson8b-clkc.h
+++ b/include/dt-bindings/clock/meson8b-clkc.h
@@ -102,5 +102,8 @@
#define CLKID_MPLL0 93
#define CLKID_MPLL1 94
#define CLKID_MPLL2 95
+#define CLKID_VDEC_1_SEL 96
+#define CLKID_VDEC_1_DIV 97
+#define CLKID_VDEC_1 98

#endif /* __MESON8B_CLKC_H */
@@ -0,0 +1,170 @@
From f013a1deeac856e9b46f27b66463d6f978039789 Mon Sep 17 00:00:00 2001
From: Maxime Jourdan <raptorteak@gmail.com>
Date: Thu, 15 Mar 2018 13:39:41 +0100
Subject: [PATCH] soc: meson: add power controller for vdec

---
drivers/soc/amlogic/Makefile | 1 +
drivers/soc/amlogic/meson-pwrc-vdec.c | 144 ++++++++++++++++++++++++++++++++++
2 files changed, 145 insertions(+)
create mode 100644 drivers/soc/amlogic/meson-pwrc-vdec.c

diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
index 8fa3218..ffb388d 100644
--- a/drivers/soc/amlogic/Makefile
+++ b/drivers/soc/amlogic/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
+obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-pwrc-vdec.o
obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
diff --git a/drivers/soc/amlogic/meson-pwrc-vdec.c b/drivers/soc/amlogic/meson-pwrc-vdec.c
new file mode 100644
index 0000000..fac704c
--- /dev/null
+++ b/drivers/soc/amlogic/meson-pwrc-vdec.c
@@ -0,0 +1,144 @@
+/*
+ * Author: Maxime Jourdan <maxi.jourdan@wanadoo.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+/* AO Offsets */
+#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2)
+
+#define GEN_PWR_VDEC_1 (BIT(3) | BIT(2))
+
+struct meson_pwrc_vdec {
+ struct generic_pm_domain genpd;
+ struct regmap *regmap_ao;
+ struct clk *dos_parser_clk;
+ struct clk *vpu_intr_clk;
+ struct clk *vdec_1_clk;
+};
+
+static inline
+struct meson_pwrc_vdec *genpd_to_pd(struct generic_pm_domain *d)
+{
+ return container_of(d, struct meson_pwrc_vdec, genpd);
+}
+
+static int meson_pwrc_vdec_power_off(struct generic_pm_domain *genpd)
+{
+ struct meson_pwrc_vdec *pd = genpd_to_pd(genpd);
+
+ regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+ GEN_PWR_VDEC_1, GEN_PWR_VDEC_1);
+ udelay(20);
+
+ clk_disable_unprepare(pd->vpu_intr_clk);
+ clk_disable_unprepare(pd->dos_parser_clk);
+ clk_disable_unprepare(pd->vdec_1_clk);
+
+ return 0;
+}
+
+static int meson_pwrc_vdec_setup_clk(struct meson_pwrc_vdec *pd) {
+ clk_prepare_enable(pd->dos_parser_clk);
+ clk_prepare_enable(pd->vpu_intr_clk);
+ clk_prepare_enable(pd->vdec_1_clk);
+
+ return 0;
+}
+
+static int meson_pwrc_vdec_power_on(struct generic_pm_domain *genpd)
+{
+ struct meson_pwrc_vdec *pd = genpd_to_pd(genpd);
+
+ meson_pwrc_vdec_setup_clk(pd);
+ regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, GEN_PWR_VDEC_1, 0);
+ udelay(10);
+
+ return 0;
+}
+
+static bool meson_pwrc_vdec_get_power(struct meson_pwrc_vdec *pd)
+{
+ u32 reg;
+
+ regmap_read(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, &reg);
+
+ return ((reg & GEN_PWR_VDEC_1) == GEN_PWR_VDEC_1);
+}
+
+static struct meson_pwrc_vdec vdec_pd = {
+ .genpd = {
+ .name = "vdec",
+ .power_off = meson_pwrc_vdec_power_off,
+ .power_on = meson_pwrc_vdec_power_on,
+ },
+};
+
+static int meson_pwrc_vdec_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap_ao;
+ bool powered_off;
+ int ret;
+
+ regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
+ if (IS_ERR(regmap_ao)) {
+ dev_err(&pdev->dev, "failed to get AO regmap\n");
+ return PTR_ERR(regmap_ao);
+ }
+
+ vdec_pd.vpu_intr_clk = devm_clk_get(&pdev->dev, "vpu_intr");
+ vdec_pd.dos_parser_clk = devm_clk_get(&pdev->dev, "dos_parser");
+ vdec_pd.vdec_1_clk = devm_clk_get(&pdev->dev, "vdec_1");
+ vdec_pd.regmap_ao = regmap_ao;
+
+ powered_off = meson_pwrc_vdec_get_power(&vdec_pd);
+
+ pm_genpd_init(&vdec_pd.genpd, &pm_domain_always_on_gov,
+ powered_off);
+
+ /* If already powered, sync the clock states */
+ if (!powered_off) {
+ ret = meson_pwrc_vdec_setup_clk(&vdec_pd);
+ if (ret)
+ return ret;
+ } else {
+ meson_pwrc_vdec_power_on(&vdec_pd.genpd);
+ }
+
+ return of_genpd_add_provider_simple(pdev->dev.of_node,
+ &vdec_pd.genpd);
+}
+
+static void meson_pwrc_vdec_shutdown(struct platform_device *pdev)
+{
+ bool powered_off;
+
+ powered_off = meson_pwrc_vdec_get_power(&vdec_pd);
+ if (!powered_off)
+ meson_pwrc_vdec_power_off(&vdec_pd.genpd);
+}
+
+static const struct of_device_id meson_pwrc_vdec_match_table[] = {
+ { .compatible = "amlogic,meson-pwrc-vdec" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver meson_pwrc_vdec_driver = {
+ .probe = meson_pwrc_vdec_probe,
+ .shutdown = meson_pwrc_vdec_shutdown,
+ .driver = {
+ .name = "meson_pwrc_vdec",
+ .of_match_table = meson_pwrc_vdec_match_table,
+ },
+};
+builtin_platform_driver(meson_pwrc_vdec_driver);

0 comments on commit b3b60c3

Please sign in to comment.