mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
lcd: mute: wait vsync for display shadow [2/2]
PD#170101: lcd: mute: wait vsync for display shadow Change-Id: If17838c40d46fd6f4b943d313456738fec50185a Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
@@ -32,8 +32,10 @@
|
||||
"dsi_meas",
|
||||
"mipi_enable_gate",
|
||||
"mipi_bandgap_gate";
|
||||
reg = <0x0 0xffd06000 0x0 0x400
|
||||
0x0 0xff640000 0x0 0x100>;
|
||||
reg = <0x0 0xffd06000 0x0 0x400 /* dsi_host */
|
||||
0x0 0xff640000 0x0 0x100>; /* dsi_phy */
|
||||
interrupts = <0 3 1>;
|
||||
interrupt-names = "vsync";
|
||||
pinctrl_version = <1>; /* for uboot */
|
||||
|
||||
/* power type:
|
||||
|
||||
@@ -32,8 +32,10 @@
|
||||
"dsi_meas",
|
||||
"encl_top_gate",
|
||||
"encl_int_gate";
|
||||
reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */
|
||||
0x0 0xff644000 0x0 0x2000>; /* dsi_phy */
|
||||
reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */
|
||||
0x0 0xff644000 0x0 0x200>; /* dsi_phy */
|
||||
interrupts = <0 3 1>;
|
||||
interrupt-names = "vsync";
|
||||
pinctrl_version = <2>; /* for uboot */
|
||||
|
||||
/* power type:
|
||||
|
||||
@@ -32,8 +32,10 @@
|
||||
"dsi_meas",
|
||||
"encl_top_gate",
|
||||
"encl_int_gate";
|
||||
reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */
|
||||
0x0 0xff644000 0x0 0x2000>; /* dsi_phy */
|
||||
reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */
|
||||
0x0 0xff644000 0x0 0x200>; /* dsi_phy */
|
||||
interrupts = <0 3 1>;
|
||||
interrupt-names = "vsync";
|
||||
pinctrl_version = <2>; /* for uboot */
|
||||
|
||||
/* power type:
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
* "vencl_int_gate";
|
||||
*/
|
||||
reg = <0x0 0xc8834400 0x0 0x100>;
|
||||
interrupts = <0 3 1>;
|
||||
interrupt-names = "vsync";
|
||||
pinctrl_version = <1>; /* for uboot */
|
||||
|
||||
/* power type:
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
* "vencl_int_gate";
|
||||
*/
|
||||
reg = <0x0 0xc8834400 0x0 0x100>;
|
||||
interrupts = <0 3 1>;
|
||||
interrupt-names = "vsync";
|
||||
pinctrl_version = <1>; /* for uboot */
|
||||
pinctrl-names = "ttl_6bit_hvsync_de_on","ttl_6bit_hvsync_on",
|
||||
"ttl_6bit_de_on","ttl_8bit_hvsync_de_on",
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
/* 20180425: tvconfig suuport */
|
||||
/* 20180620: fix coverity errors */
|
||||
/* 20180626: txl suuport */
|
||||
#define LCD_DRV_VERSION "20180626"
|
||||
/* 20180718: mute: wait vsync for display shadow */
|
||||
#define LCD_DRV_VERSION "20180718"
|
||||
|
||||
#define VPP_OUT_SATURATE (1 << 0)
|
||||
|
||||
@@ -97,6 +98,7 @@ extern void lcd_venc_change(struct lcd_config_s *pconf);
|
||||
extern void lcd_if_enable_retry(struct lcd_config_s *pconf);
|
||||
|
||||
/* lcd debug */
|
||||
extern void lcd_debug_test(unsigned int num);
|
||||
extern void lcd_mute_setting(unsigned char flag);
|
||||
extern int lcd_class_creat(void);
|
||||
extern int lcd_class_remove(void);
|
||||
|
||||
@@ -967,6 +967,16 @@ static int lcd_hdr_info_print(char *buf, int offset)
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct work_struct lcd_test_check_work;
|
||||
static void lcd_test_pattern_check(struct work_struct *p_work)
|
||||
{
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
int flag;
|
||||
|
||||
flag = (lcd_drv->lcd_test_state > 0) ? 1 : 0;
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_TEST_PATTERN, &flag);
|
||||
}
|
||||
|
||||
#define LCD_ENC_TST_NUM_MAX 9
|
||||
static char *lcd_enc_tst_str[] = {
|
||||
"0-None", /* 0 */
|
||||
@@ -993,15 +1003,17 @@ static unsigned int lcd_enc_tst[][7] = {
|
||||
{0, 0x0, 0x0, 0x0, 1, 0, 3}, /* 8 */
|
||||
};
|
||||
|
||||
static void lcd_debug_test(unsigned int num)
|
||||
void lcd_debug_test(unsigned int num)
|
||||
{
|
||||
unsigned int h_active, video_on_pixel;
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
int flag;
|
||||
|
||||
num = (num >= LCD_ENC_TST_NUM_MAX) ? 0 : num;
|
||||
flag = (num > 0) ? 1 : 0;
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_TEST_PATTERN, &flag);
|
||||
|
||||
if (lcd_drv->workqueue)
|
||||
queue_work(lcd_drv->workqueue, &lcd_test_check_work);
|
||||
else
|
||||
schedule_work(&lcd_test_check_work);
|
||||
|
||||
h_active = lcd_drv->lcd_config->lcd_basic.h_active;
|
||||
video_on_pixel = lcd_drv->lcd_config->lcd_timing.video_on_pixel;
|
||||
@@ -1022,7 +1034,6 @@ static void lcd_debug_test(unsigned int num)
|
||||
|
||||
void lcd_mute_setting(unsigned char flag)
|
||||
{
|
||||
LCDPR("set lcd mute: %d\n", flag);
|
||||
if (flag) {
|
||||
lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL, 3);
|
||||
lcd_vcbus_write(ENCL_TST_MDSEL, 0);
|
||||
@@ -1042,14 +1053,14 @@ static void lcd_screen_restore(void)
|
||||
unsigned int h_active, video_on_pixel;
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
unsigned int num;
|
||||
int flag;
|
||||
|
||||
lcd_drv->lcd_mute = 0;
|
||||
|
||||
num = lcd_drv->lcd_test_flag;
|
||||
num = (num >= LCD_ENC_TST_NUM_MAX) ? 0 : num;
|
||||
flag = (num > 0) ? 1 : 0;
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_TEST_PATTERN, &flag);
|
||||
|
||||
if (lcd_drv->workqueue)
|
||||
queue_work(lcd_drv->workqueue, &lcd_test_check_work);
|
||||
else
|
||||
schedule_work(&lcd_test_check_work);
|
||||
|
||||
h_active = lcd_drv->lcd_config->lcd_basic.h_active;
|
||||
video_on_pixel = lcd_drv->lcd_config->lcd_timing.video_on_pixel;
|
||||
@@ -1267,8 +1278,8 @@ static ssize_t lcd_debug_store(struct class *class,
|
||||
case 't': /* test */
|
||||
ret = sscanf(buf, "test %d", &temp);
|
||||
if (ret == 1) {
|
||||
lcd_drv->lcd_test_flag = (unsigned char)temp;
|
||||
lcd_debug_test(temp);
|
||||
lcd_drv->lcd_test_flag =
|
||||
(unsigned char)(temp | LCD_TEST_UPDATE);
|
||||
} else {
|
||||
LCDERR("invalid data\n");
|
||||
return -EINVAL;
|
||||
@@ -1826,14 +1837,14 @@ static ssize_t lcd_debug_test_show(struct class *class,
|
||||
{
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
|
||||
return sprintf(buf, "test pattern: %d\n", lcd_drv->lcd_test_flag);
|
||||
return sprintf(buf, "test pattern: %d\n", lcd_drv->lcd_test_state);
|
||||
}
|
||||
|
||||
static ssize_t lcd_debug_test_store(struct class *class,
|
||||
struct class_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int temp = 0;
|
||||
unsigned int temp = 0, i = 0;
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
|
||||
ret = kstrtouint(buf, 10, &temp);
|
||||
@@ -1841,8 +1852,13 @@ static ssize_t lcd_debug_test_store(struct class *class,
|
||||
pr_info("invalid data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
lcd_drv->lcd_test_flag = (unsigned char)temp;
|
||||
lcd_debug_test(temp);
|
||||
temp = (temp >= LCD_ENC_TST_NUM_MAX) ? 0 : temp;
|
||||
lcd_drv->lcd_test_flag = (unsigned char)(temp | LCD_TEST_UPDATE);
|
||||
while (i++ < 5000) {
|
||||
if (lcd_drv->lcd_test_state == temp)
|
||||
break;
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -1852,14 +1868,15 @@ static ssize_t lcd_debug_mute_show(struct class *class,
|
||||
{
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
|
||||
return sprintf(buf, "get lcd mute state: %d\n", lcd_drv->lcd_mute);
|
||||
return sprintf(buf, "get lcd mute state: %d\n",
|
||||
lcd_drv->lcd_mute_state);
|
||||
}
|
||||
|
||||
static ssize_t lcd_debug_mute_store(struct class *class,
|
||||
struct class_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int temp = 0;
|
||||
unsigned int temp = 0, i = 0;
|
||||
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
|
||||
|
||||
ret = kstrtouint(buf, 10, &temp);
|
||||
@@ -1867,8 +1884,13 @@ static ssize_t lcd_debug_mute_store(struct class *class,
|
||||
pr_info("invalid data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
lcd_drv->lcd_mute = (unsigned char)temp;
|
||||
lcd_mute_setting(lcd_drv->lcd_mute);
|
||||
temp = temp ? 1 : 0;
|
||||
lcd_drv->lcd_mute_flag = (unsigned char)(temp | LCD_MUTE_UPDATE);
|
||||
while (i++ < 5000) {
|
||||
if (lcd_drv->lcd_mute_state == temp)
|
||||
break;
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -3045,6 +3067,8 @@ int lcd_class_creat(void)
|
||||
lcd_drv->lcd_screen_restore = lcd_screen_restore;
|
||||
lcd_drv->lcd_screen_black = lcd_screen_black;
|
||||
|
||||
INIT_WORK(&lcd_test_check_work, lcd_test_pattern_check);
|
||||
|
||||
lcd_drv->lcd_debug_class = class_create(THIS_MODULE, "lcd");
|
||||
if (IS_ERR(lcd_drv->lcd_debug_class)) {
|
||||
LCDERR("create lcd debug class fail\n");
|
||||
|
||||
@@ -371,6 +371,14 @@ static void lcd_venc_set(struct lcd_config_s *pconf)
|
||||
lcd_vcbus_write(ENCL_VIDEO_VSO_ELINE, pconf->lcd_timing.vs_ve_addr);
|
||||
lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL, 3);
|
||||
|
||||
/* default black pattern */
|
||||
lcd_vcbus_write(ENCL_TST_MDSEL, 0);
|
||||
lcd_vcbus_write(ENCL_TST_Y, 0);
|
||||
lcd_vcbus_write(ENCL_TST_CB, 0);
|
||||
lcd_vcbus_write(ENCL_TST_CR, 0);
|
||||
lcd_vcbus_write(ENCL_TST_EN, 1);
|
||||
lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV, 0, 3, 1);
|
||||
|
||||
lcd_vcbus_write(ENCL_VIDEO_EN, 1);
|
||||
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, NULL);
|
||||
@@ -915,7 +923,7 @@ void lcd_tablet_driver_init_pre(void)
|
||||
lcd_clk_set(pconf);
|
||||
lcd_venc_set(pconf);
|
||||
lcd_encl_tcon_set(pconf);
|
||||
lcd_mute_setting(1);
|
||||
lcd_drv->lcd_mute_state = 1;
|
||||
|
||||
lcd_vcbus_write(VENC_INTCTRL, 0x200);
|
||||
|
||||
|
||||
@@ -245,6 +245,14 @@ static void lcd_venc_set(struct lcd_config_s *pconf)
|
||||
|
||||
lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL, 3);
|
||||
|
||||
/* default black pattern */
|
||||
lcd_vcbus_write(ENCL_TST_MDSEL, 0);
|
||||
lcd_vcbus_write(ENCL_TST_Y, 0);
|
||||
lcd_vcbus_write(ENCL_TST_CB, 0);
|
||||
lcd_vcbus_write(ENCL_TST_CR, 0);
|
||||
lcd_vcbus_write(ENCL_TST_EN, 1);
|
||||
lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV, 0, 3, 1);
|
||||
|
||||
lcd_vcbus_write(ENCL_VIDEO_EN, 1);
|
||||
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, NULL);
|
||||
@@ -1259,7 +1267,7 @@ void lcd_tv_driver_init_pre(void)
|
||||
lcd_clk_set(pconf);
|
||||
lcd_venc_set(pconf);
|
||||
lcd_encl_tcon_set(pconf);
|
||||
lcd_mute_setting(1);
|
||||
lcd_drv->lcd_mute_state = 1;
|
||||
|
||||
lcd_vcbus_write(VENC_INTCTRL, 0x200);
|
||||
|
||||
|
||||
@@ -328,7 +328,8 @@ static void lcd_power_screen_black(void)
|
||||
{
|
||||
mutex_lock(&lcd_vout_mutex);
|
||||
|
||||
lcd_driver->lcd_screen_black();
|
||||
lcd_driver->lcd_mute_flag = (unsigned char)(1 | LCD_MUTE_UPDATE);
|
||||
LCDPR("set mute\n");
|
||||
|
||||
mutex_unlock(&lcd_vout_mutex);
|
||||
}
|
||||
@@ -337,7 +338,8 @@ static void lcd_power_screen_restore(void)
|
||||
{
|
||||
mutex_lock(&lcd_vout_mutex);
|
||||
|
||||
lcd_driver->lcd_screen_restore();
|
||||
lcd_driver->lcd_mute_flag = (unsigned char)(0 | LCD_MUTE_UPDATE);
|
||||
LCDPR("clear mute\n");
|
||||
|
||||
mutex_unlock(&lcd_vout_mutex);
|
||||
}
|
||||
@@ -368,6 +370,41 @@ static void lcd_resume_work(struct work_struct *p_work)
|
||||
mutex_unlock(&lcd_driver->power_mutex);
|
||||
}
|
||||
|
||||
static irqreturn_t lcd_vsync_isr(int irq, void *dev_id)
|
||||
{
|
||||
int flag;
|
||||
|
||||
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (lcd_driver->lcd_mute_flag & LCD_MUTE_UPDATE) {
|
||||
flag = lcd_driver->lcd_mute_flag & 0x1;
|
||||
if (flag) {
|
||||
if (lcd_driver->lcd_mute_state == 0) {
|
||||
lcd_driver->lcd_mute_state = 1;
|
||||
lcd_driver->lcd_screen_black();
|
||||
}
|
||||
} else {
|
||||
if (lcd_driver->lcd_mute_state) {
|
||||
lcd_driver->lcd_mute_state = 0;
|
||||
lcd_driver->lcd_screen_restore();
|
||||
}
|
||||
}
|
||||
lcd_driver->lcd_mute_flag &= ~(LCD_MUTE_UPDATE);
|
||||
}
|
||||
|
||||
if (lcd_driver->lcd_test_flag & LCD_TEST_UPDATE) {
|
||||
flag = lcd_driver->lcd_test_flag & 0xf;
|
||||
if (flag != lcd_driver->lcd_test_state) {
|
||||
lcd_driver->lcd_test_state = (unsigned char)flag;
|
||||
lcd_debug_test(flag);
|
||||
}
|
||||
lcd_driver->lcd_test_flag &= ~(LCD_TEST_UPDATE);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* ****************************************
|
||||
* lcd notify
|
||||
* ****************************************
|
||||
@@ -888,7 +925,10 @@ static int lcd_config_probe(struct platform_device *pdev)
|
||||
|
||||
lcd_driver->lcd_info = &lcd_vinfo;
|
||||
lcd_driver->lcd_config = &lcd_config_dft;
|
||||
lcd_driver->lcd_test_state = 0;
|
||||
lcd_driver->lcd_test_flag = 0;
|
||||
lcd_driver->lcd_mute_state = 0;
|
||||
lcd_driver->lcd_mute_flag = 0;
|
||||
lcd_driver->lcd_resume_type = 1; /* default workqueue */
|
||||
lcd_driver->power_ctrl = lcd_power_ctrl;
|
||||
lcd_driver->module_reset = lcd_module_reset;
|
||||
@@ -922,6 +962,28 @@ static int lcd_config_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_vsync_irq_init(void)
|
||||
{
|
||||
if (!lcd_driver->res_vsync_irq) {
|
||||
LCDERR("res_vsync_irq is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (request_irq(lcd_driver->res_vsync_irq->start, lcd_vsync_isr,
|
||||
IRQF_SHARED, "lcd_vsync", (void *)"lcd_vsync"))
|
||||
LCDERR("can't request lcd_vsync_irq\n");
|
||||
else
|
||||
LCDPR("request lcd_vsync_irq successful\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lcd_vsync_irq_remove(void)
|
||||
{
|
||||
if (lcd_driver->res_vsync_irq)
|
||||
free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static struct lcd_data_s lcd_data_gxtvbb = {
|
||||
@@ -1053,6 +1115,7 @@ static int lcd_probe(struct platform_device *pdev)
|
||||
|
||||
lcd_ioremap(pdev);
|
||||
ret = lcd_config_probe(pdev);
|
||||
lcd_vsync_irq_init();
|
||||
|
||||
LCDPR("%s %s\n", __func__, (ret ? "failed" : "ok"));
|
||||
return 0;
|
||||
@@ -1066,6 +1129,7 @@ static int lcd_remove(struct platform_device *pdev)
|
||||
destroy_workqueue(lcd_driver->workqueue);
|
||||
|
||||
if (lcd_driver) {
|
||||
lcd_vsync_irq_remove();
|
||||
lcd_fops_remove();
|
||||
lcd_class_remove();
|
||||
lcd_config_remove(lcd_driver->dev);
|
||||
|
||||
@@ -393,6 +393,8 @@ struct lcd_duration_s {
|
||||
#define LCD_STATUS_VMODE_ACTIVE (1 << 2)
|
||||
#define LCD_STATUS_ON (LCD_STATUS_IF_ON | LCD_STATUS_ENCL_ON)
|
||||
|
||||
#define LCD_MUTE_UPDATE (1 << 4)
|
||||
#define LCD_TEST_UPDATE (1 << 4)
|
||||
struct aml_lcd_drv_s {
|
||||
char version[20];
|
||||
struct lcd_data_s *data;
|
||||
@@ -401,9 +403,11 @@ struct aml_lcd_drv_s {
|
||||
unsigned char lcd_key_valid;
|
||||
unsigned char lcd_clk_path; /* 0=hpll, 1=gp0_pll */
|
||||
unsigned char lcd_config_load;
|
||||
unsigned char lcd_test_flag;
|
||||
unsigned char lcd_resume_type; /* 0=directly, 1=workqueue */
|
||||
unsigned char lcd_mute;
|
||||
unsigned char lcd_test_state;
|
||||
unsigned char lcd_test_flag;
|
||||
unsigned char lcd_mute_state;
|
||||
unsigned char lcd_mute_flag;
|
||||
|
||||
unsigned char clk_gate_state;
|
||||
struct clk *encl_top_gate;
|
||||
|
||||
Reference in New Issue
Block a user