From 231a12fb9c740f0fee8e36cc1691399ae3ad7d30 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 29 Dec 2017 22:11:10 +0800 Subject: [PATCH] vpu: add vpu support for g12a PD#156734: vpu: add vpu support for g12a Change-Id: I65f559e34408a6c2ecf2ff8b34a3fe1f9d1e440a Signed-off-by: Evoke Zhang --- arch/arm64/boot/dts/amlogic/axg_pxp.dts | 2 +- arch/arm64/boot/dts/amlogic/axg_s400.dts | 2 +- arch/arm64/boot/dts/amlogic/axg_s400_v03.dts | 2 +- arch/arm64/boot/dts/amlogic/axg_s400emmc.dts | 2 +- .../boot/dts/amlogic/axg_s400emmc_v03.dts | 2 +- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 19 ++ arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 2 +- drivers/amlogic/media/common/vpu/vpu.c | 266 ++++++++++++++---- drivers/amlogic/media/common/vpu/vpu.h | 14 + drivers/amlogic/media/common/vpu/vpu_ctrl.h | 31 +- drivers/amlogic/media/common/vpu/vpu_module.h | 3 - 13 files changed, 271 insertions(+), 78 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/axg_pxp.dts b/arch/arm64/boot/dts/amlogic/axg_pxp.dts index f7427fc24b65..0404a81b4c2b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/axg_pxp.dts @@ -208,7 +208,7 @@ &clkc CLKID_VPU_P1_MUX &clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "vpu_clk0", "vpu_clk1", "vpu_clk"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 881451e1a1de..a089f5040074 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -430,7 +430,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "vpu_clk0", "vpu_clk1", "vpu_clk"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts index 4f50553f0b70..8e223ab2d3f9 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts @@ -430,7 +430,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "vpu_clk0", "vpu_clk1", "vpu_clk"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts index 2787d41f7ffc..6bbd8569add7 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts @@ -426,7 +426,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "vpu_clk0", "vpu_clk1", "vpu_clk"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts index 5811c3280e03..b46dff01fe06 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts @@ -426,7 +426,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "vpu_clk0", "vpu_clk1", "vpu_clk"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 3bab27fda8e9..499be99c18d8 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -199,6 +199,25 @@ cpuinfo_cmd = <0x82000044>; }; + vpu { + compatible = "amlogic, vpu-g12a"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + pinctrl_aobus: pinctrl@ff800014{ compatible = "amlogic,meson-g12a-aobus-pinctrl"; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index d1ccd22e1e6b..5751bfa9f0dd 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -287,7 +287,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "gp_pll", "vpu_clk0", "vpu_clk1", diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index cedbded68e3e..16c7259cccbf 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -370,7 +370,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "gp_pll", "vpu_clk0", "vpu_clk1", diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 26c67a8ee99a..38d9e0871bd3 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -286,7 +286,7 @@ <&clkc CLKID_VPU_P1_COMP>, <&clkc CLKID_VPU_MUX>; clock-names = "vapb_clk", - "vpu_intr", + "vpu_intr_gate", "gp_pll", "vpu_clk0", "vpu_clk1", diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index b11576e3c8e4..e37a04300d63 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -36,7 +36,8 @@ /* v01: initial version */ /* v02: add axg support */ /* v03: add txlx support */ -#define VPU_VERION "v03" +/* v04: add g12a support */ +#define VPU_VERION "v04" int vpu_debug_print_flag; static spinlock_t vpu_mem_lock; @@ -93,7 +94,7 @@ static unsigned int get_vpu_clk_level(unsigned int video_clk) int i; for (i = 0; i < vpu_conf.data->clk_level_max; i++) { - if (video_clk <= vpu_clk_table[i][0]) + if (video_clk <= vpu_clk_table[i].freq) break; } clk_level = i; @@ -101,46 +102,93 @@ static unsigned int get_vpu_clk_level(unsigned int video_clk) return clk_level; } -unsigned int get_vpu_clk(void) +static unsigned int get_fclk_div_freq(unsigned int mux_id) { - unsigned long clk_freq; - unsigned long fclk, clk_source; - unsigned long mux, div; + struct fclk_div_s *fclk_div; + unsigned int fclk, div, clk_source = 0; + unsigned int i; fclk = CLK_FPLL_FREQ * 1000000; - mux = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 9, 3); - switch (mux) { - case FCLK_DIV4: - case FCLK_DIV3: - case FCLK_DIV5: - case FCLK_DIV7: - clk_source = ((fclk * 100 / fclk_div_table[mux]) + 99) / 100; - break; - case GPLL_CLK: - clk_source = vpu_clk_table[8][0]; - break; - default: - clk_source = 0; - break; + + for (i = 0; i < FCLK_DIV_MAX; i++) { + fclk_div = vpu_conf.data->fclk_div_table + i; + if (fclk_div->fclk_id == mux_id) { + div = fclk_div->fclk_div; + clk_source = fclk / div; + break; + } + if (fclk_div->fclk_id == FCLK_DIV_MAX) + break; } - div = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 0, 7) + 1; - clk_freq = ((clk_source * 100 / div) + 99) / 100; + return clk_source; +} - return (unsigned int)clk_freq; +static unsigned int get_vpu_clk_mux_id(void) +{ + struct fclk_div_s *fclk_div; + unsigned int i, mux, mux_id; + + mux = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 9, 3); + mux_id = mux; + for (i = 0; i < FCLK_DIV_MAX; i++) { + fclk_div = vpu_conf.data->fclk_div_table + i; + if (fclk_div->fclk_mux == mux) { + mux_id = fclk_div->fclk_id; + break; + } + if (fclk_div->fclk_id == FCLK_DIV_MAX) + break; + } + + return mux_id; +} + +unsigned int get_vpu_clk(void) +{ + unsigned int clk_freq; + unsigned int clk_source, div; + unsigned int mux_id; + + if (IS_ERR_OR_NULL(vpu_conf.vpu_clk)) { + VPUERR("%s: vpu_clk\n", __func__); + mux_id = get_vpu_clk_mux_id(); + switch (mux_id) { + case FCLK_DIV4: + case FCLK_DIV3: + case FCLK_DIV5: + case FCLK_DIV7: + clk_source = get_fclk_div_freq(mux_id); + break; + case GPLL_CLK: + clk_source = vpu_clk_table[8].freq; + break; + default: + clk_source = 0; + break; + } + + div = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 0, 7) + 1; + clk_freq = clk_source / div; + + return clk_freq; + } + + clk_freq = clk_get_rate(vpu_conf.vpu_clk); + return clk_freq; } static int switch_gp_pll(int flag) { unsigned int clk; - if ((vpu_conf.gp_pll == NULL) || (IS_ERR(vpu_conf.gp_pll))) { + if (IS_ERR_OR_NULL(vpu_conf.gp_pll)) { VPUERR("%s: gp_pll\n", __func__); return -1; } if (flag) { /* enable */ - clk = vpu_clk_table[8][0]; + clk = vpu_clk_table[8].freq; clk_set_rate(vpu_conf.gp_pll, clk); clk_prepare_enable(vpu_conf.gp_pll); } else { /* disable */ @@ -152,15 +200,14 @@ static int switch_gp_pll(int flag) static int adjust_vpu_clk(unsigned int clk_level) { - unsigned int mux, clk; + unsigned int clk; int ret = 0; ret = vpu_chip_valid_check(); if (ret) return -1; - mux = vpu_clk_table[vpu_conf.clk_level][1]; - if (mux == GPLL_CLK) { + if (vpu_clk_table[vpu_conf.clk_level].mux == GPLL_CLK) { if (vpu_conf.data->gp_pll_valid == 0) { VPUERR("gp_pll is invalid\n"); return -1; @@ -173,9 +220,9 @@ static int adjust_vpu_clk(unsigned int clk_level) } } - if ((IS_ERR(vpu_conf.vpu_clk0)) || - (IS_ERR(vpu_conf.vpu_clk1)) || - (IS_ERR(vpu_conf.vpu_clk))) { + if ((IS_ERR_OR_NULL(vpu_conf.vpu_clk0)) || + (IS_ERR_OR_NULL(vpu_conf.vpu_clk1)) || + (IS_ERR_OR_NULL(vpu_conf.vpu_clk))) { VPUERR("%s: vpu_clk\n", __func__); return -1; } @@ -183,12 +230,12 @@ static int adjust_vpu_clk(unsigned int clk_level) vpu_conf.clk_level = clk_level; /* step 1: switch to 2nd vpu clk patch */ - clk = vpu_clk_table[vpu_conf.data->clk_level_dft][0]; + clk = vpu_clk_table[vpu_conf.data->clk_level_dft].freq; clk_set_rate(vpu_conf.vpu_clk1, clk); clk_set_parent(vpu_conf.vpu_clk, vpu_conf.vpu_clk1); udelay(10); /* step 2: adjust 1st vpu clk frequency */ - clk = vpu_clk_table[vpu_conf.clk_level][0]; + clk = vpu_clk_table[vpu_conf.clk_level].freq; clk_set_rate(vpu_conf.vpu_clk0, clk); udelay(20); /* step 3: switch back to 1st vpu clk patch */ @@ -196,7 +243,7 @@ static int adjust_vpu_clk(unsigned int clk_level) clk = clk_get_rate(vpu_conf.vpu_clk); VPUPR("set vpu clk: %uHz(%d), readback: %uHz(0x%x)\n", - vpu_clk_table[vpu_conf.clk_level][0], vpu_conf.clk_level, + vpu_clk_table[vpu_conf.clk_level].freq, vpu_conf.clk_level, clk, (vpu_hiu_read(HHI_VPU_CLK_CNTL))); return ret; @@ -205,7 +252,7 @@ static int adjust_vpu_clk(unsigned int clk_level) static int set_vpu_clk(unsigned int vclk) { int ret = 0; - unsigned int clk_level; + unsigned int clk_level, clk; mutex_lock(&vpu_clk_mutex); @@ -227,7 +274,9 @@ static int set_vpu_clk(unsigned int vclk) #endif } - if (get_vpu_clk() != vpu_clk_table[clk_level][0]) + clk = get_vpu_clk(); + if ((clk > (vpu_clk_table[clk_level].freq + VPU_CLK_TOLERANCE)) || + (clk < (vpu_clk_table[clk_level].freq - VPU_CLK_TOLERANCE))) ret = adjust_vpu_clk(clk_level); set_vpu_clk_limit: @@ -269,7 +318,7 @@ unsigned int get_vpu_clk_vmod(unsigned int vmod) if (vmod < VPU_MOD_MAX) { vpu_clk = vpu_conf.clk_vmod[vmod]; - vpu_clk = vpu_clk_table[vpu_clk][0]; + vpu_clk = vpu_clk_table[vpu_clk].freq; } else { vpu_clk = 0; VPUERR("invalid vmod\n"); @@ -333,7 +382,7 @@ int request_vpu_clk_vmod(unsigned int vclk, unsigned int vmod) if (vpu_debug_print_flag) { VPUPR("request vpu clk: %s %uHz\n", vpu_mod_table[vmod], - vpu_clk_table[clk_level][0]); + vpu_clk_table[clk_level].freq); dump_stack(); } @@ -601,6 +650,10 @@ void switch_vpu_clk_gate_vmod(unsigned int vmod, int flag) /* *********************************************** */ static const char *vpu_usage_str = { "Usage:\n" +" echo w > reg ; write data to vcbus reg\n" +" echo r > reg ; read vcbus reg\n" +" echo d > reg ; dump vcbus regs\n" +"\n" " echo r > mem ; read vpu memory power down status\n" " echo w > mem ; write vpu memory power down\n" " : 0=power up, 1=power down\n" @@ -640,7 +693,8 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr, switch (buf[0]) { case 'g': /* get */ - VPUPR("get current clk: %uHz\n", get_vpu_clk()); + VPUPR("get current clk: %uHz(0x%08x)\n", + get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL))); break; case 's': /* set */ tmp[0] = 4; @@ -683,12 +737,12 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr, if (ret == 1) { VPUPR("clk holdings:\n"); pr_info("%s: %uHz(%u)\n", vpu_mod_table[tmp[0]], - vpu_clk_table[vpu_conf.clk_vmod[tmp[0]]][0], + vpu_clk_table[vpu_conf.clk_vmod[tmp[0]]].freq, vpu_conf.clk_vmod[tmp[0]]); } else { n = get_vpu_clk_level_max_vmod(); VPUPR("clk max holdings: %uHz(%u)\n", - vpu_clk_table[n][0], n); + vpu_clk_table[n].freq, n); } break; default: @@ -845,7 +899,10 @@ static ssize_t vpu_debug_info(struct class *class, { unsigned int level_max, clk; ssize_t len = 0; - int i, ret; + int ret; +#ifdef CONFIG_VPU_DYNAMIC_ADJ + int i; +#endif ret = vpu_chip_valid_check(); if (ret) { @@ -853,11 +910,7 @@ static ssize_t vpu_debug_info(struct class *class, return len; } - if (IS_ERR(vpu_conf.vpu_clk)) { - VPUERR("%s: vpu_clk\n", __func__); - clk = get_vpu_clk(); - } else - clk = clk_get_rate(vpu_conf.vpu_clk); + clk = get_vpu_clk(); level_max = vpu_conf.data->clk_level_max - 1; len = sprintf(buf, "driver version: %s(%d-%s)\n", @@ -869,10 +922,10 @@ static ssize_t vpu_debug_info(struct class *class, "clk_level dft: %d(%dHz)\n" "clk_level max: %d(%dHz)\n\n", clk, - vpu_conf.clk_level, vpu_clk_table[vpu_conf.clk_level][0], + vpu_conf.clk_level, vpu_clk_table[vpu_conf.clk_level].freq, vpu_conf.data->clk_level_dft, - vpu_clk_table[vpu_conf.data->clk_level_dft][0], - level_max, vpu_clk_table[level_max][0]); + vpu_clk_table[vpu_conf.data->clk_level_dft].freq, + level_max, vpu_clk_table[level_max].freq); len += sprintf(buf+len, "mem_pd:\n" " mem_pd0: 0x%08x\n", @@ -886,6 +939,7 @@ static ssize_t vpu_debug_info(struct class *class, vpu_hiu_read(HHI_VPU_MEM_PD_REG2)); } +#ifdef CONFIG_VPU_DYNAMIC_ADJ if (vpu_conf.clk_vmod) { len += sprintf(buf+len, "\nclk_vmod:\n"); for (i = 0; i < VPU_MOD_MAX; i++) { @@ -893,17 +947,69 @@ static ssize_t vpu_debug_info(struct class *class, i, vpu_conf.clk_vmod[i]); } } +#endif len += sprintf(buf+len, "\n"); return len; } +static ssize_t vpu_debug_reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret = 0; + unsigned int reg32 = 0, data32 = 0; + int i; + + switch (buf[0]) { + case 'w': + ret = sscanf(buf, "w %x %x", ®32, &data32); + if (ret == 2) { + vpu_vcbus_write(reg32, data32); + pr_info("write vcbus[0x%04x]=0x%08x, readback 0x%08x\n", + reg32, data32, vpu_vcbus_read(reg32)); + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'r': + ret = sscanf(buf, "r %x", ®32); + if (ret == 1) { + pr_info("read vcbus[0x%04x] = 0x%08x\n", + reg32, vpu_vcbus_read(reg32)); + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'd': + ret = sscanf(buf, "d %x %d", ®32, &data32); + if (ret == 2) { + pr_info("dump vcbus regs:\n"); + for (i = 0; i < data32; i++) { + pr_info("[0x%04x] = 0x%08x\n", + (reg32 + i), vpu_vcbus_read(reg32 + i)); + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + default: + pr_info("wrong command\n"); + break; + } + + return count; +} + static struct class_attribute vpu_debug_class_attrs[] = { __ATTR(clk, 0644, vpu_debug_help, vpu_clk_debug), __ATTR(mem, 0644, vpu_debug_help, vpu_mem_debug), __ATTR(gate, 0644, vpu_debug_help, vpu_clk_gate_debug), __ATTR(test, 0644, vpu_debug_help, vpu_test_debug), __ATTR(print, 0644, vpu_debug_help, vpu_print_debug), + __ATTR(reg, 0644, vpu_debug_help, vpu_debug_reg_store), __ATTR(info, 0444, vpu_debug_info, NULL), __ATTR(help, 0444, vpu_debug_help, NULL), }; @@ -914,7 +1020,7 @@ static int creat_vpu_debug_class(void) int i; vpu_debug_class = class_create(THIS_MODULE, "vpu"); - if (IS_ERR(vpu_debug_class)) { + if (IS_ERR_OR_NULL(vpu_debug_class)) { VPUERR("create vpu_debug_class failed\n"); return -1; } @@ -944,11 +1050,16 @@ static int remove_vpu_debug_class(void) #ifdef CONFIG_PM static int vpu_suspend(struct platform_device *pdev, pm_message_t state) { + VPUPR("suspend clk: %uHz(0x%x)\n", + get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL))); return 0; } static int vpu_resume(struct platform_device *pdev) { + VPUPR("resume clk: %uHz(0x%x)\n", + get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL))); + set_vpu_clk(vpu_conf.clk_level); return 0; } #endif @@ -977,7 +1088,7 @@ static int get_vpu_config(struct platform_device *pdev) vpu_conf.clk_level = val; } VPUPR("load vpu_clk: %uHz(%u)\n", - vpu_clk_table[val][0], vpu_conf.clk_level); + vpu_clk_table[val].freq, vpu_conf.clk_level); return ret; } @@ -988,20 +1099,20 @@ static void vpu_clktree_init(struct device *dev) /* init & enable vapb_clk */ clk_vapb = devm_clk_get(dev, "vapb_clk"); - if (IS_ERR(clk_vapb)) + if (IS_ERR_OR_NULL(clk_vapb)) VPUERR("%s: vapb_clk\n", __func__); else clk_prepare_enable(clk_vapb); - clk_vpu_intr = devm_clk_get(dev, "vpu_intr"); - if (IS_ERR(clk_vpu_intr)) - VPUERR("%s: vpu_intr\n", __func__); + clk_vpu_intr = devm_clk_get(dev, "vpu_intr_gate"); + if (IS_ERR_OR_NULL(clk_vpu_intr)) + VPUERR("%s: vpu_intr_gate\n", __func__); else clk_prepare_enable(clk_vpu_intr); if (vpu_conf.data->gp_pll_valid) { vpu_conf.gp_pll = devm_clk_get(dev, "gp_pll"); - if (IS_ERR(vpu_conf.gp_pll)) + if (IS_ERR_OR_NULL(vpu_conf.gp_pll)) VPUERR("%s: gp_pll\n", __func__); } @@ -1009,9 +1120,9 @@ static void vpu_clktree_init(struct device *dev) vpu_conf.vpu_clk0 = devm_clk_get(dev, "vpu_clk0"); vpu_conf.vpu_clk1 = devm_clk_get(dev, "vpu_clk1"); vpu_conf.vpu_clk = devm_clk_get(dev, "vpu_clk"); - if ((IS_ERR(vpu_conf.vpu_clk0)) || - (IS_ERR(vpu_conf.vpu_clk1)) || - (IS_ERR(vpu_conf.vpu_clk))) { + if ((IS_ERR_OR_NULL(vpu_conf.vpu_clk0)) || + (IS_ERR_OR_NULL(vpu_conf.vpu_clk1)) || + (IS_ERR_OR_NULL(vpu_conf.vpu_clk))) { VPUERR("%s: vpu_clk\n", __func__); } else { clk_set_parent(vpu_conf.vpu_clk, vpu_conf.vpu_clk0); @@ -1026,6 +1137,8 @@ static struct vpu_data_s vpu_data_gxb = { .chip_name = "gxbb", .clk_level_dft = CLK_LEVEL_DFT_GXBB, .clk_level_max = CLK_LEVEL_MAX_GXBB, + .fclk_div_table = fclk_div_table_gxb, + .gp_pll_valid = 1, .mem_pd_reg1_valid = 1, .mem_pd_reg2_valid = 0, @@ -1043,6 +1156,8 @@ static struct vpu_data_s vpu_data_gxtvbb = { .chip_name = "gxtvbb", .clk_level_dft = CLK_LEVEL_DFT_GXTVBB, .clk_level_max = CLK_LEVEL_MAX_GXTVBB, + .fclk_div_table = fclk_div_table_gxb, + .gp_pll_valid = 1, .mem_pd_reg1_valid = 1, .mem_pd_reg2_valid = 0, @@ -1060,6 +1175,8 @@ static struct vpu_data_s vpu_data_gxl = { .chip_name = "gxl", .clk_level_dft = CLK_LEVEL_DFT_GXL, .clk_level_max = CLK_LEVEL_MAX_GXL, + .fclk_div_table = fclk_div_table_gxb, + .gp_pll_valid = 1, .mem_pd_reg1_valid = 1, .mem_pd_reg2_valid = 1, @@ -1077,6 +1194,8 @@ static struct vpu_data_s vpu_data_gxm = { .chip_name = "gxm", .clk_level_dft = CLK_LEVEL_DFT_GXM, .clk_level_max = CLK_LEVEL_MAX_GXM, + .fclk_div_table = fclk_div_table_gxb, + .gp_pll_valid = 1, .mem_pd_reg1_valid = 1, .mem_pd_reg2_valid = 1, @@ -1094,6 +1213,8 @@ static struct vpu_data_s vpu_data_txlx = { .chip_name = "txlx", .clk_level_dft = CLK_LEVEL_DFT_TXLX, .clk_level_max = CLK_LEVEL_MAX_TXLX, + .fclk_div_table = fclk_div_table_gxb, + .gp_pll_valid = 1, .mem_pd_reg1_valid = 1, .mem_pd_reg2_valid = 1, @@ -1111,6 +1232,8 @@ static struct vpu_data_s vpu_data_axg = { .chip_name = "axg", .clk_level_dft = CLK_LEVEL_DFT_AXG, .clk_level_max = CLK_LEVEL_MAX_AXG, + .fclk_div_table = fclk_div_table_gxb, + .gp_pll_valid = 0, .mem_pd_reg1_valid = 0, .mem_pd_reg2_valid = 0, @@ -1123,6 +1246,25 @@ static struct vpu_data_s vpu_data_axg = { .clk_gate_table = vpu_clk_gate_axg, }; +static struct vpu_data_s vpu_data_g12a = { + .chip_type = VPU_CHIP_G12A, + .chip_name = "g12a", + .clk_level_dft = CLK_LEVEL_DFT_G12A, + .clk_level_max = CLK_LEVEL_MAX_G12A, + .fclk_div_table = fclk_div_table_g12a, + + .gp_pll_valid = 0, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 1, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_gxl) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_gxl) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_gxl, + .clk_gate_table = vpu_clk_gate_gxl, +}; + static const struct of_device_id vpu_of_table[] = { { .compatible = "amlogic, vpu-gxbb", @@ -1148,6 +1290,10 @@ static const struct of_device_id vpu_of_table[] = { .compatible = "amlogic, vpu-axg", .data = &vpu_data_axg, }, + { + .compatible = "amlogic, vpu-g12a", + .data = &vpu_data_g12a, + }, {}, }; diff --git a/drivers/amlogic/media/common/vpu/vpu.h b/drivers/amlogic/media/common/vpu/vpu.h index 7dc3c0b24f80..3d5f977c2de8 100644 --- a/drivers/amlogic/media/common/vpu/vpu.h +++ b/drivers/amlogic/media/common/vpu/vpu.h @@ -32,9 +32,22 @@ enum vpu_chip_e { VPU_CHIP_GXM, VPU_CHIP_TXLX, VPU_CHIP_AXG, + VPU_CHIP_G12A, VPU_CHIP_MAX, }; +struct fclk_div_s { + unsigned int fclk_id; + unsigned int fclk_mux; + unsigned int fclk_div; +}; + +struct vpu_clk_s { + unsigned int freq; + unsigned int mux; + unsigned int div; +}; + struct vpu_ctrl_s { unsigned int vmod; unsigned int reg; @@ -47,6 +60,7 @@ struct vpu_data_s { const char *chip_name; unsigned char clk_level_dft; unsigned char clk_level_max; + struct fclk_div_s *fclk_div_table; unsigned char gp_pll_valid; unsigned char mem_pd_reg1_valid; diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h index 48a787e3738e..73215a76a9a0 100644 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.h +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -60,6 +60,11 @@ #define CLK_LEVEL_DFT_AXG 3 #define CLK_LEVEL_MAX_AXG 4 +/* G12A */ +/* freq max=666M, default=666M */ +#define CLK_LEVEL_DFT_G12A 7 +#define CLK_LEVEL_MAX_G12A 8 + /* vpu clk setting */ enum vpu_mux_e { FCLK_DIV4 = 0, @@ -70,17 +75,29 @@ enum vpu_mux_e { VID_PLL_CLK, VID2_PLL_CLK, GPLL_CLK, + FCLK_DIV_MAX, }; -static unsigned int fclk_div_table[] = { - 4, /* mux 0 */ - 3, /* mux 1 */ - 5, /* mux 2 */ - 7, /* mux 3 */ - 2, /* invalid */ +static struct fclk_div_s fclk_div_table_gxb[] = { + /* id, mux, div */ + {FCLK_DIV4, 0, 4}, + {FCLK_DIV3, 1, 3}, + {FCLK_DIV5, 2, 5}, + {FCLK_DIV7, 3, 7}, + {FCLK_DIV_MAX, 8, 1}, }; -static unsigned int vpu_clk_table[10][3] = { +static struct fclk_div_s fclk_div_table_g12a[] = { + /* id, mux, div */ + {FCLK_DIV3, 0, 3}, + {FCLK_DIV4, 1, 4}, + {FCLK_DIV5, 2, 5}, + {FCLK_DIV7, 3, 7}, + {FCLK_DIV_MAX, 8, 1}, +}; + +#define VPU_CLK_TOLERANCE 1000000 /* Hz */ +static struct vpu_clk_s vpu_clk_table[] = { /* frequency clk_mux div */ {100000000, FCLK_DIV5, 3}, /* 0 */ {166666667, FCLK_DIV3, 3}, /* 1 */ diff --git a/drivers/amlogic/media/common/vpu/vpu_module.h b/drivers/amlogic/media/common/vpu/vpu_module.h index 620467900e03..d78b21a1ccef 100644 --- a/drivers/amlogic/media/common/vpu/vpu_module.h +++ b/drivers/amlogic/media/common/vpu/vpu_module.h @@ -76,9 +76,6 @@ static char *vpu_mod_table[] = { "none", "none", "none", - "none", - "none", - "none", }; #endif