您尚未登录。

楼主 # 2022-11-18 15:38:07

LIVPO
会员
注册时间: 2022-10-09
已发帖子: 5
积分: 105

全志D1-H开发板接OLED的MIPI屏幕实时亮度改变问题

问题一
在驱动中有个接口:

/* 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);			
		}

	}

离线

#1 2022-11-18 16:54:31

stackoverF
会员
注册时间: 2020-04-20
已发帖子: 20
积分: 20

Re: 全志D1-H开发板接OLED的MIPI屏幕实时亮度改变问题

正常来说,mipi屏幕支持LP和HS的自动轮转切换的,在HS刷屏过后,由主机确定是否进入LP模式。而协议侧,dcs命令由屏幕厂商支持决定,有些屏幕的dcs-command是可以走在HS上面的

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn