From: Evoke Zhang Date: Fri, 23 Nov 2018 05:10:06 +0000 (+0800) Subject: lcd: add od support for tl1 tcon [1/1] X-Git-Tag: hardkernel-4.9.236-104~2043 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5a189ac9fb0543ffd94a2135e7886e104db50f03;p=platform%2Fkernel%2Flinux-amlogic.git lcd: add od support for tl1 tcon [1/1] 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 --- diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 8dcf72e..e112c36 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -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) */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 4d368fa..2bf4f70 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -86,6 +86,14 @@ 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/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index 4da7d47..0c5fe32 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -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); } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index dfd90ca..61c052c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -33,13 +33,19 @@ #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); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.h b/drivers/amlogic/media/vout/lcd/lcd_tcon.h index 8f210e6..e557923 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.h +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.h @@ -17,6 +17,9 @@ #ifndef __AML_LCD_TCON_H__ #define __AML_LCD_TCON_H__ +#include +#include +#include #include #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 diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 17fb569..eaab5e7 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -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; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index eafa106b..7943a6f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -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; diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 2fa20b8..3645228 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -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"); } }