lcd: add viu2 vsync interrupt & no viu vsync supoort

PD#172761: lcd: add viu2 vsync interrupt & no viu vsync supoort

Change-Id: Idefc6208af4cfe650907e97fd823353405fce35d
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2018-09-03 13:16:34 +08:00
committed by Jianxin Pan
parent 23bf6ab61f
commit e4386a05af
7 changed files with 198 additions and 20 deletions

View File

@@ -36,8 +36,9 @@
"gp0_pll";
reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */
0x0 0xff644000 0x0 0x200>; /* dsi_phy */
interrupts = <0 3 1>;
interrupt-names = "vsync";
interrupts = <0 3 1
0 56 1>;
interrupt-names = "vsync","vsync2";
pinctrl_version = <2>; /* for uboot */
/* power type:

View File

@@ -36,8 +36,9 @@
"gp0_pll";
reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */
0x0 0xff644000 0x0 0x200>; /* dsi_phy */
interrupts = <0 3 1>;
interrupt-names = "vsync";
interrupts = <0 3 1
0 56 1>;
interrupt-names = "vsync","vsync2";
pinctrl_version = <2>; /* for uboot */
/* power type:

View File

@@ -1904,6 +1904,10 @@ static ssize_t lcd_debug_mute_store(struct class *class,
}
temp = temp ? 1 : 0;
lcd_drv->lcd_mute_flag = (unsigned char)(temp | LCD_MUTE_UPDATE);
if (temp)
LCDPR("set mute\n");
else
LCDPR("clear mute\n");
while (i++ < 5000) {
if (lcd_drv->lcd_mute_state == temp)
break;

View File

@@ -118,13 +118,21 @@ static int lcd_vout_disable(enum vmode_e cur_vmod)
static int lcd_vout_state;
static int lcd_vout_set_state(int index)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_vout_state |= (1 << index);
lcd_drv->viu_sel = index;
return 0;
}
static int lcd_vout_clr_state(int index)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_vout_state &= ~(1 << index);
lcd_drv->viu_sel = LCD_VIU_SEL_NONE;
return 0;
}

View File

@@ -376,13 +376,21 @@ static int lcd_vout_disable(enum vmode_e cur_vmod)
static int lcd_vout_state;
static int lcd_vout_set_state(int index)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_vout_state |= (1 << index);
lcd_drv->viu_sel = index;
return 0;
}
static int lcd_vout_clr_state(int index)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_vout_state &= ~(1 << index);
lcd_drv->viu_sel = LCD_VIU_SEL_NONE;
return 0;
}

View File

@@ -68,6 +68,12 @@ struct lcd_cdev_s {
static struct lcd_cdev_s *lcd_cdev;
static int lcd_vsync_cnt;
static int lcd_vsync_cnt_previous;
#define LCD_VSYNC_NONE_INTERVAL msecs_to_jiffies(500)
static struct timer_list lcd_vsync_none_timer;
/* *********************************************************
* lcd config define
* *********************************************************
@@ -293,6 +299,22 @@ static void lcd_power_encl_on(void)
lcd_driver->driver_init_pre();
lcd_driver->lcd_status |= LCD_STATUS_ENCL_ON;
/* vsync_none_timer conditional enabled to save cpu loading */
if (lcd_driver->viu_sel == LCD_VIU_SEL_NONE) {
if (lcd_driver->vsync_none_timer_flag == 0) {
lcd_vsync_none_timer.expires =
jiffies + LCD_VSYNC_NONE_INTERVAL;
add_timer(&lcd_vsync_none_timer);
lcd_driver->vsync_none_timer_flag = 1;
LCDPR("add lcd_vsync_none_timer handler\n");
}
} else {
if (lcd_driver->vsync_none_timer_flag) {
del_timer_sync(&lcd_vsync_none_timer);
lcd_driver->vsync_none_timer_flag = 0;
}
}
mutex_unlock(&lcd_vout_mutex);
}
@@ -303,6 +325,11 @@ static void lcd_power_encl_off(void)
lcd_driver->lcd_status &= ~LCD_STATUS_ENCL_ON;
lcd_driver->driver_disable_post();
if (lcd_driver->vsync_none_timer_flag) {
del_timer_sync(&lcd_vsync_none_timer);
lcd_driver->vsync_none_timer_flag = 0;
}
mutex_unlock(&lcd_vout_mutex);
}
@@ -362,6 +389,7 @@ static void lcd_module_reset(void)
lcd_driver->lcd_config->change_flag = 0;
lcd_driver->lcd_mute_flag = (unsigned char)(0 | LCD_MUTE_UPDATE);
LCDPR("clear mute\n");
mutex_unlock(&lcd_vout_mutex);
}
@@ -375,16 +403,14 @@ 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)
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;
#endif
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
return IRQ_HANDLED;
#ifdef CONFIG_AMLOGIC_LCD_TABLET
if (pconf->lcd_control.mipi_config->dread) {
if (pconf->lcd_control.mipi_config->dread->flag) {
@@ -420,9 +446,81 @@ static irqreturn_t lcd_vsync_isr(int irq, void *dev_id)
lcd_driver->lcd_test_flag &= ~(LCD_TEST_UPDATE);
}
if (lcd_vsync_print_cnt++ >= LCD_DEBUG_VSYNC_INTERVAL) {
lcd_vsync_print_cnt = 0;
if (lcd_debug_print_flag & LCD_DEBUG_LEVEL_VSYNC) {
LCDPR("%s: viu_sel: %d\n",
__func__, lcd_driver->viu_sel);
}
}
}
static irqreturn_t lcd_vsync_isr(int irq, void *dev_id)
{
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
return IRQ_HANDLED;
if (lcd_driver->viu_sel == 1) {
lcd_vsync_handler();
if (lcd_vsync_cnt++ >= 65536)
lcd_vsync_cnt = 0;
}
return IRQ_HANDLED;
}
static irqreturn_t lcd_vsync2_isr(int irq, void *dev_id)
{
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
return IRQ_HANDLED;
if (lcd_driver->viu_sel == 2) {
lcd_vsync_handler();
if (lcd_vsync_cnt++ >= 65536)
lcd_vsync_cnt = 0;
}
return IRQ_HANDLED;
}
#define LCD_WAIT_VSYNC_TIMEOUT 50000
static void lcd_wait_vsync(void)
{
int line_cnt, line_cnt_previous;
int i = 0;
line_cnt = 0x1fff;
line_cnt_previous = lcd_vcbus_getb(ENCL_INFO_READ, 16, 13);
while (i++ < LCD_WAIT_VSYNC_TIMEOUT) {
line_cnt = lcd_vcbus_getb(ENCL_INFO_READ, 16, 13);
if (line_cnt < line_cnt_previous)
break;
line_cnt_previous = line_cnt;
udelay(2);
}
/*LCDPR("line_cnt=%d, line_cnt_previous=%d, i=%d\n",
* line_cnt, line_cnt_previous, i);
*/
}
static void lcd_vsync_none_timer_handler(unsigned long arg)
{
if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0)
goto lcd_vsync_none_timer_handler_end;
if (lcd_vsync_cnt == lcd_vsync_cnt_previous) {
lcd_wait_vsync();
lcd_vsync_handler();
}
lcd_vsync_cnt_previous = lcd_vsync_cnt;
lcd_vsync_none_timer_handler_end:
if (lcd_driver->vsync_none_timer_flag) {
lcd_vsync_none_timer.expires =
jiffies + LCD_VSYNC_NONE_INTERVAL;
add_timer(&lcd_vsync_none_timer);
}
}
/* ****************************************
* lcd notify
* ****************************************
@@ -934,6 +1032,10 @@ static int lcd_config_probe(struct platform_device *pdev)
return -1;
}
lcd_driver->res_vsync_irq = NULL;
lcd_driver->res_vsync2_irq = NULL;
lcd_driver->res_vx1_irq = NULL;
/* lcd driver assign */
ret = of_property_read_string(lcd_driver->dev->of_node, "mode", &str);
if (ret) {
@@ -982,6 +1084,24 @@ static int lcd_config_probe(struct platform_device *pdev)
LCDPR("detect lcd_auto_test: %d\n", lcd_driver->lcd_auto_test);
}
ret = of_property_read_string_index(lcd_driver->dev->of_node,
"interrupt-names", 0, &str);
if (ret == 0) {
lcd_driver->res_vsync_irq = platform_get_resource(pdev,
IORESOURCE_IRQ, 0);
}
ret = of_property_read_string_index(lcd_driver->dev->of_node,
"interrupt-names", 1, &str);
if (ret == 0) {
if (strcmp(str, "vbyone") == 0) {
lcd_driver->res_vx1_irq =
platform_get_resource(pdev, IORESOURCE_IRQ, 1);
} else if (strcmp(str, "vsync2") == 0) {
lcd_driver->res_vsync2_irq =
platform_get_resource(pdev, IORESOURCE_IRQ, 1);
}
}
lcd_driver->lcd_info = &lcd_vinfo;
lcd_driver->lcd_config = &lcd_config_dft;
lcd_driver->lcd_test_state = 0;
@@ -989,12 +1109,10 @@ static int lcd_config_probe(struct platform_device *pdev)
lcd_driver->lcd_mute_state = 0;
lcd_driver->lcd_mute_flag = 0;
lcd_driver->lcd_resume_type = 1; /* default workqueue */
lcd_driver->viu_sel = LCD_VIU_SEL_NONE;
lcd_driver->vsync_none_timer_flag = 0;
lcd_driver->power_ctrl = lcd_power_ctrl;
lcd_driver->module_reset = lcd_module_reset;
lcd_driver->res_vsync_irq = platform_get_resource(pdev,
IORESOURCE_IRQ, 0);
lcd_driver->res_vx1_irq = platform_get_resource(pdev,
IORESOURCE_IRQ, 1);
lcd_clk_config_probe();
lcd_config_default();
lcd_init_vout();
@@ -1023,16 +1141,33 @@ static int lcd_config_probe(struct platform_device *pdev)
static int lcd_vsync_irq_init(void)
{
if (!lcd_driver->res_vsync_irq) {
LCDERR("res_vsync_irq is null\n");
return -1;
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 {
LCDPR("request lcd_vsync_irq successful\n");
}
}
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");
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 {
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;
}
@@ -1041,6 +1176,16 @@ 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

View File

@@ -29,6 +29,12 @@
* debug print define
* **********************************
*/
#define LCD_DEBUG_LEVEL_NORMAL (1 << 0)
#define LCD_DEBUG_LEVEL_CLK (1 << 1)
#define LCD_DEBUG_LEVEL_VSYNC (1 << 3)
#define LCD_DEBUG_VSYNC_INTERVAL 60
/* #define LCD_DEBUG_INFO */
extern unsigned char lcd_debug_print_flag;
#define LCDPR(fmt, args...) pr_info("lcd: "fmt"", ## args)
@@ -410,6 +416,8 @@ struct lcd_duration_s {
#define LCD_MUTE_UPDATE (1 << 4)
#define LCD_TEST_UPDATE (1 << 4)
#define LCD_VIU_SEL_NONE 0
struct aml_lcd_drv_s {
char version[20];
struct lcd_data_s *data;
@@ -424,6 +432,8 @@ struct aml_lcd_drv_s {
unsigned char lcd_test_flag;
unsigned char lcd_mute_state;
unsigned char lcd_mute_flag;
unsigned char viu_sel;
unsigned char vsync_none_timer_flag;
unsigned char clk_gate_state;
struct clk *encl_top_gate;
@@ -459,6 +469,7 @@ struct aml_lcd_drv_s {
struct delayed_work lcd_probe_delayed_work;
struct work_struct lcd_resume_work;
struct resource *res_vsync_irq;
struct resource *res_vsync2_irq;
struct resource *res_vx1_irq;
struct mutex power_mutex;