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 <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2018-11-23 13:10:06 +08:00
committed by Jianxin Pan
parent 01e29ceb6d
commit 5a189ac9fb
8 changed files with 178 additions and 72 deletions

View 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) */

View File

@@ -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;

View 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);
}
}

View File

@@ -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;
ret = lcd_tcon_config(lcd_drv);
/* 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
}
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);

View 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

View 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;

View 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;

View 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");
}
}