From 9585305649a013d7ddfd76da3184decdce7d7dc6 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 14 Nov 2017 09:22:38 +0800 Subject: [PATCH] vpu: add vpu support for txlx PD#154260: vpu: add vpu support for txlx Update dts for all platforms. 1. add support for txlx 2. add clktree support for clk change 3. remove unused vpu module for mem_pd 4. remove vpu_parent "vid_pll","mpll1","mpll2" Change-Id: I43aa2435305fd02664ae825bc2f62664ffb526be Signed-off-by: Evoke Zhang --- MAINTAINERS | 4 + arch/arm64/boot/dts/amlogic/axg_pxp.dts | 16 +- arch/arm64/boot/dts/amlogic/axg_s400.dts | 20 +- arch/arm64/boot/dts/amlogic/axg_s400_v03.dts | 20 +- arch/arm64/boot/dts/amlogic/axg_s400emmc.dts | 20 +- .../boot/dts/amlogic/axg_s400emmc_v03.dts | 20 +- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 22 +- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 22 +- drivers/amlogic/clk/axg/axg_clk_media.c | 4 +- drivers/amlogic/clk/gxl/clk_media.c | 2 +- drivers/amlogic/media/common/vpu/Makefile | 2 +- drivers/amlogic/media/common/vpu/vpu.c | 847 ++++++++++++------ drivers/amlogic/media/common/vpu/vpu.h | 59 +- drivers/amlogic/media/common/vpu/vpu_clk.h | 91 -- drivers/amlogic/media/common/vpu/vpu_ctrl.c | 630 ------------- drivers/amlogic/media/common/vpu/vpu_ctrl.h | 335 +++++++ drivers/amlogic/media/common/vpu/vpu_module.h | 26 +- drivers/amlogic/media/common/vpu/vpu_reg.c | 162 +--- drivers/amlogic/media/common/vpu/vpu_reg.h | 15 - include/linux/amlogic/media/vpu/vpu.h | 40 +- 20 files changed, 1086 insertions(+), 1271 deletions(-) delete mode 100644 drivers/amlogic/media/common/vpu/vpu_clk.h delete mode 100644 drivers/amlogic/media/common/vpu/vpu_ctrl.c create mode 100644 drivers/amlogic/media/common/vpu/vpu_ctrl.h diff --git a/MAINTAINERS b/MAINTAINERS index 5ec4ed6f8087..d20fc79c059f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14147,6 +14147,10 @@ AMLOGIC LED DRVIER M: Peipeng Zhao F: Documentation/leds/leds-is31fl32xx.txt +AMLOGIC VPU DRIVER +M: Evoke Zhang +F: drivers/amlogic/media/common/vpu/* + AMLOGIC ADD P241 V2 DTS M: Siming Chen F: arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts diff --git a/arch/arm64/boot/dts/amlogic/axg_pxp.dts b/arch/arm64/boot/dts/amlogic/axg_pxp.dts index 192f70fc1275..f8806a565a4e 100644 --- a/arch/arm64/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/axg_pxp.dts @@ -202,12 +202,16 @@ compatible = "amlogic, vpu"; dev_name = "vpu"; status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + clocks = <&clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_INTR + &clkc CLKID_VPU_P0_MUX + &clkc CLKID_VPU_P1_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; clk_level = <3>; /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ }; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index a381e78aebeb..80b6470e11ec 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -421,15 +421,19 @@ }; vpu { - compatible = "amlogic, vpu"; + compatible = "amlogic, vpu-axg"; dev_name = "vpu"; - status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + 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", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; clk_level = <3>; /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ }; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts index 549b5cc085f0..117a58ea5a4b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts @@ -421,15 +421,19 @@ }; vpu { - compatible = "amlogic, vpu"; + compatible = "amlogic, vpu-axg"; dev_name = "vpu"; - status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + 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", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; clk_level = <3>; /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ }; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts index 8d7c7f2e4b84..601cd2baaa66 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts @@ -417,15 +417,19 @@ }; vpu { - compatible = "amlogic, vpu"; + compatible = "amlogic, vpu-axg"; dev_name = "vpu"; - status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + 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", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; clk_level = <3>; /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ }; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts index 90bfac3d4905..099379c748cf 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts @@ -417,15 +417,19 @@ }; vpu { - compatible = "amlogic, vpu"; + compatible = "amlogic, vpu-axg"; dev_name = "vpu"; - status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + 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", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; clk_level = <3>; /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 1b01b9d60d66..555af264a4e7 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -271,15 +271,21 @@ }; vpu { - compatible = "amlogic, vpu"; + compatible = "amlogic, vpu-gxl"; dev_name = "vpu"; - status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_GP0_PLL>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr", + "gp_pll", + "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 */ diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 5ca347ae0fb9..b6fded215ddf 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -354,15 +354,21 @@ }; vpu { - compatible = "amlogic, vpu"; + compatible = "amlogic, vpu-gxm"; dev_name = "vpu"; - status = "ok"; - clocks = <&clkc CLKID_VPU_MUX - &clkc CLKID_VAPB_MUX - &clkc CLKID_VPU_INTR>; - clock-names = "vpu_clk", - "vapb_clk", - "vpu_intr"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_GP0_PLL>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr", + "gp_pll", + "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 */ diff --git a/drivers/amlogic/clk/axg/axg_clk_media.c b/drivers/amlogic/clk/axg/axg_clk_media.c index f57aba4c01f2..1d8a4dbde4e0 100644 --- a/drivers/amlogic/clk/axg/axg_clk_media.c +++ b/drivers/amlogic/clk/axg/axg_clk_media.c @@ -79,8 +79,8 @@ static struct clk_hw *dsi_meas_clk_hws[] = { }; static const char * const vpu_parent_names[] = { "fclk_div4", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll1", "null", - "mpll2", "null"}; + "fclk_div3", "fclk_div5", "fclk_div7", "null", "null", + "null", "null"}; /* cts_vpu_clk */ static struct clk_mux vpu_p0_mux = { diff --git a/drivers/amlogic/clk/gxl/clk_media.c b/drivers/amlogic/clk/gxl/clk_media.c index 8e8b8b997035..bf21342b25cd 100644 --- a/drivers/amlogic/clk/gxl/clk_media.c +++ b/drivers/amlogic/clk/gxl/clk_media.c @@ -360,7 +360,7 @@ static struct clk_hw *hevc_clk_hws[] = { }; const char *vpu_parent_names[] = { "fclk_div4", "fclk_div3", "fclk_div5", - "fclk_div7", "mpll1", "vid_pll_clk", "mpll2", "gp1_pll"}; + "fclk_div7", "null", "null", "null", "gp1_pll"}; /* cts_vpu_clk */ static struct clk_mux vpu_p0_mux = { diff --git a/drivers/amlogic/media/common/vpu/Makefile b/drivers/amlogic/media/common/vpu/Makefile index 92bf5a4a2e5c..988a9eba10ac 100644 --- a/drivers/amlogic/media/common/vpu/Makefile +++ b/drivers/amlogic/media/common/vpu/Makefile @@ -1,2 +1,2 @@ -obj-$(CONFIG_AMLOGIC_VPU) += vpu.o vpu_ctrl.o vpu_reg.o +obj-$(CONFIG_AMLOGIC_VPU) += vpu.o vpu_reg.o diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index c80e236004cb..b11576e3c8e4 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -30,97 +30,58 @@ #include #include "vpu_reg.h" #include "vpu.h" -#include "vpu_clk.h" +#include "vpu_ctrl.h" #include "vpu_module.h" /* v01: initial version */ /* v02: add axg support */ -#define VPU_VERION "v02" +/* v03: add txlx support */ +#define VPU_VERION "v03" -enum vpu_chip_e vpu_chip_type; int vpu_debug_print_flag; -static spinlock_t vpu_lock; -static DEFINE_MUTEX(vpu_mutex); +static spinlock_t vpu_mem_lock; +static spinlock_t vpu_clk_gate_lock; +static DEFINE_MUTEX(vpu_clk_mutex); -static unsigned int clk_vmod[VPU_MAX]; - -static struct vpu_conf_s vpu_conf = { +struct vpu_conf_s vpu_conf = { + .data = NULL, + .clk_level = 0, .mem_pd0 = 0, .mem_pd1 = 0, - .clk_level_dft = 0, - .clk_level_max = 1, - .clk_level = 0, - /*.fclk_type = 0,*/ + .mem_pd2 = 0, + + /* clocktree */ + .gp_pll = NULL, + .vpu_clk0 = NULL, + .vpu_clk1 = NULL, + .vpu_clk = NULL, + + .clk_vmod = NULL, }; int vpu_chip_valid_check(void) { int ret = 0; - if (vpu_chip_type == VPU_CHIP_MAX) { + if (vpu_conf.data == NULL) { VPUERR("invalid VPU in current chip\n"); ret = -1; } return ret; } -static void vpu_chip_detect(void) -{ -#if 1 - unsigned int cpu_type; - - cpu_type = get_cpu_type(); - switch (cpu_type) { - case MESON_CPU_MAJOR_ID_GXBB: - vpu_chip_type = VPU_CHIP_GXBB; - vpu_conf.clk_level_dft = CLK_LEVEL_DFT_GXBB; - vpu_conf.clk_level_max = CLK_LEVEL_MAX_GXBB; - break; - case MESON_CPU_MAJOR_ID_GXTVBB: - vpu_chip_type = VPU_CHIP_GXTVBB; - vpu_conf.clk_level_dft = CLK_LEVEL_DFT_GXTVBB; - vpu_conf.clk_level_max = CLK_LEVEL_MAX_GXTVBB; - break; - case MESON_CPU_MAJOR_ID_GXL: - case MESON_CPU_MAJOR_ID_GXM: - vpu_chip_type = VPU_CHIP_GXL; - vpu_conf.clk_level_dft = CLK_LEVEL_DFT_GXL; - vpu_conf.clk_level_max = CLK_LEVEL_MAX_GXL; - break; - case MESON_CPU_MAJOR_ID_TXL: - vpu_chip_type = VPU_CHIP_TXL; - vpu_conf.clk_level_dft = CLK_LEVEL_DFT_TXL; - vpu_conf.clk_level_max = CLK_LEVEL_MAX_TXL; - break; - case MESON_CPU_MAJOR_ID_AXG: - vpu_chip_type = VPU_CHIP_AXG; - vpu_conf.clk_level_dft = CLK_LEVEL_DFT_AXG; - vpu_conf.clk_level_max = CLK_LEVEL_MAX_AXG; - break; - default: - vpu_chip_type = VPU_CHIP_MAX; - vpu_conf.clk_level_dft = 0; - vpu_conf.clk_level_max = 1; - } -#else - vpu_chip_type = VPU_CHIP_GXL; - vpu_conf.clk_level_dft = CLK_LEVEL_DFT_GXL; - vpu_conf.clk_level_max = CLK_LEVEL_MAX_GXL; -#endif - - if (vpu_debug_print_flag) - VPUPR("detect chip type: %d\n", vpu_chip_type); -} - static unsigned int get_vpu_clk_level_max_vmod(void) { - unsigned int max_level; + unsigned int max_level = 0; int i; + if (vpu_conf.clk_vmod == NULL) + return max_level; + max_level = 0; - for (i = 0; i < VPU_MAX; i++) { - if (clk_vmod[i] > max_level) - max_level = clk_vmod[i]; + for (i = 0; i < VPU_MOD_MAX; i++) { + if (vpu_conf.clk_vmod[i] > max_level) + max_level = vpu_conf.clk_vmod[i]; } return max_level; @@ -128,14 +89,11 @@ static unsigned int get_vpu_clk_level_max_vmod(void) static unsigned int get_vpu_clk_level(unsigned int video_clk) { - unsigned int video_bw; unsigned int clk_level; int i; - video_bw = video_clk + 1000000; - - for (i = 0; i < vpu_conf.clk_level_max; i++) { - if (video_bw <= vpu_clk_table[i][0]) + for (i = 0; i < vpu_conf.data->clk_level_max; i++) { + if (video_clk <= vpu_clk_table[i][0]) break; } clk_level = i; @@ -145,24 +103,21 @@ static unsigned int get_vpu_clk_level(unsigned int video_clk) unsigned int get_vpu_clk(void) { - unsigned int clk_freq; - unsigned int fclk, clk_source; - unsigned int mux, div; + unsigned long clk_freq; + unsigned long fclk, clk_source; + unsigned long mux, div; - fclk = CLK_FPLL_FREQ * 100; /* 0.01M resolution */ + 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 / fclk_div_table[mux]; + clk_source = ((fclk * 100 / fclk_div_table[mux]) + 99) / 100; break; case GPLL_CLK: - if (vpu_chip_type == VPU_CHIP_GXTVBB) - clk_source = 696 * 100; /* 0.01MHz */ - else - clk_source = 0; + clk_source = vpu_clk_table[8][0]; break; default: clk_source = 0; @@ -170,122 +125,89 @@ unsigned int get_vpu_clk(void) } div = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 0, 7) + 1; - clk_freq = (clk_source / div) * 10 * 1000; /* change to Hz */ + clk_freq = ((clk_source * 100 / div) + 99) / 100; - return clk_freq; -} - -static int switch_gp1_pll_gxtvbb(int flag) -{ - int cnt = 100; - int ret = 0; - - if (flag) { /* enable gp1_pll */ - /* GP1 DPLL 696MHz output*/ - vpu_hiu_write(HHI_GP1_PLL_CNTL2, 0x69c80000); - vpu_hiu_write(HHI_GP1_PLL_CNTL3, 0x0a5590c4); - vpu_hiu_write(HHI_GP1_PLL_CNTL4, 0x0000500d); - vpu_hiu_write(HHI_GP1_PLL_CNTL, 0x6a01023a); - vpu_hiu_write(HHI_GP1_PLL_CNTL, 0x4a01023a); - do { - udelay(10); - vpu_hiu_setb(HHI_GP1_PLL_CNTL, 1, 29, 1); /* reset */ - udelay(50); - /* release reset */ - vpu_hiu_setb(HHI_GP1_PLL_CNTL, 0, 29, 1); - udelay(50); - cnt--; - if (cnt == 0) - break; - } while (vpu_hiu_getb(HHI_GP1_PLL_CNTL, 31, 1) == 0); - if (vpu_hiu_getb(HHI_GP1_PLL_CNTL, 31, 1) == 0) { - ret = -1; - vpu_hiu_setb(HHI_GP1_PLL_CNTL, 0, 30, 1); - VPUERR("GP1_PLL lock failed\n"); - } - } else { /* disable gp1_pll */ - vpu_hiu_setb(HHI_GP1_PLL_CNTL, 0, 30, 1); - } - - return ret; + return (unsigned int)clk_freq; } static int switch_gp_pll(int flag) { - int ret = 0; + unsigned int clk; - switch (vpu_chip_type) { - case VPU_CHIP_GXTVBB: - ret = switch_gp1_pll_gxtvbb(flag); - break; - default: - ret = -1; - break; + if ((vpu_conf.gp_pll == NULL) || (IS_ERR(vpu_conf.gp_pll))) { + VPUERR("%s: gp_pll\n", __func__); + return -1; } - return ret; -} + if (flag) { /* enable */ + clk = vpu_clk_table[8][0]; + clk_set_rate(vpu_conf.gp_pll, clk); + clk_prepare_enable(vpu_conf.gp_pll); + } else { /* disable */ + clk_disable_unprepare(vpu_conf.gp_pll); + } -#define VPU_CLKB_MAX 350 /* unit: MHz */ + return 0; +} static int adjust_vpu_clk(unsigned int clk_level) { - unsigned long flags = 0; - unsigned int mux, div; + unsigned int mux, clk; int ret = 0; ret = vpu_chip_valid_check(); if (ret) return -1; - spin_lock_irqsave(&vpu_lock, flags); - mux = vpu_clk_table[vpu_conf.clk_level][1]; if (mux == GPLL_CLK) { + if (vpu_conf.data->gp_pll_valid == 0) { + VPUERR("gp_pll is invalid\n"); + return -1; + } + ret = switch_gp_pll(1); if (ret) { - VPUERR("%s exit\n", __func__); - spin_unlock_irqrestore(&vpu_lock, flags); + VPUERR("%s: exit\n", __func__); return ret; } } + if ((IS_ERR(vpu_conf.vpu_clk0)) || + (IS_ERR(vpu_conf.vpu_clk1)) || + (IS_ERR(vpu_conf.vpu_clk))) { + VPUERR("%s: vpu_clk\n", __func__); + return -1; + } + vpu_conf.clk_level = clk_level; /* step 1: switch to 2nd vpu clk patch */ - mux = vpu_clk_table[0][1]; - vpu_hiu_setb(HHI_VPU_CLK_CNTL, mux, 25, 3); - div = vpu_clk_table[0][2]; - vpu_hiu_setb(HHI_VPU_CLK_CNTL, div, 16, 7); - vpu_hiu_setb(HHI_VPU_CLK_CNTL, 1, 24, 1); - vpu_hiu_setb(HHI_VPU_CLK_CNTL, 1, 31, 1); + clk = vpu_clk_table[vpu_conf.data->clk_level_dft][0]; + 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 */ - vpu_hiu_setb(HHI_VPU_CLK_CNTL, 0, 8, 1); - mux = vpu_clk_table[vpu_conf.clk_level][1]; - vpu_hiu_setb(HHI_VPU_CLK_CNTL, mux, 9, 3); - div = vpu_clk_table[vpu_conf.clk_level][2]; - vpu_hiu_setb(HHI_VPU_CLK_CNTL, div, 0, 7); - vpu_hiu_setb(HHI_VPU_CLK_CNTL, 1, 8, 1); + clk = vpu_clk_table[vpu_conf.clk_level][0]; + clk_set_rate(vpu_conf.vpu_clk0, clk); udelay(20); /* step 3: switch back to 1st vpu clk patch */ - vpu_hiu_setb(HHI_VPU_CLK_CNTL, 0, 31, 1); - vpu_hiu_setb(HHI_VPU_CLK_CNTL, 0, 24, 1); + clk_set_parent(vpu_conf.vpu_clk, vpu_conf.vpu_clk0); - VPUPR("set vpu clk: %uHz, readback: %uHz(0x%x)\n", - vpu_clk_table[vpu_conf.clk_level][0], - get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL))); + 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, + clk, (vpu_hiu_read(HHI_VPU_CLK_CNTL))); - spin_unlock_irqrestore(&vpu_lock, flags); return ret; } static int set_vpu_clk(unsigned int vclk) { int ret = 0; - unsigned int clk_level, mux, div; + unsigned int clk_level; - mutex_lock(&vpu_mutex); + mutex_lock(&vpu_clk_mutex); if (vclk >= 100) { /* regard as vpu_clk */ clk_level = get_vpu_clk_level(vclk); @@ -293,11 +215,11 @@ static int set_vpu_clk(unsigned int vclk) clk_level = vclk; } - if (clk_level >= vpu_conf.clk_level_max) { + if (clk_level >= vpu_conf.data->clk_level_max) { ret = 1; VPUERR("set vpu clk out of supported range\n"); goto set_vpu_clk_limit; - } else if (clk_level < vpu_conf.clk_level_dft) { + } else if (clk_level < vpu_conf.data->clk_level_dft) { #ifdef LIMIT_VPU_CLK_LOW ret = 3; VPUERR("set vpu clk less than system default\n"); @@ -305,15 +227,11 @@ static int set_vpu_clk(unsigned int vclk) #endif } - mux = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 9, 3); - div = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 0, 7); - if ((mux != vpu_clk_table[clk_level][1]) - || (div != vpu_clk_table[clk_level][2])) { + if (get_vpu_clk() != vpu_clk_table[clk_level][0]) ret = adjust_vpu_clk(clk_level); - } set_vpu_clk_limit: - mutex_unlock(&vpu_mutex); + mutex_unlock(&vpu_clk_mutex); return ret; } @@ -344,18 +262,20 @@ unsigned int get_vpu_clk_vmod(unsigned int vmod) ret = vpu_chip_valid_check(); if (ret) return 0; + if (vpu_conf.clk_vmod == NULL) + return 0; - mutex_lock(&vpu_mutex); + mutex_lock(&vpu_clk_mutex); - if (vmod < VPU_MAX) { - vpu_clk = clk_vmod[vmod]; + if (vmod < VPU_MOD_MAX) { + vpu_clk = vpu_conf.clk_vmod[vmod]; vpu_clk = vpu_clk_table[vpu_clk][0]; } else { vpu_clk = 0; - VPUERR("unsupport vmod\n"); + VPUERR("invalid vmod\n"); } - mutex_unlock(&vpu_mutex); + mutex_unlock(&vpu_clk_mutex); return vpu_clk; } @@ -386,28 +306,30 @@ int request_vpu_clk_vmod(unsigned int vclk, unsigned int vmod) ret = vpu_chip_valid_check(); if (ret) - return 1; + return -1; + if (vmod >= VPU_MOD_MAX) { + VPUERR("request_vpu_clk: invalid vmod: %d\n", vmod); + return -1; + } + if (vpu_conf.clk_vmod == NULL) { + VPUERR("request_vpu_clk: clk_vmod is null\n"); + return -1; + } - mutex_lock(&vpu_mutex); + mutex_lock(&vpu_clk_mutex); if (vclk >= 100) /* regard as vpu_clk */ clk_level = get_vpu_clk_level(vclk); else /* regard as clk_level */ clk_level = vclk; - if (clk_level >= vpu_conf.clk_level_max) { - ret = 1; - VPUERR("set vpu clk out of supported range\n"); - goto request_vpu_clk_limit; + if (clk_level >= vpu_conf.data->clk_level_max) { + VPUERR("request_vpu_clk: set clk is out of supported\n"); + mutex_unlock(&vpu_clk_mutex); + return -1; } - if (vmod == VPU_MAX) { - ret = 1; - VPUERR("unsupport vmod\n"); - goto request_vpu_clk_limit; - } - - clk_vmod[vmod] = clk_level; + vpu_conf.clk_vmod[vmod] = clk_level; if (vpu_debug_print_flag) { VPUPR("request vpu clk: %s %uHz\n", vpu_mod_table[vmod], @@ -419,8 +341,7 @@ int request_vpu_clk_vmod(unsigned int vclk, unsigned int vmod) if (clk_level != vpu_conf.clk_level) adjust_vpu_clk(clk_level); -request_vpu_clk_limit: - mutex_unlock(&vpu_mutex); + mutex_unlock(&vpu_clk_mutex); #endif return ret; } @@ -452,21 +373,22 @@ int release_vpu_clk_vmod(unsigned int vmod) ret = vpu_chip_valid_check(); if (ret) - return 1; - - mutex_lock(&vpu_mutex); - - clk_level = 0; - if (vmod == VPU_MAX) { - ret = 1; - VPUERR("unsupport vmod\n"); - goto release_vpu_clk_limit; + return -1; + if (vmod >= VPU_MOD_MAX) { + VPUERR("release_vpu_clk: invalid vmod: %d\n", vmod); + return -1; + } + if (vpu_conf.clk_vmod == NULL) { + VPUERR("release_vpu_clk: clk_vmod is null\n"); + return -1; } - clk_vmod[vmod] = clk_level; + mutex_lock(&vpu_clk_mutex); + + clk_level = 0; + vpu_conf.clk_vmod[vmod] = clk_level; if (vpu_debug_print_flag) { - VPUPR("release vpu clk: %s\n", - vpu_mod_table[vmod]); + VPUPR("release vpu clk: %s\n", vpu_mod_table[vmod]); dump_stack(); } @@ -474,14 +396,206 @@ int release_vpu_clk_vmod(unsigned int vmod) if (clk_level != vpu_conf.clk_level) adjust_vpu_clk(clk_level); -release_vpu_clk_limit: - mutex_unlock(&vpu_mutex); + mutex_unlock(&vpu_clk_mutex); #endif return ret; } /* *********************************************** */ +/* *********************************************** */ +/* VPU_MEM_PD control */ +/* *********************************************** */ +/* + * Function: switch_vpu_mem_pd_vmod + * switch vpu memory power down by specified vmod + * + * Parameters: + * vmod - unsigned int, must be the following constants: + * VPU_MOD, supported by vpu_mod_e + * flag - int, on/off switch flag, must be one of the following constants: + * VPU_MEM_POWER_ON + * VPU_MEM_POWER_DOWN + * + * Example: + * switch_vpu_mem_pd_vmod(VPU_VENCP, VPU_MEM_POWER_ON); + * switch_vpu_mem_pd_vmod(VPU_VIU_OSD1, VPU_MEM_POWER_DOWN); + * + */ +void switch_vpu_mem_pd_vmod(unsigned int vmod, int flag) +{ + unsigned long flags = 0; + unsigned int _val, _reg, _bit, _len; + struct vpu_ctrl_s *table; + int i = 0, ret = 0, cnt; + + ret = vpu_chip_valid_check(); + if (ret) + return; + if (vmod >= VPU_MOD_MAX) { + VPUERR("switch_vpu_mem_pd: invalid vpu mod: %d\n", vmod); + return; + } + + spin_lock_irqsave(&vpu_mem_lock, flags); + + cnt = vpu_conf.data->mem_pd_table_cnt; + table = vpu_conf.data->mem_pd_table; + while (i < cnt) { + if (table[i].vmod == vmod) + break; + if (table[i].vmod == VPU_MOD_MAX) + break; + i++; + } + if (table[i].vmod < VPU_MOD_MAX) { + _val = (flag == VPU_MEM_POWER_ON) ? 0x0 : 0x3; + _reg = table[i].reg; + _bit = table[i].bit; + _len = table[i].len; + vpu_hiu_setb(_reg, _val, _bit, _len); + } + + spin_unlock_irqrestore(&vpu_mem_lock, flags); + + if (table[i].vmod == VPU_MOD_MAX) + VPUPR("switch_vpu_mem_pd: unsupport vpu mod: %d\n", vmod); + if (vpu_debug_print_flag) { + VPUPR("switch_vpu_mem_pd: %s %s\n", + vpu_mod_table[vmod], + ((flag == VPU_MEM_POWER_ON) ? "ON" : "OFF")); + dump_stack(); + } +} + +/* + * Function: get_vpu_mem_pd_vmod + * switch vpu memory power down by specified vmod + * + * Parameters: + * vmod - unsigned int, must be the following constants: + * VPU_MOD, supported by vpu_mod_e + * + * Returns: + * int, 0 for power on, 1 for power down, -1 for error + * + * Example: + * ret = get_vpu_mem_pd_vmod(VPU_VENCP); + * ret = get_vpu_mem_pd_vmod(VPU_VIU_OSD1); + * + */ +#define VPU_MEM_PD_ERR 0xffff + +int get_vpu_mem_pd_vmod(unsigned int vmod) +{ + unsigned int _reg, _bit, _len; + struct vpu_ctrl_s *table; + int i = 0, ret = 0, cnt; + + ret = vpu_chip_valid_check(); + if (ret) + return -1; + if (vmod >= VPU_MOD_MAX) { + VPUERR("get_vpu_mem_pd: invalid vpu mod: %d\n", vmod); + return -1; + } + + cnt = vpu_conf.data->mem_pd_table_cnt; + table = vpu_conf.data->mem_pd_table; + while (i < cnt) { + if (table[i].vmod == vmod) + break; + if (table[i].vmod == VPU_MOD_MAX) + break; + i++; + } + if (table[i].vmod == VPU_MOD_MAX) { + VPUPR("get_vpu_mem_pd: unsupport vpu mod: %d\n", vmod); + return -1; + } + + _reg = table[i].reg; + _bit = table[i].bit; + _len = table[i].len; + ret = vpu_hiu_getb(_reg, _bit, _len); + + if (ret == 0) + return VPU_MEM_POWER_ON; + else if ((ret == 0x3) || (ret == 0xf)) + return VPU_MEM_POWER_DOWN; + else + return -1; +} + +/* *********************************************** */ +/* VPU_CLK_GATE control */ +/* *********************************************** */ +/* + * Function: switch_vpu_clk_gate_vmod + * switch vpu clk gate by specified vmod + * + * Parameters: + * vmod - unsigned int, must be the following constants: + * VPU_MOD, supported by vpu_mod_e + * flag - int, on/off switch flag, must be one of the following constants: + * VPU_CLK_GATE_ON + * VPU_CLK_GATE_OFF + * + * Example: + * switch_vpu_clk_gate_vmod(VPU_VENCP, VPU_CLK_GATE_ON); + * switch_vpu_clk_gate_vmod(VPU_VPP, VPU_CLK_GATE_OFF); + * + */ +void switch_vpu_clk_gate_vmod(unsigned int vmod, int flag) +{ + unsigned int _val, _reg, _bit, _len; + struct vpu_ctrl_s *table; + int i = 0, ret = 0, m = 0, cnt; + unsigned long flags = 0; + + ret = vpu_chip_valid_check(); + if (ret) + return; + if (vmod >= VPU_MAX) { + VPUERR("switch_vpu_clk_gate: invalid vpu mod: %d\n", vmod); + return; + } + + spin_lock_irqsave(&vpu_clk_gate_lock, flags); + + cnt = vpu_conf.data->clk_gate_table_cnt; + table = vpu_conf.data->clk_gate_table; + while (i < cnt) { + if (table[i].vmod == vmod) { + _reg = table[i].reg; + _bit = table[i].bit; + _len = table[i].len; + if (flag == VPU_CLK_GATE_ON) + _val = (1 << _len) - 1; + else + _val = 0; + vpu_vcbus_setb(_reg, _val, _bit, _len); + m++; + } else if (table[i].vmod == VPU_MAX) + break; + i++; + } + + spin_unlock_irqrestore(&vpu_clk_gate_lock, flags); + + if (m == 0) + VPUPR("switch_vpu_clk_gate: unsupport vpu mod: %d\n", vmod); + + if (vpu_debug_print_flag) { + VPUPR("switch_vpu_clk_gate: %s %s\n", + vpu_mod_table[vmod], + ((flag == VPU_CLK_GATE_ON) ? "ON" : "OFF")); + dump_stack(); + } +} + +/* *********************************************** */ + /* *********************************************** */ /* VPU sysfs function */ /* *********************************************** */ @@ -523,9 +637,7 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr, { unsigned int ret = 0; unsigned int tmp[2], n; - unsigned int fclk_type; - fclk_type = vpu_conf.fclk_type; switch (buf[0]) { case 'g': /* get */ VPUPR("get current clk: %uHz\n", get_vpu_clk()); @@ -546,14 +658,14 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr, case 'r': if (buf[2] == 'q') { /* request */ tmp[0] = 0; - tmp[1] = VPU_MAX; + tmp[1] = VPU_MOD_MAX; ret = sscanf(buf, "request %u %u", &tmp[0], &tmp[1]); if (ret == 2) request_vpu_clk_vmod(tmp[0], tmp[1]); else VPUERR("invalid parameters\n"); } else if (buf[2] == 'l') { /* release */ - tmp[0] = VPU_MAX; + tmp[0] = VPU_MOD_MAX; ret = sscanf(buf, "release %u", &tmp[0]); if (ret == 1) release_vpu_clk_vmod(tmp[0]); @@ -562,13 +674,17 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr, } break; case 'd': - tmp[0] = VPU_MAX; + if (vpu_conf.clk_vmod == NULL) { + VPUERR("clk_vmod is null\n"); + return count; + } + tmp[0] = VPU_MOD_MAX; ret = sscanf(buf, "dump %u", &tmp[0]); if (ret == 1) { VPUPR("clk holdings:\n"); pr_info("%s: %uHz(%u)\n", vpu_mod_table[tmp[0]], - vpu_clk_table[clk_vmod[tmp[0]]][0], - clk_vmod[tmp[0]]); + vpu_clk_table[vpu_conf.clk_vmod[tmp[0]]][0], + vpu_conf.clk_vmod[tmp[0]]); } else { n = get_vpu_clk_level_max_vmod(); VPUPR("clk max holdings: %uHz(%u)\n", @@ -586,31 +702,25 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr, static ssize_t vpu_mem_debug(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { - unsigned int ret = 0; unsigned int tmp[2]; unsigned int _reg0, _reg1, _reg2; + int ret = 0; _reg0 = HHI_VPU_MEM_PD_REG0; _reg1 = HHI_VPU_MEM_PD_REG1; _reg2 = HHI_VPU_MEM_PD_REG2; switch (buf[0]) { case 'r': - if (vpu_chip_type == VPU_CHIP_AXG) { - VPUPR("mem_pd0: 0x%08x\n", vpu_hiu_read(_reg0)); - } else { - VPUPR("mem_pd0: 0x%08x\n", vpu_hiu_read(_reg0)); + VPUPR("mem_pd0: 0x%08x\n", vpu_hiu_read(_reg0)); + if (vpu_conf.data->mem_pd_reg1_valid) VPUPR("mem_pd1: 0x%08x\n", vpu_hiu_read(_reg1)); - if ((vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg2)); - } - } + if (vpu_conf.data->mem_pd_reg2_valid) + VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg2)); break; case 'w': ret = sscanf(buf, "w %u %u", &tmp[0], &tmp[1]); if (ret == 2) { - tmp[0] = (tmp[0] > VPU_MAX) ? VPU_MAX : tmp[0]; + tmp[0] = (tmp[0] > VPU_MOD_MAX) ? VPU_MOD_MAX : tmp[0]; tmp[1] = (tmp[1] == VPU_MEM_POWER_ON) ? 0 : 1; VPUPR("switch_vpu_mem_pd: %s %s\n", vpu_mod_table[tmp[0]], @@ -631,31 +741,26 @@ static ssize_t vpu_mem_debug(struct class *class, struct class_attribute *attr, static ssize_t vpu_clk_gate_debug(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { - unsigned int ret = 0; unsigned int tmp[2]; + unsigned int _reg = 0; + struct vpu_ctrl_s *table; + int i = 0, ret = 0; switch (buf[0]) { case 'r': - VPUPR("HHI_GCLK_OTHER: 0x%08x\n", vpu_hiu_read(HHI_GCLK_OTHER)); - VPUPR("VPU_CLK_GATE: 0x%08x\n", vpu_vcbus_read(VPU_CLK_GATE)); - VPUPR("VDIN0_COM_GCLK_CTRL: 0x%08x\n", - vpu_vcbus_read(VDIN0_COM_GCLK_CTRL)); - VPUPR("VDIN0_COM_GCLK_CTRL2: 0x%08x\n", - vpu_vcbus_read(VDIN0_COM_GCLK_CTRL2)); - VPUPR("VDIN1_COM_GCLK_CTRL: 0x%08x\n", - vpu_vcbus_read(VDIN1_COM_GCLK_CTRL)); - VPUPR("VDIN1_COM_GCLK_CTRL2: 0x%08x\n", - vpu_vcbus_read(VDIN1_COM_GCLK_CTRL2)); - VPUPR("DI_CLKG_CTRL: 0x%08x\n", - vpu_vcbus_read(DI_CLKG_CTRL)); - VPUPR("VPP_GCLK_CTRL0: 0x%08x\n", - vpu_vcbus_read(VPP_GCLK_CTRL0)); - VPUPR("VPP_GCLK_CTRL1: 0x%08x\n", - vpu_vcbus_read(VPP_GCLK_CTRL1)); - VPUPR("VPP_SC_GCLK_CTRL: 0x%08x\n", - vpu_vcbus_read(VPP_SC_GCLK_CTRL)); - VPUPR("VPP_XVYCC_GCLK_CTRL: 0x%08x\n", - vpu_vcbus_read(VPP_XVYCC_GCLK_CTRL)); + table = vpu_conf.data->clk_gate_table; + while (1) { + if (table[i].vmod == VPU_MAX) + break; + if (table[i].reg == _reg) { + i++; + continue; + } + _reg = table[i].reg; + pr_info("VPU_CLK_GATE: 0x%04x = 0x%08x\n", + _reg, vpu_vcbus_read(_reg)); + i++; + } break; case 'w': ret = sscanf(buf, "w %u %u", &tmp[0], &tmp[1]); @@ -729,20 +834,78 @@ static ssize_t vpu_print_debug(struct class *class, { unsigned int ret; - /*ret = sscanf(buf, "%u", &temp);*/ ret = kstrtoint(buf, 10, &vpu_debug_print_flag); pr_info("set vpu debug_print_flag: %d\n", vpu_debug_print_flag); return count; } +static ssize_t vpu_debug_info(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned int level_max, clk; + ssize_t len = 0; + int i, ret; + + ret = vpu_chip_valid_check(); + if (ret) { + len = sprintf(buf, "vpu invalid\n"); + 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); + level_max = vpu_conf.data->clk_level_max - 1; + + len = sprintf(buf, "driver version: %s(%d-%s)\n", + VPU_VERION, + vpu_conf.data->chip_type, + vpu_conf.data->chip_name); + len += sprintf(buf+len, "actual clk: %dHz\n" + "clk_level: %d(%dHz)\n" + "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.data->clk_level_dft, + vpu_clk_table[vpu_conf.data->clk_level_dft][0], + level_max, vpu_clk_table[level_max][0]); + + len += sprintf(buf+len, "mem_pd:\n" + " mem_pd0: 0x%08x\n", + vpu_hiu_read(HHI_VPU_MEM_PD_REG0)); + if (vpu_conf.data->mem_pd_reg1_valid) { + len += sprintf(buf+len, " mem_pd1: 0x%08x\n", + vpu_hiu_read(HHI_VPU_MEM_PD_REG1)); + } + if (vpu_conf.data->mem_pd_reg2_valid) { + len += sprintf(buf+len, " mem_pd2: 0x%08x\n", + vpu_hiu_read(HHI_VPU_MEM_PD_REG2)); + } + + if (vpu_conf.clk_vmod) { + len += sprintf(buf+len, "\nclk_vmod:\n"); + for (i = 0; i < VPU_MOD_MAX; i++) { + len += sprintf(buf+len, " %02d: %dHz\n", + i, vpu_conf.clk_vmod[i]); + } + } + len += sprintf(buf+len, "\n"); + + return len; +} + 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(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(help, 0444, vpu_debug_help, NULL), + __ATTR(info, 0444, vpu_debug_info, NULL), + __ATTR(help, 0444, vpu_debug_help, NULL), }; static struct class *vpu_debug_class; @@ -806,9 +969,9 @@ static int get_vpu_config(struct platform_device *pdev) if (ret) { VPUPR("don't find clk_level, use default setting\n"); } else { - if (val >= vpu_conf.clk_level_max) { + if (val >= vpu_conf.data->clk_level_max) { VPUERR("clk_level is out of support, set to default\n"); - val = vpu_conf.clk_level_dft; + val = vpu_conf.data->clk_level_dft; } vpu_conf.clk_level = val; @@ -821,38 +984,176 @@ static int get_vpu_config(struct platform_device *pdev) static void vpu_clktree_init(struct device *dev) { - struct clk *vpu_clktree; + struct clk *clk_vapb, *clk_vpu_intr; - vpu_clktree = devm_clk_get(dev, "vapb_clk"); - if (IS_ERR(vpu_clktree)) + /* init & enable vapb_clk */ + clk_vapb = devm_clk_get(dev, "vapb_clk"); + if (IS_ERR(clk_vapb)) VPUERR("%s: vapb_clk\n", __func__); else - clk_prepare_enable(vpu_clktree); + clk_prepare_enable(clk_vapb); - vpu_clktree = devm_clk_get(dev, "vpu_clk"); - if (IS_ERR(vpu_clktree)) - VPUERR("%s: vpu_clk\n", __func__); - else - clk_prepare_enable(vpu_clktree); - - vpu_clktree = devm_clk_get(dev, "vpu_intr"); - if (IS_ERR(vpu_clktree)) + clk_vpu_intr = devm_clk_get(dev, "vpu_intr"); + if (IS_ERR(clk_vpu_intr)) VPUERR("%s: vpu_intr\n", __func__); else - clk_prepare_enable(vpu_clktree); + clk_prepare_enable(clk_vpu_intr); - VPUPR("%s\n", __func__); + if (vpu_conf.data->gp_pll_valid) { + vpu_conf.gp_pll = devm_clk_get(dev, "gp_pll"); + if (IS_ERR(vpu_conf.gp_pll)) + VPUERR("%s: gp_pll\n", __func__); + } + + /* init & enable vpu_clk */ + 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))) { + VPUERR("%s: vpu_clk\n", __func__); + } else { + clk_set_parent(vpu_conf.vpu_clk, vpu_conf.vpu_clk0); + clk_prepare_enable(vpu_conf.vpu_clk); + } + + VPUPR("clktree_init\n"); } +static struct vpu_data_s vpu_data_gxb = { + .chip_type = VPU_CHIP_GXBB, + .chip_name = "gxbb", + .clk_level_dft = CLK_LEVEL_DFT_GXBB, + .clk_level_max = CLK_LEVEL_MAX_GXBB, + .gp_pll_valid = 1, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 0, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_gxb) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_gxb) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_gxb, + .clk_gate_table = vpu_clk_gate_gxb, +}; + +static struct vpu_data_s vpu_data_gxtvbb = { + .chip_type = VPU_CHIP_GXBB, + .chip_name = "gxtvbb", + .clk_level_dft = CLK_LEVEL_DFT_GXTVBB, + .clk_level_max = CLK_LEVEL_MAX_GXTVBB, + .gp_pll_valid = 1, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 0, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_gxtvbb) / 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_gxtvbb, + .clk_gate_table = vpu_clk_gate_gxl, +}; + +static struct vpu_data_s vpu_data_gxl = { + .chip_type = VPU_CHIP_GXL, + .chip_name = "gxl", + .clk_level_dft = CLK_LEVEL_DFT_GXL, + .clk_level_max = CLK_LEVEL_MAX_GXL, + .gp_pll_valid = 1, + .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 struct vpu_data_s vpu_data_gxm = { + .chip_type = VPU_CHIP_GXM, + .chip_name = "gxm", + .clk_level_dft = CLK_LEVEL_DFT_GXM, + .clk_level_max = CLK_LEVEL_MAX_GXM, + .gp_pll_valid = 1, + .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 struct vpu_data_s vpu_data_txlx = { + .chip_type = VPU_CHIP_TXLX, + .chip_name = "txlx", + .clk_level_dft = CLK_LEVEL_DFT_TXLX, + .clk_level_max = CLK_LEVEL_MAX_TXLX, + .gp_pll_valid = 1, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 1, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_txlx) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_txlx) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_txlx, + .clk_gate_table = vpu_clk_gate_txlx, +}; + +static struct vpu_data_s vpu_data_axg = { + .chip_type = VPU_CHIP_AXG, + .chip_name = "axg", + .clk_level_dft = CLK_LEVEL_DFT_AXG, + .clk_level_max = CLK_LEVEL_MAX_AXG, + .gp_pll_valid = 0, + .mem_pd_reg1_valid = 0, + .mem_pd_reg2_valid = 0, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_axg) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_axg) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_axg, + .clk_gate_table = vpu_clk_gate_axg, +}; + static const struct of_device_id vpu_of_table[] = { { - .compatible = "amlogic, vpu", + .compatible = "amlogic, vpu-gxbb", + .data = &vpu_data_gxb, + }, + { + .compatible = "amlogic, vpu-gxtvbb", + .data = &vpu_data_gxtvbb, + }, + { + .compatible = "amlogic, vpu-gxl", + .data = &vpu_data_gxl, + }, + { + .compatible = "amlogic, vpu-gxm", + .data = &vpu_data_gxm, + }, + { + .compatible = "amlogic, vpu-txlx", + .data = &vpu_data_txlx, + }, + { + .compatible = "amlogic, vpu-axg", + .data = &vpu_data_axg, }, {}, }; static int vpu_probe(struct platform_device *pdev) { + const struct of_device_id *match; int ret = 0; #ifdef VPU_DEBUG_PRINT @@ -860,21 +1161,35 @@ static int vpu_probe(struct platform_device *pdev) #else vpu_debug_print_flag = 0; #endif - spin_lock_init(&vpu_lock); - VPUPR("driver version: %s\n", VPU_VERION); - memset(clk_vmod, 0, sizeof(clk_vmod)); - vpu_chip_detect(); + match = of_match_device(vpu_of_table, &pdev->dev); + if (match == NULL) { + VPUERR("%s: no match table\n", __func__); + return -1; + } + vpu_conf.data = (struct vpu_data_s *)match->data; + + VPUPR("driver version: %s(%d-%s)\n", + VPU_VERION, + vpu_conf.data->chip_type, + vpu_conf.data->chip_name); + + vpu_conf.clk_vmod = kzalloc((sizeof(unsigned int) * VPU_MOD_MAX), + GFP_KERNEL); + if (vpu_conf.clk_vmod == NULL) + VPUERR("%s: Not enough memory\n", __func__); + ret = vpu_chip_valid_check(); if (ret) - return 0; + return -1; + + spin_lock_init(&vpu_mem_lock); + spin_lock_init(&vpu_clk_gate_lock); - vpu_ioremap(); get_vpu_config(pdev); - vpu_ctrl_probe(); - set_vpu_clk(vpu_conf.clk_level); vpu_clktree_init(&pdev->dev); + set_vpu_clk(vpu_conf.clk_level); creat_vpu_debug_class(); diff --git a/drivers/amlogic/media/common/vpu/vpu.h b/drivers/amlogic/media/common/vpu/vpu.h index 62c16ffc6ee9..7dc3c0b24f80 100644 --- a/drivers/amlogic/media/common/vpu/vpu.h +++ b/drivers/amlogic/media/common/vpu/vpu.h @@ -17,6 +17,8 @@ #ifndef __VPU_PARA_H__ #define __VPU_PARA_H__ +#include +#include /*#define VPU_DEBUG_PRINT*/ @@ -28,38 +30,55 @@ enum vpu_chip_e { VPU_CHIP_GXTVBB, VPU_CHIP_GXL, VPU_CHIP_GXM, - VPU_CHIP_TXL, + VPU_CHIP_TXLX, VPU_CHIP_AXG, VPU_CHIP_MAX, }; -/* - * static char *vpu_chip_name[] = { - * "gxbb", - * "gxtvbb", - * "gxl", - * "gxm", - * "txl", - * "invalid", - * }; - */ +struct vpu_ctrl_s { + unsigned int vmod; + unsigned int reg; + unsigned int bit; + unsigned int len; +}; + +struct vpu_data_s { + enum vpu_chip_e chip_type; + const char *chip_name; + unsigned char clk_level_dft; + unsigned char clk_level_max; + + unsigned char gp_pll_valid; + unsigned char mem_pd_reg1_valid; + unsigned char mem_pd_reg2_valid; + + unsigned int mem_pd_table_cnt; + unsigned int clk_gate_table_cnt; + struct vpu_ctrl_s *mem_pd_table; + struct vpu_ctrl_s *clk_gate_table; +}; struct vpu_conf_s { - unsigned int clk_level_dft; - unsigned int clk_level_max; - unsigned int clk_level; - unsigned int fclk_type; - unsigned int mem_pd0; - unsigned int mem_pd1; + struct vpu_data_s *data; + unsigned int clk_level; + unsigned int mem_pd0; + unsigned int mem_pd1; + unsigned int mem_pd2; + + /* clktree */ + struct clk *gp_pll; + struct clk *vpu_clk0; + struct clk *vpu_clk1; + struct clk *vpu_clk; + + unsigned int *clk_vmod; }; /* ************************************************ */ +extern struct vpu_conf_s vpu_conf; - -extern enum vpu_chip_e vpu_chip_type; extern int vpu_debug_print_flag; -extern int vpu_ioremap(void); extern int vpu_chip_valid_check(void); extern void vpu_ctrl_probe(void); diff --git a/drivers/amlogic/media/common/vpu/vpu_clk.h b/drivers/amlogic/media/common/vpu/vpu_clk.h deleted file mode 100644 index e17773c9e711..000000000000 --- a/drivers/amlogic/media/common/vpu/vpu_clk.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * drivers/amlogic/media/common/vpu/vpu_clk.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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 __VPU_CLK_H__ -#define __VPU_CLK_H__ - -/* #define LIMIT_VPU_CLK_LOW */ - -/* ************************************************ */ -/* VPU frequency table, important. DO NOT modify!! */ -/* ************************************************ */ - -#define CLK_FPLL_FREQ 2000 /* MHz */ - -/* GXBB */ -/* freq max=666M, default=666M */ -#define CLK_LEVEL_DFT_GXBB 7 -#define CLK_LEVEL_MAX_GXBB 8 -/* GXTVBB */ -/* freq max=666M, default=666M */ -#define CLK_LEVEL_DFT_GXTVBB 7 -#define CLK_LEVEL_MAX_GXTVBB 8 -/* GXL */ -/* freq max=666M, default=666M */ -#define CLK_LEVEL_DFT_GXL 7 -#define CLK_LEVEL_MAX_GXL 8 -/* GXM */ -/* freq max=666M, default=666M */ -#define CLK_LEVEL_DFT_GXM 7 -#define CLK_LEVEL_MAX_GXM 8 -/* TXL */ -/* freq max=666M, default=666M */ -#define CLK_LEVEL_DFT_TXL 7 -#define CLK_LEVEL_MAX_TXL 8 -/* AXG */ -/* freq max=250M, default=250M */ -#define CLK_LEVEL_DFT_AXG 3 -#define CLK_LEVEL_MAX_AXG 4 - -/* vpu clk setting */ -enum vpu_mux_e { - FCLK_DIV4 = 0, - FCLK_DIV3, - FCLK_DIV5, - FCLK_DIV7, - MPLL_CLK1, - VID_PLL_CLK, - VID2_PLL_CLK, - GPLL_CLK, -}; - -static unsigned int fclk_div_table[] = { - 4, /* mux 0 */ - 3, /* mux 1 */ - 5, /* mux 2 */ - 7, /* mux 3 */ - 2, /* invalid */ -}; - -/* gxbb, gxtvbb, gxl, gxm, txl, axg, fpll=2000M */ -static unsigned int vpu_clk_table[10][3] = { - /* frequency clk_mux div */ - {100000000, FCLK_DIV5, 3}, /* 0 */ - {166667000, FCLK_DIV3, 3}, /* 1 */ - {200000000, FCLK_DIV5, 1}, /* 2 */ - {250000000, FCLK_DIV4, 1}, /* 3 */ - {333333000, FCLK_DIV3, 1}, /* 4 */ - {400000000, FCLK_DIV5, 0}, /* 5 */ - {500000000, FCLK_DIV4, 0}, /* 6 */ - {666667000, FCLK_DIV3, 0}, /* 7 */ - {696000000, GPLL_CLK, 0}, /* 8 */ - {850000000, GPLL_CLK, 0}, /* 9 */ /* invalid */ -}; - -/* ************************************************ */ - -#endif diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.c b/drivers/amlogic/media/common/vpu/vpu_ctrl.c deleted file mode 100644 index fdbcf635b7dd..000000000000 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * drivers/amlogic/media/common/vpu/vpu_ctrl.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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 -#include -#include -#include -#include -#include -#include -#include "vpu_reg.h" -#include "vpu.h" -#include "vpu_module.h" - -static spinlock_t vpu_mem_lock; -static spinlock_t vpu_clk_gate_lock; - -/* *********************************************** */ -/* VPU_MEM_PD control */ -/* *********************************************** */ -/* - * Function: switch_vpu_mem_pd_vmod - * switch vpu memory power down by specified vmod - * - * Parameters: - * vmod - unsigned int, must be the following constants: - * VPU_MOD, supported by vpu_mod_e - * flag - int, on/off switch flag, must be one of the following constants: - * VPU_MEM_POWER_ON - * VPU_MEM_POWER_DOWN - * - * Example: - * switch_vpu_mem_pd_vmod(VPU_VENCP, VPU_MEM_POWER_ON); - * switch_vpu_mem_pd_vmod(VPU_VIU_OSD1, VPU_MEM_POWER_DOWN); - * - */ -static void switch_vpu_mem_pd_gx(unsigned int vmod, int flag) -{ - unsigned long flags = 0; - unsigned int _reg0, _reg1, _reg2; - unsigned int val; - - spin_lock_irqsave(&vpu_mem_lock, flags); - - val = (flag == VPU_MEM_POWER_ON) ? 0 : 3; - _reg0 = HHI_VPU_MEM_PD_REG0; - _reg1 = HHI_VPU_MEM_PD_REG1; - _reg2 = HHI_VPU_MEM_PD_REG2; - - switch (vmod) { - case VPU_VIU_OSD1: - vpu_hiu_setb(_reg0, val, 0, 2); - break; - case VPU_VIU_OSD2: - vpu_hiu_setb(_reg0, val, 2, 2); - break; - case VPU_VIU_VD1: - vpu_hiu_setb(_reg0, val, 4, 2); - break; - case VPU_VIU_VD2: - vpu_hiu_setb(_reg0, val, 6, 2); - break; - case VPU_VIU_CHROMA: - vpu_hiu_setb(_reg0, val, 8, 2); - break; - case VPU_VIU_OFIFO: - vpu_hiu_setb(_reg0, val, 10, 2); - break; - case VPU_VIU_SCALE: - vpu_hiu_setb(_reg0, val, 12, 2); - break; - case VPU_VIU_OSD_SCALE: - vpu_hiu_setb(_reg0, val, 14, 2); - break; - case VPU_VIU_VDIN0: - vpu_hiu_setb(_reg0, val, 16, 2); - break; - case VPU_VIU_VDIN1: - vpu_hiu_setb(_reg0, val, 18, 2); - break; - case VPU_PIC_ROT1: - case VPU_VIU_SRSCL: - vpu_hiu_setb(_reg0, val, 20, 2); - break; - case VPU_PIC_ROT2: - case VPU_VIU_OSDSR: - case VPU_AFBC_DEC1: - vpu_hiu_setb(_reg0, val, 22, 2); - break; - case VPU_PIC_ROT3: - vpu_hiu_setb(_reg0, val, 24, 2); - break; - case VPU_DI_PRE: - vpu_hiu_setb(_reg0, val, 26, 2); - break; - case VPU_DI_POST: - vpu_hiu_setb(_reg0, val, 28, 2); - break; - case VPU_SHARP: - vpu_hiu_setb(_reg0, val, 30, 2); - break; - case VPU_VIU2_OSD1: - vpu_hiu_setb(_reg1, val, 0, 2); - break; - case VPU_VIU2_OSD2: - vpu_hiu_setb(_reg1, val, 2, 2); - break; - case VPU_VIU2_VD1: - vpu_hiu_setb(_reg1, val, 4, 2); - break; - case VPU_VIU2_CHROMA: - vpu_hiu_setb(_reg1, val, 6, 2); - break; - case VPU_VIU2_OFIFO: - vpu_hiu_setb(_reg1, val, 8, 2); - break; - case VPU_VIU2_SCALE: - vpu_hiu_setb(_reg1, val, 10, 2); - break; - case VPU_VIU2_OSD_SCALE: - vpu_hiu_setb(_reg1, val, 12, 2); - break; - case VPU_VDIN_AM_ASYNC: - case VPU_VPU_ARB: - vpu_hiu_setb(_reg1, val, 14, 2); - break; - case VPU_VDISP_AM_ASYNC: - case VPU_AFBC_DEC: - case VPU_OSD1_AFBCD: - case VPU_AFBC_DEC0: - vpu_hiu_setb(_reg1, val, 16, 2); - break; - case VPU_VENCP: - vpu_hiu_setb(_reg1, val, 20, 2); - break; - case VPU_VENCL: - vpu_hiu_setb(_reg1, val, 22, 2); - break; - case VPU_VENCI: - vpu_hiu_setb(_reg1, val, 24, 2); - break; - case VPU_ISP: - vpu_hiu_setb(_reg1, val, 26, 2); - break; - case VPU_CVD2: - case VPU_LDIM_STTS: - vpu_hiu_setb(_reg1, val, 28, 2); - break; - case VPU_ATV_DMD: - case VPU_XVYCC_LUT: - vpu_hiu_setb(_reg1, val, 30, 2); - break; - case VPU_VIU1_WM: - if ((vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - vpu_hiu_setb(_reg2, val, 0, 2); - } - break; - default: - VPUPR("switch_vpu_mem_pd: unsupport vpu mod: %d\n", vmod); - break; - } - - spin_unlock_irqrestore(&vpu_mem_lock, flags); -} - -static void switch_vpu_mem_pd_axg(unsigned int vmod, int flag) -{ - unsigned long flags = 0; - unsigned int _reg0; - unsigned int val; - - spin_lock_irqsave(&vpu_mem_lock, flags); - - val = (flag == VPU_MEM_POWER_ON) ? 0 : 3; - _reg0 = HHI_VPU_MEM_PD_REG0; - - switch (vmod) { - case VPU_VIU_OSD1: - vpu_hiu_setb(_reg0, val, 0, 2); - break; - case VPU_VIU_OFIFO: - vpu_hiu_setb(_reg0, val, 2, 2); - break; - case VPU_VPU_ARB: - vpu_hiu_setb(_reg0, val, 4, 2); - break; - case VPU_VENCI: - vpu_hiu_setb(_reg0, val, 6, 2); - break; - default: - VPUPR("switch_vpu_mem_pd: unsupport vpu mod: %d\n", vmod); - break; - } - - spin_unlock_irqrestore(&vpu_mem_lock, flags); -} - -void switch_vpu_mem_pd_vmod(unsigned int vmod, int flag) -{ - int ret = 0; - - ret = vpu_chip_valid_check(); - if (ret) - return; - - switch (vpu_chip_type) { - case VPU_CHIP_AXG: - switch_vpu_mem_pd_axg(vmod, flag); - break; - default: - switch_vpu_mem_pd_gx(vmod, flag); - break; - } - - if (vpu_debug_print_flag) { - VPUPR("switch_vpu_mem_pd: %s %s\n", - vpu_mod_table[vmod], - ((flag == VPU_MEM_POWER_ON) ? "ON" : "OFF")); - dump_stack(); - } -} - -/* - * Function: get_vpu_mem_pd_vmod - * switch vpu memory power down by specified vmod - * - * Parameters: - * vmod - unsigned int, must be the following constants: - * VPU_MOD, supported by vpu_mod_e - * - * Returns: - * int, 0 for power on, 1 for power down, -1 for error - * - * Example: - * ret = get_vpu_mem_pd_vmod(VPU_VENCP); - * ret = get_vpu_mem_pd_vmod(VPU_VIU_OSD1); - * - */ -#define VPU_MEM_PD_ERR 0xffff - -static int get_vpu_mem_pd_gx(unsigned int vmod) -{ - unsigned int _reg0, _reg1, _reg2; - unsigned int val = VPU_MEM_PD_ERR; - - _reg0 = HHI_VPU_MEM_PD_REG0; - _reg1 = HHI_VPU_MEM_PD_REG1; - _reg2 = HHI_VPU_MEM_PD_REG2; - - switch (vmod) { - case VPU_VIU_OSD1: - val = vpu_hiu_getb(_reg0, 0, 2); - break; - case VPU_VIU_OSD2: - val = vpu_hiu_getb(_reg0, 2, 2); - break; - case VPU_VIU_VD1: - val = vpu_hiu_getb(_reg0, 4, 2); - break; - case VPU_VIU_VD2: - val = vpu_hiu_getb(_reg0, 6, 2); - break; - case VPU_VIU_CHROMA: - val = vpu_hiu_getb(_reg0, 8, 2); - break; - case VPU_VIU_OFIFO: - val = vpu_hiu_getb(_reg0, 10, 2); - break; - case VPU_VIU_SCALE: - val = vpu_hiu_getb(_reg0, 12, 2); - break; - case VPU_VIU_OSD_SCALE: - val = vpu_hiu_getb(_reg0, 14, 2); - break; - case VPU_VIU_VDIN0: - val = vpu_hiu_getb(_reg0, 16, 2); - break; - case VPU_VIU_VDIN1: - val = vpu_hiu_getb(_reg0, 18, 2); - break; - case VPU_PIC_ROT1: - case VPU_VIU_SRSCL: - val = vpu_hiu_getb(_reg0, 20, 2); - break; - case VPU_PIC_ROT2: - case VPU_VIU_OSDSR: - case VPU_AFBC_DEC1: - val = vpu_hiu_getb(_reg0, 22, 2); - break; - case VPU_PIC_ROT3: - val = vpu_hiu_getb(_reg0, 24, 2); - break; - case VPU_DI_PRE: - val = vpu_hiu_getb(_reg0, 26, 2); - break; - case VPU_DI_POST: - val = vpu_hiu_getb(_reg0, 28, 2); - break; - case VPU_SHARP: - val = vpu_hiu_getb(_reg0, 30, 2); - break; - case VPU_VIU2_OSD1: - val = vpu_hiu_getb(_reg1, 0, 2); - break; - case VPU_VIU2_OSD2: - val = vpu_hiu_getb(_reg1, 2, 2); - break; - case VPU_VIU2_VD1: - val = vpu_hiu_getb(_reg1, 4, 2); - break; - case VPU_VIU2_CHROMA: - val = vpu_hiu_getb(_reg1, 6, 2); - break; - case VPU_VIU2_OFIFO: - val = vpu_hiu_getb(_reg1, 8, 2); - break; - case VPU_VIU2_SCALE: - val = vpu_hiu_getb(_reg1, 10, 2); - break; - case VPU_VIU2_OSD_SCALE: - val = vpu_hiu_getb(_reg1, 12, 2); - break; - case VPU_VDIN_AM_ASYNC: - case VPU_VPU_ARB: - val = vpu_hiu_getb(_reg1, 14, 2); - break; - case VPU_VDISP_AM_ASYNC: - case VPU_AFBC_DEC: - case VPU_OSD1_AFBCD: - case VPU_AFBC_DEC0: - val = vpu_hiu_getb(_reg1, 16, 2); - break; - case VPU_VENCP: - val = vpu_hiu_getb(_reg1, 20, 2); - break; - case VPU_VENCL: - val = vpu_hiu_getb(_reg1, 22, 2); - break; - case VPU_VENCI: - val = vpu_hiu_getb(_reg1, 24, 2); - break; - case VPU_ISP: - val = vpu_hiu_getb(_reg1, 26, 2); - break; - case VPU_CVD2: - case VPU_LDIM_STTS: - val = vpu_hiu_getb(_reg1, 28, 2); - break; - case VPU_ATV_DMD: - case VPU_XVYCC_LUT: - val = vpu_hiu_getb(_reg1, 30, 2); - break; - case VPU_VIU1_WM: - if ((vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - val = vpu_hiu_getb(_reg2, 0, 2); - } else { - val = VPU_MEM_PD_ERR; - } - break; - default: - val = VPU_MEM_PD_ERR; - break; - } - - return val; -} - -static int get_vpu_mem_pd_axg(unsigned int vmod) -{ - unsigned int _reg0; - unsigned int val = VPU_MEM_PD_ERR; - - _reg0 = HHI_VPU_MEM_PD_REG0; - - switch (vmod) { - case VPU_VIU_OSD1: - val = vpu_hiu_getb(_reg0, 0, 2); - break; - case VPU_VIU_OFIFO: - val = vpu_hiu_getb(_reg0, 2, 2); - break; - case VPU_VPU_ARB: - val = vpu_hiu_getb(_reg0, 4, 2); - break; - case VPU_VENCL: - val = vpu_hiu_getb(_reg0, 6, 2); - break; - default: - val = VPU_MEM_PD_ERR; - break; - } - - return val; -} - -int get_vpu_mem_pd_vmod(unsigned int vmod) -{ - int ret = 0; - - ret = vpu_chip_valid_check(); - if (ret) - return -1; - - switch (vpu_chip_type) { - case VPU_CHIP_AXG: - ret = get_vpu_mem_pd_axg(vmod); - break; - default: - ret = get_vpu_mem_pd_gx(vmod); - break; - } - - if (ret == 0) - return VPU_MEM_POWER_ON; - else if ((ret == 0x3) || (ret == 0xf)) - return VPU_MEM_POWER_DOWN; - else - return -1; -} - -/* *********************************************** */ -/* VPU_CLK_GATE control */ -/* *********************************************** */ -/* - * Function: switch_vpu_clk_gate_vmod - * switch vpu clk gate by specified vmod - * - * Parameters: - * vmod - unsigned int, must be the following constants: - * VPU_MOD, supported by vpu_mod_e - * flag - int, on/off switch flag, must be one of the following constants: - * VPU_CLK_GATE_ON - * VPU_CLK_GATE_OFF - * - * Example: - * switch_vpu_clk_gate_vmod(VPU_VENCP, VPU_CLK_GATE_ON); - * switch_vpu_clk_gate_vmod(VPU_VPP, VPU_CLK_GATE_OFF); - * - */ -void switch_vpu_clk_gate_vmod(unsigned int vmod, int flag) -{ - unsigned long flags = 0; - unsigned int val; - int ret = 0; - - ret = vpu_chip_valid_check(); - if (ret) - return; - - spin_lock_irqsave(&vpu_clk_gate_lock, flags); - - val = (flag == VPU_CLK_GATE_ON) ? 1 : 0; - - switch (vmod) { - case VPU_VPU_TOP: - vpu_vcbus_setb(VPU_CLK_GATE, val, 1, 1); /* vpu_system_clk */ - break; - case VPU_VPU_CLKB: - if ((vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - /* clkb_gen_en */ - vpu_vcbus_setb(VPU_CLK_GATE, val, 17, 1); - } - if ((vpu_chip_type == VPU_CHIP_GXBB) || - (vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - /* clkb_gate */ - vpu_vcbus_setb(VPU_CLK_GATE, val, 16, 1); - } - break; - case VPU_RDMA: - if ((vpu_chip_type == VPU_CHIP_GXBB) || - (vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - vpu_vcbus_setb(VPU_CLK_GATE, val, 15, 1); /* rdma_clk */ - } - break; - case VPU_VLOCK: - vpu_vcbus_setb(VPU_CLK_GATE, val, 14, 1); - break; - case VPU_MISC: - vpu_vcbus_setb(VPU_CLK_GATE, val, 6, 1); /* hs,vs,interrupt */ - break; - case VPU_VENC_DAC: - /* clk for dac(r/w reg) */ - /*vpu_vcbus_setb(VPU_CLK_GATE, val, 12, 1);*/ - vpu_hiu_setb(HHI_GCLK_OTHER, val, 10, 1); /* dac top clk */ - break; - case VPU_VENCP: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(VPU_CLK_GATE, - ((1 << 3) || (1 << 0))); - vpu_hiu_set_mask(HHI_GCLK_OTHER, - ((1 << 9) || (0x3 << 3))); - } else { - vpu_vcbus_clr_mask(VPU_CLK_GATE, - ((1 << 3) || (1 << 0))); - vpu_hiu_clr_mask(HHI_GCLK_OTHER, - ((1 << 9) || (0x3 << 3))); - } - break; - case VPU_VENCL: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(VPU_CLK_GATE, (0x3 << 4)); - vpu_hiu_set_mask(HHI_GCLK_OTHER, (0x7 << 23)); - } else { - vpu_vcbus_clr_mask(VPU_CLK_GATE, (0x3 << 4)); - vpu_hiu_clr_mask(HHI_GCLK_OTHER, (0x7 << 23)); - } - break; - case VPU_VENCI: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(VPU_CLK_GATE, (0x3 << 10)); - vpu_hiu_set_mask(HHI_GCLK_OTHER, - ((1 << 8) | (0x3 << 1))); - } else { - vpu_vcbus_clr_mask(VPU_CLK_GATE, (0x3 << 10)); - vpu_hiu_clr_mask(HHI_GCLK_OTHER, - ((1 << 8) | (0x3 << 1))); - } - break; - case VPU_VIU_VDIN0: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(VDIN0_COM_GCLK_CTRL, 0x3f3ffff2); - vpu_vcbus_set_mask(VDIN0_COM_GCLK_CTRL2, 0xf); - } else { - vpu_vcbus_clr_mask(VDIN0_COM_GCLK_CTRL, 0x3f3ffff0); - vpu_vcbus_clr_mask(VDIN0_COM_GCLK_CTRL2, 0xf); - } - break; - case VPU_VIU_VDIN1: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(VDIN1_COM_GCLK_CTRL, 0x3f3ffff2); - vpu_vcbus_set_mask(VDIN1_COM_GCLK_CTRL2, 0xf); - } else { - vpu_vcbus_clr_mask(VDIN1_COM_GCLK_CTRL, 0x3f3ffff0); - vpu_vcbus_clr_mask(VDIN1_COM_GCLK_CTRL2, 0xf); - } - break; - case VPU_DI: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(DI_CLKG_CTRL, 0x1d1e0003); - if ((vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - vpu_vcbus_set_mask(DI_CLKG_CTRL, 0x60200000); - } - } else { - vpu_vcbus_clr_mask(DI_CLKG_CTRL, 0x1d1e0003); - if ((vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - vpu_vcbus_clr_mask(DI_CLKG_CTRL, 0x60200000); - } - } - break; - case VPU_VPP: - if (flag == VPU_CLK_GATE_ON) { - vpu_vcbus_set_mask(VPP_GCLK_CTRL0, 0xffff3fcc); - if ((vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - vpu_vcbus_set_mask(VPP_GCLK_CTRL0, 0xc030); - } - vpu_vcbus_set_mask(VPP_GCLK_CTRL1, 0xfff); - vpu_vcbus_set_mask(VPP_SC_GCLK_CTRL, 0x03fc0ffc); - vpu_vcbus_set_mask(VPP_XVYCC_GCLK_CTRL, 0x3ffff); - } else { - vpu_vcbus_clr_mask(VPP_GCLK_CTRL0, 0xffff3fcc); - if ((vpu_chip_type == VPU_CHIP_GXTVBB) || - (vpu_chip_type == VPU_CHIP_GXL) || - (vpu_chip_type == VPU_CHIP_GXM) || - (vpu_chip_type == VPU_CHIP_TXL)) { - vpu_vcbus_clr_mask(VPP_GCLK_CTRL0, 0xc030); - } - vpu_vcbus_clr_mask(VPP_GCLK_CTRL1, 0xfff); - vpu_vcbus_clr_mask(VPP_SC_GCLK_CTRL, 0x03fc0ffc); - vpu_vcbus_clr_mask(VPP_XVYCC_GCLK_CTRL, 0x3ffff); - } - break; - default: - VPUPR("switch_vpu_clk_gate: unsupport vpu mod\n"); - break; - } - - spin_unlock_irqrestore(&vpu_clk_gate_lock, flags); - - if (vpu_debug_print_flag) { - VPUPR("switch_vpu_clk_gate: %s %s\n", - vpu_mod_table[vmod], - ((flag == VPU_CLK_GATE_ON) ? "ON" : "OFF")); - dump_stack(); - } -} - -/* *********************************************** */ - -void vpu_ctrl_probe(void) -{ - spin_lock_init(&vpu_mem_lock); - spin_lock_init(&vpu_clk_gate_lock); -} - diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h new file mode 100644 index 000000000000..48a787e3738e --- /dev/null +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -0,0 +1,335 @@ +/* + * drivers/amlogic/media/common/vpu/vpu_ctrl.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 __VPU_CTRL_H__ +#define __VPU_CTRL_H__ +#include +#include "vpu.h" + +/* #define LIMIT_VPU_CLK_LOW */ + +#define VPU_REG_END 0xffff + +/* ************************************************ */ +/* VPU frequency table, important. DO NOT modify!! */ +/* ************************************************ */ + +#define CLK_FPLL_FREQ 2000 /* MHz */ + +/* GXBB */ +/* freq max=666M, default=666M */ +#define CLK_LEVEL_DFT_GXBB 7 +#define CLK_LEVEL_MAX_GXBB 8 + +/* GXTVBB */ +/* freq max=666M, default=666M */ +#define CLK_LEVEL_DFT_GXTVBB 7 +#define CLK_LEVEL_MAX_GXTVBB 8 + +/* GXL */ +/* freq max=666M, default=666M */ +#define CLK_LEVEL_DFT_GXL 7 +#define CLK_LEVEL_MAX_GXL 8 + +/* GXM */ +/* freq max=666M, default=666M */ +#define CLK_LEVEL_DFT_GXM 7 +#define CLK_LEVEL_MAX_GXM 8 + +/* TXLX */ +/* freq max=666M, default=666M */ +#define CLK_LEVEL_DFT_TXLX 7 +#define CLK_LEVEL_MAX_TXLX 8 + +/* AXG */ +/* freq max=250M, default=250M */ +#define CLK_LEVEL_DFT_AXG 3 +#define CLK_LEVEL_MAX_AXG 4 + +/* vpu clk setting */ +enum vpu_mux_e { + FCLK_DIV4 = 0, + FCLK_DIV3, + FCLK_DIV5, + FCLK_DIV7, + MPLL_CLK1, + VID_PLL_CLK, + VID2_PLL_CLK, + GPLL_CLK, +}; + +static unsigned int fclk_div_table[] = { + 4, /* mux 0 */ + 3, /* mux 1 */ + 5, /* mux 2 */ + 7, /* mux 3 */ + 2, /* invalid */ +}; + +static unsigned int vpu_clk_table[10][3] = { + /* frequency clk_mux div */ + {100000000, FCLK_DIV5, 3}, /* 0 */ + {166666667, FCLK_DIV3, 3}, /* 1 */ + {200000000, FCLK_DIV5, 1}, /* 2 */ + {250000000, FCLK_DIV4, 1}, /* 3 */ + {333333333, FCLK_DIV3, 1}, /* 4 */ + {400000000, FCLK_DIV5, 0}, /* 5 */ + {500000000, FCLK_DIV4, 0}, /* 6 */ + {666666667, FCLK_DIV3, 0}, /* 7 */ + {696000000, GPLL_CLK, 0}, /* 8 */ + {850000000, GPLL_CLK, 0}, /* 9 */ /* invalid */ +}; + +/* ************************************************ */ + + +/* ******************************************************* */ +/* VPU memory power down table */ +/* ******************************************************* */ +static struct vpu_ctrl_s vpu_mem_pd_gxb[] = { + /* vpu module, reg, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 20, 2}, + {VPU_VIU_OSDSR, HHI_VPU_MEM_PD_REG0, 22, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 30, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 16, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 24, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_mem_pd_gxtvbb[] = { + /* vpu module, reg, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 20, 2}, + {VPU_AFBC_DEC1, HHI_VPU_MEM_PD_REG0, 22, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 30, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 16, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 24, 2}, + {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 28, 2}, + {VPU_XVYCC_LUT, HHI_VPU_MEM_PD_REG1, 30, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_mem_pd_gxl[] = { + /* vpu module, reg, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 18, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 30, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 16, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 24, 2}, + {VPU_VIU1_WM, HHI_VPU_MEM_PD_REG2, 0, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_mem_pd_txlx[] = { + /* vpu module, reg, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 20, 2}, + {VPU_AFBC_DEC1, HHI_VPU_MEM_PD_REG0, 22, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 30, 2}, + {VPU_VKSTONE, HHI_VPU_MEM_PD_REG1, 4, 2}, + {VPU_DOLBY_CORE3, HHI_VPU_MEM_PD_REG1, 6, 2}, + {VPU_DOLBY0, HHI_VPU_MEM_PD_REG1, 8, 2}, + {VPU_DOLBY1A, HHI_VPU_MEM_PD_REG1, 10, 2}, + {VPU_DOLBY1B, HHI_VPU_MEM_PD_REG1, 12, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 16, 2}, + {VPU_OSD_AFBCD, HHI_VPU_MEM_PD_REG1, 18, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 24, 2}, + {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 28, 2}, + {VPU_XVYCC_LUT, HHI_VPU_MEM_PD_REG1, 30, 2}, + {VPU_VIU1_WM, HHI_VPU_MEM_PD_REG2, 0, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_mem_pd_axg[] = { + /* vpu module, reg, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 2, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG0, 4, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG0, 6, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0}, +}; + + +/* ******************************************************* */ +/* VPU clock gate table */ +/* ******************************************************* */ +static struct vpu_ctrl_s vpu_clk_gate_gxb[] = { + /* vpu module, reg, bit, len */ + {VPU_VPU_TOP, VPU_CLK_GATE, 1, 1}, /* vpu_system_clk */ + {VPU_VPU_CLKB, VPU_CLK_GATE, 16, 1}, + {VPU_RDMA, VPU_CLK_GATE, 15, 1}, /* rdma_clk */ + {VPU_VLOCK, VPU_CLK_GATE, 14, 1}, + {VPU_MISC, VPU_CLK_GATE, 6, 1}, /* hs,vs interrupt*/ + {VPU_VENCP, VPU_CLK_GATE, 3, 1}, + {VPU_VENCP, VPU_CLK_GATE, 0, 1}, + {VPU_VENCL, VPU_CLK_GATE, 4, 2}, + {VPU_VENCI, VPU_CLK_GATE, 10, 2}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 24, 6}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 4, 18}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 1, 1}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL2, 0, 4}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 24, 6}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 4, 18}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 1, 1}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL2, 0, 4}, + {VPU_DI, DI_CLKG_CTRL, 26, 3}, + {VPU_DI, DI_CLKG_CTRL, 24, 1}, + {VPU_DI, DI_CLKG_CTRL, 17, 4}, + {VPU_DI, DI_CLKG_CTRL, 0, 2}, + {VPU_VPP, VPP_GCLK_CTRL0, 16, 16}, + {VPU_VPP, VPP_GCLK_CTRL0, 6, 8}, + {VPU_VPP, VPP_GCLK_CTRL0, 2, 2}, + {VPU_VPP, VPP_GCLK_CTRL1, 0, 12}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 18, 8}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 2, 10}, + {VPU_VPP, VPP_XVYCC_GCLK_CTRL, 0, 18}, + {VPU_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_clk_gate_gxl[] = { + /* vpu module, reg, bit, len */ + {VPU_VPU_TOP, VPU_CLK_GATE, 1, 1}, /* vpu_system_clk */ + {VPU_VPU_CLKB, VPU_CLK_GATE, 16, 2}, + {VPU_RDMA, VPU_CLK_GATE, 15, 1}, /* rdma_clk */ + {VPU_VLOCK, VPU_CLK_GATE, 14, 1}, + {VPU_MISC, VPU_CLK_GATE, 6, 1}, /* hs,vs interrupt*/ + {VPU_VENCP, VPU_CLK_GATE, 3, 1}, + {VPU_VENCP, VPU_CLK_GATE, 0, 1}, + {VPU_VENCL, VPU_CLK_GATE, 4, 2}, + {VPU_VENCI, VPU_CLK_GATE, 10, 2}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 24, 6}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 4, 18}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 1, 1}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL2, 0, 4}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 24, 6}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 4, 18}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 1, 1}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL2, 0, 4}, + {VPU_DI, DI_CLKG_CTRL, 26, 5}, + {VPU_DI, DI_CLKG_CTRL, 24, 1}, + {VPU_DI, DI_CLKG_CTRL, 17, 5}, + {VPU_DI, DI_CLKG_CTRL, 0, 2}, + {VPU_VPP, VPP_GCLK_CTRL0, 2, 30}, + {VPU_VPP, VPP_GCLK_CTRL1, 0, 12}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 18, 8}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 2, 10}, + {VPU_VPP, VPP_XVYCC_GCLK_CTRL, 0, 18}, + {VPU_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_clk_gate_txlx[] = { + /* vpu module, reg, bit, len */ + {VPU_VPU_TOP, VPU_CLK_GATE, 1, 1}, /* vpu_system_clk */ + {VPU_VPU_CLKB, VPU_CLK_GATE, 16, 1}, + {VPU_RDMA, VPU_CLK_GATE, 15, 1}, /* rdma_clk */ + {VPU_VLOCK, VPU_CLK_GATE, 14, 1}, + {VPU_MISC, VPU_CLK_GATE, 6, 1}, /* hs,vs interrupt*/ + {VPU_VENCP, VPU_CLK_GATE, 3, 1}, + {VPU_VENCP, VPU_CLK_GATE, 0, 1}, + {VPU_VENCL, VPU_CLK_GATE, 4, 2}, + {VPU_VENCI, VPU_CLK_GATE, 10, 2}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 24, 6}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 4, 18}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL, 1, 1}, + {VPU_VIU_VDIN0, VDIN0_COM_GCLK_CTRL2, 0, 4}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 24, 6}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 4, 18}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL, 1, 1}, + {VPU_VIU_VDIN1, VDIN1_COM_GCLK_CTRL2, 0, 4}, + {VPU_VPP, VPP_GCLK_CTRL0, 2, 30}, + {VPU_VPP, VPP_GCLK_CTRL1, 0, 12}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 18, 8}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 2, 10}, + {VPU_VPP, VPP_XVYCC_GCLK_CTRL, 0, 18}, + {VPU_MAX, VPU_REG_END, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_clk_gate_axg[] = { + /* vpu module, reg, bit, len */ + {VPU_VPU_TOP, VPU_CLK_GATE, 1, 1}, + {VPU_VLOCK, VPU_CLK_GATE, 14, 1}, + {VPU_MISC, VPU_CLK_GATE, 6, 1}, + {VPU_VENCL, VPU_CLK_GATE, 4, 2}, + {VPU_VPP, VPP_GCLK_CTRL0, 16, 16}, + {VPU_VPP, VPP_GCLK_CTRL0, 6, 8}, + {VPU_VPP, VPP_GCLK_CTRL0, 2, 2}, + {VPU_VPP, VPP_GCLK_CTRL1, 0, 12}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 18, 8}, + {VPU_VPP, VPP_SC_GCLK_CTRL, 2, 10}, + {VPU_VPP, VPP_XVYCC_GCLK_CTRL, 0, 18}, + {VPU_MAX, VPU_REG_END, 0, 0}, +}; + +/* ************************************************ */ + +#endif diff --git a/drivers/amlogic/media/common/vpu/vpu_module.h b/drivers/amlogic/media/common/vpu/vpu_module.h index 61b570119b37..620467900e03 100644 --- a/drivers/amlogic/media/common/vpu/vpu_module.h +++ b/drivers/amlogic/media/common/vpu/vpu_module.h @@ -32,41 +32,36 @@ static char *vpu_mod_table[] = { "viu_osd_scaler", "viu_vdin0", "viu_vdin1", - "pic_rot1", - "pic_rot2", - "pic_rot3", "viu_super_scaler", "viu_osd_super_scaler", - "afbc_dec", + "afbc_dec1", "di_pre", "di_post", "viu_sharpness_line_buffer", "viu2_osd1", "viu2_osd2", - "d2d3", "viu2_vd1", "viu2_chroma", "viu2_ofifo", "viu2_scaler", "viu2_osd_scaler", - "vdin_arbitor_am_async", + "vkstone", + "dolby_core3", + "dolby0", + "dolby_1a", + "dolby_1b", "vpu_arb", - "display_arbitor_am_async", - "osd1_afbcd", - "afbc_dec0", "afbc_dec", - "vpu_arbitor2_am_async", + "osd_afbcd", "vencp", "vencl", "venci", - "isp", - "cvd2", - "atv_dmd", "ldim_stts", "xvycc_lut", "viu1_water_mark", + "vpu_mod_max", /* for clk_gate */ "vpu_top", @@ -79,6 +74,11 @@ static char *vpu_mod_table[] = { "vpp", "none", + "none", + "none", + "none", + "none", + "none", }; #endif diff --git a/drivers/amlogic/media/common/vpu/vpu_reg.c b/drivers/amlogic/media/common/vpu/vpu_reg.c index ac3794b2eb1a..3e6f61fb3921 100644 --- a/drivers/amlogic/media/common/vpu/vpu_reg.c +++ b/drivers/amlogic/media/common/vpu/vpu_reg.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "vpu_reg.h" #include "vpu.h" @@ -30,156 +30,14 @@ * ********************************* */ -#define VPU_MAP_HIUBUS 0 -#define VPU_MAP_VCBUS 1 - -struct reg_map_s { - unsigned int base_addr; - unsigned int size; - void __iomem *p; - int flag; -}; - -static struct reg_map_s *vpu_map; -static int vpu_map_num; - -static struct reg_map_s vpu_reg_maps_gx[] = { - { /* HIU */ - .base_addr = 0xc883c000, - .size = 0x400, - }, - { /* VCBUS */ - .base_addr = 0xd0100000, - .size = 0xa000, - }, -}; - -static struct reg_map_s vpu_reg_maps_axg[] = { - { /* HIU */ - .base_addr = 0xff63c000, - .size = 0x400, - }, - { /* VCBUS */ - .base_addr = 0xff900000, - .size = 0xa000, - }, -}; - -int vpu_ioremap(void) -{ - int i; - int ret = 0; - - switch (vpu_chip_type) { - case VPU_CHIP_GXBB: - case VPU_CHIP_GXTVBB: - case VPU_CHIP_GXL: - case VPU_CHIP_GXM: - case VPU_CHIP_TXL: - vpu_map = vpu_reg_maps_gx; - vpu_map_num = ARRAY_SIZE(vpu_reg_maps_gx); - break; - case VPU_CHIP_AXG: - vpu_map = vpu_reg_maps_axg; - vpu_map_num = ARRAY_SIZE(vpu_reg_maps_axg); - break; - default: - vpu_map = NULL; - vpu_map_num = 0; - VPUERR("%s: invalid chip type\n", __func__); - break; - } - - for (i = 0; i < vpu_map_num; i++) { - vpu_map[i].p = ioremap(vpu_map[i].base_addr, vpu_map[i].size); - if (vpu_map[i].p == NULL) { - vpu_map[i].flag = 0; - VPUERR("VPU reg map failed: 0x%x\n", - vpu_map[i].base_addr); - ret = -1; - } else { - vpu_map[i].flag = 1; -#if 0 - VPUPR("VPU reg mapped: 0x%x -> %p\n", - vpu_map[i].base_addr, vpu_map[i].p); -#endif - } - } - return ret; -} - -static int vpu_ioremap_check(int n) -{ - if (vpu_map == NULL) - return -1; - if (n >= vpu_map_num) - return -1; - - if (vpu_map[n].flag == 0) { - VPUERR("reg 0x%x mapped error\n", vpu_map[n].base_addr); - return -1; - } - return 0; -} - -static void __iomem *vpu_hiu_reg_check(unsigned int _reg) -{ - void __iomem *p = NULL; - int reg_bus; - unsigned int reg_offset; - - reg_bus = VPU_MAP_HIUBUS; - if (vpu_ioremap_check(reg_bus)) - return NULL; - - reg_offset = REG_OFFSET_HIU(_reg); - if (reg_offset > vpu_map[reg_bus].size) { - VPUERR("invalid reg offset: 0x%02x\n", _reg); - return NULL; - } - p = vpu_map[reg_bus].p + reg_offset; - - return p; -} - -static void __iomem *vpu_vcbus_reg_check(unsigned int _reg) -{ - void __iomem *p = NULL; - int reg_bus; - unsigned int reg_offset; - - reg_bus = VPU_MAP_VCBUS; - if (vpu_ioremap_check(reg_bus)) - return NULL; - - reg_offset = REG_OFFSET_VCBUS(_reg); - if (reg_offset > vpu_map[reg_bus].size) { - VPUERR("invalid reg offset: 0x%04x\n", _reg); - return NULL; - } - p = vpu_map[reg_bus].p + reg_offset; - - return p; -} - unsigned int vpu_hiu_read(unsigned int _reg) { - void __iomem *p; - - p = vpu_hiu_reg_check(_reg); - if (p) - return readl(p); - else - return 0; + return aml_read_hiubus(_reg); }; void vpu_hiu_write(unsigned int _reg, unsigned int _value) { - void __iomem *p; - - p = vpu_hiu_reg_check(_reg); - if (p) - writel(_value, p); + aml_write_hiubus(_reg, _value); }; void vpu_hiu_setb(unsigned int _reg, unsigned int _value, @@ -208,22 +66,12 @@ void vpu_hiu_clr_mask(unsigned int _reg, unsigned int _mask) unsigned int vpu_vcbus_read(unsigned int _reg) { - void __iomem *p; - - p = vpu_vcbus_reg_check(_reg); - if (p) - return readl(p); - else - return 0; + return aml_read_vcbus(_reg); }; void vpu_vcbus_write(unsigned int _reg, unsigned int _value) { - void __iomem *p; - - p = vpu_vcbus_reg_check(_reg); - if (p) - writel(_value, p); + aml_write_vcbus(_reg, _value); }; void vpu_vcbus_setb(unsigned int _reg, unsigned int _value, diff --git a/drivers/amlogic/media/common/vpu/vpu_reg.h b/drivers/amlogic/media/common/vpu/vpu_reg.h index 10be91901910..8e3e21e5f665 100644 --- a/drivers/amlogic/media/common/vpu/vpu_reg.h +++ b/drivers/amlogic/media/common/vpu/vpu_reg.h @@ -27,22 +27,7 @@ * register define * ********************************* */ -/* base & offset */ -#define REG_BASE_AOBUS (0xc8100000L) -#define REG_BASE_CBUS (0xc1100000L) -#define REG_BASE_HIU (0xc883c000L) -#define REG_BASE_VCBUS (0xd0100000L) -#define REG_OFFSET_AOBUS(reg) ((reg)) -#define REG_OFFSET_CBUS(reg) ((reg << 2)) -#define REG_OFFSET_HIU(reg) (((reg & 0xff) << 2)) -#define REG_OFFSET_VCBUS(reg) ((reg << 2)) -/* memory mapping */ -#define REG_ADDR_AOBUS(reg) (REG_BASE_AOBUS + REG_OFFSET_AOBUS(reg)) -#define REG_ADDR_CBUS(reg) (REG_BASE_CBUS + REG_OFFSET_CBUS(reg)) -#define REG_ADDR_HIU(reg) (REG_BASE_HIU + REG_OFFSET_HIU(reg)) -#define REG_ADDR_VCBUS(reg) (REG_BASE_VCBUS + REG_OFFSET_VCBUS(reg)) -/* offset address */ #define AO_RTI_GEN_PWR_SLEEP0 ((0x00 << 10) | (0x3a << 2)) /* HHI bus */ diff --git a/include/linux/amlogic/media/vpu/vpu.h b/include/linux/amlogic/media/vpu/vpu.h index 96b059ca9f49..0fa66d838043 100644 --- a/include/linux/amlogic/media/vpu/vpu.h +++ b/include/linux/amlogic/media/vpu/vpu.h @@ -18,6 +18,9 @@ #ifndef __VPU_H__ #define __VPU_H__ +/* ************************************************ */ +/* VPU module define */ +/* ************************************************ */ enum vpu_mod_e { VPU_VIU_OSD1 = 0, /* reg0[1:0] //common */ VPU_VIU_OSD2, /* reg0[3:2] //common */ @@ -29,41 +32,36 @@ enum vpu_mod_e { VPU_VIU_OSD_SCALE, /* reg0[15:14] //common */ VPU_VIU_VDIN0, /* reg0[17:16] //common */ VPU_VIU_VDIN1, /* reg0[19:18] //common */ - VPU_PIC_ROT1, /* reg0[21:20] */ - VPU_PIC_ROT2, /* reg0[23:22] */ - VPU_PIC_ROT3, /* reg0[25:24] */ - VPU_VIU_SRSCL, /* reg0[21:20] //G9TV, GXBB, GXTVBB */ - VPU_VIU_OSDSR, /* reg0[23:22] //G9TV, GXBB */ - VPU_AFBC_DEC1, /* reg0[23:22] //GXTVBB */ + VPU_VIU_SRSCL, /* reg0[21:20] //GXBB, GXTVBB, TXLX */ + VPU_VIU_OSDSR, /* reg0[23:22] //GXBB */ + VPU_AFBC_DEC1, /* reg0[23:22] //GXTVBB, TXLX */ VPU_DI_PRE, /* reg0[27:26] //common */ VPU_DI_POST, /* reg0[29:28] //common */ - VPU_SHARP, /* reg0[31:30] //common */ + VPU_SHARP, /* reg0[31:30] //common */ VPU_VIU2_OSD1, /* reg1[1:0] */ VPU_VIU2_OSD2, /* reg1[3:2] */ - VPU_D2D3, /* reg1[3:0] //G9TV */ VPU_VIU2_VD1, /* reg1[5:4] */ VPU_VIU2_CHROMA, /* reg1[7:6] */ VPU_VIU2_OFIFO, /* reg1[9:8] */ VPU_VIU2_SCALE, /* reg1[11:10] */ VPU_VIU2_OSD_SCALE, /* reg1[13:12] */ - VPU_VDIN_AM_ASYNC, /* reg1[15:14] //G9TV */ - VPU_VPU_ARB, /* reg1[15:14] //GXBB, GXTVBB, GXL */ - VPU_VDISP_AM_ASYNC, /* reg1[17:16] //G9TV */ - VPU_OSD1_AFBCD, /* reg1[17:16] //GXTVBB */ - VPU_AFBC_DEC0, /* reg1[17:16] //GXTVBB */ - VPU_AFBC_DEC, /* reg1[17:16] //GXBB */ - VPU_VPUARB2_AM_ASYNC, /* reg1[19:18] //G9TV */ + VPU_VKSTONE, /* reg1[5:4] //TXLX */ + VPU_DOLBY_CORE3, /* reg1[7:6] //TXLX */ + VPU_DOLBY0, /* reg1[9:8] //TXLX */ + VPU_DOLBY1A, /* reg1[11:10] //TXLX */ + VPU_DOLBY1B, /* reg1[13:12] //TXLX */ + VPU_VPU_ARB, /* reg1[15:14] //GXBB, GXTVBB, GXL, TXLX */ + VPU_AFBC_DEC, /* reg1[17:16] //GXBB, GXTVBB, TXL, TXLX */ + VPU_OSD_AFBCD, /* reg1[19:18] //TXLX */ VPU_VENCP, /* reg1[21:20] //common */ VPU_VENCL, /* reg1[23:22] //common */ VPU_VENCI, /* reg1[25:24] //common */ - VPU_ISP, /* reg1[27:26] */ - VPU_CVD2, /* reg1[29:28] //G9TV, G9BB */ - VPU_ATV_DMD, /* reg1[31:30] //G9TV, G9BB */ - VPU_LDIM_STTS, /* reg1[29:28] //GXTVBB, GXL */ - VPU_XVYCC_LUT, /* reg1[31:30] //GXTVBB, GXL */ + VPU_LDIM_STTS, /* reg1[29:28] //GXTVBB, GXL, TXL, TXLX */ + VPU_XVYCC_LUT, /* reg1[31:30] //GXTVBB, GXL, TXL, TXLX */ - VPU_VIU1_WM, /* reg2[1:0] //GXL, TXL */ + VPU_VIU1_WM, /* reg2[1:0] //GXL, TXL, TXLX */ + VPU_MOD_MAX, /* for clk_gate */ VPU_VPU_TOP,