Ili9325 based 8-bit LCD interface for olinuxino-mx233-micro

Started by tavish, February 21, 2013, 10:10:15 AM

Previous topic - Next topic

tavish

Hi, I am trying to interface http://imall.iteadstudio.com/display/im120419009.html with imx233-micro. Has anyone done this, Or with a similar LCD?

Dataedge

Hey tavish,

it is not the same LCD controller , but you can check this thread :
https://www.olimex.com/forum/index.php?topic=679.0

It is a good starting point ...


Alex-y

I have a working draft of ili9325 linux driver. It was experiment with this (http://www.gravitech.us/8tftcolcdtos.html) LCD.

This draft is similar to driver which I've attached in thread https://www.olimex.com/forum/index.php?topic=679.0
If interesting, I can publish it here.

tavish

Thanks for the replies.

@Alex-y Please do post the driver here, thanks!

Alex-y

I'm not remember where I got this code, but it works for me.  :o


#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
#include <mach/regs-lcdif.h>
#include <mach/regs-pinctrl.h>
#include <mach/regs-clkctrl.h>
#include <mach/regs-apbh.h>
#include <mach/gpio.h>
#include <mach/pins.h>
#include <mach/pinmux.h>
#include <mach/lcdif.h>
#include <mach/stmp3xxx.h>
#include <mach/platform.h>

/* ILI9325 control registers */
#define ILI9325_DRV_CODE 0x00  /* Driver code read, RO.*/
#define ILI9325_DRV_OUTPUT_CTRL_1 0x01  /* Driver output control 1, W.*/
#define ILI9325_LCD_DRV_CTRL 0x02  /* LCD driving control, W.*/
#define ILI9325_ENTRY_MOD 0x03  /* Entry mode, W.*/
#define ILI9325_RESIZE_CTRL 0x04  /* Resize Control, W.*/

#define ILI9325_DIS_CTRL_1 0x07  /* Display Control 1, W.*/
#define ILI9325_DIS_CTRL_2 0x08  /* Display Control 2, W.*/
#define ILI9325_DIS_CTRL_3 0x09  /* Display Control 3, W.*/
#define ILI9325_DIS_CTRL_4 0x0A  /* Display Control 4, W.*/

#define ILI9325_RGB_CTRL_1 0x0C  /* RGB display interface control 1, W.*/
#define ILI9325_FRAME_MARKER_POS 0x0D  /* Frame Marker Position, W.*/
#define ILI9325_RGB_CTRL_2 0x0F  /* RGB display interface control 2, W.*/

#define ILI9325_POW_CTRL_1 0x10  /* Power control 1, W.*/
#define ILI9325_POW_CTRL_2 0x11  /* Power control 2, W.*/
#define ILI9325_POW_CTRL_3 0x12  /* Power control 3, W.*/
#define ILI9325_POW_CTRL_4 0x13  /* Power control 4, W.*/

#define ILI9325_GRAM_HADDR 0x20  /* Horizontal GRAM address set, W.*/
#define ILI9325_GRAM_VADDR 0x21  /* Vertical GRAM address set, W.*/
#define ILI9325_GRAM_DATA 0x22  /* Write Data to GRAM, W.*/

#define ILI9325_POW_CTRL_7 0x29  /* Power control 7, W.*/

#define ILI9325_FRM_RATE_COLOR 0x2B  /* Frame Rate and Color Control, W. */

#define ILI9325_GAMMA_CTRL_1 0x30  /* Gamma Control 1, W. */
#define ILI9325_GAMMA_CTRL_2 0x31  /* Gamma Control 2, W. */
#define ILI9325_GAMMA_CTRL_3 0x32  /* Gamma Control 3, W. */
#define ILI9325_GAMMA_CTRL_4 0x35  /* Gamma Control 4, W. */
#define ILI9325_GAMMA_CTRL_5 0x36  /* Gamma Control 5, W. */
#define ILI9325_GAMMA_CTRL_6 0x37  /* Gamma Control 6, W. */
#define ILI9325_GAMMA_CTRL_7 0x38  /* Gamma Control 7, W. */
#define ILI9325_GAMMA_CTRL_8 0x39  /* Gamma Control 8, W. */
#define ILI9325_GAMMA_CTRL_9 0x3C  /* Gamma Control 9, W. */
#define ILI9325_GAMMA_CTRL_10 0x3D  /* Gamma Control l0, W. */

#define ILI9325_HOR_ADDR_START 0x50  /* Horizontal Address Start, W. */
#define ILI9325_HOR_ADDR_END 0x51  /* Horizontal Address End Position, W. */
#define ILI9325_VET_ADDR_START 0x52  /* Vertical Address Start, W. */
#define ILI9325_VET_ADDR_END 0x53  /* Vertical Address Start, W. */

#define ILI9325_DRV_OUTPUT_CTRL_2 0x60  /* Driver output control 2, W.*/

#define ILI9325_BASE_IMG_CTRL 0x61  /* Base Image Display Control, W.*/
#define ILI9325_VSCROLL_CTRL 0x6A  /* Vertical Scroll Control, W.*/

#define ILI9325_PAR_IMG1_POS 0x80  /* Partial Image 1 Display Position, W.*/
#define ILI9325_PAR_IMG1_START 0x81  /* Partial Image 1 Area (Start Line), W.*/
#define ILI9325_PAR_IMG1_END 0x82  /* Partial Image 1 Area (End Line), W.*/
#define ILI9325_PAR_IMG2_POS 0x83  /* Partial Image 2 Display Position, W.*/
#define ILI9325_PAR_IMG2_START 0x84  /* Partial Image 2 Area (Start Line), W.*/
#define ILI9325_PAR_IMG2_END 0x85  /* Partial Image 2 Area (End Line), W.*/

#define ILI9325_PAN_CTRL_1 0x90  /* Panel Interface Control 1, W.*/
#define ILI9325_PAN_CTRL_2 0x92  /* Panel Interface Control 2, W.*/
#define ILI9325_PAN_CTRL_3 0x93  /* Panel Interface Control 3, W.*/
#define ILI9325_PAN_CTRL_4 0x95  /* Panel Interface Control 4, W.*/


#define ILI9325_OTP_PROG_CTRL 0xA1  /* OTP VCM Programming Control, W.*/
#define ILI9325_OTP_STATUS 0xA2  /* OTP VCM Status and Enable, W.*/
#define ILI9325_OTP_ID_KEY 0xA5  /* OTP Programming ID Key, W.*/

/* Registers not depicted on the datasheet :-( */
#define ILI9325_TIMING_CTRL_1 0xE3  /* Timing control. */
#define ILI9325_TIMING_CTRL_2 0xE7  /* Timing control. */
#define ILI9325_TIMING_CTRL_3 0xEF  /* Timing control. */

#define ILI9325_PAN_CTRL_5 0x97  /* Panel Interface Control 5, W.*/
#define ILI9325_PAN_CTRL_6 0x98  /* Panel Interface Control 6, W.*/


#define CMD     0
#define DATA    1

#define lcdif_read(reg) __raw_readl(REGS_LCDIF_BASE + reg)
#define lcdif_write(reg,val) __raw_writel(val, REGS_LCDIF_BASE + reg)

static struct pin_desc lcd_ili9325_desc[] = {
        { PINID_LCD_D00, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D01, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D02, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D03, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D04, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D05, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D06, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_D07, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_RESET, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_RS, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_CS, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
        { PINID_LCD_WR, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 }
};

struct pin_group lcd_ili9325_pins = {
        .pins           = lcd_ili9325_desc,
        .nr_pins        = ARRAY_SIZE(lcd_ili9325_desc),
};


static struct clk *lcd_clk;


static void mpulcd_setup_pannel_register( u8 data, u8 val)
{
    lcdif_write(HW_LCDIF_CTRL_CLR, BM_LCDIF_CTRL_LCDIF_MASTER | BM_LCDIF_CTRL_RUN);

    lcdif_write(HW_LCDIF_TRANSFER_COUNT,
        BF_LCDIF_TRANSFER_COUNT_V_COUNT(1) |
                BF_LCDIF_TRANSFER_COUNT_H_COUNT(1));

    if(data)
        lcdif_write(HW_LCDIF_CTRL_SET, BM_LCDIF_CTRL_DATA_SELECT);
    else
        lcdif_write(HW_LCDIF_CTRL_CLR, BM_LCDIF_CTRL_DATA_SELECT);

    lcdif_write(HW_LCDIF_CTRL_SET, BM_LCDIF_CTRL_RUN);

    lcdif_write(HW_LCDIF_DATA, val);

    while(lcdif_read(HW_LCDIF_CTRL) & BM_LCDIF_CTRL_RUN)
    ;

    lcdif_write(HW_LCDIF_CTRL1_CLR, BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ);
}
static void ili932x_write_reg( u8 reg, u16 data )
{
    for(;;)
    {   
        mpulcd_setup_pannel_register( CMD, 0x09 );
       
        mpulcd_setup_pannel_register( DATA, 0x90 );
        msleep(10);
    }
mpulcd_setup_pannel_register( CMD, reg );
mpulcd_setup_pannel_register( DATA, (data >> 8) );
mpulcd_setup_pannel_register( DATA, data );
}



void mpulcd_start_refresh(void)
{
ili932x_write_reg(ILI9325_GRAM_HADDR, 0x0000); /* GRAM horizontal Address. */ 
    ili932x_write_reg(ILI9325_GRAM_VADDR, 0x0000); /* GRAM Vertical Address. */

mpulcd_setup_pannel_register(CMD, ILI9325_GRAM_DATA );

    lcdif_write(HW_LCDIF_CTRL_SET, BM_LCDIF_CTRL_DATA_SELECT);
    lcdif_write(HW_LCDIF_TRANSFER_COUNT,
        BF_LCDIF_TRANSFER_COUNT_V_COUNT(240) |
        BF_LCDIF_TRANSFER_COUNT_H_COUNT(320*3));

    stmp3xxx_lcdif_run();
}

static void mpulcd_init_lcdif(void)
{

    lcdif_write(HW_LCDIF_CTRL_CLR, BM_LCDIF_CTRL_CLKGATE | BM_LCDIF_CTRL_SFTRST);

    lcdif_write(HW_LCDIF_CTRL,
        BF_LCDIF_CTRL_LCD_DATABUS_WIDTH(BV_LCDIF_CTRL_LCD_DATABUS_WIDTH__8_BIT) |
        BF_LCDIF_CTRL_WORD_LENGTH(BV_LCDIF_CTRL_WORD_LENGTH__8_BIT));

    lcdif_write(HW_LCDIF_TIMING, 0x12121212);
}

/* Power On sequence */ 
static void ili9325_pow_on( void ) 

    ili932x_write_reg(ILI9325_POW_CTRL_1, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ 
    ili932x_write_reg(ILI9325_POW_CTRL_2, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0]  */ 
    ili932x_write_reg(ILI9325_POW_CTRL_3, 0x0000); /* VREG1OUT voltage  */ 
    ili932x_write_reg(ILI9325_POW_CTRL_4, 0x0000); /* VDV[4:0] for VCOM amplitude  */ 
    msleep(200); /* Dis-charge capacitor power voltage */ 
 
    ili932x_write_reg(ILI9325_POW_CTRL_1, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ 
    ili932x_write_reg(ILI9325_POW_CTRL_2, 0x0227); /* R11h=0x0221 at VCI=3.3V, DC1[2:0], DC0[2:0], VC[2:0]  */ 
    msleep(50); 
 
    ili932x_write_reg(ILI9325_POW_CTRL_3, 0x001D); /* External reference voltage= Vci  */ 
    msleep(50); 
 
    ili932x_write_reg(ILI9325_POW_CTRL_4, 0x0800); /* R13=1D00 when R12=009D;VDV[4:0] for VCOM amplitude  */ 
    ili932x_write_reg(ILI9325_POW_CTRL_7, 0x0012); /* R29=0013 when R12=009D;VCM[5:0] for VCOMH  */ 
    ili932x_write_reg(ILI9325_FRM_RATE_COLOR, 0x000B); /* Frame Rate = 70Hz  */ 
    msleep(50);

 
/* Adjust the Gamma Curve  */ 
static void ili9325_gamma_adjust( void ) 

    ili932x_write_reg(ILI9325_GAMMA_CTRL_1, 0x0007); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_2, 0x0707); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_3, 0x0006); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_4, 0x0704); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_5, 0x1F04); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_6, 0x0004); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_7, 0x0000); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_8, 0x0706); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_9, 0x0701); 
    ili932x_write_reg(ILI9325_GAMMA_CTRL_10, 0x000F); 

 
