mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
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:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user