diff --git a/drivers/algorithm/Kconfig b/drivers/algorithm/Kconfig index a82a1efe6..4fa0fef72 100644 --- a/drivers/algorithm/Kconfig +++ b/drivers/algorithm/Kconfig @@ -14,12 +14,14 @@ config AMLOGIC_MEDIA_ALGORITHM sl_hdr ldim frc + tcon if AMLOGIC_MEDIA_ALGORITHM #source "$(COMMON_DRIVERS_DIR)/drivers/algorithm/ldim/Kconfig" #source "$(COMMON_DRIVERS_DIR)/drivers/algorithm/dnlp/Kconfig" #source "$(COMMON_DRIVERS_DIR)/drivers/algorithm/common/Kconfig" #source "$(COMMON_DRIVERS_DIR)/drivers/algorithm/frc/Kconfig" +#source "$(COMMON_DRIVERS_DIR)/drivers/algorithm/tcon/Kconfig" endif endmenu diff --git a/drivers/algorithm/Makefile b/drivers/algorithm/Makefile index f47e2b314..33539ff79 100644 --- a/drivers/algorithm/Makefile +++ b/drivers/algorithm/Makefile @@ -2,3 +2,4 @@ #obj-$(CONFIG_AMLOGIC_MEDIA_ALGORITHM) += dnlp/ #obj-$(CONFIG_AMLOGIC_MEDIA_ALGORITHM) += common/ #obj-$(CONFIG_AMLOGIC_MEDIA_ALGORITHM) += frc/ +#obj-$(CONFIG_AMLOGIC_MEDIA_ALGORITHM) += tcon/ diff --git a/drivers/media/vout/lcd/lcd_common.h b/drivers/media/vout/lcd/lcd_common.h index 44bd60938..b47d72f23 100644 --- a/drivers/media/vout/lcd/lcd_common.h +++ b/drivers/media/vout/lcd/lcd_common.h @@ -32,7 +32,8 @@ /* 20230303: fix hdmi mode 47hz & 95hz timing*/ /* 20230313: update tcon debug info print*/ /* 20230319: optimize phy code*/ -#define LCD_DRV_VERSION "20230319" +/* 20230510: support tcon fw*/ +#define LCD_DRV_VERSION "20230510" extern struct mutex lcd_vout_mutex; extern spinlock_t lcd_reg_spinlock; @@ -129,9 +130,6 @@ void lcd_tcon_reg_write(struct aml_lcd_drv_s *pdrv, unsigned int addr, unsigned int val); int lcd_tcon_probe(struct aml_lcd_drv_s *pdrv); void lcd_tcon_global_reset(struct aml_lcd_drv_s *pdrv); -int lcd_tcon_gamma_set_pattern(struct aml_lcd_drv_s *pdrv, - unsigned int bit_width, unsigned int gamma_r, - unsigned int gamma_g, unsigned int gamma_b); unsigned int lcd_tcon_table_read(unsigned int addr); unsigned int lcd_tcon_table_write(unsigned int addr, unsigned int val); int lcd_tcon_core_update(struct aml_lcd_drv_s *pdrv); @@ -177,7 +175,8 @@ void lcd_clk_config_init(void); void aml_lcd_prbs_test(struct aml_lcd_drv_s *pdrv, unsigned int ms, unsigned int mode_flag); /* lcd venc */ -unsigned int lcd_get_encl_lint_cnt(struct aml_lcd_drv_s *pdrv); +unsigned int lcd_get_encl_line_cnt(struct aml_lcd_drv_s *pdrv); +unsigned int lcd_get_encl_frm_cnt(struct aml_lcd_drv_s *pdrv); void lcd_wait_vsync(struct aml_lcd_drv_s *pdrv); void lcd_gamma_debug_test_en(struct aml_lcd_drv_s *pdrv, int flag); diff --git a/drivers/media/vout/lcd/lcd_debug.c b/drivers/media/vout/lcd/lcd_debug.c index ad1a9f646..1617debf9 100644 --- a/drivers/media/vout/lcd/lcd_debug.c +++ b/drivers/media/vout/lcd/lcd_debug.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "lcd_reg.h" #include "lcd_common.h" #ifdef CONFIG_AMLOGIC_LCD_TABLET @@ -31,8 +32,8 @@ #include "lcd_tcon.h" #include "./lcd_clk/lcd_clk_config.h" -/* 1: unlocked, 0: locked, negative: locked, possible waiters */ -struct mutex lcd_tcon_adb_mutex; +//1: unlocked, 0: locked, negative: locked, possible waiters +struct mutex lcd_tcon_dbg_mutex; /*device attribute buf max size 4k*/ #define PR_BUF_MAX (4 * 1024) @@ -5041,7 +5042,6 @@ static ssize_t lcd_tcon_debug_store(struct device *dev, struct device_attribute char *buf_orig; char **parm = NULL; unsigned int temp = 0, val, back_val, i, n, size = 0; - unsigned int gamma_r, gamma_g, gamma_b; struct tcon_mem_map_table_s *mm_table = get_lcd_tcon_mm_table(); unsigned char data; unsigned char *table = NULL; @@ -5193,22 +5193,6 @@ static ssize_t lcd_tcon_debug_store(struct device *dev, struct device_attribute lcd_tcon_read(pdrv, temp + i)); } } - } else if (strcmp(parm[0], "gamma") == 0) { /* save buf to bin */ - if (!parm[4]) - goto lcd_tcon_debug_store_err; - ret = kstrtouint(parm[1], 10, &temp); - if (ret) - goto lcd_tcon_debug_store_err; - ret = kstrtouint(parm[2], 16, &gamma_r); - if (ret) - goto lcd_tcon_debug_store_err; - ret = kstrtouint(parm[3], 16, &gamma_g); - if (ret) - goto lcd_tcon_debug_store_err; - ret = kstrtouint(parm[4], 16, &gamma_b); - if (ret) - goto lcd_tcon_debug_store_err; - lcd_tcon_gamma_set_pattern(pdrv, temp, gamma_r, gamma_g, gamma_b); } else if (strcmp(parm[0], "table") == 0) { if (lcd_tcon_reg_table_check(table, size)) goto lcd_tcon_debug_store_end; @@ -5444,12 +5428,12 @@ static ssize_t lcd_tcon_adb_status_show(struct device *dev, int len = 0; unsigned int i, addr; - mutex_lock(&lcd_tcon_adb_mutex); + mutex_lock(&lcd_tcon_dbg_mutex); len += sprintf(buf + len, "for_tool:"); if ((pdrv->status & LCD_STATUS_IF_ON) == 0) { len += sprintf(buf + len, "ERROR\n"); - mutex_unlock(&lcd_tcon_adb_mutex); + mutex_unlock(&lcd_tcon_dbg_mutex); return len; } switch (adb_reg.rw_mode) { @@ -5523,7 +5507,7 @@ static ssize_t lcd_tcon_adb_status_show(struct device *dev, break; } len += sprintf(buf + len, "\n"); - mutex_unlock(&lcd_tcon_adb_mutex); + mutex_unlock(&lcd_tcon_dbg_mutex); return len; } @@ -5544,18 +5528,18 @@ static ssize_t lcd_tcon_adb_debug_store(struct device *dev, struct device_attrib if (!buf) return count; - mutex_lock(&lcd_tcon_adb_mutex); + mutex_lock(&lcd_tcon_dbg_mutex); buf_orig = kstrdup(buf, GFP_KERNEL); if (!buf_orig) { - mutex_unlock(&lcd_tcon_adb_mutex); + mutex_unlock(&lcd_tcon_dbg_mutex); return count; } parm = kcalloc(1500, sizeof(char *), GFP_KERNEL); if (!parm) { kfree(buf_orig); - mutex_unlock(&lcd_tcon_adb_mutex); + mutex_unlock(&lcd_tcon_dbg_mutex); return count; } @@ -5713,7 +5697,7 @@ static ssize_t lcd_tcon_adb_debug_store(struct device *dev, struct device_attrib kfree(parm); kfree(buf_orig); - mutex_unlock(&lcd_tcon_adb_mutex); + mutex_unlock(&lcd_tcon_dbg_mutex); return count; lcd_tcon_adb_debug_store_err: @@ -5721,7 +5705,45 @@ lcd_tcon_adb_debug_store_err: kfree(parm); kfree(buf_orig); - mutex_unlock(&lcd_tcon_adb_mutex); + mutex_unlock(&lcd_tcon_dbg_mutex); + return count; +} + +static ssize_t lcd_tcon_fw_dbg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); + ssize_t ret = 0; + + if (!tcon_fw) + return ret; + + if (tcon_fw->debug_show) + ret = tcon_fw->debug_show(tcon_fw, buf); + + return ret; +} + +static ssize_t lcd_tcon_fw_dbg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); + struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); + + if ((pdrv->status & LCD_STATUS_IF_ON) == 0) + return count; + + if (!buf) + return count; + if (!tcon_fw) + return count; + + mutex_lock(&lcd_tcon_dbg_mutex); + + if (tcon_fw->debug_store) + tcon_fw->debug_store(tcon_fw, buf); + + mutex_unlock(&lcd_tcon_dbg_mutex); return count; } @@ -6278,6 +6300,7 @@ static struct device_attribute lcd_debug_attrs_mlvds[] = { __ATTR(tcon, 0644, lcd_tcon_debug_show, lcd_tcon_debug_store), __ATTR(tcon_status, 0444, lcd_tcon_status_show, NULL), __ATTR(tcon_reg, 0644, lcd_tcon_adb_status_show, lcd_tcon_adb_debug_store), + __ATTR(tcon_fw, 0644, lcd_tcon_fw_dbg_show, lcd_tcon_fw_dbg_store), __ATTR(null, 0644, NULL, NULL) }; @@ -6287,6 +6310,7 @@ static struct device_attribute lcd_debug_attrs_p2p[] = { __ATTR(tcon, 0644, lcd_tcon_debug_show, lcd_tcon_debug_store), __ATTR(tcon_status, 0444, lcd_tcon_status_show, NULL), __ATTR(tcon_reg, 0644, lcd_tcon_adb_status_show, lcd_tcon_adb_debug_store), + __ATTR(tcon_fw, 0644, lcd_tcon_fw_dbg_show, lcd_tcon_fw_dbg_store), __ATTR(null, 0644, NULL, NULL) }; @@ -6814,11 +6838,11 @@ int lcd_debug_probe(struct aml_lcd_drv_s *pdrv) lcd_debug_info->debug_if = lcd_debug_info->debug_if_edp; break; case LCD_MLVDS: - mutex_init(&lcd_tcon_adb_mutex); + mutex_init(&lcd_tcon_dbg_mutex); lcd_debug_info->debug_if = lcd_debug_info->debug_if_mlvds; break; case LCD_P2P: - mutex_init(&lcd_tcon_adb_mutex); + mutex_init(&lcd_tcon_dbg_mutex); lcd_debug_info->debug_if = lcd_debug_info->debug_if_p2p; break; default: diff --git a/drivers/media/vout/lcd/lcd_reg.c b/drivers/media/vout/lcd/lcd_reg.c index 1724abf28..410d3ff56 100644 --- a/drivers/media/vout/lcd/lcd_reg.c +++ b/drivers/media/vout/lcd/lcd_reg.c @@ -826,6 +826,7 @@ unsigned int lcd_tcon_read(struct aml_lcd_drv_s *pdrv, unsigned int reg) return temp; }; +EXPORT_SYMBOL(lcd_tcon_read); void lcd_tcon_write(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned int val) @@ -839,6 +840,7 @@ void lcd_tcon_write(struct aml_lcd_drv_s *pdrv, writel(val, p); spin_unlock_irqrestore(&lcd_reg_spinlock, flags); }; +EXPORT_SYMBOL(lcd_tcon_write); void lcd_tcon_setb(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned int value, @@ -858,6 +860,7 @@ void lcd_tcon_setb(struct aml_lcd_drv_s *pdrv, } spin_unlock_irqrestore(&lcd_reg_spinlock, flags); } +EXPORT_SYMBOL(lcd_tcon_setb); unsigned int lcd_tcon_getb(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned int start, unsigned int len) @@ -877,6 +880,7 @@ unsigned int lcd_tcon_getb(struct aml_lcd_drv_s *pdrv, unsigned int reg, return temp; } +EXPORT_SYMBOL(lcd_tcon_getb); void lcd_tcon_update_bits(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned int mask, unsigned int value) @@ -898,6 +902,7 @@ void lcd_tcon_update_bits(struct aml_lcd_drv_s *pdrv, unsigned int reg, } spin_unlock_irqrestore(&lcd_reg_spinlock, flags); } +EXPORT_SYMBOL(lcd_tcon_update_bits); int lcd_tcon_check_bits(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned int mask, unsigned int value) @@ -921,6 +926,7 @@ int lcd_tcon_check_bits(struct aml_lcd_drv_s *pdrv, unsigned int reg, return temp; } +EXPORT_SYMBOL(lcd_tcon_check_bits); unsigned char lcd_tcon_read_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg) { @@ -936,6 +942,7 @@ unsigned char lcd_tcon_read_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg) return temp; }; +EXPORT_SYMBOL(lcd_tcon_read_byte); void lcd_tcon_write_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned char val) @@ -949,6 +956,7 @@ void lcd_tcon_write_byte(struct aml_lcd_drv_s *pdrv, writeb(val, p); spin_unlock_irqrestore(&lcd_reg_spinlock, flags); }; +EXPORT_SYMBOL(lcd_tcon_write_byte); void lcd_tcon_setb_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned char value, @@ -968,6 +976,7 @@ void lcd_tcon_setb_byte(struct aml_lcd_drv_s *pdrv, } spin_unlock_irqrestore(&lcd_reg_spinlock, flags); } +EXPORT_SYMBOL(lcd_tcon_setb_byte); unsigned char lcd_tcon_getb_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned int start, unsigned int len) @@ -986,6 +995,7 @@ unsigned char lcd_tcon_getb_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, return temp; } +EXPORT_SYMBOL(lcd_tcon_getb_byte); void lcd_tcon_update_bits_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned char mask, unsigned char value) @@ -1007,6 +1017,7 @@ void lcd_tcon_update_bits_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, } spin_unlock_irqrestore(&lcd_reg_spinlock, flags); } +EXPORT_SYMBOL(lcd_tcon_update_bits_byte); int lcd_tcon_check_bits_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, unsigned char mask, unsigned char value) @@ -1030,6 +1041,7 @@ int lcd_tcon_check_bits_byte(struct aml_lcd_drv_s *pdrv, unsigned int reg, return temp; } +EXPORT_SYMBOL(lcd_tcon_check_bits_byte); unsigned int dptx_reg_read(struct aml_lcd_drv_s *pdrv, unsigned int reg) { diff --git a/drivers/media/vout/lcd/lcd_tcon.c b/drivers/media/vout/lcd/lcd_tcon.c index c9b58428b..83812d024 100644 --- a/drivers/media/vout/lcd/lcd_tcon.c +++ b/drivers/media/vout/lcd/lcd_tcon.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifdef CONFIG_AMLOGIC_BACKLIGHT #include @@ -51,6 +52,7 @@ static struct lcd_tcon_local_cfg_s tcon_local_cfg; static int lcd_tcon_data_multi_remvoe(struct tcon_mem_map_table_s *mm_table); static int lcd_tcon_data_multi_reset(struct tcon_mem_map_table_s *mm_table); +static void lcd_tcon_fw_prepare(struct aml_lcd_drv_s *pdrv); static unsigned long long *dbg_vsync_time, *dbg_list_trave_time; static unsigned int dbg_vsync_cnt, dbg_list_trave_cnt; @@ -185,6 +187,48 @@ void lcd_tcon_dbg_trace_print(unsigned int flag) * tcon common function * ********************************** */ +static struct tcon_fw_config_s lcd_tcon_fw_config = { + .config_size = sizeof(struct tcon_fw_config_s), + .chip_type = TCON_CHIP_MAX, + .if_type = TCON_IF_TYPE_MAX, + .axi_cnt = 0, + .axi_rmem = NULL, +}; + +static struct lcd_tcon_fw_s lcd_tcon_fw = { + /* init by driver */ + .para_ver = TCON_FW_PARA_VER, + .para_size = sizeof(struct lcd_tcon_fw_s), + .valid = 0, + .tcon_state = 0, + + /* init by fw */ + .flag = 0, + .fw_ver = "not installed", + .dbg_level = 0, + + /* driver resource */ + .drvdat = NULL, + .dev = NULL, + .config = &lcd_tcon_fw_config, + + /* fw resource */ + .buf_table_in = NULL, + .buf_table_out = NULL, + + /* API */ + .vsync_isr = NULL, + .tcon_alg = NULL, + .debug_show = NULL, + .debug_store = NULL, +}; + +struct lcd_tcon_fw_s *aml_lcd_tcon_get_fw(void) +{ + return &lcd_tcon_fw; +} +EXPORT_SYMBOL(aml_lcd_tcon_get_fw); + int lcd_tcon_valid_check(void) { if (!lcd_tcon_conf) { @@ -939,27 +983,6 @@ void lcd_tcon_global_reset(struct aml_lcd_drv_s *pdrv) } } -int lcd_tcon_gamma_set_pattern(struct aml_lcd_drv_s *pdrv, - unsigned int bit_width, unsigned int gamma_r, - unsigned int gamma_g, unsigned int gamma_b) -{ - int ret; - - ret = lcd_tcon_valid_check(); - if (ret) - return -1; - - if (lcd_tcon_conf->tcon_gamma_pattern) { - ret = lcd_tcon_conf->tcon_gamma_pattern(pdrv, - bit_width, gamma_r, - gamma_g, gamma_b); - LCDPR("%s: %dbits gamma r:0x%x g:0x%x b:0x%x\n", - __func__, bit_width, gamma_r, gamma_g, gamma_b); - } - - return ret; -} - int lcd_tcon_core_update(struct aml_lcd_drv_s *pdrv) { int ret; @@ -1004,6 +1027,7 @@ int lcd_tcon_reload(struct aml_lcd_drv_s *pdrv) int lcd_tcon_enable(struct aml_lcd_drv_s *pdrv) { + struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); int ret; ret = lcd_tcon_valid_check(); @@ -1013,11 +1037,14 @@ int lcd_tcon_enable(struct aml_lcd_drv_s *pdrv) if (lcd_tcon_conf->tcon_enable) lcd_tcon_conf->tcon_enable(pdrv); + tcon_fw->tcon_state |= TCON_FW_STATE_TCON_EN; + return 0; } void lcd_tcon_disable(struct aml_lcd_drv_s *pdrv) { + struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); unsigned int i; int ret; @@ -1027,6 +1054,8 @@ void lcd_tcon_disable(struct aml_lcd_drv_s *pdrv) LCDPR("%s\n", __func__); + tcon_fw->tcon_state &= ~TCON_FW_STATE_TCON_EN; + /* release data*/ if (tcon_mm_table.version) { if (tcon_mm_table.init_load == 0) { @@ -1665,7 +1694,7 @@ static int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, if (lcd_debug_print_flag & LCD_DBG_PR_TEST) { local_time[0] = sched_clock(); - line_cnt = lcd_get_encl_lint_cnt(pdrv); + line_cnt = lcd_get_encl_line_cnt(pdrv); lcd_tcon_dbg_vsync_time_save(local_time[0], line_cnt, 0); } @@ -1678,14 +1707,14 @@ static int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, if (lcd_debug_print_flag & LCD_DBG_PR_TEST) { local_time[1] = sched_clock(); - line_cnt = lcd_get_encl_lint_cnt(pdrv); + line_cnt = lcd_get_encl_line_cnt(pdrv); lcd_tcon_dbg_vsync_time_save(local_time[1] - local_time[0], line_cnt, 1); } lcd_tcon_data_multi_update(pdrv, &tcon_mm_table); if (lcd_debug_print_flag & LCD_DBG_PR_TEST) { local_time[2] = sched_clock(); - line_cnt = lcd_get_encl_lint_cnt(pdrv); + line_cnt = lcd_get_encl_line_cnt(pdrv); lcd_tcon_dbg_vsync_time_save(local_time[2] - local_time[0], line_cnt, 2); } @@ -1711,7 +1740,7 @@ static int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, } if (lcd_debug_print_flag & LCD_DBG_PR_TEST) { local_time[3] = sched_clock(); - line_cnt = lcd_get_encl_lint_cnt(pdrv); + line_cnt = lcd_get_encl_line_cnt(pdrv); temp = (0xf << 12) | (lut_hit << 4) | 3; lcd_tcon_dbg_vsync_time_save(local_time[3] - local_time[0], line_cnt, temp); lcd_tcon_time_sort_save(mm_table->vsync_time, (local_time[3] - local_time[0])); @@ -1722,6 +1751,7 @@ static int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, void lcd_tcon_vsync_isr(struct aml_lcd_drv_s *pdrv) { + struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); unsigned long flags = 0; if ((pdrv->status & LCD_STATUS_IF_ON) == 0) @@ -1736,6 +1766,9 @@ void lcd_tcon_vsync_isr(struct aml_lcd_drv_s *pdrv) spin_unlock_irqrestore(&tcon_local_cfg.multi_list_lock, flags); } } + + if (tcon_fw->vsync_isr) + tcon_fw->vsync_isr(tcon_fw); } /* ********************************** @@ -3061,6 +3094,8 @@ static int lcd_tcon_get_config(struct aml_lcd_drv_s *pdrv) lcd_tcon_intr_init(pdrv); + lcd_tcon_fw_prepare(pdrv); + return 0; } @@ -3088,6 +3123,81 @@ static void lcd_tcon_get_config_work(struct work_struct *p_work) lcd_tcon_get_config(pdrv); } +static void lcd_tcon_fw_prepare(struct aml_lcd_drv_s *pdrv) +{ + struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); + int i; + + if (!tcon_fw || !tcon_fw->config) + return; + if (!lcd_tcon_conf) + return; + + switch (pdrv->data->chip_type) { + case LCD_CHIP_TL1: + tcon_fw->config->chip_type = TCON_CHIP_TL1; + break; + case LCD_CHIP_TM2: + case LCD_CHIP_TM2B: + tcon_fw->config->chip_type = TCON_CHIP_TM2; + break; + case LCD_CHIP_T5: + tcon_fw->config->chip_type = TCON_CHIP_T5; + break; + case LCD_CHIP_T5D: + tcon_fw->config->chip_type = TCON_CHIP_T5D; + break; + case LCD_CHIP_T3: + tcon_fw->config->chip_type = TCON_CHIP_T3; + break; + case LCD_CHIP_T5W: + tcon_fw->config->chip_type = TCON_CHIP_T5W; + break; + default: + break; + } + switch (pdrv->config.basic.lcd_type) { + case LCD_MLVDS: + tcon_fw->config->if_type = TCON_IF_MLVDS; + break; + case LCD_P2P: + tcon_fw->config->if_type = TCON_IF_P2P; + break; + default: + break; + } + + tcon_fw->config->axi_cnt = lcd_tcon_conf->axi_bank; + if (!tcon_rmem.axi_rmem) + return; + tcon_fw->config->axi_rmem = kcalloc(tcon_fw->config->axi_cnt, + sizeof(struct tcon_fw_axi_rmem_s), GFP_KERNEL); + for (i = 0; i < tcon_fw->config->axi_cnt; i++) { + tcon_fw->config->axi_rmem[i].mem_paddr = tcon_rmem.axi_rmem[i].mem_paddr; + tcon_fw->config->axi_rmem[i].mem_size = tcon_rmem.axi_rmem[i].mem_size; + } + + if (pdrv->status & LCD_STATUS_IF_ON) + tcon_fw->tcon_state |= TCON_FW_STATE_TCON_EN; + if (tcon_mm_table.valid_flag & LCD_TCON_DATA_VALID_VAC) + tcon_fw->tcon_state |= TCON_FW_STATE_VAC_VALID; + if (tcon_mm_table.valid_flag & LCD_TCON_DATA_VALID_DEMURA) + tcon_fw->tcon_state |= TCON_FW_STATE_DEMURA_VALID; + if (tcon_mm_table.valid_flag & LCD_TCON_DATA_VALID_ACC) + tcon_fw->tcon_state |= TCON_FW_STATE_ACC_VALID; + if (tcon_mm_table.valid_flag & LCD_TCON_DATA_VALID_DITHER) + tcon_fw->tcon_state |= TCON_FW_STATE_DITHER_VALID; + if (tcon_mm_table.valid_flag & LCD_TCON_DATA_VALID_OD) + tcon_fw->tcon_state |= TCON_FW_STATE_OD_VALID; + if (tcon_mm_table.valid_flag & LCD_TCON_DATA_VALID_LOD) + tcon_fw->tcon_state |= TCON_FW_STATE_LOD_VALID; + + tcon_fw->drvdat = (void *)pdrv; + tcon_fw->dev = pdrv->dev; + + tcon_fw->valid = 1; +} + /* ********************************** * tcon match data * ********************************** @@ -3131,7 +3241,6 @@ static struct lcd_tcon_config_s tcon_data_tl1 = { .tcon_axi_mem_secure = lcd_tcon_axi_mem_secure_tl1, .tcon_axi_mem_update = NULL, .tcon_global_reset = NULL, - .tcon_gamma_pattern = lcd_tcon_gamma_pattern_tl1, .tcon_enable = lcd_tcon_enable_tl1, .tcon_disable = lcd_tcon_disable_tl1, .tcon_reload = NULL, @@ -3177,7 +3286,6 @@ static struct lcd_tcon_config_s tcon_data_t5 = { .tcon_axi_mem_secure = lcd_tcon_axi_mem_secure_t3, .tcon_axi_mem_update = lcd_tcon_axi_rmem_update_t5, .tcon_global_reset = lcd_tcon_global_reset_t5, - .tcon_gamma_pattern = lcd_tcon_gamma_pattern_t5, .tcon_enable = lcd_tcon_enable_t5, .tcon_disable = lcd_tcon_disable_t5, .tcon_reload = NULL, @@ -3219,7 +3327,6 @@ static struct lcd_tcon_config_s tcon_data_t5d = { .tcon_axi_mem_secure = lcd_tcon_axi_mem_secure_t3, .tcon_axi_mem_update = lcd_tcon_axi_rmem_update_t5d, .tcon_global_reset = lcd_tcon_global_reset_t5, - .tcon_gamma_pattern = lcd_tcon_gamma_pattern_t5, .tcon_enable = lcd_tcon_enable_t5, .tcon_disable = lcd_tcon_disable_t5, .tcon_reload = NULL, @@ -3265,7 +3372,6 @@ static struct lcd_tcon_config_s tcon_data_t3 = { .tcon_axi_mem_secure = lcd_tcon_axi_mem_secure_t3, .tcon_axi_mem_update = lcd_tcon_axi_rmem_update_t5, .tcon_global_reset = lcd_tcon_global_reset_t3, - .tcon_gamma_pattern = lcd_tcon_gamma_pattern_t5, .tcon_enable = lcd_tcon_enable_t3, .tcon_disable = lcd_tcon_disable_t3, .tcon_reload = lcd_tcon_reload_t3, @@ -3311,7 +3417,6 @@ static struct lcd_tcon_config_s tcon_data_t5w = { .tcon_axi_mem_secure = lcd_tcon_axi_mem_secure_t3, .tcon_axi_mem_update = lcd_tcon_axi_rmem_update_t5, .tcon_global_reset = lcd_tcon_global_reset_t5, - .tcon_gamma_pattern = lcd_tcon_gamma_pattern_t5, .tcon_enable = lcd_tcon_enable_t5, .tcon_disable = lcd_tcon_disable_t5, .tcon_reload = lcd_tcon_reload_t3, diff --git a/drivers/media/vout/lcd/lcd_tcon.h b/drivers/media/vout/lcd/lcd_tcon.h index 635465275..11fb8b214 100644 --- a/drivers/media/vout/lcd/lcd_tcon.h +++ b/drivers/media/vout/lcd/lcd_tcon.h @@ -52,9 +52,6 @@ struct lcd_tcon_config_s { void (*tcon_axi_mem_secure)(void); void (*tcon_axi_mem_update)(unsigned int *table); void (*tcon_global_reset)(struct aml_lcd_drv_s *pdrv); - int (*tcon_gamma_pattern)(struct aml_lcd_drv_s *pdrv, - unsigned int bit_width, unsigned int gamma_r, - unsigned int gamma_g, unsigned int gamma_b); int (*tcon_reload_pre)(struct aml_lcd_drv_s *pdrv); int (*tcon_reload)(struct aml_lcd_drv_s *pdrv); int (*tcon_enable)(struct aml_lcd_drv_s *pdrv); diff --git a/drivers/media/vout/lcd/lcd_tcon_hw.c b/drivers/media/vout/lcd/lcd_tcon_hw.c index 973acf650..b0f88244b 100644 --- a/drivers/media/vout/lcd/lcd_tcon_hw.c +++ b/drivers/media/vout/lcd/lcd_tcon_hw.c @@ -1121,138 +1121,6 @@ void lcd_tcon_global_reset_t3(struct aml_lcd_drv_s *pdrv) udelay(2); } -int lcd_tcon_gamma_pattern_tl1(struct aml_lcd_drv_s *pdrv, - unsigned int bit_width, unsigned int gamma_r, - unsigned int gamma_g, unsigned int gamma_b) -{ - unsigned int val_r = 0, val_g = 0, val_b = 0, reg; - unsigned char temp[3]; - int i; - - switch (bit_width) { - case 12: - val_r = gamma_r; - val_g = gamma_g; - val_b = gamma_b; - break; - case 10: - val_r = (gamma_r << 2); - val_g = (gamma_g << 2); - val_b = (gamma_b << 2); - break; - case 8: - val_r = (gamma_r << 4); - val_g = (gamma_g << 4); - val_b = (gamma_b << 4); - break; - default: - LCDERR("gamma_set: invalid bit_width %d\n", bit_width); - return -1; - } - - /* enable lut access, disable gamma en*/ - lcd_tcon_setb_byte(pdrv, 0x262, 0x2, 0, 2); - - /* gamma_r */ - /*2 data splice 3 bytes*/ - temp[0] = val_r & 0xff; - temp[1] = ((val_r >> 8) & 0xf) | ((val_r & 0xf) << 4); - temp[2] = (val_r >> 4) & 0xff; - reg = 0xb50; - for (i = 0; i < 384; i += 3) { /* 256 * 1.5 */ - lcd_tcon_write_byte(pdrv, (reg + i), temp[0]); - lcd_tcon_write_byte(pdrv, (reg + i + 1), temp[1]); - lcd_tcon_write_byte(pdrv, (reg + i + 2), temp[2]); - } - temp[0] = val_r & 0xff; - temp[1] = ((val_r >> 8) & 0xf); - temp[2] = 0; - reg += 384; - lcd_tcon_write_byte(pdrv, (reg), temp[0]); - lcd_tcon_write_byte(pdrv, (reg + 1), temp[1]); - lcd_tcon_write_byte(pdrv, (reg + 2), temp[2]); - - /* gamma_g */ - /*2 data splice 3 bytes*/ - temp[0] = val_g & 0xff; - temp[1] = ((val_g >> 8) & 0xf) | ((val_g & 0xf) << 4); - temp[2] = (val_g >> 4) & 0xff; - reg += 3; - for (i = 0; i < 384; i += 3) { /* 256 * 1.5 */ - lcd_tcon_write_byte(pdrv, (reg + i), temp[0]); - lcd_tcon_write_byte(pdrv, (reg + i + 1), temp[1]); - lcd_tcon_write_byte(pdrv, (reg + i + 2), temp[2]); - } - temp[0] = val_g & 0xff; - temp[1] = ((val_g >> 8) & 0xf); - temp[2] = 0; - reg += 384; - lcd_tcon_write_byte(pdrv, (reg), temp[0]); - lcd_tcon_write_byte(pdrv, (reg + 1), temp[1]); - lcd_tcon_write_byte(pdrv, (reg + 2), temp[2]); - - /* gamma_b */ - /*2 data splice 3 bytes*/ - temp[0] = val_b & 0xff; - temp[1] = ((val_b >> 8) & 0xf) | ((val_b & 0xf) << 4); - temp[2] = (val_b >> 4) & 0xff; - reg += 3; - for (i = 0; i < 384; i += 3) { /* 256 * 1.5 */ - lcd_tcon_write_byte(pdrv, (reg + i), temp[0]); - lcd_tcon_write_byte(pdrv, (reg + i + 1), temp[1]); - lcd_tcon_write_byte(pdrv, (reg + i + 2), temp[2]); - } - temp[0] = val_b & 0xff; - temp[1] = ((val_b >> 8) & 0xf); - temp[2] = 0; - reg += 384; - lcd_tcon_write_byte(pdrv, (reg), temp[0]); - lcd_tcon_write_byte(pdrv, (reg + 1), temp[1]); - lcd_tcon_write_byte(pdrv, (reg + 2), temp[2]); - - /* enable gamma */ - lcd_tcon_setb_byte(pdrv, 0x262, 0x3, 0, 2); - - return 0; -} - -int lcd_tcon_gamma_pattern_t5(struct aml_lcd_drv_s *pdrv, - unsigned int bit_width, unsigned int gamma_r, - unsigned int gamma_g, unsigned int gamma_b) -{ - unsigned int val_r = 0, val_g = 0, val_b = 0; - unsigned int temp; - - switch (bit_width) { - case 10: - val_r = gamma_r & 0x3ff; - val_g = gamma_g & 0x3ff; - val_b = gamma_b & 0x3ff; - break; - case 8: - val_r = (gamma_r << 2) & 0x3ff; - val_g = (gamma_g << 2) & 0x3ff; - val_b = (gamma_b << 2) & 0x3ff; - break; - default: - LCDERR("gamma_set: invalid bit_width %d\n", bit_width); - return -1; - } - - /* gamma calibrate mode */ - lcd_tcon_setb(pdrv, 0x222, 1, 13, 1); - lcd_tcon_setb(pdrv, 0x222, 0, 12, 1); - lcd_tcon_setb(pdrv, 0x222, 0, 8, 2); - lcd_tcon_setb(pdrv, 0x201, 1, 31, 1); //test pattern enable - - /* gamma pattern */ - lcd_tcon_setb(pdrv, 0x201, 0, 26, 4); - temp = (val_r << 0) | (val_g << 10) | (val_b << 20); - lcd_tcon_setb(pdrv, 0x204, temp, 0, 30); - - return 0; -} - int lcd_tcon_enable_tl1(struct aml_lcd_drv_s *pdrv) { struct lcd_config_s *pconf = &pdrv->config; diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc.h b/drivers/media/vout/lcd/lcd_venc/lcd_venc.h index c168eab0b..fcf2d90af 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc.h +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc.h @@ -21,7 +21,8 @@ struct lcd_venc_op_s { void (*mute_set)(struct aml_lcd_drv_s *pdrv, unsigned char flag); int (*get_venc_init_config)(struct aml_lcd_drv_s *pdrv); void (*venc_vrr_recovery)(struct aml_lcd_drv_s *pdrv); - unsigned int (*get_encl_lint_cnt)(struct aml_lcd_drv_s *pdrv); + unsigned int (*get_encl_line_cnt)(struct aml_lcd_drv_s *pdrv); + unsigned int (*get_encl_frm_cnt)(struct aml_lcd_drv_s *pdrv); }; int lcd_venc_op_init_dft(struct aml_lcd_drv_s *pdrv, struct lcd_venc_op_s *venc_op); diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_c3.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_c3.c index 87fc79fdf..881a61b8f 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_c3.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_c3.c @@ -168,7 +168,8 @@ int lcd_venc_op_init_c3(struct aml_lcd_drv_s *pdrv, struct lcd_venc_op_s *venc_o venc_op->mute_set = lcd_venc_mute_set; venc_op->get_venc_init_config = lcd_venc_get_init_config; venc_op->venc_vrr_recovery = NULL; - venc_op->get_encl_lint_cnt = NULL; + venc_op->get_encl_line_cnt = NULL; + venc_op->get_encl_frm_cnt = NULL; return 0; }; diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c index 4f80d3fd8..922d5084e 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c @@ -389,11 +389,18 @@ static void lcd_venc_set_vrr_recovery(struct aml_lcd_drv_s *pdrv) lcd_vcbus_write(ENCL_VIDEO_MAX_LNCNT, vtotal); } -static unsigned int lcd_venc_get_encl_lint_cnt(struct aml_lcd_drv_s *pdrv) +static unsigned int lcd_venc_get_encl_line_cnt(struct aml_lcd_drv_s *pdrv) { - unsigned int line_cnt = lcd_vcbus_getb(ENCL_INFO_READ, 16, 13); + unsigned int cnt = lcd_vcbus_getb(ENCL_INFO_READ, 16, 13); - return line_cnt; + return cnt; +} + +static unsigned int lcd_venc_get_encl_frm_cnt(struct aml_lcd_drv_s *pdrv) +{ + unsigned int cnt = lcd_vcbus_getb(ENCL_INFO_READ, 29, 3); + + return cnt; } int lcd_venc_op_init_dft(struct aml_lcd_drv_s *pdrv, struct lcd_venc_op_s *venc_op) @@ -411,7 +418,8 @@ int lcd_venc_op_init_dft(struct aml_lcd_drv_s *pdrv, struct lcd_venc_op_s *venc_ venc_op->mute_set = lcd_venc_mute_set; venc_op->get_venc_init_config = lcd_venc_get_init_config; venc_op->venc_vrr_recovery = lcd_venc_set_vrr_recovery; - venc_op->get_encl_lint_cnt = lcd_venc_get_encl_lint_cnt; + venc_op->get_encl_line_cnt = lcd_venc_get_encl_line_cnt; + venc_op->get_encl_frm_cnt = lcd_venc_get_encl_frm_cnt; INIT_WORK(&pdrv->test_check_work, lcd_test_pattern_check); diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_if.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_if.c index f3fb4c17b..b73022f41 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_if.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_if.c @@ -30,7 +30,8 @@ static struct lcd_venc_op_s lcd_venc_op = { .mute_set = NULL, .get_venc_init_config = NULL, .venc_vrr_recovery = NULL, - .get_encl_lint_cnt = NULL + .get_encl_line_cnt = NULL, + .get_encl_frm_cnt = NULL, }; void lcd_wait_vsync(struct aml_lcd_drv_s *pdrv) @@ -161,19 +162,35 @@ int lcd_get_venc_init_config(struct aml_lcd_drv_s *pdrv) return ret; } -unsigned int lcd_get_encl_lint_cnt(struct aml_lcd_drv_s *pdrv) +unsigned int lcd_get_encl_line_cnt(struct aml_lcd_drv_s *pdrv) { - if (!lcd_venc_op.get_encl_lint_cnt) + unsigned int cnt = 0; + + if (!lcd_venc_op.get_encl_line_cnt) return 0; - int ret = 0; - - if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL) + if (lcd_debug_print_flag & LCD_DBG_PR_ISR) LCDPR("[%d]: %s\n", pdrv->index, __func__); - ret = lcd_venc_op.get_encl_lint_cnt(pdrv); - return ret; + cnt = lcd_venc_op.get_encl_line_cnt(pdrv); + return cnt; } +EXPORT_SYMBOL(lcd_get_encl_line_cnt); + +unsigned int lcd_get_encl_frm_cnt(struct aml_lcd_drv_s *pdrv) +{ + unsigned int cnt = 0; + + if (!lcd_venc_op.get_encl_frm_cnt) + return 0; + + if (lcd_debug_print_flag & LCD_DBG_PR_ISR) + LCDPR("[%d]: %s\n", pdrv->index, __func__); + + cnt = lcd_venc_op.get_encl_frm_cnt(pdrv); + return cnt; +} +EXPORT_SYMBOL(lcd_get_encl_frm_cnt); void lcd_venc_vrr_recovery(struct aml_lcd_drv_s *pdrv) { diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c index bf2b4c6dd..a418efa64 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c @@ -511,9 +511,9 @@ static void lcd_venc_set_vrr_recovery(struct aml_lcd_drv_s *pdrv) lcd_vcbus_write(ENCL_VIDEO_MAX_LNCNT + offset, vtotal); } -static unsigned int lcd_venc_get_encl_lint_cnt(struct aml_lcd_drv_s *pdrv) +static unsigned int lcd_venc_get_encl_line_cnt(struct aml_lcd_drv_s *pdrv) { - unsigned int reg, offset, line_cnt; + unsigned int reg, offset, cnt; if (!pdrv) return 0; @@ -521,8 +521,22 @@ static unsigned int lcd_venc_get_encl_lint_cnt(struct aml_lcd_drv_s *pdrv) offset = pdrv->data->offset_venc[pdrv->index]; reg = VPU_VENCP_STAT + offset; - line_cnt = lcd_vcbus_getb(reg, 16, 13); - return line_cnt; + cnt = lcd_vcbus_getb(reg, 16, 13); + return cnt; +} + +static unsigned int lcd_venc_get_encl_frm_cnt(struct aml_lcd_drv_s *pdrv) +{ + unsigned int reg, offset, cnt; + + if (!pdrv) + return 0; + + offset = pdrv->data->offset_venc[pdrv->index]; + reg = VPU_VENCP_STAT + offset; + + cnt = lcd_vcbus_getb(reg, 29, 3); + return cnt; } int lcd_venc_op_init_t7(struct aml_lcd_drv_s *pdrv, struct lcd_venc_op_s *venc_op) @@ -540,7 +554,8 @@ int lcd_venc_op_init_t7(struct aml_lcd_drv_s *pdrv, struct lcd_venc_op_s *venc_o venc_op->mute_set = lcd_venc_mute_set; venc_op->get_venc_init_config = lcd_venc_get_init_config; venc_op->venc_vrr_recovery = lcd_venc_set_vrr_recovery; - venc_op->get_encl_lint_cnt = lcd_venc_get_encl_lint_cnt; + venc_op->get_encl_line_cnt = lcd_venc_get_encl_line_cnt; + venc_op->get_encl_frm_cnt = lcd_venc_get_encl_frm_cnt; return 0; }; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_tcon_fw.h b/include/linux/amlogic/media/vout/lcd/lcd_tcon_fw.h new file mode 100644 index 000000000..40b7b64be --- /dev/null +++ b/include/linux/amlogic/media/vout/lcd/lcd_tcon_fw.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + */ + +#ifndef _INC_AML_LCD_TCON_FW_H +#define _INC_AML_LCD_TCON_FW_H +#include + +#define TCON_FW_PARA_VER 1 + +enum tcon_fw_chip_e { + TCON_CHIP_TL1 = 0, + TCON_CHIP_TM2, /* 1 */ + TCON_CHIP_T5, /* 2 */ + TCON_CHIP_T5D, /* 3 */ + TCON_CHIP_T3, /* 4 */ + TCON_CHIP_T5W, /* 5 */ + TCON_CHIP_T5M, /* 6 */ + TCON_CHIP_T3X, /* 7 */ + TCON_CHIP_TXHD2, /* 8 */ + TCON_CHIP_MAX, +}; + +enum tcon_fw_if_type_e { + TCON_IF_MLVDS = 0, + TCON_IF_P2P, + TCON_IF_TYPE_MAX, +}; + +struct tcon_fw_axi_rmem_s { + phys_addr_t mem_paddr; + unsigned int mem_size; +}; + +struct tcon_fw_config_s { + unsigned int config_size; + unsigned int chip_type; + unsigned int if_type; + unsigned char axi_cnt; + struct tcon_fw_axi_rmem_s *axi_rmem; +}; + +#define TCON_FW_DATA_HEADER_SIZE 32 +struct tcon_fw_data_header_s { + unsigned int crc32; + unsigned int data_size; + unsigned char block_cnt; + unsigned char reserved[55]; +}; + +#define TCON_FW_STATE_TCON_EN 0x00000001 +#define TCON_FW_STATE_VAC_VALID 0x00000100 +#define TCON_FW_STATE_DEMURA_VALID 0x00000200 +#define TCON_FW_STATE_DITHER_VALID 0x00000400 +#define TCON_FW_STATE_ACC_VALID 0x00001000 +#define TCON_FW_STATE_PRE_ACC_VALID 0x00002000 +#define TCON_FW_STATE_OD_VALID 0x00010000 +#define TCON_FW_STATE_LOD_VALID 0x00100000 + +struct lcd_tcon_fw_s { + /* init by driver */ + unsigned int para_ver; + unsigned int para_size; + unsigned char valid; + unsigned int tcon_state; + + /* init by fw */ + char fw_ver[20]; + unsigned char flag; + unsigned int dbg_level; + + /* driver resource */ + void *drvdat; + struct device *dev; + struct tcon_fw_config_s *config; + + /* fw resource */ + unsigned char *buf_table_in; + unsigned char *buf_table_out; + + /* API */ + int (*vsync_isr)(struct lcd_tcon_fw_s *fw); + int (*tcon_alg)(struct lcd_tcon_fw_s *fw, unsigned int flag); + ssize_t (*debug_show)(struct lcd_tcon_fw_s *fw, char *buf); + int (*debug_store)(struct lcd_tcon_fw_s *fw, const char *buf); +}; + +struct lcd_tcon_fw_s *aml_lcd_tcon_get_fw(void); + +#endif /* _INC_AML_LCD_TCON_FW_H */