From caf7882c0b4376b32a5beccfb47e0bf5c9b8d065 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 6 Sep 2017 09:57:35 +0800 Subject: [PATCH] lcd: driver defect clean up PD#150465: driver defect clean up: #71 #77 #109 #127 #411 #600 #602 #603 #604 #611 #612 Change-Id: I38ac5ed6583bd6e57df9f42eaab04d05ee4ed663 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/lcd/lcd_clk_config.c | 16 +- drivers/amlogic/media/vout/lcd/lcd_clk_config.h | 41 ++- drivers/amlogic/media/vout/lcd/lcd_common.c | 32 ++- drivers/amlogic/media/vout/lcd/lcd_common.h | 3 +- drivers/amlogic/media/vout/lcd/lcd_debug.c | 195 +++++++++++--- drivers/amlogic/media/vout/lcd/lcd_reg.h | 2 + .../amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c | 6 +- .../amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c | 290 ++++++++++++++------- drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 8 +- drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 275 +++++++++++++------ drivers/amlogic/media/vout/lcd/lcd_vout.c | 83 ++++-- .../linux/amlogic/media/vout/lcd/lcd_unifykey.h | 70 ++++- include/linux/amlogic/media/vout/lcd/lcd_vout.h | 40 ++- 13 files changed, 773 insertions(+), 288 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index a69e6f0e..96618f2 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -229,14 +229,16 @@ void lcd_clk_config_print(void) "div_sel: %s(index %d)\n" "xd: %d\n" "fout: %dkHz\n" - "ss_level: %d\n\n", + "ss_level: %d\n" + "pll_mode: %d\n\n", clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_od2_sel, clk_conf.pll_od3_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout, clk_conf.ss_level, + clk_conf.pll_mode); break; } } @@ -587,7 +589,10 @@ static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) lcd_hiu_write(HHI_HDMI_PLL_CNTL, pll_ctrl); lcd_hiu_write(HHI_HDMI_PLL_CNTL2, pll_ctrl2); lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); - lcd_hiu_write(HHI_HDMI_PLL_CNTL4, 0x0c8e0000); + if (cConf->pll_mode) + lcd_hiu_write(HHI_HDMI_PLL_CNTL4, 0x0d160000); + else + lcd_hiu_write(HHI_HDMI_PLL_CNTL4, 0x0c8e0000); lcd_hiu_write(HHI_HDMI_PLL_CNTL5, 0x001fa729); lcd_hiu_write(HHI_HDMI_PLL_CNTL6, 0x01a31500); lcd_hiu_setb(HHI_HDMI_PLL_CNTL, 1, LCD_PLL_RST_TXL, 1); @@ -1286,6 +1291,11 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) goto generate_clk_done_txl; } + if (pconf->lcd_timing.clk_auto == 2) + cConf->pll_mode = 1; + else + cConf->pll_mode = 0; + switch (pconf->lcd_basic.lcd_type) { case LCD_TTL: clk_div_sel = CLK_DIV_SEL_1; diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 911a843..863509c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -21,7 +21,10 @@ #include #include -/* clk config */ +/* ********************************** + * clk config + * ********************************** + */ struct lcd_clk_config_s { /* unit: kHz */ /* IN-OUT parameters */ unsigned int fin; @@ -69,9 +72,13 @@ struct lcd_clk_config_s { /* unit: kHz */ unsigned int div_out_fmax; /* g9tv, g9bb, gxbb */ unsigned int xd_out_fmax; unsigned int err_fmin; + unsigned int pll_mode; }; -/* pll & clk parameter */ +/* ********************************** + * pll & clk parameter + * ********************************** + */ /* ******** clk calculation ******** */ #define PLL_WAIT_LOCK_CNT 200 /* frequency unit: kHz */ @@ -110,7 +117,10 @@ enum div_sel_e { }; -/* GXTVBB */ +/* ********************************** + * GXTVBB + * ********************************** + */ /* ******** register bit ******** */ /* PLL_CNTL 0x10c8 */ #define LCD_PLL_LOCK_GXTVBB 31 @@ -143,7 +153,10 @@ enum div_sel_e { #define CRT_VID_CLK_IN_MAX_GXTVBB (3100 * 1000) #define ENCL_CLK_IN_MAX_GXTVBB (620 * 1000) -/* GXL */ +/* ********************************** + * GXL + * ********************************** + */ /* ******** register bit ******** */ /* PLL_CNTL 0x10c8 */ #define LCD_PLL_LOCK_GXL 31 @@ -176,7 +189,10 @@ enum div_sel_e { #define CRT_VID_CLK_IN_MAX_GXL (3100 * 1000) #define ENCL_CLK_IN_MAX_GXL (620 * 1000) -/* GXM */ +/* ********************************** + * GXM + * ********************************** + */ /* ******** register bit ******** */ /* PLL_CNTL 0x10c8 */ #define LCD_PLL_LOCK_GXM 31 @@ -209,7 +225,10 @@ enum div_sel_e { #define CRT_VID_CLK_IN_MAX_GXM (3100 * 1000) #define ENCL_CLK_IN_MAX_GXM (620 * 1000) -/* TXL */ +/* ********************************** + * TXL + * ********************************** + */ /* ******** register bit ******** */ /* PLL_CNTL 0x10c8 */ #define LCD_PLL_LOCK_TXL 31 @@ -242,7 +261,10 @@ enum div_sel_e { #define CRT_VID_CLK_IN_MAX_TXL (3100 * 1000) #define ENCL_CLK_IN_MAX_TXL (620 * 1000) -/* TXLX */ +/* ********************************** + * TXLX + * ********************************** + */ /* ******** register bit ******** */ /* PLL_CNTL 0x10c8 */ #define LCD_PLL_LOCK_TXLX 31 @@ -275,7 +297,10 @@ enum div_sel_e { #define CRT_VID_CLK_IN_MAX_TXLX (3100 * 1000) #define ENCL_CLK_IN_MAX_TXLX (620 * 1000) -/* AXG */ +/* ********************************** + * AXG + * ********************************** + */ /* ******** register bit ******** */ /* PLL_CNTL */ #define LCD_PLL_LOCK_AXG 31 diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index dcd0be7..85b0441 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -38,7 +38,10 @@ #include "lcd_common.h" #include "lcd_reg.h" -/* lcd type */ +/* ********************************** + * lcd type + * ********************************** + */ struct lcd_type_match_s { char *name; enum lcd_type_e type; @@ -102,7 +105,10 @@ char *lcd_mode_mode_to_str(int mode) return lcd_mode_table[mode]; } -/* lcd gpio */ +/* ********************************** + * lcd gpio + * ********************************** + */ #if 0 #define lcd_gpio_request(dev, str) gpiod_get(dev, str) #define lcd_gpio_free(gdesc) gpiod_put(gdesc) @@ -780,7 +786,7 @@ int lcd_vmode_change(struct lcd_config_s *pconf) char str[100]; int len = 0; - pconf->lcd_timing.clk_change = 0; /* clear clk flga */ + pconf->lcd_timing.clk_change = 0; /* clear clk flag */ switch (type) { case 0: /* pixel clk adjust */ pclk = (h_period * v_period) / duration_den * duration_num; @@ -788,9 +794,9 @@ int lcd_vmode_change(struct lcd_config_s *pconf) pconf->lcd_timing.clk_change = LCD_CLK_PLL_CHANGE; break; case 1: /* htotal adjust */ - h_period = ((pclk / v_period) * duration_den * 10) / + h_period = ((pclk / v_period) * duration_den * 100) / duration_num; - h_period = (h_period + 5) / 10; /* round off */ + h_period = (h_period + 99) / 100; /* round off */ if (pconf->lcd_basic.h_period != h_period) { /* check clk frac update */ pclk = (h_period * v_period) / duration_den * @@ -802,9 +808,9 @@ int lcd_vmode_change(struct lcd_config_s *pconf) } break; case 2: /* vtotal adjust */ - v_period = ((pclk / h_period) * duration_den * 10) / + v_period = ((pclk / h_period) * duration_den * 100) / duration_num; - v_period = (v_period + 5) / 10; /* round off */ + v_period = (v_period + 99) / 100; /* round off */ if (pconf->lcd_basic.v_period != v_period) { /* check clk frac update */ pclk = (h_period * v_period) / duration_den * @@ -817,14 +823,14 @@ int lcd_vmode_change(struct lcd_config_s *pconf) break; case 3: /* free adjust, use min/max range to calculate */ default: - v_period = ((pclk / h_period) * duration_den * 10) / + v_period = ((pclk / h_period) * duration_den * 100) / duration_num; - v_period = (v_period + 5) / 10; /* round off */ + v_period = (v_period + 99) / 100; /* round off */ if (v_period > pconf->lcd_basic.v_period_max) { v_period = pconf->lcd_basic.v_period_max; - h_period = ((pclk / v_period) * duration_den * 10) / + h_period = ((pclk / v_period) * duration_den * 100) / duration_num; - h_period = (h_period + 5) / 10; /* round off */ + h_period = (h_period + 99) / 100; /* round off */ if (h_period > pconf->lcd_basic.h_period_max) { h_period = pconf->lcd_basic.h_period_max; pclk = (h_period * v_period) / duration_den * @@ -841,9 +847,9 @@ int lcd_vmode_change(struct lcd_config_s *pconf) } } else if (v_period < pconf->lcd_basic.v_period_min) { v_period = pconf->lcd_basic.v_period_min; - h_period = ((pclk / v_period) * duration_den * 10) / + h_period = ((pclk / v_period) * duration_den * 100) / duration_num; - h_period = (h_period + 5) / 10; /* round off */ + h_period = (h_period + 99) / 100; /* round off */ if (h_period < pconf->lcd_basic.h_period_min) { h_period = pconf->lcd_basic.h_period_min; pclk = (h_period * v_period) / duration_den * diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 08ae6af..3fadbef 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -23,7 +23,8 @@ #include "lcd_clk_config.h" /* 20170505: add a113 support to linux4.9 */ -#define LCD_DRV_VERSION "20170505" +/* 20170905: fix coverity errors */ +#define LCD_DRV_VERSION "20170905" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 99a9c76..bee979e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -349,37 +349,37 @@ static void lcd_ttl_reg_print(void) reg, lcd_vcbus_read(reg)); reg = L_STH1_HE_ADDR; pr_info("STH1_HE_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_STH1_VS_ADDR; pr_info("STH1_VS_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_STH1_VE_ADDR; pr_info("STH1_VE_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_STV1_HS_ADDR; pr_info("STV1_HS_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_STV1_HE_ADDR; pr_info("STV1_HE_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_STV1_VS_ADDR; pr_info("STV1_VS_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_STV1_VE_ADDR; pr_info("STV1_VE_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_OEH_HS_ADDR; pr_info("OEH_HS_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_OEH_HE_ADDR; pr_info("OEH_HE_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_OEH_VS_ADDR; pr_info("OEH_VS_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); reg = L_OEH_VE_ADDR; pr_info("OEH_VE_ADDR [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); + reg, lcd_vcbus_read(reg)); } static void lcd_lvds_reg_print(void) @@ -407,14 +407,37 @@ static void lcd_lvds_reg_print(void) static void lcd_vbyone_reg_print(void) { unsigned int reg; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); pr_info("\nvbyone registers:\n"); - reg = PERIPHS_PIN_MUX_7; - pr_info("VX1_PINMUX [0x%04x] = 0x%08x\n", - reg, lcd_periphs_read(reg)); + switch (lcd_drv->chip_type) { + case LCD_CHIP_GXTVBB: + reg = PERIPHS_PIN_MUX_7; + pr_info("VX1_PINMUX [0x%04x] = 0x%08x\n", + reg, lcd_periphs_read(reg)); + break; + case LCD_CHIP_TXL: + case LCD_CHIP_TXLX: + reg = PERIPHS_PIN_MUX_0; + pr_info("VX1_PINMUX [0x%04x] = 0x%08x\n", + reg, lcd_periphs_read(reg)); + break; + default: + break; + } reg = VBO_STATUS_L; pr_info("VX1_STATUS [0x%04x] = 0x%08x\n", reg, lcd_vcbus_read(reg)); + switch (lcd_drv->chip_type) { + case LCD_CHIP_TXL: + case LCD_CHIP_TXLX: + reg = VBO_INSGN_CTRL; + pr_info("VBO_INSGN_CTRL [0x%04x] = 0x%08x\n", + reg, lcd_vcbus_read(reg)); + break; + default: + break; + } reg = VBO_FSM_HOLDER_L; pr_info("VX1_FSM_HOLDER_L [0x%04x] = 0x%08x\n", reg, lcd_vcbus_read(reg)); @@ -505,7 +528,7 @@ static void lcd_reg_print(void) struct lcd_config_s *pconf; pconf = lcd_drv->lcd_config; - pr_info("clk registers:\n"); + LCDPR("clk registers:\n"); switch (lcd_drv->chip_type) { case LCD_CHIP_AXG: for (i = 0; i < ARRAY_SIZE(lcd_reg_dump_clk_axg); i++) { @@ -616,20 +639,19 @@ static void lcd_debug_test(unsigned int num) h_active = lcd_drv->lcd_config->lcd_basic.h_active; video_on_pixel = lcd_drv->lcd_config->lcd_timing.video_on_pixel; - if (num >= 0) { - lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL, lcd_enc_tst[num][6]); - lcd_vcbus_write(ENCL_TST_MDSEL, lcd_enc_tst[num][0]); - lcd_vcbus_write(ENCL_TST_Y, lcd_enc_tst[num][1]); - lcd_vcbus_write(ENCL_TST_CB, lcd_enc_tst[num][2]); - lcd_vcbus_write(ENCL_TST_CR, lcd_enc_tst[num][3]); - lcd_vcbus_write(ENCL_TST_CLRBAR_STRT, video_on_pixel); - lcd_vcbus_write(ENCL_TST_CLRBAR_WIDTH, (h_active / 9)); - lcd_vcbus_write(ENCL_TST_EN, lcd_enc_tst[num][4]); - lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV, lcd_enc_tst[num][5], 3, 1); + lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL, lcd_enc_tst[num][6]); + lcd_vcbus_write(ENCL_TST_MDSEL, lcd_enc_tst[num][0]); + lcd_vcbus_write(ENCL_TST_Y, lcd_enc_tst[num][1]); + lcd_vcbus_write(ENCL_TST_CB, lcd_enc_tst[num][2]); + lcd_vcbus_write(ENCL_TST_CR, lcd_enc_tst[num][3]); + lcd_vcbus_write(ENCL_TST_CLRBAR_STRT, video_on_pixel); + lcd_vcbus_write(ENCL_TST_CLRBAR_WIDTH, (h_active / 9)); + lcd_vcbus_write(ENCL_TST_EN, lcd_enc_tst[num][4]); + lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV, lcd_enc_tst[num][5], 3, 1); + if (num > 0) LCDPR("show test pattern: %s\n", lcd_enc_tst_str[num]); - } else { + else LCDPR("disable test pattern\n"); - } } static void lcd_mute_setting(unsigned char flag) @@ -680,11 +702,37 @@ static void lcd_test_check(void) } } +static void lcd_vinfo_update(void) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct vinfo_s *vinfo; + struct lcd_config_s *pconf; + + vinfo = lcd_drv->lcd_info; + pconf = lcd_drv->lcd_config; + if (vinfo) { + vinfo->width = pconf->lcd_basic.h_active; + vinfo->height = pconf->lcd_basic.v_active; + vinfo->field_height = pconf->lcd_basic.v_active; + vinfo->aspect_ratio_num = pconf->lcd_basic.screen_width; + vinfo->aspect_ratio_den = pconf->lcd_basic.screen_height; + vinfo->screen_real_width = pconf->lcd_basic.screen_width; + vinfo->screen_real_height = pconf->lcd_basic.screen_height; + vinfo->sync_duration_num = pconf->lcd_timing.sync_duration_num; + vinfo->sync_duration_den = pconf->lcd_timing.sync_duration_den; + vinfo->video_clk = pconf->lcd_timing.lcd_clk; + } + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, + &lcd_drv->lcd_info->mode); +} + static void lcd_debug_config_update(void) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); lcd_drv->module_reset(); + + lcd_vinfo_update(); } static void lcd_debug_clk_change(unsigned int pclk) @@ -697,6 +745,7 @@ static void lcd_debug_clk_change(unsigned int pclk) sync_duration = pclk / pconf->lcd_basic.h_period; sync_duration = sync_duration * 100 / pconf->lcd_basic.v_period; pconf->lcd_timing.lcd_clk = pclk; + pconf->lcd_timing.lcd_clk_dft = pconf->lcd_timing.lcd_clk; pconf->lcd_timing.sync_duration_num = sync_duration; pconf->lcd_timing.sync_duration_den = 100; @@ -761,6 +810,8 @@ static ssize_t lcd_debug_store(struct class *class, pconf->lcd_basic.v_active = val[1]; pconf->lcd_basic.h_period = val[2]; pconf->lcd_basic.v_period = val[3]; + pconf->lcd_timing.h_period_dft = val[2]; + pconf->lcd_timing.v_period_dft = val[3]; pr_info("set h_active=%d, v_active=%d\n", val[0], val[1]); pr_info("set h_period=%d, v_period=%d\n", @@ -772,6 +823,8 @@ static ssize_t lcd_debug_store(struct class *class, pconf->lcd_basic.v_active = val[1]; pconf->lcd_basic.h_period = val[2]; pconf->lcd_basic.v_period = val[3]; + pconf->lcd_timing.h_period_dft = val[2]; + pconf->lcd_timing.v_period_dft = val[3]; pconf->lcd_basic.lcd_bits = val[4]; pr_info("set h_active=%d, v_active=%d\n", val[0], val[1]); @@ -916,6 +969,15 @@ static ssize_t lcd_debug_store(struct class *class, return count; } +static ssize_t lcd_debug_enable_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + return sprintf(buf, "lcd_status: %d\n", + lcd_drv->lcd_status); +} + static ssize_t lcd_debug_enable_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { @@ -923,6 +985,10 @@ static ssize_t lcd_debug_enable_store(struct class *class, unsigned int temp = 1; ret = kstrtouint(buf, 10, &temp); + if (ret) { + LCDERR("invalid data\n"); + return -EINVAL; + } if (temp) { mutex_lock(&lcd_power_mutex); aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); @@ -936,6 +1002,34 @@ static ssize_t lcd_debug_enable_store(struct class *class, return count; } +static ssize_t lcd_debug_resume_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + return sprintf(buf, "lcd resume flag: %d(%s)\n", + lcd_drv->lcd_resume_flag, + lcd_drv->lcd_resume_flag ? "workqueue" : "directly"); +} + +static ssize_t lcd_debug_resume_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int temp = 1; + + ret = kstrtouint(buf, 10, &temp); + if (ret) { + LCDERR("invalid data\n"); + return -EINVAL; + } + lcd_drv->lcd_resume_flag = (unsigned char)temp; + LCDPR("set lcd resume flag: %d\n", lcd_drv->lcd_resume_flag); + + return count; +} + static ssize_t lcd_debug_power_show(struct class *class, struct class_attribute *attr, char *buf) { @@ -1064,6 +1158,10 @@ static ssize_t lcd_debug_fr_policy_store(struct class *class, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); ret = kstrtouint(buf, 10, &temp); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } lcd_drv->fr_auto_policy = temp; pr_info("set fr_auto_policy: %d\n", temp); @@ -1085,6 +1183,10 @@ static ssize_t lcd_debug_ss_store(struct class *class, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); ret = kstrtouint(buf, 10, &temp); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } lcd_drv->lcd_config->lcd_timing.ss_level = temp; lcd_set_spread_spectrum(); @@ -1106,6 +1208,10 @@ static ssize_t lcd_debug_test_store(struct class *class, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); ret = kstrtouint(buf, 10, &temp); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } lcd_drv->lcd_test_flag = (unsigned char)temp; lcd_debug_test(temp); @@ -1128,6 +1234,10 @@ static ssize_t lcd_debug_mute_store(struct class *class, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); ret = kstrtouint(buf, 10, &temp); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } lcd_drv->lcd_mute = (unsigned char)temp; lcd_mute_setting(lcd_drv->lcd_mute); @@ -1483,6 +1593,10 @@ static ssize_t lcd_debug_print_store(struct class *class, unsigned int temp = 0; ret = kstrtouint(buf, 10, &temp); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } lcd_debug_print_flag = (unsigned char)temp; LCDPR("set debug print flag: %d\n", lcd_debug_print_flag); @@ -1490,19 +1604,22 @@ static ssize_t lcd_debug_print_store(struct class *class, } static struct class_attribute lcd_debug_class_attrs[] = { - __ATTR(help, 0644, lcd_debug_common_help, NULL), + __ATTR(help, 0444, lcd_debug_common_help, NULL), __ATTR(debug, 0644, lcd_debug_show, lcd_debug_store), - __ATTR(enable, 0644, NULL, lcd_debug_enable_store), + __ATTR(enable, 0644, + lcd_debug_enable_show, lcd_debug_enable_store), + __ATTR(resume, 0644, + lcd_debug_resume_show, lcd_debug_resume_store), __ATTR(power, 0644, lcd_debug_power_show, lcd_debug_power_store), __ATTR(frame_rate, 0644, lcd_debug_frame_rate_show, lcd_debug_frame_rate_store), __ATTR(fr_policy, 0644, lcd_debug_fr_policy_show, lcd_debug_fr_policy_store), __ATTR(ss, 0644, lcd_debug_ss_show, lcd_debug_ss_store), - __ATTR(clk, 0644, lcd_debug_clk_show, NULL), - __ATTR(test, 0644, NULL, lcd_debug_test_store), + __ATTR(clk, 0444, lcd_debug_clk_show, NULL), + __ATTR(test, 0200, NULL, lcd_debug_test_store), __ATTR(mute, 0644, lcd_debug_mute_show, lcd_debug_mute_store), - __ATTR(reg, 0644, NULL, lcd_debug_reg_store), + __ATTR(reg, 0200, NULL, lcd_debug_reg_store), __ATTR(dither, 0644, lcd_debug_dither_show, lcd_debug_dither_store), __ATTR(print, 0644, lcd_debug_print_show, lcd_debug_print_store), @@ -1524,7 +1641,7 @@ static const char *lcd_lvds_debug_usage_str = { "Usage:\n" " echo > lvds ; set lvds config\n" "data format:\n" -" : 0=JEIDA mode, 1=VESA mode\n" +" : 0=JEIDA mode, 1=VESA mode(8bit), 2=VESA mode(10bit)\n" " : 0=single port, 1=dual port\n" " : 0=normal, 1=swap p/n channels\n" " : 0=normal, 1=swap A/B port\n" @@ -1673,17 +1790,22 @@ static ssize_t lcd_lvds_debug_store(struct class *class, return count; } +#ifdef CONFIG_AMLOGIC_LCD_TV static int vx1_intr_state = 1; +#endif static ssize_t lcd_vx1_debug_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); struct vbyone_config_s *vx1_conf; +#ifdef CONFIG_AMLOGIC_LCD_TV int val[2]; +#endif vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config; if (buf[0] == 'i') { /* intr */ +#ifdef CONFIG_AMLOGIC_LCD_TV ret = sscanf(buf, "intr %d %d", &val[0], &val[1]); if (ret == 1) { pr_info("set vbyone interrupt enable: %d\n", val[0]); @@ -1700,7 +1822,11 @@ static ssize_t lcd_vx1_debug_store(struct class *class, vx1_intr_state, vx1_conf->intr_en); return -EINVAL; } +#else + return -EINVAL; +#endif } else if (buf[0] == 'v') { /* vintr */ +#ifdef CONFIG_AMLOGIC_LCD_TV ret = sscanf(buf, "vintr %d", &val[0]); if (ret == 1) { pr_info("set vbyone vsync interrupt enable: %d\n", @@ -1712,6 +1838,9 @@ static ssize_t lcd_vx1_debug_store(struct class *class, vx1_conf->vsync_intr_en); return -EINVAL; } +#else + return -EINVAL; +#endif } else { ret = sscanf(buf, "%d %d %d", &vx1_conf->lane_count, &vx1_conf->region_num, &vx1_conf->byte_mode); diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index f7c4f09..a200f73 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -814,6 +814,8 @@ #define VBO_TMCHK_VDE_STATE_L 0x14f6 #define VBO_TMCHK_VDE_STATE_H 0x14f7 #define VBO_INTR_STATE 0x14f8 +#define VBO_INFILTER_CTRL 0x14f9 +#define VBO_INSGN_CTRL 0x14fa /* ******************************** * Video Interface: VENC_VCBUS_BASE = 0x1b diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 183dc1f..b70241e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -356,8 +356,6 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) switch (pconf->lcd_basic.lcd_bits) { case 10: bit_num = 0; - if (lvds_repack == 1) - lvds_repack = 2; break; case 8: bit_num = 1; @@ -734,7 +732,6 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) { unsigned int band_width, bit_rate, pclk, phy_div; unsigned int byte_mode, lane_count, minlane; - unsigned int lcd_bits; unsigned int temp, i; if (lcd_debug_print_flag) @@ -742,8 +739,7 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) /* auto calculate bandwidth, clock */ lane_count = pconf->lcd_control.vbyone_config->lane_count; - lcd_bits = 10; /* pconf->lcd_basic.lcd_bits */ - byte_mode = (lcd_bits == 10) ? 4 : 3; + byte_mode = pconf->lcd_control.vbyone_config->byte_mode; /* byte_mode * byte2bit * 8/10_encoding * pclk = byte_mode * 8 * 10 / 8 * pclk */ pclk = pconf->lcd_timing.lcd_clk / 1000; /* kHz */ diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 54e0c9d..f33f38c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -140,6 +140,8 @@ static int lcd_framerate_automation_set_mode(void) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + LCDPR("%s\n", __func__); + /* update lcd config sync_duration, for calculate */ lcd_drv->lcd_config->lcd_timing.sync_duration_num = lcd_drv->lcd_info->sync_duration_num; @@ -296,15 +298,35 @@ static int lcd_suspend(void) mutex_unlock(&lcd_power_mutex); return 0; } + static int lcd_resume(void) { - mutex_lock(&lcd_power_mutex); - if (lcd_resume_flag == 0) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (lcd_resume_flag) + return 0; + + if (lcd_drv->lcd_resume_flag) { + if (lcd_drv->workqueue) { + queue_work(lcd_drv->workqueue, + &(lcd_drv->lcd_resume_work)); + } else { + LCDPR("Warning: no lcd workqueue\n"); + mutex_lock(&lcd_power_mutex); + lcd_resume_flag = 1; + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); + } + } else { + LCDPR("directly lcd late resume\n"); + mutex_lock(&lcd_power_mutex); lcd_resume_flag = 1; aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); } - mutex_unlock(&lcd_power_mutex); + return 0; } #endif @@ -336,6 +358,13 @@ static void lcd_tablet_vinfo_update(void) vinfo = lcd_drv->lcd_info; pconf = lcd_drv->lcd_config; + + /* store standard duration */ + lcd_drv->std_duration.duration_num = + pconf->lcd_timing.sync_duration_num; + lcd_drv->std_duration.duration_den = + pconf->lcd_timing.sync_duration_den; + if (vinfo) { vinfo->name = PANEL_NAME; vinfo->mode = VMODE_LCD; @@ -524,10 +553,13 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, ret = of_property_read_string(child, "model_name", &str); if (ret) { LCDERR("failed to get model_name\n"); - strcpy(pconf->lcd_basic.model_name, pconf->lcd_propname); + strncpy(pconf->lcd_basic.model_name, pconf->lcd_propname, + MOD_LEN_MAX); } else { - strcpy(pconf->lcd_basic.model_name, str); + strncpy(pconf->lcd_basic.model_name, str, MOD_LEN_MAX); } + /* ensure string ending */ + pconf->lcd_basic.model_name[MOD_LEN_MAX-1] = '\0'; ret = of_property_read_string(child, "interface", &str); if (ret) { @@ -705,7 +737,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_control.vbyone_config->phy_vswing = para[0]; pconf->lcd_control.vbyone_config->phy_preem = para[1]; if (lcd_debug_print_flag) { - LCDPR("phy vswing=%d, preemphasis=%d\n", + LCDPR("phy vswing=0x%x, preemphasis=0x%x\n", pconf->lcd_control.vbyone_config->phy_vswing, pconf->lcd_control.vbyone_config->phy_preem); } @@ -791,12 +823,19 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) } lcd_unifykey_header_check(para, &lcd_header); - len = 10 + 36 + 18 + 31 + 20; + LCDPR("unifykey version: 0x%04x\n", lcd_header.version); + switch (lcd_header.version) { + case 2: + len = 10 + 36 + 18 + 31 + 20 + 44 + 10; + break; + default: + len = 10 + 36 + 18 + 31 + 20; + break; + } if (lcd_debug_print_flag) { LCDPR("unifykey header:\n"); LCDPR("crc32 = 0x%08x\n", lcd_header.crc32); LCDPR("data_len = %d\n", lcd_header.data_len); - LCDPR("version = 0x%04x\n", lcd_header.version); LCDPR("reserved = 0x%04x\n", lcd_header.reserved); } @@ -808,11 +847,15 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) return -1; } + /* panel_type update */ + sprintf(pconf->lcd_propname, "%s", "unifykey"); + /* basic: 36byte */ p = para + LCD_UKEY_HEAD_SIZE; - *(p + LCD_UKEY_MODEL_NAME - 1) = '\0'; /* ensure string ending */ str = (const char *)p; - strcpy(pconf->lcd_basic.model_name, str); + strncpy(pconf->lcd_basic.model_name, str, MOD_LEN_MAX); + /* ensure string ending */ + pconf->lcd_basic.model_name[MOD_LEN_MAX-1] = '\0'; p += LCD_UKEY_MODEL_NAME; pconf->lcd_basic.lcd_type = *p; p += LCD_UKEY_INTERFACE; @@ -875,68 +918,59 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) /* interface: 20byte */ if (pconf->lcd_basic.lcd_type == LCD_LVDS) { - if (lcd_header.version == 1) { + if (lcd_header.version == 2) { pconf->lcd_control.lvds_config->lvds_repack = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_0; pconf->lcd_control.lvds_config->dual_port = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.lvds_config->pn_swap = + pconf->lcd_control.lvds_config->pn_swap = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.lvds_config->port_swap = + pconf->lcd_control.lvds_config->port_swap = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.lvds_config->phy_vswing = + pconf->lcd_control.lvds_config->lane_reverse = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.lvds_config->phy_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; + /* dummy pointer */ p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.lvds_config->phy_clk_vswing = - (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.lvds_config->phy_clk_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_7; - pconf->lcd_control.lvds_config->lane_reverse = 0; p += LCD_UKEY_IF_ATTR_8; - - /* dummy pointer */ p += LCD_UKEY_IF_ATTR_9; - } - else if (lcd_header.version == 2) { + } else { pconf->lcd_control.lvds_config->lvds_repack = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_0; pconf->lcd_control.lvds_config->dual_port = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.lvds_config->pn_swap = + pconf->lcd_control.lvds_config->pn_swap = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.lvds_config->port_swap = + pconf->lcd_control.lvds_config->port_swap = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.lvds_config->lane_reverse = + pconf->lcd_control.lvds_config->phy_vswing = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.lvds_config->phy_vswing = + pconf->lcd_control.lvds_config->phy_preem = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.lvds_config->phy_preem = + pconf->lcd_control.lvds_config->phy_clk_vswing = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.lvds_config->phy_clk_vswing = + pconf->lcd_control.lvds_config->phy_clk_preem = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_7; - pconf->lcd_control.lvds_config->phy_clk_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_8; /* dummy pointer */ + p += LCD_UKEY_IF_ATTR_8; p += LCD_UKEY_IF_ATTR_9; - } + + pconf->lcd_control.lvds_config->lane_reverse = 0; + } } else if (pconf->lcd_basic.lcd_type == LCD_TTL) { pconf->lcd_control.ttl_config->clk_pol = (*p | ((*(p + 1)) << 8)) & 0x1; @@ -960,67 +994,59 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) p += LCD_UKEY_IF_ATTR_8; p += LCD_UKEY_IF_ATTR_9; } else if (pconf->lcd_basic.lcd_type == LCD_VBYONE) { - pconf->lcd_control.vbyone_config->lane_count = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_0; - pconf->lcd_control.vbyone_config->region_num = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.vbyone_config->byte_mode = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.vbyone_config->color_fmt = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.vbyone_config->phy_vswing = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.vbyone_config->phy_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.vbyone_config->intr_en = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.vbyone_config->vsync_intr_en = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_7; - /* dummy pointer */ - p += LCD_UKEY_IF_ATTR_8; - p += LCD_UKEY_IF_ATTR_9; - } else if (pconf->lcd_basic.lcd_type == LCD_MIPI) { - pconf->lcd_control.mipi_config->lane_num = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_0; - pconf->lcd_control.mipi_config->bit_rate_max = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.mipi_config->factor_numerator = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.mipi_config->factor_denominator = - 100; - pconf->lcd_control.mipi_config->operation_mode_init = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.mipi_config->operation_mode_display = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.mipi_config->video_mode_type = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.mipi_config->clk_lp_continuous = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.mipi_config->phy_stop_wait = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_7; - pconf->lcd_control.mipi_config->extern_init = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_8; - - /* dummy pointer */ - p += LCD_UKEY_IF_ATTR_9; - + if (lcd_header.version == 2) { + pconf->lcd_control.vbyone_config->lane_count = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_0; + pconf->lcd_control.vbyone_config->region_num = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_1; + pconf->lcd_control.vbyone_config->byte_mode = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_2; + pconf->lcd_control.vbyone_config->color_fmt = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_3; + pconf->lcd_control.vbyone_config->intr_en = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_4; + pconf->lcd_control.vbyone_config->vsync_intr_en = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_5; + /* dummy pointer */ + p += LCD_UKEY_IF_ATTR_6; + p += LCD_UKEY_IF_ATTR_7; + p += LCD_UKEY_IF_ATTR_8; + p += LCD_UKEY_IF_ATTR_9; + } else { + pconf->lcd_control.vbyone_config->lane_count = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_0; + pconf->lcd_control.vbyone_config->region_num = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_1; + pconf->lcd_control.vbyone_config->byte_mode = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_2; + pconf->lcd_control.vbyone_config->color_fmt = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_3; + pconf->lcd_control.vbyone_config->phy_vswing = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_4; + pconf->lcd_control.vbyone_config->phy_preem = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_5; + pconf->lcd_control.vbyone_config->intr_en = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_6; + pconf->lcd_control.vbyone_config->vsync_intr_en = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_7; + /* dummy pointer */ + p += LCD_UKEY_IF_ATTR_8; + p += LCD_UKEY_IF_ATTR_9; + } } else { LCDERR("unsupport lcd_type: %d\n", pconf->lcd_basic.lcd_type); p += LCD_UKEY_IF_ATTR_0; @@ -1035,6 +1061,78 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) p += LCD_UKEY_IF_ATTR_9; } + if (lcd_header.version == 2) { + /* ctrl: 44byte */ /* v2 */ + /* dummy pointer */ + p += LCD_UKEY_CTRL_FLAG; + p += LCD_UKEY_CTRL_ATTR_0; + p += LCD_UKEY_CTRL_ATTR_1; + p += LCD_UKEY_CTRL_ATTR_2; + p += LCD_UKEY_CTRL_ATTR_3; + p += LCD_UKEY_CTRL_ATTR_4; + p += LCD_UKEY_CTRL_ATTR_5; + p += LCD_UKEY_CTRL_ATTR_6; + p += LCD_UKEY_CTRL_ATTR_7; + p += LCD_UKEY_CTRL_ATTR_8; + p += LCD_UKEY_CTRL_ATTR_9; + p += LCD_UKEY_CTRL_ATTR_10; + p += LCD_UKEY_CTRL_ATTR_11; + p += LCD_UKEY_CTRL_ATTR_12; + p += LCD_UKEY_CTRL_ATTR_13; + p += LCD_UKEY_CTRL_ATTR_14; + p += LCD_UKEY_CTRL_ATTR_15; + p += LCD_UKEY_CTRL_ATTR_16; + p += LCD_UKEY_CTRL_ATTR_17; + p += LCD_UKEY_CTRL_ATTR_18; + p += LCD_UKEY_CTRL_ATTR_19; + + /* phy: 10byte */ /* v2 */ + if (pconf->lcd_basic.lcd_type == LCD_LVDS) { + pconf->lcd_control.lvds_config->phy_vswing = *p; + p += LCD_UKEY_PHY_ATTR_0; + pconf->lcd_control.lvds_config->phy_preem = *p; + p += LCD_UKEY_PHY_ATTR_1; + pconf->lcd_control.lvds_config->phy_clk_vswing = *p; + p += LCD_UKEY_PHY_ATTR_2; + pconf->lcd_control.lvds_config->phy_clk_preem = *p; + p += LCD_UKEY_PHY_ATTR_3; + /* dummy pointer */ + p += LCD_UKEY_PHY_ATTR_4; + p += LCD_UKEY_PHY_ATTR_5; + p += LCD_UKEY_PHY_ATTR_6; + p += LCD_UKEY_PHY_ATTR_7; + p += LCD_UKEY_PHY_ATTR_8; + p += LCD_UKEY_PHY_ATTR_9; + } else if (pconf->lcd_basic.lcd_type == LCD_VBYONE) { + pconf->lcd_control.vbyone_config->phy_vswing = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_PHY_ATTR_0; + pconf->lcd_control.vbyone_config->phy_preem = + (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_PHY_ATTR_1; + /* dummy pointer */ + p += LCD_UKEY_PHY_ATTR_2; + p += LCD_UKEY_PHY_ATTR_3; + p += LCD_UKEY_PHY_ATTR_4; + p += LCD_UKEY_PHY_ATTR_5; + p += LCD_UKEY_PHY_ATTR_6; + p += LCD_UKEY_PHY_ATTR_7; + p += LCD_UKEY_PHY_ATTR_8; + p += LCD_UKEY_PHY_ATTR_9; + } else { + p += LCD_UKEY_PHY_ATTR_0; + p += LCD_UKEY_PHY_ATTR_1; + p += LCD_UKEY_PHY_ATTR_2; + p += LCD_UKEY_PHY_ATTR_3; + p += LCD_UKEY_PHY_ATTR_4; + p += LCD_UKEY_PHY_ATTR_5; + p += LCD_UKEY_PHY_ATTR_6; + p += LCD_UKEY_PHY_ATTR_7; + p += LCD_UKEY_PHY_ATTR_8; + p += LCD_UKEY_PHY_ATTR_9; + } + } + /* step 3: check power sequence */ ret = lcd_power_load_from_unifykey(pconf, para, key_len, len); if (ret < 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 a2ec892..9a33c53 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -244,8 +244,6 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) switch (pconf->lcd_basic.lcd_bits) { case 10: bit_num = 0; - if (lvds_repack == 1) - lvds_repack = 2; break; case 8: bit_num = 1; @@ -321,8 +319,8 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) unsigned int div_sel, phy_div; phy_div = pconf->lcd_control.vbyone_config->phy_div; + lcd_bits = pconf->lcd_basic.lcd_bits; - lcd_bits = 10; switch (lcd_bits) { case 6: div_sel = 0; @@ -1047,7 +1045,6 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) { unsigned int band_width, bit_rate, pclk, phy_div; unsigned int byte_mode, lane_count, minlane; - unsigned int lcd_bits; unsigned int temp, i; if (lcd_debug_print_flag) @@ -1055,8 +1052,7 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) /* auto calculate bandwidth, clock */ lane_count = pconf->lcd_control.vbyone_config->lane_count; - lcd_bits = 10; /* pconf->lcd_basic.lcd_bits */ - byte_mode = (lcd_bits == 10) ? 4 : 3; + byte_mode = pconf->lcd_control.vbyone_config->byte_mode; /* byte_mode * byte2bit * 8/10_encoding * pclk = * byte_mode * 8 * 10 / 8 * pclk */ 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 0076c3f..383e70a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -44,7 +44,10 @@ static unsigned int lcd_output_vmode; static char lcd_output_name[30]; -/* lcd mode function */ +/* ************************************************** * + * lcd mode function + * ************************************************** + */ static unsigned int lcd_std_frame_rate[] = { 50, 60, @@ -225,7 +228,10 @@ static void lcd_vmode_vinfo_update(enum vmode_e mode) lcd_hdr_vinfo_update(); } -/* vout server api */ +/* ************************************************** * + * vout server api + * ************************************************** + */ static enum vmode_e lcd_validate_vmode(char *mode) { int lcd_vmode, frame_rate; @@ -352,6 +358,8 @@ static int lcd_framerate_automation_set_mode(void) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + LCDPR("%s\n", __func__); + /* update interface timing */ lcd_tv_config_update(lcd_drv->lcd_config); #ifdef CONFIG_AML_VPU @@ -519,13 +527,32 @@ static int lcd_suspend(void) static int lcd_resume(void) { - mutex_lock(&lcd_power_mutex); - if (lcd_resume_flag == 0) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (lcd_resume_flag) + return 0; + + if (lcd_drv->lcd_resume_flag) { + if (lcd_drv->workqueue) { + queue_work(lcd_drv->workqueue, + &(lcd_drv->lcd_resume_work)); + } else { + LCDPR("Warning: no lcd workqueue\n"); + mutex_lock(&lcd_power_mutex); + lcd_resume_flag = 1; + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); + } + } else { + LCDPR("directly lcd late resume\n"); + mutex_lock(&lcd_power_mutex); lcd_resume_flag = 1; aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); } - mutex_unlock(&lcd_power_mutex); + return 0; } @@ -592,7 +619,10 @@ void lcd_tv_vout_server_init(void) vout_register_server(&lcd_vout_server); } -/* lcd tv config */ +/* ************************************************** * + * lcd tv config + * ************************************************** + */ static void lcd_config_print(struct lcd_config_s *pconf) { LCDPR("%s, %s, %dbit, %dx%d\n", @@ -686,10 +716,13 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, ret = of_property_read_string(child, "model_name", &str); if (ret) { LCDERR("failed to get model_name\n"); - strcpy(pconf->lcd_basic.model_name, pconf->lcd_propname); + strncpy(pconf->lcd_basic.model_name, pconf->lcd_propname, + MOD_LEN_MAX); } else { - strcpy(pconf->lcd_basic.model_name, str); + strncpy(pconf->lcd_basic.model_name, str, MOD_LEN_MAX); } + /* ensure string ending */ + pconf->lcd_basic.model_name[MOD_LEN_MAX-1] = '\0'; ret = of_property_read_string(child, "interface", &str); if (ret) { @@ -863,6 +896,8 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) unsigned char *p; const char *str; struct aml_lcd_unifykey_header_s lcd_header; + struct lvds_config_s *lvdsconf = pconf->lcd_control.lvds_config; + struct vbyone_config_s *vx1_conf = pconf->lcd_control.vbyone_config; int ret; para = kmalloc((sizeof(unsigned char) * LCD_UKEY_LCD_SIZE), GFP_KERNEL); @@ -888,12 +923,19 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) } lcd_unifykey_header_check(para, &lcd_header); - len = 10 + 36 + 18 + 31 + 20; + LCDPR("unifykey version: 0x%04x\n", lcd_header.version); + switch (lcd_header.version) { + case 2: + len = 10 + 36 + 18 + 31 + 20 + 44 + 10; + break; + default: + len = 10 + 36 + 18 + 31 + 20; + break; + } if (lcd_debug_print_flag) { LCDPR("unifykey header:\n"); LCDPR("crc32 = 0x%08x\n", lcd_header.crc32); LCDPR("data_len = %d\n", lcd_header.data_len); - LCDPR("version = 0x%04x\n", lcd_header.version); LCDPR("reserved = 0x%04x\n", lcd_header.reserved); } @@ -905,11 +947,15 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) return -1; } + /* panel_type update */ + sprintf(pconf->lcd_propname, "%s", "unifykey"); + /* basic: 36byte */ p = para + LCD_UKEY_HEAD_SIZE; - *(p + LCD_UKEY_MODEL_NAME - 1) = '\0'; /* ensure string ending */ str = (const char *)p; - strcpy(pconf->lcd_basic.model_name, str); + strncpy(pconf->lcd_basic.model_name, str, MOD_LEN_MAX); + /* ensure string ending */ + pconf->lcd_basic.model_name[MOD_LEN_MAX-1] = '\0'; p += LCD_UKEY_MODEL_NAME; pconf->lcd_basic.lcd_type = *p; p += LCD_UKEY_INTERFACE; @@ -971,95 +1017,91 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) /* interface: 20byte */ if (pconf->lcd_basic.lcd_type == LCD_VBYONE) { - pconf->lcd_control.vbyone_config->lane_count = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_0; - pconf->lcd_control.vbyone_config->region_num = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.vbyone_config->byte_mode = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.vbyone_config->color_fmt = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.vbyone_config->phy_vswing = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.vbyone_config->phy_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.vbyone_config->intr_en = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.vbyone_config->vsync_intr_en = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_7; - /* dummy pointer */ - p += LCD_UKEY_IF_ATTR_8; - p += LCD_UKEY_IF_ATTR_9; - } else if (pconf->lcd_basic.lcd_type == LCD_LVDS) { - if (lcd_header.version == 1) { - pconf->lcd_control.lvds_config->lvds_repack = - (*p | ((*(p + 1)) << 8)) & 0xff; + if (lcd_header.version == 2) { + vx1_conf->lane_count = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_0; - pconf->lcd_control.lvds_config->dual_port = - (*p | ((*(p + 1)) << 8)) & 0xff; + vx1_conf->region_num = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.lvds_config->pn_swap = - (*p | ((*(p + 1)) << 8)) & 0xff; + vx1_conf->byte_mode = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.lvds_config->port_swap = - (*p | ((*(p + 1)) << 8)) & 0xff; + vx1_conf->color_fmt = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.lvds_config->phy_vswing = - (*p | ((*(p + 1)) << 8)) & 0xff; + vx1_conf->intr_en = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.lvds_config->phy_preem = + vx1_conf->vsync_intr_en = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.lvds_config->phy_clk_vswing = - (*p | ((*(p + 1)) << 8)) & 0xff; + /* dummy pointer */ p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.lvds_config->phy_clk_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_7; - pconf->lcd_control.lvds_config->lane_reverse = 0; p += LCD_UKEY_IF_ATTR_8; - /* dummy pointer */ p += LCD_UKEY_IF_ATTR_9; - } - else if (lcd_header.version == 2) { - pconf->lcd_control.lvds_config->lvds_repack = - (*p | ((*(p + 1)) << 8)) & 0xff; + } else { + vx1_conf->lane_count = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_0; - pconf->lcd_control.lvds_config->dual_port = - (*p | ((*(p + 1)) << 8)) & 0xff; + vx1_conf->region_num = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_1; - pconf->lcd_control.lvds_config->pn_swap = - (*p | ((*(p + 1)) << 8)) & 0xff; + vx1_conf->byte_mode = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_2; - pconf->lcd_control.lvds_config->port_swap = + vx1_conf->color_fmt = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_3; + vx1_conf->phy_vswing = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_4; + vx1_conf->phy_preem = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_5; + vx1_conf->intr_en = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_6; + vx1_conf->vsync_intr_en = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_7; + /* dummy pointer */ + p += LCD_UKEY_IF_ATTR_8; + p += LCD_UKEY_IF_ATTR_9; + } + } else if (pconf->lcd_basic.lcd_type == LCD_LVDS) { + if (lcd_header.version == 2) { + lvdsconf->lvds_repack = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_0; + lvdsconf->dual_port = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_1; + lvdsconf->pn_swap = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_2; + lvdsconf->port_swap = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_3; - pconf->lcd_control.lvds_config->lane_reverse = + lvdsconf->lane_reverse = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_4; - pconf->lcd_control.lvds_config->phy_vswing = - (*p | ((*(p + 1)) << 8)) & 0xff; + /* dummy pointer */ p += LCD_UKEY_IF_ATTR_5; - pconf->lcd_control.lvds_config->phy_preem = + p += LCD_UKEY_IF_ATTR_6; + p += LCD_UKEY_IF_ATTR_7; + p += LCD_UKEY_IF_ATTR_8; + p += LCD_UKEY_IF_ATTR_9; + } else { + lvdsconf->lvds_repack = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_0; + lvdsconf->dual_port = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_1; + lvdsconf->pn_swap = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_2; + lvdsconf->port_swap = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_3; + lvdsconf->phy_vswing = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_4; + lvdsconf->phy_preem = (*p | ((*(p + 1)) << 8)) & 0xff; + p += LCD_UKEY_IF_ATTR_5; + lvdsconf->phy_clk_vswing = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_6; - pconf->lcd_control.lvds_config->phy_clk_vswing = + lvdsconf->phy_clk_preem = (*p | ((*(p + 1)) << 8)) & 0xff; p += LCD_UKEY_IF_ATTR_7; - pconf->lcd_control.lvds_config->phy_clk_preem = - (*p | ((*(p + 1)) << 8)) & 0xff; - p += LCD_UKEY_IF_ATTR_8; /* dummy pointer */ + p += LCD_UKEY_IF_ATTR_8; p += LCD_UKEY_IF_ATTR_9; - } + + lvdsconf->lane_reverse = 0; + } } else { LCDERR("unsupport lcd_type: %d\n", pconf->lcd_basic.lcd_type); p += LCD_UKEY_IF_ATTR_0; @@ -1074,6 +1116,75 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) p += LCD_UKEY_IF_ATTR_9; } + if (lcd_header.version == 2) { + /* ctrl: 44byte */ /* v2 */ + p += LCD_UKEY_CTRL_FLAG; + p += LCD_UKEY_CTRL_ATTR_0; + p += LCD_UKEY_CTRL_ATTR_1; + p += LCD_UKEY_CTRL_ATTR_2; + p += LCD_UKEY_CTRL_ATTR_3; + p += LCD_UKEY_CTRL_ATTR_4; + p += LCD_UKEY_CTRL_ATTR_5; + p += LCD_UKEY_CTRL_ATTR_6; + p += LCD_UKEY_CTRL_ATTR_7; + p += LCD_UKEY_CTRL_ATTR_8; + p += LCD_UKEY_CTRL_ATTR_9; + p += LCD_UKEY_CTRL_ATTR_10; + p += LCD_UKEY_CTRL_ATTR_11; + p += LCD_UKEY_CTRL_ATTR_12; + p += LCD_UKEY_CTRL_ATTR_13; + p += LCD_UKEY_CTRL_ATTR_14; + p += LCD_UKEY_CTRL_ATTR_15; + p += LCD_UKEY_CTRL_ATTR_16; + p += LCD_UKEY_CTRL_ATTR_17; + p += LCD_UKEY_CTRL_ATTR_18; + p += LCD_UKEY_CTRL_ATTR_19; + + /* phy: 10byte */ /* v2 */ + if (pconf->lcd_basic.lcd_type == LCD_VBYONE) { + vx1_conf->phy_vswing = *p; + p += LCD_UKEY_PHY_ATTR_0; + vx1_conf->phy_preem = *p; + p += LCD_UKEY_PHY_ATTR_1; + /* dummy pointer */ + p += LCD_UKEY_PHY_ATTR_2; + p += LCD_UKEY_PHY_ATTR_3; + p += LCD_UKEY_PHY_ATTR_4; + p += LCD_UKEY_PHY_ATTR_5; + p += LCD_UKEY_PHY_ATTR_6; + p += LCD_UKEY_PHY_ATTR_7; + p += LCD_UKEY_PHY_ATTR_8; + p += LCD_UKEY_PHY_ATTR_9; + } else if (pconf->lcd_basic.lcd_type == LCD_LVDS) { + lvdsconf->phy_vswing = *p; + p += LCD_UKEY_PHY_ATTR_0; + lvdsconf->phy_preem = *p; + p += LCD_UKEY_PHY_ATTR_1; + lvdsconf->phy_clk_vswing = *p; + p += LCD_UKEY_PHY_ATTR_2; + lvdsconf->phy_clk_preem = *p; + p += LCD_UKEY_PHY_ATTR_3; + /* dummy pointer */ + p += LCD_UKEY_PHY_ATTR_4; + p += LCD_UKEY_PHY_ATTR_5; + p += LCD_UKEY_PHY_ATTR_6; + p += LCD_UKEY_PHY_ATTR_7; + p += LCD_UKEY_PHY_ATTR_8; + p += LCD_UKEY_PHY_ATTR_9; + } else { + p += LCD_UKEY_PHY_ATTR_0; + p += LCD_UKEY_PHY_ATTR_1; + p += LCD_UKEY_PHY_ATTR_2; + p += LCD_UKEY_PHY_ATTR_3; + p += LCD_UKEY_PHY_ATTR_4; + p += LCD_UKEY_PHY_ATTR_5; + p += LCD_UKEY_PHY_ATTR_6; + p += LCD_UKEY_PHY_ATTR_7; + p += LCD_UKEY_PHY_ATTR_8; + p += LCD_UKEY_PHY_ATTR_9; + } + } + /* step 3: check power sequence */ ret = lcd_power_load_from_unifykey(pconf, para, key_len, len); if (ret < 0) { @@ -1098,7 +1209,6 @@ static void lcd_vmode_init(struct lcd_config_s *pconf) vmode = VMODE_LCD; } lcd_vmode_vinfo_update(vmode & VMODE_MODE_BIT_MASK); - lcd_tv_config_update(pconf); } static void lcd_config_init(struct lcd_config_s *pconf) @@ -1116,6 +1226,7 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_vmode_init(pconf); + lcd_tv_config_update(pconf); lcd_clk_generate_parameter(pconf); ss_level = pconf->lcd_timing.ss_level; cconf->ss_level = (ss_level >= cconf->ss_level_max) ? 0 : ss_level; @@ -1157,7 +1268,10 @@ static int lcd_get_config(struct lcd_config_s *pconf, struct device *dev) return 0; } -/* lcd notify */ +/* ************************************************** * + * lcd notify + * ************************************************** + */ /* sync_duration is real_value * 100 */ static void lcd_set_vinfo(unsigned int sync_duration) { @@ -1217,7 +1331,10 @@ static struct notifier_block lcd_frame_rate_adjust_nb = { .notifier_call = lcd_frame_rate_adjust_notifier, }; -/* lcd tv */ +/* ************************************************** * + * lcd tv + * ************************************************** + */ int lcd_tv_probe(struct device *dev) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 758f460..967612f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -57,7 +57,7 @@ struct mutex lcd_power_mutex; struct mutex lcd_vout_mutex; int lcd_vout_serve_bypass; -static char lcd_propname[20] = "lvds_0"; +static char lcd_propname[20] = "null"; struct lcd_cdev_s { dev_t devno; @@ -67,7 +67,10 @@ struct lcd_cdev_s { static struct lcd_cdev_s *lcd_cdev; -/* lcd config define */ +/* ********************************************************* + * lcd config define + * ********************************************************* + */ static struct ttl_config_s lcd_ttl_config = { .clk_pol = 0, .sync_valid = ((1 << 1) | (1 << 0)), @@ -179,6 +182,7 @@ static struct lcd_config_s lcd_config_dft = { .mipi_config = &lcd_mipi_config, }, .lcd_power = &lcd_power_config, + .pinmux_flag = 0, }; static struct vinfo_s lcd_vinfo = { @@ -416,19 +420,32 @@ static void lcd_module_tiny_reset(void) mutex_unlock(&lcd_vout_mutex); } -/* lcd notify */ +static void lcd_resume_work(struct work_struct *p_work) +{ + mutex_lock(&lcd_power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); +} + +/* **************************************** + * lcd notify + * **************************************** + */ static int lcd_power_notifier(struct notifier_block *nb, unsigned long event, void *data) { - if (lcd_debug_print_flag) - LCDPR("%s: 0x%lx\n", __func__, event); - - if (event & LCD_EVENT_LCD_ON) + if (event & LCD_EVENT_LCD_ON) { + if (lcd_debug_print_flag) + LCDPR("%s: 0x%lx\n", __func__, event); lcd_module_enable(); - else if (event & LCD_EVENT_LCD_OFF) + } else if (event & LCD_EVENT_LCD_OFF) { + if (lcd_debug_print_flag) + LCDPR("%s: 0x%lx\n", __func__, event); lcd_module_disable(); - else + } else { return NOTIFY_DONE; + } return NOTIFY_OK; } @@ -441,15 +458,17 @@ static struct notifier_block lcd_power_nb = { static int lcd_interface_notifier(struct notifier_block *nb, unsigned long event, void *data) { - if (lcd_debug_print_flag) - LCDPR("%s: 0x%lx\n", __func__, event); - - if (event & LCD_EVENT_IF_ON) + if (event & LCD_EVENT_IF_ON) { + if (lcd_debug_print_flag) + LCDPR("%s: 0x%lx\n", __func__, event); lcd_driver->power_tiny_ctrl(1); - else if (event & LCD_EVENT_IF_OFF) + } else if (event & LCD_EVENT_IF_OFF) { + if (lcd_debug_print_flag) + LCDPR("%s: 0x%lx\n", __func__, event); lcd_driver->power_tiny_ctrl(0); - else + } else { return NOTIFY_DONE; + } return NOTIFY_OK; } @@ -464,9 +483,9 @@ static int lcd_bl_select_notifier(struct notifier_block *nb, { unsigned int *index; - /* LCDPR("%s: 0x%lx\n", __func__, event); */ if ((event & LCD_EVENT_BACKLIGHT_SEL) == 0) return NOTIFY_DONE; + /* LCDPR("%s: 0x%lx\n", __func__, event); */ index = (unsigned int *)data; *index = lcd_driver->lcd_config->backlight_index; @@ -802,8 +821,8 @@ static int lcd_config_probe(void) lcd_driver->lcd_info = &lcd_vinfo; lcd_driver->lcd_config = &lcd_config_dft; - lcd_driver->lcd_config->pinmux_flag = 0; lcd_driver->lcd_test_flag = 0; + lcd_driver->lcd_resume_flag = 1; /* default workqueue */ lcd_driver->power_ctrl = lcd_power_ctrl; lcd_driver->module_reset = lcd_module_reset; lcd_driver->power_tiny_ctrl = lcd_power_tiny_ctrl; @@ -837,15 +856,6 @@ static int lcd_config_probe(void) return 0; } -static void lcd_resume_work(struct work_struct *p_work) -{ - mutex_lock(&lcd_power_mutex); - lcd_resume_flag = 1; - aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); - LCDPR("%s finished\n", __func__); - mutex_unlock(&lcd_power_mutex); -} - static int lcd_probe(struct platform_device *pdev) { int ret = 0; @@ -915,7 +925,26 @@ static int lcd_remove(struct platform_device *pdev) static int lcd_resume(struct platform_device *pdev) { - queue_work(lcd_driver->workqueue, &(lcd_driver->lcd_resume_work)); + if (lcd_driver->lcd_resume_flag) { + lcd_resume_flag = 1; + if (lcd_driver->workqueue) { + queue_work(lcd_driver->workqueue, + &(lcd_driver->lcd_resume_work)); + } else { + LCDPR("Warning: no lcd workqueue\n"); + mutex_lock(&lcd_power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); + } + } else { + LCDPR("directly lcd resume\n"); + mutex_lock(&lcd_power_mutex); + lcd_resume_flag = 1; + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + LCDPR("%s finished\n", __func__); + mutex_unlock(&lcd_power_mutex); + } return 0; } diff --git a/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h b/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h index 6413024..9dccb3e 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h @@ -51,8 +51,13 @@ struct aml_lcd_unifykey_header_s { unsigned short reserved; }; -/* lcd */ -#define LCD_UKEY_LCD_SIZE 265 +/* ******************************** + * lcd + * ********************************* + */ +/* V1: 265 */ +/* V2: 319 */ +#define LCD_UKEY_LCD_SIZE 319 /* header (10Byte) */ /* LCD_UKEY_HEAD_SIZE */ @@ -97,13 +102,49 @@ struct aml_lcd_unifykey_header_s { #define LCD_UKEY_IF_ATTR_7 2 #define LCD_UKEY_IF_ATTR_8 2 #define LCD_UKEY_IF_ATTR_9 2 +/* ctrl (44Byte) */ /* V2 */ +#define LCD_UKEY_CTRL_FLAG 4 +#define LCD_UKEY_CTRL_ATTR_0 2 +#define LCD_UKEY_CTRL_ATTR_1 2 +#define LCD_UKEY_CTRL_ATTR_2 2 +#define LCD_UKEY_CTRL_ATTR_3 2 +#define LCD_UKEY_CTRL_ATTR_4 2 +#define LCD_UKEY_CTRL_ATTR_5 2 +#define LCD_UKEY_CTRL_ATTR_6 2 +#define LCD_UKEY_CTRL_ATTR_7 2 +#define LCD_UKEY_CTRL_ATTR_8 2 +#define LCD_UKEY_CTRL_ATTR_9 2 +#define LCD_UKEY_CTRL_ATTR_10 2 +#define LCD_UKEY_CTRL_ATTR_11 2 +#define LCD_UKEY_CTRL_ATTR_12 2 +#define LCD_UKEY_CTRL_ATTR_13 2 +#define LCD_UKEY_CTRL_ATTR_14 2 +#define LCD_UKEY_CTRL_ATTR_15 2 +#define LCD_UKEY_CTRL_ATTR_16 2 +#define LCD_UKEY_CTRL_ATTR_17 2 +#define LCD_UKEY_CTRL_ATTR_18 2 +#define LCD_UKEY_CTRL_ATTR_19 2 +/* phy (10Byte) */ /* V2 */ +#define LCD_UKEY_PHY_ATTR_0 1 +#define LCD_UKEY_PHY_ATTR_1 1 +#define LCD_UKEY_PHY_ATTR_2 1 +#define LCD_UKEY_PHY_ATTR_3 1 +#define LCD_UKEY_PHY_ATTR_4 1 +#define LCD_UKEY_PHY_ATTR_5 1 +#define LCD_UKEY_PHY_ATTR_6 1 +#define LCD_UKEY_PHY_ATTR_7 1 +#define LCD_UKEY_PHY_ATTR_8 1 +#define LCD_UKEY_PHY_ATTR_9 1 /* power (5Byte * n) */ #define LCD_UKEY_PWR_TYPE 1 #define LCD_UKEY_PWR_INDEX 1 #define LCD_UKEY_PWR_VAL 1 #define LCD_UKEY_PWR_DELAY 2 -/* lcd extern */ +/* ******************************** + * lcd extern + * ********************************* + */ #define LCD_UKEY_LCD_EXT_SIZE 550 /* header (10Byte) */ @@ -129,8 +170,13 @@ struct aml_lcd_unifykey_header_s { /*#define LCD_UKEY_EXT_INIT_VAL 1 //not defined */ #define LCD_UKEY_EXT_INIT_DELAY 1 -/* backlight */ -#define LCD_UKEY_BL_SIZE 92 +/* ******************************** + * backlight + * ********************************* + */ +/* V1: 92 */ +/* V2: 102 */ +#define LCD_UKEY_BL_SIZE 102 /* header (10Byte) */ /* LCD_UKEY_HEAD_SIZE */ @@ -171,9 +217,17 @@ struct aml_lcd_unifykey_header_s { #define LCD_UKEY_BL_PWM_LEVEL_MIN 2 #define LCD_UKEY_BL_PWM2_LEVEL_MAX 2 #define LCD_UKEY_BL_PWM2_LEVEL_MIN 2 - - -/* API */ +/* customer(10Byte) */ /* V2 */ +#define LCD_UKEY_BL_CUST_VAL_0 2 +#define LCD_UKEY_BL_CUST_VAL_1 2 +#define LCD_UKEY_BL_CUST_VAL_2 2 +#define LCD_UKEY_BL_CUST_VAL_3 2 +#define LCD_UKEY_BL_CUST_VAL_4 2 + +/* ******************************** + * API + * ********************************* + */ extern int lcd_unifykey_len_check(int key_len, int len); extern int lcd_unifykey_check(char *key_name); extern int lcd_unifykey_header_check(unsigned char *buf, diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 8f1b086c7..350b4a9 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -23,15 +23,20 @@ #include #include -/* debug print define */ +/* ********************************** + * debug print define + * ********************************** + */ /* #define LCD_DEBUG_INFO */ extern unsigned char lcd_debug_print_flag; #define LCDPR(fmt, args...) pr_info("lcd: "fmt"", ## args) #define LCDERR(fmt, args...) pr_err("lcd: error: "fmt"", ## args) -/* clk parameter bit define */ -/* pll_ctrl, div_ctrl, clk_ctrl */ - +/* ********************************** + * clk parameter bit define + * pll_ctrl, div_ctrl, clk_ctrl + * ********************************** + */ /* ******** pll_ctrl ******** */ #define PLL_CTRL_OD3 20 /* [21:20] */ #define PLL_CTRL_OD2 18 /* [19:18] */ @@ -51,7 +56,10 @@ extern unsigned char lcd_debug_print_flag; #define CLK_CTRL_LEVEL 12 /* [14:12] */ #define CLK_CTRL_FRAC 0 /* [11:0] */ -/* VENC to TCON sync delay */ +/* ********************************** + * VENC to TCON sync delay + * ********************************** + */ #define TTL_DELAY 13 /* ******** AXG ******** */ @@ -73,7 +81,10 @@ extern unsigned char lcd_debug_print_flag; DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3) -/* global control define */ +/* ********************************** + * global control define + * ********************************** + */ enum lcd_mode_e { LCD_MODE_TV = 0, LCD_MODE_TABLET, @@ -169,7 +180,10 @@ struct lcd_timing_s { unsigned short vs_ve_addr; }; -/* HDR info define */ +/* ********************************** + * HDR info define + * ********************************** + */ struct lcd_hdr_info_s { unsigned int hdr_support; unsigned int features; @@ -270,7 +284,10 @@ struct lcd_control_config_s { struct dsi_config_s *mipi_config; }; -/* power control define */ +/* ********************************** + * power control define + * ********************************** + */ enum lcd_power_type_e { LCD_POWER_TYPE_CPU = 0, LCD_POWER_TYPE_PMU, @@ -355,6 +372,7 @@ struct aml_lcd_drv_s { unsigned char lcd_key_valid; unsigned char lcd_config_load; unsigned char lcd_test_flag; + unsigned char lcd_resume_flag; /* 0=directly, 1=workqueue */ unsigned char lcd_mute; struct clk *vencl_top; @@ -393,7 +411,11 @@ struct aml_lcd_drv_s { extern struct aml_lcd_drv_s *aml_lcd_get_driver(void); -/* IOCTL define */ + +/* ********************************** + * IOCTL define + * ********************************** + */ #define LCD_IOC_TYPE 'C' #define LCD_IOC_NR_GET_HDR_INFO 0x0 #define LCD_IOC_NR_SET_HDR_INFO 0x1 -- 2.7.4