lcd: add od support for tl1 tcon [1/1]
authorEvoke Zhang <evoke.zhang@amlogic.com>
Fri, 23 Nov 2018 05:10:06 +0000 (13:10 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 12 Dec 2018 03:34:25 +0000 (19:34 -0800)
PD#SWPL-2759

Problem:
need over-driver function for tl1 tcon

Solution:
add tcon cma memory and od setting support

Verify:
x301

Change-Id: I926d221fef3317be8b3879a35298035ac9babcce
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
drivers/amlogic/media/vout/lcd/lcd_common.c
drivers/amlogic/media/vout/lcd/lcd_tcon.c
drivers/amlogic/media/vout/lcd/lcd_tcon.h
drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c
drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c
drivers/amlogic/media/vout/lcd/lcd_vout.c

index 8dcf72e..e112c36 100644 (file)
@@ -44,6 +44,8 @@
                pinctrl-2 = <&lcd_tcon_pins>;
                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 4d368fa..2bf4f70 100644 (file)
                        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 4da7d47..0c5fe32 100644 (file)
@@ -390,11 +390,11 @@ void lcd_tcon_pinmux_set(int status)
        pconf->pin = devm_pinctrl_get_select(lcd_drv->dev,
                lcd_tcon_pinmux_str[index]);
        if (IS_ERR(pconf->pin)) {
-               LCDERR("set vbyone pinmux %s error\n",
+               LCDERR("set tcon pinmux %s error\n",
                        lcd_tcon_pinmux_str[index]);
        } else {
                if (lcd_debug_print_flag) {
-                       LCDPR("set vbyone pinmux %s: %p\n",
+                       LCDPR("set tcon pinmux %s: %p\n",
                                lcd_tcon_pinmux_str[index], pconf->pin);
                }
        }
index dfd90ca..61c052c 100644 (file)
 #include "lcd_common.h"
 #include "lcd_reg.h"
 #include "lcd_tcon.h"
-#include "tcon_ceds.h"
+/*#include "tcon_ceds.h"*/
 
 #define TCON_INTR_MASKN_VAL    0x0  /* default mask all */
 
-static struct reserved_mem tcon_fb_rmem = {.base = 0, .size = 0};
+static struct tcon_rmem_s tcon_rmem = {
+       .flag = 0,
+       .mem_vaddr = NULL,
+       .mem_paddr = 0,
+       .mem_size = 0,
+};
 
 static struct lcd_tcon_data_s *lcd_tcon_data;
+static struct delayed_work lcd_tcon_delayed_work;
 
 static int lcd_tcon_valid_check(void)
 {
@@ -109,7 +115,7 @@ static void lcd_tcon_od_check(unsigned char *table)
        if (((table[reg] >> bit) & 1) == 0)
                return;
 
-       if (lcd_tcon_data->axi_offset_addr == 0) {
+       if (tcon_rmem.flag == 0) {
                table[reg] &= ~(1 << bit);
                LCDPR("%s: invalid fb, disable od function\n", __func__);
        }
@@ -160,22 +166,22 @@ static int lcd_tcon_top_set_tl1(void)
                TCON_AXI_OFST0, TCON_AXI_OFST1, TCON_AXI_OFST2
        };
        unsigned int addr[3] = {0, 0, 0};
-       unsigned int size[3] = {0, 0, 0};
+       unsigned int size[3] = {4162560, 4162560, 1960440};
        int i;
 
        LCDPR("lcd tcon top set\n");
 
-       if (lcd_tcon_data->axi_offset_addr == 0) {
-               LCDERR("%s: invalid axi_offset_addr\n", __func__);
-       } else {
-               addr[0] = lcd_tcon_data->axi_offset_addr;
+       if (tcon_rmem.flag) {
+               addr[0] = tcon_rmem.mem_paddr;
                addr[1] = addr[0] + size[0];
                addr[2] = addr[1] + size[1];
                for (i = 0; i < 3; i++) {
                        lcd_tcon_write(axi_reg[i], addr[i]);
-                       LCDPR("set tcon axi_offset_addr[%d]: 0x%08x\n",
+                       LCDPR("set tcon axi_mem_paddr[%d]: 0x%08x\n",
                                i, addr[i]);
                }
+       } else {
+               LCDERR("%s: invalid axi_mem\n", __func__);
        }
 
        lcd_tcon_write(TCON_CLK_CTRL, 0x001f);
@@ -243,13 +249,15 @@ static void lcd_tcon_intr_init(struct aml_lcd_drv_s *lcd_drv)
                return;
        }
        tcon_irq = lcd_drv->res_tcon_irq->start;
-       LCDPR("tcon_irq: %d\n", tcon_irq);
+       if (lcd_debug_print_flag)
+               LCDPR("tcon_irq: %d\n", tcon_irq);
 
        if (request_irq(tcon_irq, lcd_tcon_isr, IRQF_SHARED,
                "lcd_tcon", (void *)"lcd_tcon"))
                LCDERR("can't request lcd_tcon irq\n");
        else {
-               LCDPR("request lcd_tcon successful\n");
+               if (lcd_debug_print_flag)
+                       LCDPR("request lcd_tcon irq successful\n");
        }
 
        lcd_tcon_write(TCON_INTR_MASKN, TCON_INTR_MASKN_VAL);
@@ -259,18 +267,7 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv)
 {
        int key_len, reg_len, ret;
 
-       /* init reserved memory */
-       ret = of_reserved_mem_device_init(lcd_drv->dev);
-       if ((ret != 0) && ((void *)tcon_fb_rmem.base == NULL)) {
-               LCDERR("failed to init tcon axi reserved memory\n");
-       } else {
-               lcd_tcon_data->axi_offset_addr =
-                       virt_to_phys((void *)tcon_fb_rmem.base);
-       }
-       LCDPR("tcon axi_offset_addr = 0x%08x\n",
-               lcd_tcon_data->axi_offset_addr);
-
-#if 0
+#if 1
        /* get reg table from unifykey */
        reg_len = lcd_tcon_data->reg_table_len;
        if (lcd_tcon_data->reg_table == NULL) {
@@ -298,6 +295,7 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv)
                        __func__);
                return -1;
        }
+       LCDPR("tcon: load unifykey len: %d\n", key_len);
 #else
        reg_len = lcd_tcon_data->reg_table_len;
        lcd_tcon_data->reg_table = uhd_tcon_setting_ceds_h10;
@@ -308,14 +306,32 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv)
                        __func__);
                return -1;
        }