/*  Partial Display Control */ 
static void ili9325_par_dis_ctrl( void ) 

    ili932x_write_reg(ILI9325_PAR_IMG1_POS, 0); 
    ili932x_write_reg(ILI9325_PAR_IMG1_START, 0); 
    ili932x_write_reg(ILI9325_PAR_IMG1_END, 0); 
    ili932x_write_reg(ILI9325_PAR_IMG2_POS, 0); 
    ili932x_write_reg(ILI9325_PAR_IMG2_START, 0); 
    ili932x_write_reg(ILI9325_PAR_IMG2_END, 0);   

 
/* Panel Control */ 
static void ili9325_pan_ctrl( void ) 

    ili932x_write_reg(ILI9325_PAN_CTRL_1, 0x0010); 
    ili932x_write_reg(ILI9325_PAN_CTRL_2, 0x0000); 
    ili932x_write_reg(ILI9325_PAN_CTRL_3, 0x0003); 
    ili932x_write_reg(ILI9325_PAN_CTRL_4, 0x0110); 
    ili932x_write_reg(ILI9325_PAN_CTRL_5, 0x0000); 
    ili932x_write_reg(ILI9325_PAN_CTRL_6, 0x0000); 
    ili932x_write_reg(ILI9325_DIS_CTRL_1, 0x0133); /* 262K color and display ON */ 



