lcd: fix tcon crash with reserved-memory fail and tcon_clk mistake [2/2]
authorEvoke Zhang <evoke.zhang@amlogic.com>
Thu, 27 Dec 2018 09:41:44 +0000 (17:41 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 4 Jan 2019 02:04:03 +0000 (18:04 -0800)
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 <evoke.zhang@amlogic.com>
12 files changed:
arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi
arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi
arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi
arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi
arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts
arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts
drivers/amlogic/media/vout/lcd/lcd_clk_config.c
drivers/amlogic/media/vout/lcd/lcd_clk_config.h
drivers/amlogic/media/vout/lcd/lcd_tcon.c
drivers/amlogic/media/vout/lcd/lcd_vout.c

index b43b9c5..79fa79d 100644 (file)
@@ -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) */
index 41ff2ba..15c01c2 100644 (file)
@@ -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) */
index d77d187..f1a96ff 100644 (file)
                        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;
                        //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;
index 7f1b084..a782784 100644 (file)
                        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;
                        //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;
index 4b56366..33c1769 100644 (file)
@@ -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) */
index 76e7b4f..95d59da 100644 (file)
@@ -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) */
index fe7d7fa..ddd8975 100644 (file)
                        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;
                        //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;
index 1ab044e..eea95ec 100644 (file)
                        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;
                        //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;
index f30ef40..7841445 100644 (file)
@@ -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,
index 41c7601..f013fd8 100644 (file)
@@ -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;
index 61c052c..f26812a 100644 (file)
@@ -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);
        }
 
index c4eaff1..8bfaba0 100644 (file)
@@ -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();