问题一
在驱动中有个接口:
/* sel: 0:lcd0; 1:lcd1 */
static s32 LCD_set_bright(u32 sel, u32 bright)
{
sunxi_lcd_dsi_dcs_write_1para(sel,0x51,bright);
return 0;
}
操作这个接口调整亮度的话,显示是无法正常的。是否驱动在操作这个接口过程中需要等待屏幕数据发帧结束? 感觉是要等的,但是目前还没详细看代码流程。
解答:
发送命令要处于LP模式,在送帧(HP模式)的时候去切换模式肯定会导致黑屏的,需要在中断的消隐区间去设置背光,可以翻一下lcd调试说明文档,里面有esd这个章节,显示驱动中也有esd相关代码,做esd就是在中断的消隐区间去读mipi的寄存器,判断屏的状态。可以读那么就可以写了。
问题二
模仿esd程序进行中断中修改亮度操作,可以写入亮度成功,也可以读到东西,但是中断就无法重新进入了。是否有什么注意到的地方。
static s32 lcd_set_oled_bright(u32 sel,u32 bright)
{
s32 ret = 0;
u8 result[16] = {0};
s32 nump = 1;
ret = sunxi_lcd_dsi_dcs_read(0, 0x54, result,&nump);
dsi_dcs_wr_1para(sel, 0xFE, 0x00); //{ 0xFE,1,{0x00} },
dsi_dcs_wr_1para(sel, 0x51, 0x50);
printk(KERN_WARNING "wwwwwwwwwwww lcd_set_oled_bright :bright = %d read result :%02x \n",bright,result[0]);
return 0;
}
/*此处省略*/
struct __lcd_panel rm69330_139_panel = {
/* panel driver name, must mach the name of
* lcd_drv_name in sys_config.fex
*/
.name = "rm69330_139",
.func = {
.cfg_panel_info = lcd_cfg_panel_info,
.cfg_open_flow = lcd_open_flow,
.cfg_close_flow = lcd_close_flow,
.lcd_user_defined_func = lcd_user_defined_func,
.set_bright = LCD_set_bright,
.esd_check = lcd_esd_check,
.reset_panel = lcd_reset_panel,
.set_esd_info = lcd_set_esd_info,
.oled_set_bright = lcd_set_oled_bright,
},
};
#if defined(__LINUX_PLAT__)
static irqreturn_t disp_lcd_event_proc(int irq, void *parg)
#else
static irqreturn_t disp_lcd_event_proc(void *parg)
#endif
{
struct disp_device *lcd = (struct disp_device *)parg;
struct disp_lcd_private_data *lcdp = NULL;
struct disp_manager *mgr = NULL;
#if defined(SUPPORT_EINK) && defined(CONFIG_EINK_PANEL_USED)
struct disp_eink_manager *eink_manager = NULL;
#endif
u32 hwdev_index;
u32 irq_flag = 0;
unsigned int panel_extend_dirty;
unsigned int panel_extend_modify_oledbright;
unsigned long flags;
if (lcd == NULL)
return DISP_IRQ_RETURN;
hwdev_index = lcd->hwdev_index;
lcdp = disp_lcd_get_priv(lcd);
if (lcdp == NULL)
return DISP_IRQ_RETURN;
#if defined(SUPPORT_EINK) && defined(CONFIG_EINK_PANEL_USED)
eink_manager = disp_get_eink_manager(0);
if (eink_manager == NULL)
return DISP_IRQ_RETURN;
#endif
if (disp_al_lcd_query_irq
(hwdev_index, LCD_IRQ_TCON0_VBLK, &lcdp->panel_info)) {
#if defined(SUPPORT_EINK) && defined(CONFIG_EINK_PANEL_USED)
eink_display_one_frame(eink_manager);
#else
int cur_line =
disp_al_lcd_get_cur_line(hwdev_index, &lcdp->panel_info);
int start_delay =
disp_al_lcd_get_start_delay(hwdev_index, &lcdp->panel_info);
#if defined(CONFIG_DISP2_LCD_ESD_DETECT)
if (lcdp->lcd_panel_fun.esd_check &&
lcdp->lcd_panel_fun.reset_panel) {
++lcdp->esd_inf.cnt;
if (cur_line < 2 &&
!atomic_read(&lcdp->lcd_resetting) &&
lcdp->esd_inf.cnt >= lcdp->esd_inf.freq) {
disp_al_lcd_disable_irq(hwdev_index, LCD_IRQ_TCON0_VBLK,
&lcdp->panel_info);
if (!lcdp->esd_inf.esd_check_func_pos ||
lcdp->lcd_panel_fun.esd_check(lcd->disp)) {
/*request reset*/
atomic_set(&lcdp->lcd_resetting, 1);
schedule_work(&lcdp->reflush_work);
printk(KERN_WARNING "wwwwwwwwwwww lcd_esd_check disp_lcd_event_proc 1633 \n");
}
disp_al_lcd_enable_irq(hwdev_index, LCD_IRQ_TCON0_VBLK,
&lcdp->panel_info);
printk(KERN_WARNING "wwwwwwwwwwww after lcd_esd_check disp_lcd_event_proc 1635 \n");
lcdp->esd_inf.cnt = 0;
}
}
#endif
mgr = lcd->manager;
if (mgr == NULL)
{
printk(KERN_WARNING "wwwwwwwwwwww after if (mgr == NULL) 1644 \n");
return DISP_IRQ_RETURN;
}
if (cur_line <= (start_delay - lcdp->judge_line))
sync_event_proc(mgr->disp, false);
else
sync_event_proc(mgr->disp, true);
#endif
} else {
irq_flag = disp_al_lcd_query_irq(hwdev_index, LCD_IRQ_TCON0_CNTR,
&lcdp->panel_info);
irq_flag |=
disp_al_lcd_query_irq(hwdev_index, LCD_IRQ_TCON0_TRIF,
&lcdp->panel_info);
if (irq_flag == 0)
goto exit;
if (disp_al_lcd_tri_busy(hwdev_index, &lcdp->panel_info)) {
/* if lcd is still busy when tri/cnt irq coming,
* take it as failture, record failture times,
* when it reach 2 times, clear counter
*/
lcdp->tri_finish_fail++;
lcdp->tri_finish_fail = (lcdp->tri_finish_fail == 2) ?
0 : lcdp->tri_finish_fail;
} else
lcdp->tri_finish_fail = 0;
mgr = lcd->manager;
if (mgr == NULL)
return DISP_IRQ_RETURN;
#if defined(CONFIG_DISP2_LCD_ESD_DETECT)
if (lcdp->lcd_panel_fun.esd_check &&
lcdp->lcd_panel_fun.reset_panel) {
++lcdp->esd_inf.cnt;
if (!atomic_read(&lcdp->lcd_resetting) &&
lcdp->esd_inf.cnt >= lcdp->esd_inf.freq) {
if (!lcdp->esd_inf.esd_check_func_pos ||
lcdp->lcd_panel_fun.esd_check(lcd->disp)) {
/*request reset*/
atomic_set(&lcdp->lcd_resetting, 1);
schedule_work(&lcdp->reflush_work);
printk(KERN_WARNING "wwwwwwwwwwww lcd_esd_check disp_lcd_event_proc 1685 \n");
}
printk(KERN_WARNING "wwwwwwwwwwww after lcd_esd_check disp_lcd_event_proc 1688 \n");
lcdp->esd_inf.cnt = 0;
}
}
#endif
if (lcdp->tri_finish_fail == 0) {
sync_event_proc(mgr->disp, false);
disp_al_lcd_tri_start(hwdev_index, &lcdp->panel_info);
} else
sync_event_proc(mgr->disp, true);
}
spin_lock_irqsave(&lcd_data_lock, flags);
panel_extend_dirty = lcdp->panel_extend_dirty;
lcdp->panel_extend_dirty = 0;
/*这里是我添加的调整oled亮度的地方, bright的值通过ioctl修改,并 lcdp->panel_extend_modify_oledbright; 置位,让中断来处理这个亮度*/
panel_extend_modify_oledbright = lcdp->panel_extend_modify_oledbright;
lcdp->panel_extend_modify_oledbright = 0;
spin_unlock_irqrestore(&lcd_data_lock, flags);
if (panel_extend_dirty == 1)
disp_al_lcd_cfg_ext(lcd->disp, &lcdp->panel_extend_info_set);
if(panel_extend_modify_oledbright == 1)
{
if(lcdp->lcd_panel_fun.oled_set_bright)
{
u32 getbl = disp_lcd_get_bright(lcd);
lcdp->lcd_panel_fun.oled_set_bright(lcd->disp,getbl);
}
}
exit:
printk(KERN_WARNING "wwwwwwwwwwww before DISP_IRQ_RETURN 1709 \n");
/*尝试加入的打印信息, 一旦执行了亮度调整,这个中断服务不再重新进入了,但是亮度调节是成功的*/
return DISP_IRQ_RETURN;
}
解答:
在代码块2里做如下修改
#if 1
if(panel_extend_modify_oledbright == 1)
{
if(lcdp->lcd_panel_fun.oled_set_bright)
{
u32 getbl = disp_lcd_get_bright(lcd);
lcdp->lcd_panel_fun.oled_set_bright(lcd->disp,getbl);
/*加入下面这部分逻辑,让他重新触发中断即可*/
if (lcdp->tri_finish_fail == 0) {
sync_event_proc(mgr->disp, false);
disp_al_lcd_tri_start(hwdev_index, &lcdp->panel_info);
} else
sync_event_proc(mgr->disp, true);
}
}
|