static void mpulcd_init_panel_hw(void)
{
    stmp3xxx_request_pin_group(&lcd_ili9325_pins, "mpulcd_pin");

    gpio_request(PINID_LCD_ENABLE, "ili9325");
    gpio_direction_output(PINID_LCD_ENABLE, 1);

    ili932x_write_reg(ILI9325_TIMING_CTRL_1, 0x3008); /* Set internal timing*/ 
    ili932x_write_reg(ILI9325_TIMING_CTRL_2, 0x0012); /* Set internal timing*/ 
    ili932x_write_reg(ILI9325_TIMING_CTRL_3, 0x1231); /* Set internal timing*/ 
 
    ili932x_write_reg(ILI9325_DRV_OUTPUT_CTRL_1, 0x0100); /* set SS and SM bit */ 
    ili932x_write_reg(ILI9325_LCD_DRV_CTRL, 0x0700); /* set 1 line inversion */ 
     
//#if ILI9325_BPP     == 16   
//    printk("ili9325_chip init bpp16.\n"); 
//    ili932x_write_reg(ILI9325_ENTRY_MOD, 0x1030); /* 16bit mode, set GRAM write direction and BGR=1. */ 
//#elif ILI9325_BPP       == 32   
    ili932x_write_reg(ILI9325_ENTRY_MOD, 0x9030); /* 18bit mode, set GRAM write direction and BGR=1. */ 
//#endif   
 
    ili932x_write_reg(ILI9325_RESIZE_CTRL, 0x0000); /* Resize register. */ 
    ili932x_write_reg(ILI9325_DIS_CTRL_2, 0x0207); /* set the back porch and front porch. */ 
    ili932x_write_reg(ILI9325_DIS_CTRL_3, 0x0000); /* set non-display area refresh cycle ISC[3:0]. */ 
    ili932x_write_reg(ILI9325_DIS_CTRL_4, 0x0000); /* FMARK function. */ 
    ili932x_write_reg(ILI9325_RGB_CTRL_1, 0x0000); /* RGB interface setting. */ 
    ili932x_write_reg(ILI9325_FRAME_MARKER_POS, 0x0000); /* Frame marker Position. */ 
    ili932x_write_reg(ILI9325_RGB_CTRL_2, 0x0000); /* RGB interface polarity. */ 
 
    ili9325_pow_on(); 
    ili9325_gamma_adjust(); 
 
    /* Set GRAM area */ 
    ili932x_write_reg(ILI9325_HOR_ADDR_START, 0x0000); /* Horizontal GRAM Start Address. */ 
    ili932x_write_reg(ILI9325_HOR_ADDR_END, 0x00EF); /* Horizontal GRAM End Address. */ 
    ili932x_write_reg(ILI9325_VET_ADDR_START, 0x0000); /* Vertical GRAM Start Address. */ 
    ili932x_write_reg(ILI9325_VET_ADDR_END, 0x013F); /* Vertical GRAM End Address. */ 
    ili932x_write_reg(ILI9325_DRV_OUTPUT_CTRL_2, 0xA700); /* Gate Scan Line. */ 
    ili932x_write_reg(ILI9325_BASE_IMG_CTRL, 0x0001); /* NDL,VLE, REV. */ 
    ili932x_write_reg(ILI9325_VSCROLL_CTRL, 0x0000); /* set scrolling line. */ 
 
    ili9325_par_dis_ctrl(); 
    ili9325_pan_ctrl(); 
 
    ili932x_write_reg(ILI9325_GRAM_HADDR, 0x0000); /* GRAM horizontal Address. */ 
    ili932x_write_reg(ILI9325_GRAM_VADDR, 0x0000); /* GRAM Vertical Address. */ 
}

