/* 20170505: add a113 support to linux4.9 */
/* 20170905: fix coverity errors */
-#define LCD_DRV_VERSION "20171201"
+/* 20180122: support txlx, optimize lcd noitfier event */
+#define LCD_DRV_VERSION "20180122"
#define VPP_OUT_SATURATE (1 << 0)
-extern struct mutex lcd_power_mutex;
extern struct mutex lcd_vout_mutex;
extern unsigned char lcd_resume_flag;
extern int lcd_vout_serve_bypass;
}
}
-static void lcd_test_check(void)
+static void lcd_screen_restore(void)
{
unsigned int h_active, video_on_pixel;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
}
}
+static void lcd_screen_black(void)
+{
+ lcd_mute_setting(1);
+}
+
static void lcd_vinfo_update(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
&lcd_drv->lcd_info->mode);
}
+static void lcd_power_interface_ctrl(int state)
+{
+ struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
+
+ mutex_lock(&lcd_drv->power_mutex);
+ LCDPR("%s: %d\n", __func__, state);
+ if (state) {
+ if (lcd_drv->lcd_status & LCD_STATUS_ENCL_ON) {
+ aml_lcd_notifier_call_chain(
+ LCD_EVENT_IF_POWER_ON, NULL);
+ } else {
+ LCDERR("%s: can't power on when controller is off\n",
+ __func__);
+ }
+ } else {
+ aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL);
+ }
+ mutex_unlock(&lcd_drv->power_mutex);
+}
+
static ssize_t lcd_debug_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
case 'p': /* power */
ret = sscanf(buf, "power %d", &temp);
if (ret == 1) {
- mutex_lock(&lcd_power_mutex);
- LCDPR("power: %d\n", temp);
- if (temp) {
- aml_lcd_notifier_call_chain(
- LCD_EVENT_IF_POWER_ON, NULL);
- } else {
- aml_lcd_notifier_call_chain(
- LCD_EVENT_IF_POWER_OFF, NULL);
- }
- mutex_unlock(&lcd_power_mutex);
+ lcd_power_interface_ctrl(temp);
} else {
LCDERR("invalid data\n");
return -EINVAL;
static ssize_t lcd_debug_enable_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
+ struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
int ret = 0;
unsigned int temp = 1;
return -EINVAL;
}
if (temp) {
- mutex_lock(&lcd_power_mutex);
+ mutex_lock(&lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL);
- mutex_unlock(&lcd_power_mutex);
+ mutex_unlock(&lcd_drv->power_mutex);
} else {
- mutex_lock(&lcd_power_mutex);
+ mutex_lock(&lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
- mutex_unlock(&lcd_power_mutex);
+ mutex_unlock(&lcd_drv->power_mutex);
}
return count;
lcd_phy_debug_show, lcd_phy_debug_store),
};
-static int lcd_black_screen_notifier(struct notifier_block *nb,
- unsigned long event, void *data)
-{
- if ((event & LCD_EVENT_BLACK_SCREEN) == 0)
- return NOTIFY_DONE;
- if (lcd_debug_print_flag)
- LCDPR("%s: 0x%lx\n", __func__, event);
-
- lcd_mute_setting(1);
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block lcd_black_screen_nb = {
- .notifier_call = lcd_black_screen_notifier,
- .priority = LCD_PRIORITY_BLACK_SCREEN,
-};
-
int lcd_class_creat(void)
{
int i;
- int ret;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
int type;
- ret = aml_lcd_notifier_register(&lcd_black_screen_nb);
- if (ret)
- LCDERR("register lcd_black_screen_notifier failed\n");
-
- lcd_drv->lcd_test_pattern_restore = lcd_test_check;
+ lcd_drv->lcd_screen_restore = lcd_screen_restore;
+ lcd_drv->lcd_screen_black = lcd_screen_black;
lcd_drv->lcd_debug_class = class_create(THIS_MODULE, "lcd");
if (IS_ERR(lcd_drv->lcd_debug_class)) {
lcd_clk_set(pconf);
lcd_venc_set(pconf);
lcd_tcon_set(pconf);
- lcd_drv->lcd_test_pattern_restore();
-}
-
-int lcd_tablet_driver_init(void)
-{
- struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
- struct lcd_config_s *pconf;
- int ret;
-
- pconf = lcd_drv->lcd_config;
- ret = lcd_type_supported(pconf);
- if (ret)
- return -1;
-
- /* init driver */
- switch (pconf->lcd_basic.lcd_type) {
- case LCD_TTL:
- lcd_ttl_control_set(pconf);
- lcd_ttl_pinmux_set(1);
- break;
- case LCD_LVDS:
- lcd_lvds_control_set(pconf);
- lcd_lvds_phy_set(pconf, 1);
- break;
- case LCD_VBYONE:
- lcd_vbyone_pinmux_set(1);
- lcd_vbyone_control_set(pconf);
- lcd_vx1_wait_hpd();
- lcd_vbyone_phy_set(pconf, 1);
- lcd_tablet_vbyone_wait_stable();
- case LCD_MIPI:
- lcd_mipi_phy_set(pconf, 1);
- lcd_mipi_control_set(pconf, 1);
- break;
- default:
- break;
- }
lcd_vcbus_write(VENC_INTCTRL, 0x200);
if (lcd_debug_print_flag)
LCDPR("%s finished\n", __func__);
-
- return 0;
}
-void lcd_tablet_driver_disable(void)
+void lcd_tablet_driver_disable_post(void)
{
- struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
- struct lcd_config_s *pconf;
- int ret;
-
- LCDPR("disable driver\n");
- pconf = lcd_drv->lcd_config;
- ret = lcd_type_supported(pconf);
- if (ret)
- return;
-
- switch (pconf->lcd_basic.lcd_type) {
- case LCD_TTL:
- lcd_ttl_pinmux_set(0);
- break;
- case LCD_LVDS:
- lcd_lvds_phy_set(pconf, 0);
- lcd_lvds_disable();
- break;
- case LCD_VBYONE:
- lcd_vbyone_phy_set(pconf, 0);
- lcd_vbyone_pinmux_set(0);
- lcd_vbyone_disable();
- case LCD_MIPI:
- mipi_dsi_link_off(pconf);
- lcd_mipi_phy_set(pconf, 0);
- lcd_mipi_control_set(pconf, 0);
- break;
- default:
- break;
- }
-
lcd_vcbus_write(ENCL_VIDEO_EN, 0); /* disable encl */
lcd_clk_disable();
LCDPR("%s finished\n", __func__);
}
-void lcd_tablet_driver_tiny_enable(void)
+int lcd_tablet_driver_init(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
struct lcd_config_s *pconf;
pconf = lcd_drv->lcd_config;
ret = lcd_type_supported(pconf);
if (ret)
- return;
+ return -1;
/* init driver */
switch (pconf->lcd_basic.lcd_type) {
break;
}
- LCDPR("enable driver\n");
+ if (lcd_debug_print_flag)
+ LCDPR("%s finished\n", __func__);
+
+ return 0;
}
-void lcd_tablet_driver_tiny_disable(void)
+void lcd_tablet_driver_disable(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
struct lcd_config_s *pconf;
default:
break;
}
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s finished\n", __func__);
}
#ifdef CONFIG_PM
static int lcd_suspend(void)
{
- mutex_lock(&lcd_power_mutex);
+ struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
+
+ mutex_lock(&lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
lcd_resume_flag = 0;
LCDPR("%s finished\n", __func__);
- mutex_unlock(&lcd_power_mutex);
+ mutex_unlock(&lcd_drv->power_mutex);
return 0;
}
queue_work(lcd_drv->workqueue,
&(lcd_drv->lcd_resume_work));
} else {
+ mutex_lock(&lcd_drv->power_mutex);
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);
+ mutex_unlock(&lcd_drv->power_mutex);
}
} else {
+ mutex_lock(&lcd_drv->power_mutex);
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_drv->power_mutex);
}
return 0;
lcd_drv->version = LCD_DRV_VERSION;
lcd_drv->vout_server_init = lcd_tablet_vout_server_init;
lcd_drv->driver_init_pre = lcd_tablet_driver_init_pre;
+ lcd_drv->driver_disable_post = lcd_tablet_driver_disable_post;
lcd_drv->driver_init = lcd_tablet_driver_init;
lcd_drv->driver_disable = lcd_tablet_driver_disable;
- lcd_drv->driver_tiny_enable = lcd_tablet_driver_tiny_enable;
- lcd_drv->driver_tiny_disable = lcd_tablet_driver_tiny_disable;
lcd_get_config(lcd_drv->lcd_config, dev);
extern void lcd_tablet_config_update(struct lcd_config_s *pconf);
extern void lcd_tablet_config_post_update(struct lcd_config_s *pconf);
extern void lcd_tablet_driver_init_pre(void);
+extern void lcd_tablet_driver_disable_post(void);
extern int lcd_tablet_driver_init(void);
extern void lcd_tablet_driver_disable(void);
-extern void lcd_tablet_driver_tiny_enable(void);
-extern void lcd_tablet_driver_tiny_disable(void);
#endif
return;
LCDPR("%s\n", __func__);
- if (vx1_timeout_reset_flag == 1)
- lcd_drv->module_reset();
- else
- lcd_drv->module_tiny_reset();
+ lcd_drv->module_reset();
if (lcd_drv->lcd_config->lcd_control.vbyone_config->intr_en)
lcd_vx1_hold_reset();
vx1_timeout_reset_flag = 0;
struct vbyone_config_s *vx1_conf;
vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config;
- if (lcd_drv->lcd_status == 0)
+ if ((lcd_drv->lcd_status & LCD_STATUS_IF_ON) == 0)
return IRQ_HANDLED;
if (lcd_vcbus_read(VBO_STATUS_L) & 0x40) /* hpd detect */
return IRQ_HANDLED;
lcd_clk_set(pconf);
lcd_venc_set(pconf);
lcd_tcon_set(pconf);
- lcd_drv->lcd_test_pattern_restore();
+
+ lcd_vcbus_write(VENC_INTCTRL, 0x200);
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s finished\n", __func__);
+}
+
+void lcd_tv_driver_disable_post(void)
+{
+ lcd_vcbus_write(ENCL_VIDEO_EN, 0); /* disable encl */
+
+ lcd_clk_disable();
+ lcd_clk_gate_switch(0);
+#ifdef CONFIG_AMLOGIC_VPU
+ switch_vpu_mem_pd_vmod(VPU_VENCL, VPU_MEM_POWER_DOWN);
+ release_vpu_clk_vmod(VPU_VENCL);
+#endif
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s finished\n", __func__);
}
int lcd_tv_driver_init(void)
lcd_vbyone_phy_set(pconf, 1);
lcd_vx1_intr_request = 1;
queue_delayed_work(lcd_drv->workqueue,
- &lcd_drv->lcd_vx1_delayed_work,
- msecs_to_jiffies(LCD_VX1_WAIT_STABLE_DELAY));
+ &lcd_drv->lcd_vx1_delayed_work,
+ msecs_to_jiffies(LCD_VX1_WAIT_STABLE_DELAY));
break;
default:
break;
}
- lcd_vcbus_write(VENC_INTCTRL, 0x200);
-
if (lcd_debug_print_flag)
LCDPR("%s finished\n", __func__);
return 0;
break;
}
- lcd_vcbus_write(ENCL_VIDEO_EN, 0); /* disable encl */
-
- lcd_clk_disable();
- lcd_clk_gate_switch(0);
-#ifdef CONFIG_AMLOGIC_VPU
- switch_vpu_mem_pd_vmod(VPU_VENCL, VPU_MEM_POWER_DOWN);
- release_vpu_clk_vmod(VPU_VENCL);
-#endif
-
if (lcd_debug_print_flag)
LCDPR("%s finished\n", __func__);
}
request_vpu_clk_vmod(pconf->lcd_timing.lcd_clk, VPU_VENCL);
#endif
- if (lcd_drv->lcd_status == 0) {
- /* only change parameters when panel is off */
- switch (pconf->lcd_timing.clk_change) {
- case LCD_CLK_PLL_CHANGE:
- lcd_clk_generate_parameter(pconf);
- break;
- default:
- break;
+ if (lcd_drv->lcd_status & LCD_STATUS_ENCL_ON) {
+ if (pconf->lcd_basic.lcd_type == LCD_VBYONE) {
+ if (lcd_drv->lcd_status & LCD_STATUS_IF_ON)
+ lcd_vbyone_interrupt_enable(0);
}
- } else {
- if (pconf->lcd_basic.lcd_type == LCD_VBYONE)
- lcd_vbyone_interrupt_enable(0);
switch (pconf->lcd_timing.clk_change) {
case LCD_CLK_PLL_CHANGE:
}
lcd_venc_change(pconf);
- if (pconf->lcd_basic.lcd_type == LCD_VBYONE)
- lcd_vbyone_wait_stable();
+ if (pconf->lcd_basic.lcd_type == LCD_VBYONE) {
+ if (lcd_drv->lcd_status & LCD_STATUS_IF_ON)
+ lcd_vbyone_wait_stable();
+ }
+ } else {
+ /* only change parameters when panel is off */
+ switch (pconf->lcd_timing.clk_change) {
+ case LCD_CLK_PLL_CHANGE:
+ lcd_clk_generate_parameter(pconf);
+ break;
+ default:
+ break;
+ }
}
if (lcd_debug_print_flag)
return 0;
}
-void lcd_tv_driver_tiny_enable(void)
-{
- struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
- struct lcd_config_s *pconf;
- int ret;
-
- pconf = lcd_drv->lcd_config;
- ret = lcd_type_supported(pconf);
- if (ret)
- return;
-
- switch (pconf->lcd_basic.lcd_type) {
- case LCD_LVDS:
- lcd_lvds_control_set(pconf);
- lcd_lvds_phy_set(pconf, 1);
- break;
- case LCD_VBYONE:
- lcd_vbyone_pinmux_set(1);
- lcd_vbyone_control_set(pconf);
- lcd_vbyone_wait_hpd(pconf);
- lcd_vbyone_phy_set(pconf, 1);
- lcd_vbyone_power_on_wait_stable(pconf);
- break;
- default:
- break;
- }
-
- LCDPR("enable driver\n");
-}
-
-void lcd_tv_driver_tiny_disable(void)
-{
- struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
- struct lcd_config_s *pconf;
- int ret;
-
- LCDPR("disable driver\n");
- pconf = lcd_drv->lcd_config;
- ret = lcd_type_supported(pconf);
- if (ret)
- return;
-
- switch (pconf->lcd_basic.lcd_type) {
- case LCD_LVDS:
- lcd_lvds_phy_set(pconf, 0);
- lcd_lvds_disable();
- break;
- case LCD_VBYONE:
- lcd_vbyone_interrupt_enable(0);
- lcd_vbyone_phy_set(pconf, 0);
- lcd_vbyone_pinmux_set(0);
- lcd_vbyone_disable();
- break;
- default:
- break;
- }
-}
-
#define VBYONE_IRQF IRQF_SHARED /* IRQF_DISABLED */ /* IRQF_SHARED */
int lcd_vbyone_interrupt_up(void)
{
- int ret = 0;
unsigned int viu_vsync_irq = 0, venc_vx1_irq = 0;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_vx1_intr_request = 0;
lcd_encl_clk_err_cnt = 0;
- tasklet_init(&lcd_vx1_reset_tasklet, lcd_vx1_timeout_reset,
- 123);
+ tasklet_init(&lcd_vx1_reset_tasklet, lcd_vx1_timeout_reset, 123);
INIT_DELAYED_WORK(&lcd_drv->lcd_vx1_delayed_work,
lcd_vx1_wait_stable_delayed);
if (!lcd_drv->res_vsync_irq) {
- ret = -ENODEV;
- goto err;
- } else {
- viu_vsync_irq = lcd_drv->res_vsync_irq->start;
- LCDPR("viu_vsync_irq: %d\n", viu_vsync_irq);
-
- if (request_irq(viu_vsync_irq, lcd_vbyone_vsync_isr,
- IRQF_SHARED, "vbyone_vsync", (void *)"vbyone_vsync"))
- LCDERR("can't request viu_vsync_irq\n");
- else {
- if (lcd_debug_print_flag)
- LCDPR("request viu_vsync_irq successful\n");
- }
+ LCDERR("res_vsync_irq is null\n");
+ return -1;
+ }
+ viu_vsync_irq = lcd_drv->res_vsync_irq->start;
+ LCDPR("viu_vsync_irq: %d\n", viu_vsync_irq);
+
+ if (request_irq(viu_vsync_irq, lcd_vbyone_vsync_isr,
+ IRQF_SHARED, "vbyone_vsync", (void *)"vbyone_vsync"))
+ LCDERR("can't request viu_vsync_irq\n");
+ else {
+ if (lcd_debug_print_flag)
+ LCDPR("request viu_vsync_irq successful\n");
}
if (!lcd_drv->res_vx1_irq) {
- ret = -ENODEV;
- goto err;
- } else {
- venc_vx1_irq = lcd_drv->res_vx1_irq->start;
- LCDPR("venc_vx1_irq: %d\n", venc_vx1_irq);
-
- if (request_irq(venc_vx1_irq, lcd_vbyone_interrupt_handler, 0,
- "vbyone", (void *)"vbyone"))
- LCDERR("can't request venc_vx1_irq\n");
- else {
- if (lcd_debug_print_flag)
- LCDPR("request venc_vx1_irq successful\n");
- }
+ LCDERR("res_vx1_irq is null\n");
+ return -1;
+ }
+ venc_vx1_irq = lcd_drv->res_vx1_irq->start;
+ LCDPR("venc_vx1_irq: %d\n", venc_vx1_irq);
+
+ if (request_irq(venc_vx1_irq, lcd_vbyone_interrupt_handler, 0,
+ "vbyone", (void *)"vbyone"))
+ LCDERR("can't request venc_vx1_irq\n");
+ else {
+ if (lcd_debug_print_flag)
+ LCDPR("request venc_vx1_irq successful\n");
}
lcd_vx1_intr_request = 1;
LCDPR("add vbyone hpll timer handler\n");
return 0;
-
-err:
- return -ENODEV;
-
}
void lcd_vbyone_interrupt_down(void)
#ifdef CONFIG_PM
static int lcd_suspend(void)
{
- mutex_lock(&lcd_power_mutex);
+ struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
+
+ mutex_lock(&lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
lcd_resume_flag = 0;
LCDPR("%s finished\n", __func__);
- mutex_unlock(&lcd_power_mutex);
+ mutex_unlock(&lcd_drv->power_mutex);
return 0;
}
queue_work(lcd_drv->workqueue,
&(lcd_drv->lcd_resume_work));
} else {
+ mutex_lock(&lcd_drv->power_mutex);
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);
+ mutex_unlock(&lcd_drv->power_mutex);
}
} else {
+ mutex_lock(&lcd_drv->power_mutex);
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_drv->power_mutex);
}
return 0;
lcd_drv->version = LCD_DRV_VERSION;
lcd_drv->vout_server_init = lcd_tv_vout_server_init;
lcd_drv->driver_init_pre = lcd_tv_driver_init_pre;
+ lcd_drv->driver_disable_post = lcd_tv_driver_disable_post;
lcd_drv->driver_init = lcd_tv_driver_init;
lcd_drv->driver_disable = lcd_tv_driver_disable;
lcd_drv->driver_change = lcd_tv_driver_change;
- lcd_drv->driver_tiny_enable = lcd_tv_driver_tiny_enable;
- lcd_drv->driver_tiny_disable = lcd_tv_driver_tiny_disable;
lcd_get_config(lcd_drv->lcd_config, dev);
extern void lcd_tv_config_update(struct lcd_config_s *pconf);
extern void lcd_tv_driver_init_pre(void);
+extern void lcd_tv_driver_disable_post(void);
extern int lcd_tv_driver_init(void);
extern void lcd_tv_driver_disable(void);
extern int lcd_tv_driver_change(void);
-extern void lcd_tv_driver_tiny_enable(void);
-extern void lcd_tv_driver_tiny_disable(void);
extern void lcd_vbyone_wait_stable(void);
extern int lcd_vbyone_interrupt_up(void);
unsigned char lcd_resume_flag;
static struct aml_lcd_drv_s *lcd_driver;
-struct mutex lcd_power_mutex;
struct mutex lcd_vout_mutex;
int lcd_vout_serve_bypass;
}
/* ********************************************************* */
-static void lcd_power_tiny_ctrl(int status)
-{
- struct lcd_power_ctrl_s *lcd_power = lcd_driver->lcd_config->lcd_power;
- struct lcd_power_step_s *power_step;
-#ifdef CONFIG_AMLOGIC_LCD_EXTERN
- struct aml_lcd_extern_driver_s *ext_drv;
-#endif
- int i, index;
-
- LCDPR("%s: %d\n", __func__, status);
- i = 0;
- while (i < LCD_PWR_STEP_MAX) {
- if (status)
- power_step = &lcd_power->power_on_step[i];
- else
- power_step = &lcd_power->power_off_step[i];
-
- if (power_step->type >= LCD_POWER_TYPE_MAX)
- break;
- if (lcd_debug_print_flag) {
- LCDPR("power_tiny_ctrl: %d, step %d\n", status, i);
- LCDPR("type=%d, index=%d, value=%d, delay=%d\n",
- power_step->type, power_step->index,
- power_step->value, power_step->delay);
- }
- switch (power_step->type) {
- case LCD_POWER_TYPE_CPU:
- index = power_step->index;
- lcd_cpu_gpio_set(index, power_step->value);
- break;
- case LCD_POWER_TYPE_PMU:
- LCDPR("to do\n");
- break;
- case LCD_POWER_TYPE_SIGNAL:
- if (status)
- lcd_driver->driver_tiny_enable();
- else
- lcd_driver->driver_tiny_disable();
- break;
-#ifdef CONFIG_AMLOGIC_LCD_EXTERN
- case LCD_POWER_TYPE_EXTERN:
- index = power_step->index;
- ext_drv = aml_lcd_extern_get_driver(index);
- if (ext_drv) {
- if (status) {
- if (ext_drv->power_on)
- ext_drv->power_on();
- else
- LCDERR("no ext power on\n");
- } else {
- if (ext_drv->power_off)
- ext_drv->power_off();
- else
- LCDERR("no ext power off\n");
- }
- }
- break;
-#endif
- default:
- break;
- }
- if (power_step->delay)
- mdelay(power_step->delay);
- i++;
- }
-
- if (lcd_debug_print_flag)
- LCDPR("%s: %d finished\n", __func__, status);
-}
-
static void lcd_power_ctrl(int status)
{
struct lcd_power_ctrl_s *lcd_power = lcd_driver->lcd_config->lcd_power;
LCDPR("%s: %d finished\n", __func__, status);
}
-static void lcd_module_enable(void)
+static void lcd_power_encl_on(void)
{
mutex_lock(&lcd_vout_mutex);
lcd_driver->driver_init_pre();
+ lcd_driver->lcd_status |= LCD_STATUS_ENCL_ON;
+
+ mutex_unlock(&lcd_vout_mutex);
+}
+
+static void lcd_power_encl_off(void)
+{
+ mutex_lock(&lcd_vout_mutex);
+
+ lcd_driver->lcd_status &= ~LCD_STATUS_ENCL_ON;
+ lcd_driver->driver_disable_post();
+
+ mutex_unlock(&lcd_vout_mutex);
+}
+
+static void lcd_power_if_on(void)
+{
+ mutex_lock(&lcd_vout_mutex);
+
lcd_driver->power_ctrl(1);
- lcd_driver->lcd_status = 1;
+ lcd_driver->lcd_status |= LCD_STATUS_IF_ON;
lcd_driver->lcd_config->change_flag = 0;
mutex_unlock(&lcd_vout_mutex);
}
-static void lcd_module_disable(void)
+static void lcd_power_if_off(void)
{
mutex_lock(&lcd_vout_mutex);
- lcd_driver->lcd_status = 0;
+ lcd_driver->lcd_status &= ~LCD_STATUS_IF_ON;
lcd_driver->power_ctrl(0);
mutex_unlock(&lcd_vout_mutex);
}
-static void lcd_module_reset(void)
+static void lcd_power_screen_black(void)
{
mutex_lock(&lcd_vout_mutex);
- lcd_driver->lcd_status = 0;
- lcd_driver->power_ctrl(0);
+ lcd_driver->lcd_screen_black();
- msleep(500);
+ mutex_unlock(&lcd_vout_mutex);
+}
- lcd_driver->driver_init_pre();
- lcd_driver->power_ctrl(1);
- lcd_driver->lcd_status = 1;
- lcd_driver->lcd_config->change_flag = 0;
+static void lcd_power_screen_restore(void)
+{
+ mutex_lock(&lcd_vout_mutex);
+
+ lcd_driver->lcd_screen_restore();
mutex_unlock(&lcd_vout_mutex);
}
-static void lcd_module_tiny_reset(void)
+static void lcd_module_reset(void)
{
mutex_lock(&lcd_vout_mutex);
- lcd_driver->lcd_status = 0;
- lcd_power_tiny_ctrl(0);
- mdelay(500);
- lcd_power_tiny_ctrl(1);
- lcd_driver->lcd_status = 1;
+ lcd_driver->lcd_status &= ~LCD_STATUS_ON;
+ lcd_driver->power_ctrl(0);
+
+ msleep(500);
+
+ lcd_driver->driver_init_pre();
+ lcd_driver->power_ctrl(1);
+ lcd_driver->lcd_status |= LCD_STATUS_ON;
lcd_driver->lcd_config->change_flag = 0;
mutex_unlock(&lcd_vout_mutex);
static void lcd_resume_work(struct work_struct *p_work)
{
- mutex_lock(&lcd_power_mutex);
+ mutex_lock(&lcd_driver->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL);
LCDPR("%s finished\n", __func__);
- mutex_unlock(&lcd_power_mutex);
+ mutex_unlock(&lcd_driver->power_mutex);
}
/* ****************************************
* lcd notify
* ****************************************
*/
-static int lcd_power_notifier(struct notifier_block *nb,
+static int lcd_power_encl_on_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
- 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) {
- if (lcd_debug_print_flag)
- LCDPR("%s: 0x%lx\n", __func__, event);
- lcd_module_disable();
- } else {
+ if ((event & LCD_EVENT_ENCL_ON) == 0)
return NOTIFY_DONE;
- }
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s: 0x%lx\n", __func__, event);
+ lcd_power_encl_on();
return NOTIFY_OK;
}
-static struct notifier_block lcd_power_nb = {
- .notifier_call = lcd_power_notifier,
- .priority = LCD_PRIORITY_POWER_LCD,
+static struct notifier_block lcd_power_encl_on_nb = {
+ .notifier_call = lcd_power_encl_on_notifier,
+ .priority = LCD_PRIORITY_POWER_ENCL_ON,
};
-static int lcd_interface_notifier(struct notifier_block *nb,
+static int lcd_power_encl_off_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
- 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) {
- if (lcd_debug_print_flag)
- LCDPR("%s: 0x%lx\n", __func__, event);
- lcd_driver->power_tiny_ctrl(0);
- } else {
+ if ((event & LCD_EVENT_ENCL_OFF) == 0)
+ return NOTIFY_DONE;
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s: 0x%lx\n", __func__, event);
+ lcd_power_encl_off();
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block lcd_power_encl_off_nb = {
+ .notifier_call = lcd_power_encl_off_notifier,
+ .priority = LCD_PRIORITY_POWER_ENCL_OFF,
+};
+
+static int lcd_power_if_on_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if ((event & LCD_EVENT_IF_ON) == 0)
return NOTIFY_DONE;
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s: 0x%lx\n", __func__, event);
+
+ if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) {
+ lcd_power_if_on();
+ } else {
+ LCDERR("%s: can't power on when controller is off\n",
+ __func__);
+ return NOTIFY_DONE;
}
return NOTIFY_OK;
}
-static struct notifier_block lcd_interface_nb = {
- .notifier_call = lcd_interface_notifier,
- .priority = LCD_PRIORITY_POWER_LCD,
+static struct notifier_block lcd_power_if_on_nb = {
+ .notifier_call = lcd_power_if_on_notifier,
+ .priority = LCD_PRIORITY_POWER_IF_ON,
+};
+
+static int lcd_power_if_off_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if ((event & LCD_EVENT_IF_OFF) == 0)
+ return NOTIFY_DONE;
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s: 0x%lx\n", __func__, event);
+ lcd_power_if_off();
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block lcd_power_if_off_nb = {
+ .notifier_call = lcd_power_if_off_notifier,
+ .priority = LCD_PRIORITY_POWER_IF_OFF,
+};
+
+static int lcd_power_screen_black_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if ((event & LCD_EVENT_SCREEN_BLACK) == 0)
+ return NOTIFY_DONE;
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s: 0x%lx\n", __func__, event);
+ lcd_power_screen_black();
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block lcd_power_screen_black_nb = {
+ .notifier_call = lcd_power_screen_black_notifier,
+ .priority = LCD_PRIORITY_SCREEN_BLACK,
+};
+
+static int lcd_power_screen_restore_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if ((event & LCD_EVENT_SCREEN_RESTORE) == 0)
+ return NOTIFY_DONE;
+
+ if (lcd_debug_print_flag)
+ LCDPR("%s: 0x%lx\n", __func__, event);
+ lcd_power_screen_restore();
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block lcd_power_screen_restore_nb = {
+ .notifier_call = lcd_power_screen_restore_notifier,
+ .priority = LCD_PRIORITY_SCREEN_RESTORE,
};
static int lcd_bl_select_notifier(struct notifier_block *nb,
static struct notifier_block lcd_bl_select_nb = {
.notifier_call = lcd_bl_select_notifier,
};
+
+static int lcd_notifier_register(void)
+{
+ int ret = 0;
+
+ ret = aml_lcd_notifier_register(&lcd_bl_select_nb);
+ if (ret)
+ LCDERR("register aml_bl_select_notifier failed\n");
+
+ ret = aml_lcd_notifier_register(&lcd_power_encl_on_nb);
+ if (ret)
+ LCDERR("register lcd_power_encl_on_nb failed\n");
+ ret = aml_lcd_notifier_register(&lcd_power_encl_off_nb);
+ if (ret)
+ LCDERR("register lcd_power_encl_off_nb failed\n");
+ ret = aml_lcd_notifier_register(&lcd_power_if_on_nb);
+ if (ret)
+ LCDERR("register lcd_power_if_on_nb failed\n");
+ ret = aml_lcd_notifier_register(&lcd_power_if_off_nb);
+ if (ret)
+ LCDERR("register lcd_power_if_off_nb failed\n");
+ ret = aml_lcd_notifier_register(&lcd_power_screen_black_nb);
+ if (ret)
+ LCDERR("register lcd_power_screen_black_nb failed\n");
+ ret = aml_lcd_notifier_register(&lcd_power_screen_restore_nb);
+ if (ret)
+ LCDERR("register lcd_power_screen_restore_nb failed\n");
+
+ return 0;
+}
+
+static void lcd_notifier_unregister(void)
+{
+ aml_lcd_notifier_unregister(&lcd_power_screen_restore_nb);
+ aml_lcd_notifier_unregister(&lcd_power_screen_black_nb);
+ aml_lcd_notifier_unregister(&lcd_power_if_off_nb);
+ aml_lcd_notifier_unregister(&lcd_power_if_on_nb);
+ aml_lcd_notifier_unregister(&lcd_power_encl_off_nb);
+ aml_lcd_notifier_unregister(&lcd_power_encl_on_nb);
+
+ aml_lcd_notifier_unregister(&lcd_bl_select_nb);
+}
/* **************************************** */
/* ************************************************************* */
static int lcd_mode_probe(struct device *dev)
{
- int ret;
-
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
lcd_class_creat();
lcd_fops_create();
- ret = aml_lcd_notifier_register(&lcd_interface_nb);
- if (ret)
- LCDERR("register aml_bl_select_notifier failed\n");
- ret = aml_lcd_notifier_register(&lcd_bl_select_nb);
- if (ret)
- LCDERR("register aml_bl_select_notifier failed\n");
- ret = aml_lcd_notifier_register(&lcd_power_nb);
- if (ret)
- LCDPR("register lcd_power_notifier failed\n");
+ lcd_notifier_register();
/* add notifier for video sync_duration info refresh */
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
static int lcd_mode_remove(struct device *dev)
{
+ lcd_notifier_unregister();
+
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
pconf->lcd_basic.v_active = lcd_vcbus_read(ENCL_VIDEO_VAVON_ELINE)
- lcd_vcbus_read(ENCL_VIDEO_VAVON_BLINE) + 1;
if (lcd_vcbus_read(ENCL_VIDEO_EN)) {
- lcd_driver->lcd_status = 1;
+ lcd_driver->lcd_status = LCD_STATUS_ON;
lcd_resume_flag = 1;
} else {
lcd_driver->lcd_status = 0;
lcd_driver->lcd_resume_type = 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;
- lcd_driver->module_tiny_reset = lcd_module_tiny_reset;
lcd_driver->res_vsync_irq = platform_get_resource(pdev,
IORESOURCE_IRQ, 0);
lcd_driver->res_vx1_irq = platform_get_resource(pdev,
lcd_driver->data->chip_name);
mutex_init(&lcd_vout_mutex);
- mutex_init(&lcd_power_mutex);
+ mutex_init(&lcd_driver->power_mutex);
lcd_vout_serve_bypass = 0;
/* init workqueue */
destroy_workqueue(lcd_driver->workqueue);
if (lcd_driver) {
- aml_lcd_notifier_unregister(&lcd_power_nb);
- aml_lcd_notifier_unregister(&lcd_bl_select_nb);
- aml_lcd_notifier_unregister(&lcd_interface_nb);
-
lcd_fops_remove();
lcd_class_remove();
lcd_clk_config_remove();
queue_work(lcd_driver->workqueue,
&(lcd_driver->lcd_resume_work));
} else {
+ mutex_lock(&lcd_driver->power_mutex);
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);
+ mutex_unlock(&lcd_driver->power_mutex);
}
} else {
+ mutex_lock(&lcd_driver->power_mutex);
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);
+ mutex_unlock(&lcd_driver->power_mutex);
}
return 0;
static int lcd_suspend(struct platform_device *pdev, pm_message_t state)
{
- mutex_lock(&lcd_power_mutex);
+ mutex_lock(&lcd_driver->power_mutex);
if (lcd_driver->lcd_status) {
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
lcd_resume_flag = 0;
LCDPR("%s finished\n", __func__);
}
- mutex_unlock(&lcd_power_mutex);
+ mutex_unlock(&lcd_driver->power_mutex);
return 0;
}
#include <linux/notifier.h>
-#define LCD_PRIORITY_INIT_CONFIG 4
-#define LCD_PRIORITY_INIT_VOUT 3
-
-#define LCD_PRIORITY_BLACK_SCREEN 3
-#define LCD_PRIORITY_POWER_BL_OFF 2
-#define LCD_PRIORITY_POWER_LCD 1
-#define LCD_PRIORITY_POWER_BL_ON 0
-
-#define LCD_EVENT_BL_ON (1 << 0)
-#define LCD_EVENT_LCD_ON (1 << 1)
-#define LCD_EVENT_IF_ON (1 << 2)
-#define LCD_EVENT_POWER_ON (LCD_EVENT_BL_ON | LCD_EVENT_LCD_ON)
-#define LCD_EVENT_IF_POWER_ON (LCD_EVENT_BL_ON | LCD_EVENT_IF_ON)
-#define LCD_EVENT_BLACK_SCREEN (1 << 3)
-#define LCD_EVENT_BL_OFF (1 << 4)
-#define LCD_EVENT_LCD_OFF (1 << 5)
-#define LCD_EVENT_IF_OFF (1 << 6)
-#define LCD_EVENT_POWER_OFF (LCD_EVENT_BL_OFF | LCD_EVENT_LCD_OFF |\
- LCD_EVENT_BLACK_SCREEN)
-#define LCD_EVENT_IF_POWER_OFF (LCD_EVENT_BL_OFF | LCD_EVENT_IF_OFF |\
- LCD_EVENT_BLACK_SCREEN)
+#define LCD_PRIORITY_INIT_CONFIG 12
+#define LCD_PRIORITY_INIT_VOUT 11
+
+#define LCD_PRIORITY_SCREEN_BLACK 7
+#define LCD_PRIORITY_POWER_BL_OFF 6
+#define LCD_PRIORITY_POWER_IF_OFF 5
+#define LCD_PRIORITY_POWER_ENCL_OFF 4
+#define LCD_PRIORITY_POWER_ENCL_ON 3
+#define LCD_PRIORITY_POWER_IF_ON 2
+#define LCD_PRIORITY_POWER_BL_ON 1
+#define LCD_PRIORITY_SCREEN_RESTORE 0
+
+/* orignal event */
+#define LCD_EVENT_SCREEN_BLACK (1 << 0)
+#define LCD_EVENT_BL_OFF (1 << 1)
+#define LCD_EVENT_IF_OFF (1 << 2)
+#define LCD_EVENT_ENCL_OFF (1 << 3)
+#define LCD_EVENT_ENCL_ON (1 << 4)
+#define LCD_EVENT_IF_ON (1 << 5)
+#define LCD_EVENT_BL_ON (1 << 6)
+#define LCD_EVENT_SCREEN_RESTORE (1 << 7)
+
+/* combined event */
+#define LCD_EVENT_POWER_ON (LCD_EVENT_BL_ON | LCD_EVENT_IF_ON | \
+ LCD_EVENT_ENCL_ON | LCD_EVENT_SCREEN_RESTORE)
+#define LCD_EVENT_IF_POWER_ON (LCD_EVENT_IF_ON | LCD_EVENT_BL_ON | \
+ LCD_EVENT_SCREEN_RESTORE)
+#define LCD_EVENT_POWER_OFF (LCD_EVENT_SCREEN_BLACK | \
+ LCD_EVENT_BL_OFF | LCD_EVENT_IF_OFF | \
+ LCD_EVENT_ENCL_OFF)
+#define LCD_EVENT_IF_POWER_OFF (LCD_EVENT_SCREEN_BLACK | \
+ LCD_EVENT_BL_OFF | LCD_EVENT_IF_OFF)
+
+#define LCD_EVENT_PREPARE (LCD_EVENT_ENCL_ON)
+#define LCD_EVENT_ENABLE (LCD_EVENT_IF_ON | LCD_EVENT_BL_ON | \
+ LCD_EVENT_SCREEN_RESTORE)
+#define LCD_EVENT_DISABLE (LCD_EVENT_SCREEN_BLACK | \
+ LCD_EVENT_BL_OFF | LCD_EVENT_IF_OFF)
+#define LCD_EVENT_UNPREPARE (LCD_EVENT_ENCL_OFF)
/* lcd backlight index select */
#define LCD_EVENT_BACKLIGHT_SEL (1 << 8)
unsigned int duration_den;
};
+#define LCD_STATUS_IF_ON (1 << 0)
+#define LCD_STATUS_ENCL_ON (1 << 1)
+#define LCD_STATUS_ON (LCD_STATUS_IF_ON | LCD_STATUS_ENCL_ON)
+
struct aml_lcd_drv_s {
char *version;
struct lcd_data_s *data;
void (*vout_server_init)(void);
void (*driver_init_pre)(void);
+ void (*driver_disable_post)(void);
int (*driver_init)(void);
void (*driver_disable)(void);
int (*driver_change)(void);
void (*module_reset)(void);
- void (*power_tiny_ctrl)(int status);
- void (*driver_tiny_enable)(void);
- void (*driver_tiny_disable)(void);
void (*module_tiny_reset)(void);
- void (*lcd_test_pattern_restore)(void);
+ void (*lcd_screen_black)(void);
+ void (*lcd_screen_restore)(void);
void (*power_ctrl)(int status);
struct workqueue_struct *workqueue;
struct work_struct lcd_resume_work;
struct resource *res_vsync_irq;
struct resource *res_vx1_irq;
+
+ struct mutex power_mutex;
};
extern struct aml_lcd_drv_s *aml_lcd_get_driver(void);