Navigation

    全志在线开发者论坛

    • Register
    • Login
    • Search
    • Categories
    • Tags
    • 在线文档
    • 社区主页

    OLED的MIPI屏幕实时亮度改变问题

    MR Series
    3
    11
    4597
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      TEVET LV 7 last edited by

      如题,在驱动中有个接口:
      /* 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;
      }

      操作这个接口调整亮度的话,显示是无法正常的。
      是否驱动在操作这个接口过程中需要等待屏幕数据发帧结束?
      感觉是要等的,但是目前还没详细看代码流程。
      先来问一波!

      期待大佬解惑!

      A 1 Reply Last reply Reply Quote Share 0
      • A
        anruliu LV 6 @TEVET last edited by

        @tevet 发送命令要处于LP模式,在送帧(HP模式)的时候去切换模式肯定会导致黑屏的,需要在中断的消隐区间去设置背光

        T 1 Reply Last reply Reply Quote Share 0
        • T
          TEVET LV 7 @anruliu last edited by

          @anruliu
          感谢大佬,请教下, 中断的这个状态如何同步到呢?

          A 1 Reply Last reply Reply Quote Share 0
          • A
            anruliu LV 6 @TEVET last edited by

            @tevet 可以翻一下lcd调试说明文档,里面有esd这个章节,显示驱动中也有esd相关代码,做esd就是在中断的消隐区间去读mipi的寄存器,判断屏的状态。可以读那么就可以写了

            T 2 Replies Last reply Reply Quote Share 0
            • T
              TEVET LV 7 @anruliu last edited by

              @anruliu
              请教下大佬, 模仿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;
              }
              
              1 Reply Last reply Reply Quote Share 1
              • T
                TEVET LV 7 @anruliu last edited by

                @anruliu

                已经搞定了,感谢大佬的指导,非常给力。

                #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);			
                		}
                
                	}
                
                A 1 Reply Last reply Reply Quote Share 0
                • A
                  anruliu LV 6 @TEVET last edited by

                  @tevet
                  中断中不要加入太多打印,读取和写寄存器前后要调用dsi_read_mode_en

                  static s32 lcd_set_oled_bright(u32 sel,u32 bright)
                  {
                  	s32 ret = 0;
                  	u8 result[16] = {0};
                  	s32 nump = 1;
                  
                          dsi_read_mode_en(0, 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);
                  
                           dsi_read_mode_en(0, 0);
                  	return 0;	
                  }
                  

                  中断处理函数中,调用背光设置的代码要放在前面,满足cur_line < 2,并且尽量减少这里面的代码调用

                  if (cur_line < 2 && panel_extend_modify_oledbright == 1 && lcdp->lcd_panel_fun.set_oled_bright) {
                           lcdp->lcd_panel_fun.oled_set_bright(lcd->disp, fix_bright);
                  }
                  

                  这样修改后应该就不用再重新触发中断

                  T A 3 Replies Last reply Reply Quote Share 0
                  • T
                    TEVET LV 7 @anruliu last edited by

                    @anruliu
                    感谢,感觉还是我的操作骚了,马上搞起来试试看。

                    谢谢大佬提示!

                    1 Reply Last reply Reply Quote Share 0
                    • T
                      TEVET LV 7 @anruliu last edited by

                      @anruliu
                      按照大佬的方式修改,是不行的喔。

                      static s32 lcd_set_oled_bright(u32 sel,u32 bright)
                      {
                      	s32 ret = 0;
                      	u8 result[16] = {0};
                      	s32 nump = 1;
                      
                      	#if 1
                      	 dsi_read_mode_en(0, 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, bright);
                      	 dsi_read_mode_en(0, 0);
                      #endif 
                      
                      	return 0;	
                      }
                      
                      
                      #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
                      #if 1
                      	if ((cur_line < 2) && (lcdp->panel_extend_modify_oledbright) && (lcdp->lcd_panel_fun.oled_set_bright))
                      	{
                      		spin_lock_irqsave(&lcd_data_lock, flags);
                      		panel_extend_modify_oledbright = lcdp->panel_extend_modify_oledbright;
                      		lcdp->panel_extend_modify_oledbright = 0;
                      		spin_unlock_irqrestore(&lcd_data_lock, flags);
                      
                      		#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);			
                      			}
                      
                      		}
                      	}
                      #endif
                      	#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
                      
                      
                      
                      	}
                      

                      我前面的操作是正常的,咋测都OK 。按照你这个改一下就黑屏了。
                      我那样改有啥隐患没,毕竟不是一直改亮度。

                      1 Reply Last reply Reply Quote Share 0
                      • A
                        a1070758302 LV 1 @anruliu last edited by

                        @anruliu 请教一下,是不是直接放到esd的detect也可以,我的是818平台,结果放detect里不行,加dsi_read_mode_en也不行

                        T 1 Reply Last reply Reply Quote Share 0
                        • Referenced by  P planevina 
                        • T
                          TEVET LV 7 @a1070758302 last edited by

                          @a1070758302 可以参考ESD的读寄存器过程,修改一下。

                          1 Reply Last reply Reply Quote Share 0
                          • Referenced by  P planevina 
                          • 1 / 1
                          • First post
                            Last post

                          Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

                          行为准则 | 用户协议 | 隐私权政策