mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
lcd: optimize unifykey read flow to avoid crash [1/1]
PD#SWPL-4682 Problem: lcd wait unifykey init timeout and read unifykey will crash Solution: incrase wait unifykey init time, and add read protection Verify: x301 Change-Id: Ib86a2b3b0c6c1491606404358420fd213dcfdaa8 Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
@@ -37,7 +37,8 @@
|
||||
/* 20181225: update phy config */
|
||||
/* 20190108: tl1 support tablet mode */
|
||||
/* 20190115: tl1 tcon all interface support */
|
||||
#define LCD_DRV_VERSION "20190115"
|
||||
/* 20190225: optimize unifykey read flow to avoid crash */
|
||||
#define LCD_DRV_VERSION "20190225"
|
||||
|
||||
#define VPP_OUT_SATURATE (1 << 0)
|
||||
|
||||
|
||||
@@ -383,7 +383,7 @@ static void lcd_tcon_config_delayed(struct work_struct *work)
|
||||
while (key_init_flag == 0) {
|
||||
if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT)
|
||||
break;
|
||||
msleep(20);
|
||||
msleep(LCD_UNIFYKEY_RETRY_INTERVAL);
|
||||
key_init_flag = key_unify_get_init_flag();
|
||||
}
|
||||
LCDPR("tcon: key_init_flag=%d, i=%d\n", key_init_flag, i);
|
||||
|
||||
@@ -463,14 +463,40 @@ static void lcd_resume_work(struct work_struct *p_work)
|
||||
mutex_unlock(&lcd_driver->power_mutex);
|
||||
}
|
||||
|
||||
static struct delayed_work lcd_test_delayed_work;
|
||||
static void lcd_auto_test_delayed(struct work_struct *work)
|
||||
{
|
||||
LCDPR("%s\n", __func__);
|
||||
mutex_lock(&lcd_driver->power_mutex);
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL);
|
||||
mutex_unlock(&lcd_driver->power_mutex);
|
||||
}
|
||||
|
||||
static void lcd_auto_test(unsigned char flag)
|
||||
{
|
||||
lcd_driver->lcd_test_state = flag;
|
||||
if (lcd_driver->workqueue) {
|
||||
queue_delayed_work(lcd_driver->workqueue,
|
||||
&lcd_test_delayed_work,
|
||||
msecs_to_jiffies(20000));
|
||||
} else {
|
||||
schedule_delayed_work(&lcd_test_delayed_work,
|
||||
msecs_to_jiffies(20000));
|
||||
}
|
||||
}
|
||||
|
||||
static int lcd_vsync_print_cnt;
|
||||
static inline void lcd_vsync_handler(void)
|
||||
{
|
||||
int flag;
|
||||
#ifdef CONFIG_AMLOGIC_LCD_TABLET
|
||||
struct lcd_config_s *pconf = lcd_driver->lcd_config;
|
||||
struct lcd_config_s *pconf;
|
||||
#endif
|
||||
|
||||
if (lcd_driver == NULL)
|
||||
return;
|
||||
|
||||
pconf = lcd_driver->lcd_config;
|
||||
#ifdef CONFIG_AMLOGIC_LCD_TABLET
|
||||
if (pconf->lcd_control.mipi_config->dread) {
|
||||
if (pconf->lcd_control.mipi_config->dread->flag) {
|
||||
@@ -517,6 +543,9 @@ static inline void lcd_vsync_handler(void)
|
||||
|
||||
static irqreturn_t lcd_vsync_isr(int irq, void *dev_id)
|
||||
{
|
||||
if (lcd_driver == NULL)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
@@ -530,6 +559,9 @@ static irqreturn_t lcd_vsync_isr(int irq, void *dev_id)
|
||||
|
||||
static irqreturn_t lcd_vsync2_isr(int irq, void *dev_id)
|
||||
{
|
||||
if (lcd_driver == NULL)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
@@ -563,6 +595,9 @@ static void lcd_wait_vsync(void)
|
||||
|
||||
static void lcd_vsync_none_timer_handler(unsigned long arg)
|
||||
{
|
||||
if (lcd_driver == NULL)
|
||||
return;
|
||||
|
||||
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
|
||||
goto lcd_vsync_none_timer_handler_end;
|
||||
|
||||
@@ -986,6 +1021,57 @@ static void lcd_fops_remove(void)
|
||||
}
|
||||
/* ************************************************************* */
|
||||
|
||||
static int lcd_vsync_irq_init(void)
|
||||
{
|
||||
if (lcd_driver->res_vsync_irq) {
|
||||
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 {
|
||||
if (lcd_debug_print_flag)
|
||||
LCDPR("request lcd_vsync_irq successful\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (lcd_driver->res_vsync2_irq) {
|
||||
if (request_irq(lcd_driver->res_vsync2_irq->start,
|
||||
lcd_vsync2_isr, IRQF_SHARED,
|
||||
"lcd_vsync2", (void *)"lcd_vsync2")) {
|
||||
LCDERR("can't request lcd_vsync2_irq\n");
|
||||
} else {
|
||||
if (lcd_debug_print_flag)
|
||||
LCDPR("request lcd_vsync2_irq successful\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* add timer to monitor hpll frequency */
|
||||
init_timer(&lcd_vsync_none_timer);
|
||||
/* lcd_vsync_none_timer.data = NULL; */
|
||||
lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler;
|
||||
lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL;
|
||||
/*add_timer(&lcd_vsync_none_timer);*/
|
||||
/*LCDPR("add lcd_vsync_none_timer handler\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");
|
||||
|
||||
if (lcd_driver->res_vsync2_irq) {
|
||||
free_irq(lcd_driver->res_vsync2_irq->start,
|
||||
(void *)"lcd_vsync");
|
||||
}
|
||||
|
||||
if (lcd_driver->vsync_none_timer_flag) {
|
||||
del_timer_sync(&lcd_vsync_none_timer);
|
||||
lcd_driver->vsync_none_timer_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_init_vout(void)
|
||||
{
|
||||
switch (lcd_driver->lcd_mode) {
|
||||
@@ -1030,11 +1116,15 @@ static int lcd_mode_probe(struct device *dev)
|
||||
lcd_fops_create();
|
||||
|
||||
lcd_notifier_register();
|
||||
lcd_vsync_irq_init();
|
||||
|
||||
/* add notifier for video sync_duration info refresh */
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
|
||||
&lcd_driver->lcd_info->mode);
|
||||
|
||||
if (lcd_driver->lcd_auto_test)
|
||||
lcd_auto_test(lcd_driver->lcd_auto_test);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1071,16 +1161,22 @@ static void lcd_config_probe_delayed(struct work_struct *work)
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
if (lcd_driver->lcd_key_valid) {
|
||||
key_init_flag = key_unify_get_init_flag();
|
||||
while (key_init_flag == 0) {
|
||||
if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT)
|
||||
break;
|
||||
msleep(LCD_UNIFYKEY_RETRY_INTERVAL);
|
||||
key_init_flag = key_unify_get_init_flag();
|
||||
while (key_init_flag == 0) {
|
||||
if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT)
|
||||
break;
|
||||
msleep(20);
|
||||
key_init_flag = key_unify_get_init_flag();
|
||||
}
|
||||
LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i);
|
||||
}
|
||||
LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i);
|
||||
|
||||
if (key_init_flag == 0) {
|
||||
kfree(lcd_driver);
|
||||
lcd_driver = NULL;
|
||||
LCDERR("key is not ready, probe exit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = lcd_mode_probe(lcd_driver->dev);
|
||||
if (ret) {
|
||||
kfree(lcd_driver);
|
||||
@@ -1234,57 +1330,6 @@ static int lcd_config_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_vsync_irq_init(void)
|
||||
{
|
||||
if (lcd_driver->res_vsync_irq) {
|
||||
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 {
|
||||
if (lcd_debug_print_flag)
|
||||
LCDPR("request lcd_vsync_irq successful\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (lcd_driver->res_vsync2_irq) {
|
||||
if (request_irq(lcd_driver->res_vsync2_irq->start,
|
||||
lcd_vsync2_isr, IRQF_SHARED,
|
||||
"lcd_vsync2", (void *)"lcd_vsync2")) {
|
||||
LCDERR("can't request lcd_vsync2_irq\n");
|
||||
} else {
|
||||
if (lcd_debug_print_flag)
|
||||
LCDPR("request lcd_vsync2_irq successful\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* add timer to monitor hpll frequency */
|
||||
init_timer(&lcd_vsync_none_timer);
|
||||
/* lcd_vsync_none_timer.data = NULL; */
|
||||
lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler;
|
||||
lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL;
|
||||
/*add_timer(&lcd_vsync_none_timer);*/
|
||||
/*LCDPR("add lcd_vsync_none_timer handler\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");
|
||||
|
||||
if (lcd_driver->res_vsync2_irq) {
|
||||
free_irq(lcd_driver->res_vsync2_irq->start,
|
||||
(void *)"lcd_vsync");
|
||||
}
|
||||
|
||||
if (lcd_driver->vsync_none_timer_flag) {
|
||||
del_timer_sync(&lcd_vsync_none_timer);
|
||||
lcd_driver->vsync_none_timer_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static struct lcd_data_s lcd_data_gxl = {
|
||||
@@ -1372,28 +1417,6 @@ static const struct of_device_id lcd_dt_match_table[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct delayed_work lcd_test_delayed_work;
|
||||
static void lcd_auto_test_delayed(struct work_struct *work)
|
||||
{
|
||||
LCDPR("%s\n", __func__);
|
||||
mutex_lock(&lcd_driver->power_mutex);
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL);
|
||||
mutex_unlock(&lcd_driver->power_mutex);
|
||||
}
|
||||
|
||||
static void lcd_auto_test(unsigned char flag)
|
||||
{
|
||||
lcd_driver->lcd_test_state = flag;
|
||||
if (lcd_driver->workqueue) {
|
||||
queue_delayed_work(lcd_driver->workqueue,
|
||||
&lcd_test_delayed_work,
|
||||
msecs_to_jiffies(20000));
|
||||
} else {
|
||||
schedule_delayed_work(&lcd_test_delayed_work,
|
||||
msecs_to_jiffies(20000));
|
||||
}
|
||||
}
|
||||
|
||||
static int lcd_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
@@ -1439,32 +1462,29 @@ 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"));
|
||||
|
||||
if (lcd_driver->lcd_auto_test)
|
||||
lcd_auto_test(lcd_driver->lcd_auto_test);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (lcd_driver == NULL)
|
||||
return 0;
|
||||
|
||||
cancel_delayed_work(&lcd_driver->lcd_probe_delayed_work);
|
||||
cancel_work_sync(&(lcd_driver->lcd_resume_work));
|
||||
if (lcd_driver->workqueue)
|
||||
destroy_workqueue(lcd_driver->workqueue);
|
||||
|
||||
if (lcd_driver) {
|
||||
lcd_vsync_irq_remove();
|
||||
lcd_fops_remove();
|
||||
lcd_debug_remove();
|
||||
lcd_config_remove(lcd_driver->dev);
|
||||
lcd_vsync_irq_remove();
|
||||
lcd_fops_remove();
|
||||
lcd_debug_remove();
|
||||
lcd_config_remove(lcd_driver->dev);
|
||||
|
||||
kfree(lcd_driver);
|
||||
lcd_driver = NULL;
|
||||
}
|
||||
kfree(lcd_driver);
|
||||
lcd_driver = NULL;
|
||||
|
||||
LCDPR("%s\n", __func__);
|
||||
return 0;
|
||||
@@ -1480,6 +1500,8 @@ static int lcd_resume(struct platform_device *pdev)
|
||||
(get_resume_method() == UDEFINED_WAKEUP))
|
||||
return 0;
|
||||
|
||||
if (lcd_driver == NULL)
|
||||
return 0;
|
||||
if ((lcd_driver->lcd_status & LCD_STATUS_VMODE_ACTIVE) == 0)
|
||||
return 0;
|
||||
|
||||
@@ -1506,6 +1528,9 @@ static int lcd_resume(struct platform_device *pdev)
|
||||
|
||||
static int lcd_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
if (lcd_driver == NULL)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&lcd_driver->power_mutex);
|
||||
if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) {
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
|
||||
@@ -1521,6 +1546,8 @@ static void lcd_shutdown(struct platform_device *pdev)
|
||||
if (lcd_debug_print_flag)
|
||||
LCDPR("%s\n", __func__);
|
||||
|
||||
if (lcd_driver == NULL)
|
||||
return;
|
||||
if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON)
|
||||
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
#ifndef _INC_AML_LCD_UNIFYKEY_H__
|
||||
#define _INC_AML_LCD_UNIFYKEY_H__
|
||||
|
||||
#define LCD_UNIFYKEY_WAIT_TIMEOUT 300
|
||||
#define LCD_UNIFYKEY_WAIT_TIMEOUT 500
|
||||
#define LCD_UNIFYKEY_RETRY_INTERVAL 20 /* ms */
|
||||
|
||||
/* declare external unifykey function */
|
||||
extern void *get_ukdev(void);
|
||||
|
||||
Reference in New Issue
Block a user