LCD 드라이브 코드 작성

14093 단어
내가 사용하는 개발판은 미니2440이기 때문에 몇 가지 절차가 다를 수 있다.
먼저 입구 함수, 출구 함수와 수식을 포함한 프레임워크를 작성하세요.함수 성명만 쓰면 돼요. 코드는 이따가 한 걸음 한 걸음 채워주세요.
함수의 대부분 기능은 입구 init 함수에서 이루어지고 이 함수를 구성하는 데 완성해야 한다는 것을 확정할 수 있다. 1.fb 할당info 구조체 2.설정 3.하드웨어 관련 작업 4.등록!
우선 fb 하나를 분배합니다.info 구조체
s3c_lcd = framebuffer_alloc(0, NULL); 첫 번째 파라미터는 분배된 개인 공간의 크기를 가리킨다.분배된 공간은 반드시 구조체의 크기가 아니라 구조체의 크기와 사유 공간의 크기의 합을 가리킨다.
다음은 간단합니다. 4단계 등록은 간단합니다registerframebuffer(s3c_lcd);
그리고 그다음에 2.설정fb 자세히 보세요.info 구조체, 여러 구조체로 나뉘어져 있음을 발견할 수 있습니다.다음은 이 단계에 대한 조작을 몇 가지 부분으로 나눈다. 2.1 고정된 파라미터 설정2.2 가변적인 파라미터 설정2.3 조작 함수 설정2.4 다른 설정
2.1 고정된 매개 변수는 fb 에 정의됨fix_screeninfo에는 다음이 포함됩니다.
//  
strcpy(s3c_lcd->fix.id, "mylcd");
// MINI2440 LCD   24,  2440    4   32 (  1  ) 
s3c_lcd->fix.smem_len = 320*240*32/8; 
//  ,              
s3c_lcd->fix.type     = FB_TYPE_PACKED_PIXELS;
 //   TFT ,       
s3c_lcd->fix.visual   = FB_VISUAL_TRUECOLOR;
//       ,320 *4  
s3c_lcd->fix.line_length = 320*4;

안에 s3c가 하나 더 있어요.lcd->fix.smem_start는 아직 메모리를 분배하지 않았기 때문에 뒤에 두고 설정합니다.다른 것은 설정하지 않아도 된다.
다음은 2.2 가변 매개변수입니다.가변 매개 변수는 fbvar_screeninfo의 정의는 다음과 같습니다.
    s3c_lcd->var.xres           = 320;//x      
    s3c_lcd->var.yres           = 240;//y      
    s3c_lcd->var.xres_virtual   = 320;//x        
    s3c_lcd->var.yres_virtual   = 240;//y        
    s3c_lcd->var.bits_per_pixel = 32;//     32 

    /* RGB:888 */
    s3c_lcd->var.red.offset     = 16;//  
    s3c_lcd->var.red.length     = 8;//  

    s3c_lcd->var.green.offset   = 8;
    s3c_lcd->var.green.length   = 8;

    s3c_lcd->var.blue.offset    = 0;
    s3c_lcd->var.blue.length    = 8;
    //    
    s3c_lcd->var.activate       = FB_ACTIVATE_NOW;

다른 건 안 고쳐도 돼요.
2.3 운영 함수 설정
    s3c_lcd->fbops              = &s3c_lcdfb_ops;

당연히 file이 하나 더 들어가죠operations 구조,
static struct fb_ops s3c_lcdfb_ops = {
    .owner      = THIS_MODULE,
    .fb_setcolreg   = s3c_lcdfb_setcolreg,
    .fb_fillrect    = cfb_fillrect,
    .fb_copyarea    = cfb_copyarea,
    .fb_imageblit   = cfb_imageblit,
};

여기서 cfbfillrect,cfb_copyarea,cfb_imageblit는 모든 LCD 드라이버가 공용하기 때문에 반드시 없어서는 안 된다. 뒤에 가서 이 세 함수를 모듈로 만들어야 한다.s3c_lcdfb_setcolreg는 가짜 팔레트를 설정하는 것입니다. 구체적으로 어떻게 설정하는지 이따가 다시 이야기합시다.
2.4 다음은 다른 설정이다.
    s3c_lcd->pseudo_palette = pseudo_palette;   
    //     
    s3c_lcd->screen_size   = 320*240*32/8;

팔레트의 역할은 뭘까요?만약에 프레임 버퍼가 32bpp가 아닌 8bpp를 사용하지만 LCD 컨트롤러 하드웨어는 반드시 32비트를 사용해야 한다고 결정한다면 우리는 팔레트를 사용하여 8bpp에서 32bpp로 전환할 수 있다.팔레트는 디스플레이 컨트롤러의 메모리로 24비트의 픽셀 데이터를 넣는다.만약 프레임 버퍼에 8자리의 색인 값이 저장되어 있다면, 이 색인 값을 통해 팔레트에서 실제 32자리의 픽셀 데이터를 찾아서 LCD에 표시합니다.
static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
                 unsigned int green, unsigned int blue,
                 unsigned int transp, struct fb_info *info)
{
    unsigned int val;

    if (regno > 16)
        return 1;

    /*  red,green,blue      val */
    val  = chan_to_field(red,   &info->var.red);
    val |= chan_to_field(green, &info->var.green);
    val |= chan_to_field(blue,  &info->var.blue);

    //((u32 *)(info->pseudo_palette))[regno] = val;
    pseudo_palette[regno] = val;
    return 0;
}

