[i.MX28] Trouble with a 1024x768 lcd

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

[i.MX28] Trouble with a 1024x768 lcd

889 Views
katte
Contributor II

Hi all. I'trying to use this LCD:

https://www.mouser.it/datasheet/2/365/LQ150X1LX95_30Jul14_Spec_LD-26206B-1131491.pdf with the i.MX28
I'm using the LTIB 2.6.35_10_12_01.

I've made some modification to the lcd_43wvf1g.c file. In particular I've changed these lines:

#define DOTCLK_H_ACTIVE  1024
#define DOTCLK_V_ACTIVE  768
ret = clk_set_rate(lcd_clk, 1000000000 / pentry->cycle_time_ns);    /* kHz */
static struct mxs_platform_fb_entry fb_entry = {
    .name = "43wvf1g",
    .x_res = DOTCLK_H_ACTIVE,
    .y_res = DOTCLK_V_ACTIVE,
    .bpp = 32,
    .cycle_time_ns = 20,
    .lcd_type = MXS_LCD_PANEL_DOTCLK,
    .init_panel = init_panel,
    .release_panel = release_panel,
    .blank_panel = blank_panel,
    .run_panel = mxs_lcdif_run,
    .stop_panel = mxs_lcdif_stop,
    .pan_display = mxs_lcdif_pan_display,
    .bl_data = &bl_data,
};

Initially I thinked about a problem in lcd clock frequency.
The static function int lcdif_set_rate(struct clk *clk, unsigned long rate) in clock.c, fix lcd clock to xtal frequency that is about 24MHz and the datasheet specify that this frequency need to be between 50 and 80MHz..

I've changed this function in that way, and now I can set the frequency that I want.

static int lcdif_set_rate(struct clk *clk, unsigned long rate)
{
    int reg_val;
    printk("LCD: \"lcdif_set_rate\" %lu\n", rate);
    {
        unsigned long int regAddr;
        #define RAW_READ_L(X, D)    do { \
                            regAddr = X; \
                            reg_val = __raw_readl(regAddr); \
                            printk("LCD: \"lcdif_set_rate\" GET_L reg: 0x%lX (%s) : 0x%X\n", regAddr, D, reg_val); \
                        } while(0)
        #define RAW_WRITE_L(X, Y, D)    do { \
                            regAddr = X; \
                            reg_val = Y; \
                            __raw_writel(reg_val, regAddr); \
                            printk("LCD: \"lcdif_set_rate\" SET_L reg: 0x%lX (%s) to: 0x%X\n", regAddr, D, reg_val); \
                        } while(0)
        #define RAW_WRITE_W(X, Y, D)    do { \
                            regAddr = X; \
                            reg_val = Y; \
                            __raw_writew(reg_val, regAddr); \
                            printk("LCD: \"lcdif_set_rate\" SET_W reg: 0x%lX (%s) to: 0x%X\n", regAddr, D, reg_val); \
                        } while(0)
        #define RAW_WRITE_B(X, Y, D)    do { \
                            regAddr = X; \
                            reg_val = Y; \
                            __raw_writeb(reg_val, regAddr); \
                            printk("LCD: \"lcdif_set_rate\" SET_B reg: 0x%lX (%s) to: 0x%X\n", regAddr, D, reg_val); \
                        } while(0)
        RAW_READ_L(CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLL0CTRL0, "HW_CLKCTRL_PLL0CTRL0");
        RAW_READ_L(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC1, "HW_CLKCTRL_FRAC1");

        reg_val &= ~BM_CLKCTRL_FRAC1_PIXFRAC;
        reg_val |= BF_CLKCTRL_FRAC1_PIXFRAC(18) & BM_CLKCTRL_FRAC1_PIXFRAC;
        //RAW_WRITE_L(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC1_SET, reg_val, "HW_CLKCTRL_FRAC1_SET");
        RAW_WRITE_B(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC1_SET, reg_val & 0xFF, "HW_CLKCTRL_FRAC1_SET");
        reg_val = BM_CLKCTRL_FRAC1_CLKGATEPIX;
        RAW_WRITE_B(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC1_CLR, reg_val & 0xFF, "HW_CLKCTRL_FRAC1_CLR");

        RAW_READ_L(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC1, "HW_CLKCTRL_FRAC1");

        //Set lcdif clock to ref_pix to generate rate frequency
        RAW_READ_L(clk->scale_reg, "HW_CLKCTRL_DIS_LCDIF");
        reg_val &= ~(BM_CLKCTRL_DIS_LCDIF_DIV | BM_CLKCTRL_DIS_LCDIF_CLKGATE | BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN);
        //reg_val |= (1 << BP_CLKCTRL_DIS_LCDIF_DIV) & BM_CLKCTRL_DIS_LCDIF_DIV;
        reg_val |= BF_CLKCTRL_DIS_LCDIF_DIV(480000000/rate) & BM_CLKCTRL_DIS_LCDIF_DIV;
        RAW_WRITE_L(clk->scale_reg, reg_val, "HW_CLKCTRL_DIS_LCDIF");
        RAW_READ_L(clk->scale_reg, "HW_CLKCTRL_DIS_LCDIF");

        if (clk->busy_reg) {
            int i;
            for (i = 1000000; i; i--)
                if (!clk_is_busy(clk))
                    break;
            if (!i) {
                return -ETIMEDOUT;
            }
        }
        RAW_READ_L(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ, "HW_CLKCTRL_CLKSEQ");
        reg_val &= ~BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF;
        RAW_WRITE_L(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ, reg_val, "HW_CLKCTRL_CLKSEQ");
        #undef RAW_READ_L
        #undef RAW_WRITE_L
        #undef RAW_WRITE_W
        #undef RAW_WRITE_B
    }
    return 0;
}

I've tryed frequency from 50Mhz to 60Mhz,

I've checked the frequency with an oscilloscope and it's ok, but the output image still have some problem, it seems horizontally shifted.

Someone can help me or give some hint?
Thanks in advance.

PS. The LVDS hardware is ok. With this hardware I'm able to use other LCD: 10"@800x600 and 7"@800x480.

Labels (3)
0 Kudos
3 Replies

712 Views
igorpadykov
NXP Employee
NXP Employee

Hi Marco

one can verify lcd timings with OBDS:

Lab and Test Software (1)
On-Board Diagnostic Suit for the i.MX28
i.MX28 Evaluation Kit|NXP 

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

712 Views
katte
Contributor II

Hi, thanks for the response.

How should I use this tool?
As I wrote above, I can use different LCD both at 800x480 and 800x600. The linked tool works at 800x480, but I have to drive an LCD at 1024x768.

0 Kudos

712 Views
igorpadykov
NXP Employee
NXP Employee

Hi Marco

usage is described in documentation included in package,

please check example in ..drivers/lcd

Best regards
igor

0 Kudos