static int mpulcd_init_panel(struct device *dev, dma_addr_t phys, int memsize,
        struct stmp3xxx_platform_fb_entry *pentry)
{
    int ret = 0;

    lcd_clk = clk_get(dev, "lcdif");
    if (IS_ERR(lcd_clk)) {
        ret = PTR_ERR(lcd_clk);
        goto out;
    }

    ret = clk_enable(lcd_clk);
    if (ret)
        goto out1;

    ret = clk_set_rate(lcd_clk, 12000/*24000*/);
    if (ret)
        goto out2;

    mpulcd_init_lcdif();
    stmp3xxx_lcdif_dma_init(dev, phys, memsize, 1);
    mpulcd_init_panel_hw();
    stmp3xxx_lcdif_notify_clients(STMP3XXX_LCDIF_PANEL_INIT, pentry);

    return 0;

out2:
    clk_disable(lcd_clk);
out1:
    clk_put(lcd_clk);
out:
    return ret;
}

static void mpulcd_display_on(void)
{
  //  mpulcd_setup_pannel_register(CMD, 0x29);
    lcdif_write(HW_LCDIF_CTRL1_SET, BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN);
    mpulcd_start_refresh();
}

static void mpulcd_display_off(void)
{

    lcdif_write(HW_LCDIF_CTRL1_CLR, BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN);
  //  mpulcd_setup_pannel_register(CMD, 0x28);
}