+       LCDPR("tcon: load default table len: %d\n", key_len);
 #endif
-       LCDPR("tcon: load key len: %d\n", key_len);
 
        lcd_tcon_intr_init(lcd_drv);
 
        return 0;
 }
 
+static void lcd_tcon_config_delayed(struct work_struct *work)
+{
+       struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
+       int key_init_flag = 0;
+       int i = 0;
+
+       key_init_flag = key_unify_get_init_flag();
+       while (key_init_flag == 0) {
+               if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT)
+                       break;
+               msleep(20);
+               key_init_flag = key_unify_get_init_flag();
+       }
+       LCDPR("tcon: key_init_flag=%d, i=%d\n", key_init_flag, i);
+       if (key_init_flag)
+               lcd_tcon_config(lcd_drv);
+}
+
 /* **********************************
  * tcon function api
  * **********************************
@@ -408,10 +424,12 @@ int lcd_tcon_info_print(char *buf, int offset)
                "tcon info:\n"
                "core_reg_width:    %d\n"
                "reg_table_len:     %d\n"
-               "axi_offset_addr:   0x%08x\n\n",
+               "axi_mem paddr:     0x%lx\n"
+               "axi_mem size:      0x%x\n\n",
                lcd_tcon_data->core_reg_width,
                lcd_tcon_data->reg_table_len,
-               lcd_tcon_data->axi_offset_addr);
+               (unsigned long)tcon_rmem.mem_paddr,
+               tcon_rmem.mem_size);
 
        return len;
 }
@@ -477,8 +495,8 @@ int lcd_tcon_od_set(int flag)
        }
 
        if (flag) {
-               if (lcd_tcon_data->axi_offset_addr == 0) {
-                       LCDERR("%s: invalid fb, disable od function\n",
+               if (tcon_rmem.flag == 0) {
+                       LCDERR("%s: invalid memory, disable od function\n",
                                __func__);
                        return -1;
                }
@@ -513,11 +531,11 @@ int lcd_tcon_od_get(void)
 
        ret = lcd_tcon_valid_check();
        if (ret)
-               return -1;
+               return 0;
 
        if (lcd_tcon_data->reg_core_od == REG_LCD_TCON_MAX) {
                LCDERR("%s: invalid od reg\n", __func__);
-               return -1;
+               return 0;
        }
 
        reg = lcd_tcon_data->reg_core_od;
@@ -605,14 +623,14 @@ static struct lcd_tcon_data_s tcon_data_tl1 = {
        .reg_top_ctrl = TCON_TOP_CTRL,
        .bit_en = BIT_TOP_EN_TL1,
 
-       .reg_core_od = REG_LCD_TCON_MAX,
+       .reg_core_od = REG_CORE_OD_TL1,
        .bit_od_en = BIT_OD_EN_TL1,
 
-       .reg_core_ctrl_timing_base = REG_CORE_CTRL_TIMING_BASE_TL1,
+       .reg_core_ctrl_timing_base = REG_LCD_TCON_MAX,
        .ctrl_timing_offset = CTRL_TIMING_OFFSET_TL1,
        .ctrl_timing_cnt = CTRL_TIMING_CNT_TL1,
 
-       .axi_offset_addr = 0,
+       .axi_mem_size = 0xc00000,
        .reg_table = NULL,
 
        .tcon_enable = lcd_tcon_enable_tl1,
@@ -620,14 +638,16 @@ static struct lcd_tcon_data_s tcon_data_tl1 = {
 
 int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv)
 {
+       int key_init_flag = 0;
        int ret = 0;
 
+       lcd_tcon_data = NULL;
        switch (lcd_drv->data->chip_type) {
        case LCD_CHIP_TL1:
-               lcd_tcon_data = &tcon_data_tl1;
                switch (lcd_drv->lcd_config->lcd_basic.lcd_type) {
                case LCD_MLVDS:
                case LCD_P2P:
+                       lcd_tcon_data = &tcon_data_tl1;
                        lcd_tcon_data->tcon_valid = 1;
                        break;
                default:
@@ -635,44 +655,103 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv)
                }
                break;
        default:
-               lcd_tcon_data = NULL;
                break;
        }
-       ret = lcd_tcon_valid_check();
-       if (ret)
-               return -1;
+       if (lcd_tcon_data == NULL)
+               return 0;
+
+       /* init reserved memory */
+       ret = of_reserved_mem_device_init(lcd_drv->dev);
+       if (ret) {
+               LCDERR("tcon: init reserved memory failed\n");
+       } else {
+#ifdef CONFIG_CMA
+               tcon_rmem.mem_vaddr = dma_alloc_coherent(lcd_drv->dev,
+                       lcd_tcon_data->axi_mem_size,
+                       &tcon_rmem.mem_paddr,
+                       GFP_KERNEL);
+               if (tcon_rmem.mem_vaddr == NULL) {
+                       LCDERR("tcon axi_mem alloc failed\n");
+                       tcon_rmem.mem_paddr = 0;
+               } else {
+                       tcon_rmem.mem_size = lcd_tcon_data->axi_mem_size;
+                       tcon_rmem.flag = 1;
+                       LCDPR("tcon: axi_mem base:0x%lx, size:0x%x\n",
+                               (unsigned long)tcon_rmem.mem_paddr,
+                               tcon_rmem.mem_size);
+               }
+#else
+               if ((void *)tcon_rmem.mem_paddr == NULL) {
+                       LCDERR("tcon axi_mem alloc failed\n");
+               } else {
+                       tcon_rmem.flag = 1;
+                       LCDPR("tcon: axi_mem base:0x%lx, size:0x%x\n",
+                               (unsigned long)tcon_rmem.mem_paddr,
+                               tcon_rmem.mem_size);
+               }
+#endif
+       }
 
