LCD 드라이브 코드 작성
먼저 입구 함수, 출구 함수와 수식을 포함한 프레임워크를 작성하세요.함수 성명만 쓰면 돼요. 코드는 이따가 한 걸음 한 걸음 채워주세요.
함수의 대부분 기능은 입구 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""리턴"을 누르면 디렉터리 아래의 내용이 표시됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.