static void mpulcd_release_panel(struct device *dev,
        struct stmp3xxx_platform_fb_entry *pentry)
{

    stmp3xxx_lcdif_notify_clients(STMP3XXX_LCDIF_PANEL_RELEASE, pentry);
    mpulcd_display_off();
    stmp3xxx_release_pin_group(&lcd_ili9325_pins, "mpulcd_pin");
    stmp3xxx_lcdif_dma_release();
    clk_disable(lcd_clk);
    clk_put(lcd_clk);
    gpio_direction_output(PINID_LCD_ENABLE, 0);
}

static int mpulcd_blank_panel(int blank)
{
    int ret = 0;

    switch (blank)
    {
        case FB_BLANK_NORMAL:
        case FB_BLANK_HSYNC_SUSPEND:
        case FB_BLANK_POWERDOWN:
        case FB_BLANK_VSYNC_SUSPEND:
        case FB_BLANK_UNBLANK:
            break;

        default:
            ret = -EINVAL;
    }

    return ret;
}

int mpulcd_pan_display(dma_addr_t addr)
{

    lcdif_write(HW_LCDIF_CUR_BUF, addr);
    return 0;
}


static struct stmp3xxx_platform_fb_entry fb_entry = {
    .name           = "ili9325",
    .x_res          = 240,
    .y_res          = 320,
    .bpp            = 24,
    .cycle_time_ns  = 150,
    .lcd_type       = STMP3XXX_LCD_PANEL_SYSTEM,
    .init_panel     = mpulcd_init_panel,
    .release_panel  = mpulcd_release_panel,
    .blank_panel    = mpulcd_blank_panel,
    .run_panel      = mpulcd_display_on,
    .stop_panel     = mpulcd_display_off,
    .pan_display    = mpulcd_pan_display,
};

