From 11b3e3c263e00aae411d397a574b1f145aa8842c Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Wed, 20 Mar 2019 17:37:08 +0800 Subject: [PATCH] ge2d: change ge2d to independent power [1/1] PD#SWPL-5391 Problem: change ge2d to independent power Solution: add independent power switch Verify: verified on SM1-AC200 board Change-Id: Ifce980fc88753db63317c11bc1126e492b677a64 Signed-off-by: Jian Cao --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 4 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 4 +- drivers/amlogic/media/common/ge2d/ge2d_io.h | 43 +++++++++++++++++ drivers/amlogic/media/common/ge2d/ge2d_main.c | 46 +++++++++++++++++++ drivers/amlogic/media/common/ge2d/ge2d_wq.c | 28 +++++++++++ drivers/amlogic/media/common/ge2d/ge2d_wq.h | 1 + include/linux/amlogic/media/ge2d/ge2d.h | 23 ++++++++++ 7 files changed, 145 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 7253639a8abe..dcedfdffaafc 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1192,9 +1192,9 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; dev_name = "ge2d"; - status = "disabled"; + status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index eab95f515145..f86c9c828d6b 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1192,9 +1192,9 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; dev_name = "ge2d"; - status = "disabled"; + status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/drivers/amlogic/media/common/ge2d/ge2d_io.h b/drivers/amlogic/media/common/ge2d/ge2d_io.h index 55f5b7505ccc..f8a3cb173202 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_io.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_io.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "ge2d_log.h" @@ -129,5 +130,47 @@ static inline void ge2d_reg_set_bits(uint32_t reg, (((value) & ((1L << (len)) - 1)) << (start)))); } +static void ge2d_hiu_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_hiubus(_reg, ((aml_read_hiubus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} +static void ge2d_ao_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_aobus(_reg, ((aml_read_aobus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} + +static void ge2d_c_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_cbus(_reg, ((aml_read_cbus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} + +static inline void ge2d_set_bus_bits(unsigned int bus_type, + unsigned int reg, unsigned int val, + unsigned int start, unsigned int len) +{ + switch (bus_type) { + case CBUS_BASE: + ge2d_c_setb(reg, val, start, len); + break; + case AOBUS_BASE: + ge2d_ao_setb(reg, val, start, len); + break; + case HIUBUS_BASE: + ge2d_hiu_setb(reg, val, start, len); + break; + default: + ge2d_log_err("unsupported bus type\n"); + break; + } +} #endif diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 7a768ce8a5be..459e164e8688 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -39,6 +39,7 @@ /* Amlogic Headers */ #include #include +#include #include #include #ifdef CONFIG_AMLOGIC_ION @@ -52,6 +53,7 @@ #define GE2D_CLASS_NAME "ge2d" #define MAX_GE2D_CLK 500000000 +#define HHI_MEM_PD_REG0 0x40 struct ge2d_device_s { char name[20]; @@ -1032,6 +1034,26 @@ static int ge2d_release(struct inode *inode, struct file *file) return -1; } +static struct ge2d_ctrl_s default_poweron_ctrl[] = { + /* power up ge2d */ + {AOBUS_BASE, AO_RTI_GEN_PWR_SLEEP0, 0, 19, 1, 0}, + /* Power up memory */ + {HIUBUS_BASE, HHI_MEM_PD_REG0, 0, 18, 8, 100}, + /* remove isolation */ + {AOBUS_BASE, AO_RTI_GEN_PWR_ISO0, 0, 19, 1, 0} + }; +static struct ge2d_ctrl_s default_poweroff_ctrl[] = { + /* add isolation */ + {AOBUS_BASE, AO_RTI_GEN_PWR_ISO0, 1, 19, 1, 0}, + /* Power down memory */ + {HIUBUS_BASE, HHI_MEM_PD_REG0, 0xff, 18, 8, 0}, + /* power down ge2d */ + {AOBUS_BASE, AO_RTI_GEN_PWR_SLEEP0, 1, 19, 1, 0} + }; + +struct ge2d_power_table_s default_poweron_table = {3, default_poweron_ctrl}; +struct ge2d_power_table_s default_poweroff_table = {3, default_poweroff_ctrl}; + static struct ge2d_device_data_s ge2d_gxl = { .ge2d_rate = 400000000, .src2_alp = 0, @@ -1039,6 +1061,7 @@ static struct ge2d_device_data_s ge2d_gxl = { .deep_color = 0, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_gxm = { @@ -1048,6 +1071,7 @@ static struct ge2d_device_data_s ge2d_gxm = { .deep_color = 0, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_txl = { @@ -1057,6 +1081,7 @@ static struct ge2d_device_data_s ge2d_txl = { .deep_color = 1, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_txlx = { @@ -1066,6 +1091,7 @@ static struct ge2d_device_data_s ge2d_txlx = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_axg = { @@ -1075,6 +1101,7 @@ static struct ge2d_device_data_s ge2d_axg = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_g12a = { @@ -1084,6 +1111,19 @@ static struct ge2d_device_data_s ge2d_g12a = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, +}; + +static struct ge2d_device_data_s ge2d_sm1 = { + .ge2d_rate = 500000000, + .src2_alp = 1, + .canvas_status = 0, + .deep_color = 1, + .hang_flag = 1, + .fifo = 1, + .has_self_pwr = 1, + .poweron_table = &default_poweron_table, + .poweroff_table = &default_poweroff_table, }; static const struct of_device_id ge2d_dt_match[] = { @@ -1111,6 +1151,10 @@ static const struct of_device_id ge2d_dt_match[] = { .compatible = "amlogic, ge2d-g12a", .data = &ge2d_g12a, }, + { + .compatible = "amlogic, ge2d-sm1", + .data = &ge2d_sm1, + }, {}, }; @@ -1171,6 +1215,7 @@ static int ge2d_probe(struct platform_device *pdev) goto failed1; } ge2d_log_info("clock clk_ge2d source %p\n", clk); + ge2d_pwr_config(true); clk_prepare_enable(clk); clk_vapb0 = devm_clk_get(&pdev->dev, "clk_vapb_0"); @@ -1240,6 +1285,7 @@ static int ge2d_remove(struct platform_device *pdev) ge2d_log_info("%s\n", __func__); ge2d_wq_deinit(); remove_ge2d_device(); + ge2d_pwr_config(false); return 0; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index 66ce8a1dacde..bc6fab6d6759 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Amlogic Headers */ #include @@ -45,6 +46,7 @@ #include "osd_io.h" #include "osd_hw.h" + #define OSD1_CANVAS_INDEX 0x40 #define OSD2_CANVAS_INDEX 0x43 #define OSD3_CANVAS_INDEX 0x41 @@ -118,6 +120,32 @@ static const int default_ge2d_color_lut[] = { GE2D_FORMAT_S32_ARGB,/* BPP_TYPE_32_ARGB=32, */ }; +void ge2d_pwr_config(bool enable) +{ + int i, table_size; + struct ge2d_ctrl_s tmp; + struct ge2d_ctrl_s *power_table; + + if (ge2d_meson_dev.has_self_pwr) { + if (enable) { + power_table = ge2d_meson_dev.poweron_table->power_btale; + table_size = ge2d_meson_dev.poweron_table->table_size; + } else { + power_table = + ge2d_meson_dev.poweroff_table->power_btale; + table_size = ge2d_meson_dev.poweroff_table->table_size; + } + + for (i = 0; i < table_size; i++) { + tmp = power_table[i]; + ge2d_set_bus_bits(tmp.bus_type, tmp.reg, tmp.val, + tmp.start, tmp.len); + if (tmp.udelay > 0) + udelay(tmp.udelay); + } + } +} + static int ge2d_clk_config(bool enable) { if (ge2d_clk == NULL) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.h b/drivers/amlogic/media/common/ge2d/ge2d_wq.h index 2fd067836211..ae81fe7e95d7 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.h @@ -39,4 +39,5 @@ int ge2d_buffer_free(int index); int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf); void ge2d_buffer_dma_flush(int dma_fd); void ge2d_buffer_cache_flush(int dma_fd); +void ge2d_pwr_config(bool enable); #endif diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index bf5c591d765f..883342ee9980 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -1012,6 +1012,26 @@ struct ge2d_dmabuf_exp_s { }; /* end of ge2d dma buffer define */ +enum { + CBUS_BASE, + AOBUS_BASE, + HIUBUS_BASE, +}; + +struct ge2d_ctrl_s { + unsigned int bus_type; + unsigned int reg; + unsigned int val; + unsigned int start; + unsigned int len; + unsigned int udelay; +}; + +struct ge2d_power_table_s { + unsigned int table_size; + struct ge2d_ctrl_s *power_btale; +}; + struct ge2d_device_data_s { int ge2d_rate; int src2_alp; @@ -1019,6 +1039,9 @@ struct ge2d_device_data_s { int deep_color; int hang_flag; int fifo; + int has_self_pwr; + struct ge2d_power_table_s *poweron_table; + struct ge2d_power_table_s *poweroff_table; }; extern struct ge2d_device_data_s ge2d_meson_dev;