This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LCD flickering issue after 2 hours

Other Parts Discussed in Thread: DA8XX

Dear All,

        in our design, We have used  LCDC to control a 24 bpp TFT display(LMS700kF07). We are facing LCD flickering issue in 1 device out of 20 devices after a long run(1 to 2 Hours). When this issue occurs it is showing following error.

<3>[  741.282379] LCDC sync lost or underflow error occured

            I am not able to get why we are facing this issue in 1 device. Is it a hardware issue?. The schematics of Boot configuration & LCD interface is as follows.

                             Fig: Boot Configuration

                                    Fig : LCD Interface

Please reply me as soon as possible. Please suggest me  what could be the issue is?

Thanks and Regards,

Bhairu

  • Hi Bhairu,

    1 out of 20 devices - this definitely sounds like a hardware problem on the board in question (not design problem). I would suggest that you check all power supplies for excessive noise, main oscillator, solder joints on the PCB.

  • You will get this error message if the LCD DMA controller has an underrun condition.

    The DMA hardware does not recover from this condition without help. This item is covered in the chip errata.

    This is in drivers/video/da8xx-fb.c

    Some patches I have made to this file:

    @@ -832,11 +832,11 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
     {
         struct da8xx_fb_par *par = arg;
         u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
         u32 reg_int;
     
    -    if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
    +    if ((stat & LCD_SYNC_LOST) || (stat & LCD_FIFO_UNDERFLOW)) {
             printk(KERN_ERR "LCDC sync lost or underflow error occured\n");
             lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
             lcdc_write(stat, LCD_MASKED_STAT_REG);
             lcd_enable_raster();
         } else if (stat & LCD_PL_LOAD_DONE) {

    @@ -894,11 +894,11 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
     {
         struct da8xx_fb_par *par = arg;
         u32 stat = lcdc_read(LCD_STAT_REG);
         u32 reg_ras;
     
    -    if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
    +    if ((stat & LCD_SYNC_LOST) || (stat & LCD_FIFO_UNDERFLOW)) {
             printk(KERN_ERR "LCDC sync lost or underflow error occured\n");
             lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
             clk_disable(par->lcdc_clk);
             lcdc_write(stat, LCD_STAT_REG);
             lcd_enable_raster();

    Make vsync callback preempt safe:

    @@ -211,10 +211,11 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
         .ypanstep = 1,
         .ywrapstep = 0,
         .accel = FB_ACCEL_NONE
     };
     
    +static spinlock_t vsync_cb_lock;
     static vsync_callback_t vsync_cb_handler;
     static void *vsync_cb_arg;
     
     static struct da8xx_panel known_lcd_panels[] = {
         /* Sharp LCD035Q3DG01 */
    @@ -801,40 +802,53 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
         return 0;
     }
     
     int register_vsync_cb(vsync_callback_t handler, void *arg, int idx)
     {
    +    unsigned long flags;
    +    int rc;
    +
    +    spin_lock_irqsave(&vsync_cb_lock, flags);
         if ((vsync_cb_handler == NULL) && (vsync_cb_arg == NULL)) {
             vsync_cb_arg = arg;
             vsync_cb_handler = handler;
    +        rc = 0;
         } else {
    -        return -EEXIST;
    +        rc = -EEXIST;
         }
    +    spin_unlock_irqrestore(&vsync_cb_lock, flags);
     
    -    return 0;
    +    return rc;
     }
     EXPORT_SYMBOL(register_vsync_cb);
     
     int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx)
     {
    +    unsigned long flags;
    +    int rc;
    +
    +    spin_lock_irqsave(&vsync_cb_lock, flags);
         if ((vsync_cb_handler == handler) && (vsync_cb_arg == arg)) {
             vsync_cb_handler = NULL;
             vsync_cb_arg = NULL;
    +        rc = 0;
         } else {
    -        return -ENXIO;
    +        rc = -ENXIO;
         }
    +    spin_unlock_irqrestore(&vsync_cb_lock, flags);
     
    -    return 0;
    +    return rc;
     }
     EXPORT_SYMBOL(unregister_vsync_cb);
     
     /* IRQ handler for version 2 of LCDC */
     static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
     {
         struct da8xx_fb_par *par = arg;
         u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
         u32 reg_int;
    +    unsigned long flags;
     
         if ((stat & LCD_SYNC_LOST) || (stat & LCD_FIFO_UNDERFLOW)) {
             printk(KERN_ERR "LCDC sync lost or underflow error occured\n");
             lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
             lcdc_write(stat, LCD_MASKED_STAT_REG);
    @@ -866,24 +880,28 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
                        LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
                 lcdc_write(par->dma_end,
                        LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
                 par->vsync_flag = 1;
                 wake_up_interruptible(&par->vsync_wait);
    +            spin_lock_irqsave(&vsync_cb_lock, flags);
                 if (vsync_cb_handler)
                     vsync_cb_handler(vsync_cb_arg);
    +            spin_unlock_irqrestore(&vsync_cb_lock, flags);
             }
     
             if (stat & LCD_END_OF_FRAME1) {
                 par->which_dma_channel_done = 1;
                 lcdc_write(par->dma_start,
                        LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
                 lcdc_write(par->dma_end,
                        LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
                 par->vsync_flag = 1;
                 wake_up_interruptible(&par->vsync_wait);
    +            spin_lock_irqsave(&vsync_cb_lock, flags);
                 if (vsync_cb_handler)
                     vsync_cb_handler(vsync_cb_arg);
    +            spin_unlock_irqrestore(&vsync_cb_lock, flags);
             }
         }
     
         lcdc_write(0, LCD_END_OF_INT_IND_REG);
         return IRQ_HANDLED;
    @@ -1476,10 +1494,11 @@ static int __devinit fb_probe(struct platform_device *device)
         /* initialize the vsync wait queue */
         init_waitqueue_head(&par->vsync_wait);
         par->vsync_timeout = HZ / 5;
         par->which_dma_channel_done = -1;
         spin_lock_init(&par->lock_for_chan_update);
    +    spin_lock_init(&vsync_cb_lock);
     
         /* Register the Frame Buffer  */
         if (register_framebuffer(da8xx_fb_info) < 0) {
             dev_err(&device->dev,
                 "GLCD: Frame Buffer Registration Failed!\n");