static int __init register_devices(void)
{

    stmp3xxx_lcd_register_entry(&fb_entry, stmp3xxx_framebuffer.dev.platform_data);
    return 0;
}

subsys_initcall(register_devices); 


Bert

How to compile it? There're no mach dir in /usr/src/include nor even such include files.

Alex-y

Quote from: Bert on March 13, 2013, 03:39:54 AM
How to compile it? There're no mach dir in /usr/src/include nor even such include files.

Hi,
You are tried compile this file as usual application? If yes, it is wrong.
This file should be compiled as part of frame buffer driver for Linux kernel.

Bert

No I meant it seems to be huge out-dated since the new linux driver's paradigm. So there're no "mach/regs-*.h" include files as well as panel-to-fb glue in 3.x kernels.

The driver also must implement framebuffer (I suppose). And for getting things worse - it must use iMX LCDIF built-in interface to draw fast.

I've spent last week trying to breed mxsfb with my own ili9325 driver but with no luck :(
The problem too complex to solve. Any help?

tavish

@Alex-y
Quote from: Alex-y on February 27, 2013, 11:33:09 PM
I'm not remember where I got this code, but it works for me.  :o

Hi again, this seems to code for <mach/stmp3xxx.h>, how does it compile for imx233?

Bert

I'm currently working on porting MXS to ili9325 framebuffer, so I'll release it soon

Alex-y

Quote from: tavish on March 22, 2013, 08:58:32 AM
@Alex-y
Quote from: Alex-y on February 27, 2013, 11:33:09 PM
I'm not remember where I got this code, but it works for me.  :o

Hi again, this seems to code for <mach/stmp3xxx.h>, how does it compile for imx233?

Hi,
I compiled this code with kernel 2.6.2x
imx233 this is full clone of stmp3xxx, just rebrand.
For imx233 just compile kernel with config for stmp3xxx machine. (MACH_STMP378X)


opentronix

Hi all,
  Here, we really wanted to wire ILI9325 and ST7735R to our olimex micro and come across this forum several times.
After some research we managed to use both LCDs with our olinuxino running with kernel 3.18.
We wrote a blog post describing how we did it to help others looking forward to do the same.

look here: http://opentronix.com

Cheers!