From a47304b7dff5bd027b7ea03c3408e952a053d307 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 27 Dec 2018 17:41:44 +0800 Subject: [PATCH] lcd: fix tcon crash with reserved-memory fail and tcon_clk mistake [2/2] PD#SWPL-3664 Problem: tcon will crash in kernel Solution: 1.prior meson-fb & lcd_tcon reserved-memory 2.fix tcon_clk not enable mistake when use panel ini Verify: x301 Change-Id: I97baec22ecabea393f9b0d712456923720fac972 Signed-off-by: Evoke Zhang --- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 1 - .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 1 - arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 32 +++---- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 32 +++---- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 1 - .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 1 - .../boot/dts/amlogic/tl1_t962x2_t309.dts | 31 +++---- .../boot/dts/amlogic/tl1_t962x2_x301.dts | 31 +++---- .../amlogic/media/vout/lcd/lcd_clk_config.c | 87 ++++++++++++------- .../amlogic/media/vout/lcd/lcd_clk_config.h | 3 + drivers/amlogic/media/vout/lcd/lcd_tcon.c | 5 +- drivers/amlogic/media/vout/lcd/lcd_vout.c | 5 +- 12 files changed, 128 insertions(+), 102 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index b43b9c50f25c..79fa79d39429 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -45,7 +45,6 @@ pinctrl-3 = <&lcd_tcon_off_pins>; pinctrl_version = <2>; /* for uboot */ memory-region = <&lcd_tcon_reserved>; - tcon_mem_addr = <0x71000000>; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 41ff2ba6d525..15c01c2d05c0 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -45,7 +45,6 @@ pinctrl-3 = <&lcd_tcon_off_pins>; pinctrl_version = <2>; /* for uboot */ memory-region = <&lcd_tcon_reserved>; - tcon_mem_addr = <0x71000000>; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index d77d187e70ee..f1a96ffcc8da 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -60,6 +60,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -78,22 +94,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x800000>; - alignment = <0x400000>; - alloc-ranges = <0x7f800000 0x800000>; - }; - - lcd_tcon_reserved:linux,lcd_tcon { - compatible = "shared-dma-pool"; - reusable; - size = <0xc00000>; - alignment = <0x400000>; - alloc-ranges = <0x71000000 0xc00000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 7f1b08425b2f..a782784fa804 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -60,6 +60,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -78,22 +94,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x800000>; - alignment = <0x400000>; - alloc-ranges = <0x7f800000 0x800000>; - }; - - lcd_tcon_reserved:linux,lcd_tcon { - compatible = "shared-dma-pool"; - reusable; - size = <0xc00000>; - alignment = <0x400000>; - alloc-ranges = <0x71000000 0xc00000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 4b5636604a45..33c1769f2c8f 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -45,7 +45,6 @@ pinctrl-3 = <&lcd_tcon_off_pins>; pinctrl_version = <2>; /* for uboot */ memory-region = <&lcd_tcon_reserved>; - tcon_mem_addr = <0x71000000>; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 76e7b4feb328..95d59da15c49 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -45,7 +45,6 @@ pinctrl-3 = <&lcd_tcon_off_pins>; pinctrl_version = <2>; /* for uboot */ memory-region = <&lcd_tcon_reserved>; - tcon_mem_addr = <0x71000000>; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts index fe7d7fa3cf7a..ddd8975fb567 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -60,6 +60,22 @@ alloc-ranges = <0x0 0x05000000 0x0 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -77,21 +93,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x800000>; - alignment = <0x0 0x400000>; - alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; - }; - - lcd_tcon_reserved:linux,lcd_tcon { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0xc00000>; - alignment = <0x0 0x400000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts index 1ab044eb2835..eea95ec7bdb1 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -60,6 +60,22 @@ alloc-ranges = <0x0 0x05000000 0x0 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -77,21 +93,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x800000>; - alignment = <0x0 0x400000>; - alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; - }; - - lcd_tcon_reserved:linux,lcd_tcon { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0xc00000>; - alignment = <0x0 0x400000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index f30ef4000bbf..78414452237b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -65,6 +65,7 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */ static struct lcd_clktree_s lcd_clktree = { .clk_gate_state = 0, + .clk_gate_optional_state = 0, /* by interface */ .encl_top_gate = NULL, .encl_int_gate = NULL, @@ -1850,17 +1851,10 @@ static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *lcd_drv, int status) } } -static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) +static void lcd_clk_gate_optional_switch_tl1(struct aml_lcd_drv_s *lcd_drv, + int status) { if (status) { - if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) - LCDERR("%s: encl_top_gate\n", __func__); - else - clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) - LCDERR("%s: encl_int_gata\n", __func__); - else - clk_prepare_enable(lcd_clktree.encl_int_gate); switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: @@ -1872,6 +1866,7 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) LCDERR("%s: tcon_clk\n", __func__); else clk_prepare_enable(lcd_clktree.tcon_clk); + lcd_clktree.clk_gate_optional_state = 1; break; default: break; @@ -1888,18 +1883,11 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) LCDERR("%s: tcon_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.tcon_gate); + lcd_clktree.clk_gate_optional_state = 0; break; default: break; } - if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) - LCDERR("%s: encl_int_gate\n", __func__); - else - clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) - LCDERR("%s: encl_top_gate\n", __func__); - else - clk_disable_unprepare(lcd_clktree.encl_top_gate); } } @@ -2512,37 +2500,63 @@ void lcd_clk_disable(void) LCDPR("%s\n", __func__); } +static void lcd_clk_gate_optional_switch(int status) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + if (clk_conf.data->clk_gate_optional_switch == NULL) + return; + + if (status) { + if (lcd_clktree.clk_gate_optional_state) + LCDPR("clk_gate_optional is already on\n"); + else + clk_conf.data->clk_gate_optional_switch(lcd_drv, 1); + } else { + if (lcd_clktree.clk_gate_optional_state == 0) + LCDPR("clk_gate_optional is already off\n"); + else + clk_conf.data->clk_gate_optional_switch(lcd_drv, 0); + } +} + void lcd_clk_gate_switch(int status) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + if (status) { if (lcd_clktree.clk_gate_state) { - LCDPR("clk gate is already on\n"); - return; - } + LCDPR("clk_gate is already on\n"); + } else { #ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_ON); + switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_ON); #endif - if (clk_conf.data) { if (clk_conf.data->clk_gate_switch) clk_conf.data->clk_gate_switch(lcd_drv, 1); + lcd_clktree.clk_gate_state = 1; } - lcd_clktree.clk_gate_state = 1; + lcd_clk_gate_optional_switch(1); } else { + lcd_clk_gate_optional_switch(0); if (lcd_clktree.clk_gate_state == 0) { - LCDPR("clk gate is already off\n"); - return; - } - - if (clk_conf.data) { + LCDPR("clk_gate is already off\n"); + } else { if (clk_conf.data->clk_gate_switch) clk_conf.data->clk_gate_switch(lcd_drv, 0); - } #ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_OFF); + switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_OFF); #endif - lcd_clktree.clk_gate_state = 0; + lcd_clktree.clk_gate_state = 0; + } } } @@ -2614,6 +2628,7 @@ static struct lcd_clk_data_s lcd_clk_data_gxl = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2655,6 +2670,7 @@ static struct lcd_clk_data_s lcd_clk_data_txl = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2696,6 +2712,7 @@ static struct lcd_clk_data_s lcd_clk_data_txlx = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_txlx, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2737,6 +2754,7 @@ static struct lcd_clk_data_s lcd_clk_data_axg = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_axg, .clk_gate_switch = lcd_clk_gate_switch_axg, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_axg, .clktree_remove = lcd_clktree_remove_axg, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2778,6 +2796,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path0 = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2819,6 +2838,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path1 = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2860,6 +2880,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path0 = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2901,6 +2922,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path1 = { .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2941,7 +2963,8 @@ static struct lcd_clk_data_s lcd_clk_data_tl1 = { .set_ss_level = lcd_set_pll_ss_level_tl1, .set_ss_advance = lcd_set_pll_ss_advance_tl1, .clk_set = lcd_clk_set_tl1, - .clk_gate_switch = lcd_clk_gate_switch_tl1, + .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1, .clktree_probe = lcd_clktree_probe_tl1, .clktree_remove = lcd_clktree_remove_tl1, .clk_config_init_print = lcd_clk_config_init_print_dft, diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 41c76016a2cd..f013fd86af47 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -75,6 +75,8 @@ struct lcd_clk_data_s { void (*set_ss_advance)(unsigned int freq, unsigned int mode); void (*clk_set)(struct lcd_config_s *pconf); void (*clk_gate_switch)(struct aml_lcd_drv_s *lcd_drv, int status); + void (*clk_gate_optional_switch)(struct aml_lcd_drv_s *lcd_drv, + int status); void (*clktree_probe)(void); void (*clktree_remove)(void); void (*clk_config_init_print)(void); @@ -113,6 +115,7 @@ struct lcd_clk_config_s { /* unit: kHz */ struct lcd_clktree_s { unsigned char clk_gate_state; + unsigned char clk_gate_optional_state; struct clk *encl_top_gate; struct clk *encl_int_gate; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index 61c052cff654..f26812aeac59 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -581,10 +581,11 @@ void lcd_tcon_disable(void) /* disable over_drive */ if (lcd_tcon_data->reg_core_od != REG_LCD_TCON_MAX) { reg = lcd_tcon_data->reg_core_od + TCON_CORE_REG_START; + bit = lcd_tcon_data->bit_od_en; if (lcd_tcon_data->core_reg_width == 8) - lcd_tcon_write_byte(reg, 0); + lcd_tcon_setb_byte(reg, 0, bit, 1); else - lcd_tcon_write(reg, 0); + lcd_tcon_setb(reg, 0, bit, 1); msleep(100); } diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index c4eaff10366a..8bfaba05c72a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -1011,8 +1011,9 @@ static int lcd_mode_probe(struct device *dev) LCDERR("invalid lcd mode: %d\n", lcd_driver->lcd_mode); break; } - if (lcd_driver->data->chip_type == LCD_CHIP_TL1) - lcd_tcon_probe(lcd_driver); + lcd_tcon_probe(lcd_driver); + if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) + lcd_clk_gate_switch(1); lcd_debug_probe(); lcd_fops_create();