打印
[RISC-V MCU 应用开发]

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

[复制链接]
1190|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
神棍地海棠|  楼主 | 2022-11-9 11:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

问题一

在驱动中有个接口:


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

        }


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

260

主题

268

帖子

0

粉丝