-       ret = lcd_tcon_config(lcd_drv);
+       INIT_DELAYED_WORK(&lcd_tcon_delayed_work, lcd_tcon_config_delayed);
+
+       key_init_flag = key_unify_get_init_flag();
+       if (key_init_flag) {
+               ret = lcd_tcon_config(lcd_drv);
+       } else {
+               if (lcd_drv->workqueue) {
+                       queue_delayed_work(lcd_drv->workqueue,
+                               &lcd_tcon_delayed_work,
+                               msecs_to_jiffies(2000));
+               } else {
+                       schedule_delayed_work(&lcd_tcon_delayed_work,
+                               msecs_to_jiffies(2000));
+               }
+       }
 
        return ret;
 }
 
-static int rmem_tcon_fb_device_init(struct reserved_mem *rmem,
+int lcd_tcon_remove(struct aml_lcd_drv_s *lcd_drv)
+{
+       if (tcon_rmem.flag) {
+               LCDPR("tcon free memory: base:0x%lx, size:0x%x\n",
+                       (unsigned long)tcon_rmem.mem_paddr,
+                       tcon_rmem.mem_size);
+#ifdef CONFIG_CMA
+               dma_free_coherent(lcd_drv->dev, tcon_rmem.mem_size,
+                       tcon_rmem.mem_vaddr,
+                       (dma_addr_t)&tcon_rmem.mem_paddr);
+#else
+               /* to do */
+#endif
+       }
+
+       if (lcd_tcon_data) {
+               /* lcd_tcon_data == NULL; */
+               lcd_tcon_data->tcon_valid = 0;
+       }
+
+       return 0;
+}
+
+static int __init tcon_fb_device_init(struct reserved_mem *rmem,
                struct device *dev)
 {
        return 0;
 }
 
-static const struct reserved_mem_ops rmem_tcon_fb_ops = {
-       .device_init = rmem_tcon_fb_device_init,
+static const struct reserved_mem_ops tcon_fb_ops = {
+       .device_init = tcon_fb_device_init,
 };
 
-static int __init rmem_tcon_fb_setup(struct reserved_mem *rmem)
+static int __init tcon_fb_setup(struct reserved_mem *rmem)
 {
-       /*
-        * phys_addr_t align = PAGE_SIZE;
-        * phys_addr_t mask = align - 1;
-        * if ((rmem->base & mask) || (rmem->size & mask)) {
-        *      LCDERR("Reserved memory: incorrect alignment of region\n");
-        *      return -EINVAL;
-        * }
-        */
-       tcon_fb_rmem.base = rmem->base;
-       tcon_fb_rmem.size = rmem->size;
-       rmem->ops = &rmem_tcon_fb_ops;
-       LCDPR("tcon: Reserved memory: created fb at 0x%p, size %ld MiB\n",
-               (void *)rmem->base, (unsigned long)rmem->size / SZ_1M);
+       tcon_rmem.mem_paddr = rmem->base;
+       tcon_rmem.mem_size = rmem->size;
+       rmem->ops = &tcon_fb_ops;
+       LCDPR("tcon: Reserved memory: created fb at 0x%lx, size %ld MiB\n",
+               (unsigned long)rmem->base, (unsigned long)rmem->size / SZ_1M);
        return 0;
 }
-RESERVEDMEM_OF_DECLARE(fb, "amlogic, lcd_tcon-memory", rmem_tcon_fb_setup);
+RESERVEDMEM_OF_DECLARE(fb, "amlogic, lcd_tcon-memory", tcon_fb_setup);
 
index 8f210e6..e557923 100644 (file)
@@ -17,6 +17,9 @@
 
 #ifndef __AML_LCD_TCON_H__
 #define __AML_LCD_TCON_H__
+#include <linux/dma-contiguous.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
 #include <linux/amlogic/media/vout/lcd/lcd_vout.h>
 
 #define REG_LCD_TCON_MAX    0xffff
@@ -37,12 +40,19 @@ struct lcd_tcon_data_s {
        unsigned int ctrl_timing_offset;
        unsigned int ctrl_timing_cnt;
 
-       unsigned int axi_offset_addr;
+       unsigned int axi_mem_size;
        unsigned char *reg_table;
 
        int (*tcon_enable)(struct lcd_config_s *pconf);
 };
 
+struct tcon_rmem_s {
+       unsigned char flag;
+       void *mem_vaddr;
+       phys_addr_t mem_paddr;
+       unsigned int mem_size;
+};
+
 /* **********************************
  * tcon config
  * **********************************
@@ -54,8 +64,8 @@ struct lcd_tcon_data_s {
 
 #define BIT_TOP_EN_TL1                   4
 
-#define REG_CORE_OD_TL1                  0x5c
-#define BIT_OD_EN_TL1                    6
+#define REG_CORE_OD_TL1                  0x247
+#define BIT_OD_EN_TL1                    0
 #define REG_CORE_CTRL_TIMING_BASE_TL1    0x1b
 #define CTRL_TIMING_OFFSET_TL1           12
 #define CTRL_TIMING_CNT_TL1              0
index 17fb569..eaab5e7 100644 (file)
@@ -1789,9 +1789,9 @@ int lcd_tv_driver_init(void)
                lcd_mlvds_phy_set(pconf, 1);
                break;
        case LCD_P2P:
+               lcd_tcon_pinmux_set(1);
                lcd_p2p_control_set(pconf);
                lcd_p2p_phy_set(pconf, 1);
-               lcd_tcon_pinmux_set(1);
                break;
        default:
                break;
index eafa106..7943a6f 100644 (file)
@@ -785,13 +785,17 @@ static int lcd_init_load_from_dts(struct lcd_config_s *pconf,
        struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
 
        /* lock pinmux if lcd in on */
-       switch (pconf->lcd_basic.lcd_type) {
-       case LCD_VBYONE:
-               if (lcd_drv->lcd_status & LCD_STATUS_IF_ON)
+       if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) {
+               switch (pconf->lcd_basic.lcd_type) {
+               case LCD_VBYONE:
                        lcd_vbyone_pinmux_set(1);
-               break;
-       default:
-               break;
+                       break;
+               case LCD_P2P:
+                       lcd_tcon_pinmux_set(1);
+                       break;
+               default:
+                       break;
+               }
        }
 
        return ret;
index 2fa20b8..3645228 100644 (file)
@@ -947,7 +947,8 @@ static int lcd_fops_create(void)
                return -1;
        }
 
-       LCDPR("%s OK\n", __func__);
+       if (lcd_debug_print_flag)
+               LCDPR("%s OK\n", __func__);
        return 0;
 }
 
@@ -1215,7 +1216,8 @@ static int lcd_vsync_irq_init(void)
                        "lcd_vsync", (void *)"lcd_vsync")) {
                        LCDERR("can't request lcd_vsync_irq\n");
                } else {
-                       LCDPR("request lcd_vsync_irq successful\n");
+                       if (lcd_debug_print_flag)
+                               LCDPR("request lcd_vsync_irq successful\n");
                }
        }
 
@@ -1225,7 +1227,8 @@ static int lcd_vsync_irq_init(void)
                        "lcd_vsync2", (void *)"lcd_vsync2")) {
                        LCDERR("can't request lcd_vsync2_irq\n");
                } else {
-                       LCDPR("request lcd_vsync2_irq successful\n");
+                       if (lcd_debug_print_flag)
+                               LCDPR("request lcd_vsync2_irq successful\n");
                }
        }