여기서 chanto_field () 의 역할은 레드, 그린, 블루 원색을 분리하는 것이다.
더 내려가면 3.하드웨어의 설정은 몇 가지 단계로 나눌 수 있다. 3.1 설정 GPIO는 LCD 3.2에 사용되고 LCD 매뉴얼에 따라 LCD 컨트롤러를 설정한다. 예를 들어 VCLK의 주파수 등 3.3 분배 메모리(framebuffer)를 사용하고 주소를 LCD 컨트롤러에 알려준다.
먼저 3.1 설정 GPIO는 LCD에 사용되고 원리도를 보면 GPIOC 파이프라인은 VD[7:0], LCDVF[2:0], VM, VFRAME, VLINE, VCLK, LEND, GPIOD 파이프라인은 VD[23:8], GPG4는 LCDPWREN
    gpccon = ioremap(0x56000020, 4);
    gpdcon = ioremap(0x56000030, 4);
    gpgcon = ioremap(0x56000060, 4);
    *gpccon  = 0xaaaaaaaa;  
    *gpdcon  = 0xaaaaaaaa;   
    *gpgcon |= (3<<8);

미니2440의 백라이트 회로와 lcd 전원으로 공용 LCDPWREN, 다른 개발판에는 백라이트 트랙터도 설치할 수 있습니다.
다음은 3.2 LCD 매뉴얼에 따라 LCD 컨트롤러를 설정합니다. 레지스터가 많기 때문에 우리는 이 레지스터를 하나의 그룹에 넣고 함께 리맵()
struct lcd_regs {
    unsigned long   lcdcon1;
    unsigned long   lcdcon2;
    unsigned long   lcdcon3;
    unsigned long   lcdcon4;
    unsigned long   lcdcon5;
    unsigned long   lcdsaddr1;
    unsigned long   lcdsaddr2;
    unsigned long   lcdsaddr3;
    unsigned long   redlut;
    unsigned long   greenlut;
    unsigned long   bluelut;
    unsigned long   reserved[9];
    unsigned long   dithmode;
    unsigned long   tpal;
    unsigned long   lcdintpnd;
    unsigned long   lcdsrcpnd;
    unsigned long   lcdintmsk;
    unsigned long   lpcsel;
};

그리고
lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));

다음은 2440 매뉴얼,lcd 매뉴얼을 열어야 합니다.2440 매뉴얼에서 레지스터의 의미를 찾은 다음lcd 매뉴얼의 시차도에 따라 값을 계산하고 레지스터를 설정합니다.
그 다음은 3.3 분배 메모리다.필요한 함수는 dmaalloc_writecombine(struct device *dev, size t size, dma addr t *handle, gfp t gfp), 첫 번째 파라미터는 장치, NULL, 두 번째 파라미터는 길이,fix를 선택합니다.smem_len, 세 번째 매개 변수는 물리적 주소, 즉fix입니다.smem_start, 우리가 고정된 매개 변수에 설정하지 않은 물리적 주소가 여기에 설정되었습니다.네 번째 매개변수는 flag입니다. GFP 선택KERNEL.이 함수의 반환값은 메모리를 분배하는 가상 주소, 즉 s3c 이다lcd->screen_base.
어떻게 주소를 LCD 컨트롤러에 알려줍니까? lcdsaddr1,lcdsaddr2,lcdsaddr3에 써야 합니다.lcdsaddr1에 메모리를 저장하는 시작 주소 (물리적),lcdsaddr2에 메모리를 저장하는 끝 주소,lcdsaddr3에 한 줄의 길이를 정의했습니다. 단위는 2바이트입니다.
lcd_regs->lcdsaddr1  = (s3c_lcd->fix.smem_start >> 1) & ~(3<<30);
lcd_regs->lcdsaddr2  = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff;
lcd_regs->lcdsaddr3  = (320*32/16); 

다음은 에너지 LCD와 LCD 컨트롤러입니다.
    lcd_regs->lcdcon1 |= (1<<0); /*   LCD    */
    lcd_regs->lcdcon5 |= (1<<3); /*   LCD  : LCD_PWREN */

지금까지 LCD 드라이버는 거의 다 썼습니다.다음은 테스트입니다.1. 먼저 커널 자체 드라이버 make menuconfig -> Device Drivers -> Graphics support S3C2410 LCD framebuffer support 2.make uImage make modules
3. 새 uImage를 사용하여 개발 보드를 시작합니다.
4. 드라이버 insmod cfbcopyarea를 설치합니다.ko insmod cfbfillrect.ko insmod cfbimgblt.ko insmod lcd.ko
5. 테스트 시작 ① echo hello >/dev/tty1을 입력하면 LCD에서 hello 수정/etc/inittab을 볼 수 있습니다."tty1:::askfirst:-/bin/sh"를 덧붙인 다음 개발판을 다시 시작하고 insmod cfbcopyarea.ko insmod cfbfillrect.ko insmod cfbimgblt.ko insmod lcd.ko insmod buttons.ko 이때, tty1이라는 장치에도 셸이 시작되었기 때문에 버튼으로 "l""s""리턴"을 누르면 디렉터리 아래의 내용이 표시됩니다.

좋은 웹페이지 즐겨찾기