📄 s3c2410fb.c
字号:
if (var->lower_margin < 0 || var->lower_margin > 255) printk(KERN_ERR "%s: invalid lower_margin %d\n", fbi->fb.fix.id, var->lower_margin);#endif#if defined(TFT240_320) new_regs.lcdcon1=(CLKVAL_TFT<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0; /* TFT LCD panel,16bpp TFT,ENVID=off */ new_regs.lcdcon2=(VBPD<<24)|((var->yres-1)<<14)|(VFPD<<6)|(VSPW); new_regs.lcdcon3=(HBPD<<19)|((var->xres-1)<<8)|(HFPD); new_regs.lcdcon4=(MVAL<<8)|(HSPW); new_regs.lcdcon5=(1<<11)|(1<<9)|(1<<8)|(1<<5)|1; // new_regs.lcdcon5=(1<<11)|(1<<9)|(1<<8)|(1<<3); new_regs.lcdsaddr1= (((unsigned long)fbi->screen_dma>>22)<<21)|M5D((unsigned long)fbi->screen_dma>>1); new_regs.lcdsaddr2= M5D(((unsigned long)fbi->screen_dma+(var->xres*var->yres*2))>>1); new_regs.lcdsaddr3=(((var->xres - var->xres)/1)<<11)|(var->xres/1); // new_regs.lcdintmsk = 3; // new_regs.lpcsel = 0x7; /* Enable PCD3600 */ // new_regs.tpal = 0x0;#elif defined(TFT640_480) GPCCON &= ~(3<<8); GPCCON |= (2<<8); new_regs.lcdcon1=(2<<8)|(0<<7)|(3<<5)|(12<<1)|0; /* TFT LCD panel,16bpp TFT,ENVID=off */ new_regs.lcdcon2=(((10-1) & 0xff)<<24)|((var->yres-1)<<14)|(((25-1)&0xff)<<6)|(((30-1)&0x3f)); new_regs.lcdcon3=(((3-1)&0x7f)<<19)|((var->xres-1)<<8)|(((5-1)&0xff)); new_regs.lcdcon4=(13<<8)|(((80-1)&0xff)); new_regs.lcdcon5=(1<<11)|(1<<9)|(1<<8)|1; // new_regs.lcdcon5=(1<<11)|(1<<9)|(1<<8)|(1<<3); new_regs.lcdsaddr1= (((unsigned long)fbi->screen_dma>>22)<<21)|M5D((unsigned long)fbi->screen_dma>>1); new_regs.lcdsaddr2= M5D(((unsigned long)fbi->screen_dma+(var->xres*var->yres*2))>>1); new_regs.lcdsaddr3=(((var->xres - var->xres)/1)<<11)|(var->xres/1); // new_regs.lcdintmsk = 3; // new_regs.lpcsel = 0x7; /* Enable PCD3600 */ // new_regs.tpal = 0x0;#elif defined(STN320_240) new_regs.lcdcon1=(CLKVAL_CSTN<<8)|(MVAL_USED<<7)|(2<<5)|(3<<1)|0; /* 8-bit single scan,8bpp CSTN,ENVID=off */ new_regs.lcdcon2=(0<<24)|(LINEVAL_CSTN<<14)|(0<<6)|(0<<0); new_regs.lcdcon3=(WDLY_CSTN<<19)|(HOZVAL_CSTN<<8)|(LINEBLANK_CSTN<<0); new_regs.lcdcon4=(MVAL<<8)|(WLH_CSTN<<0); new_regs.lcdcon5=1<<1; //BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:x,INVVFRAME:x,INVVD:x, //INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x new_regs.lcdsaddr1=(((unsigned long)fbi->screen_dma>>22)<<21 )|M5D((unsigned long)fbi->screen_dma>>1); new_regs.lcdsaddr2=M5D( ((unsigned long)fbi->screen_dma+(var->xres*var->yres/1))>>1 ); new_regs.lcdsaddr3=(((var->xres-var->xres)/2)<<11)|(var->xres/2); DITHMODE=0x0; REDLUT =0xfdb96420; GREENLUT=0xfdb96420; BLUELUT =0xfb40;#endif /* ONLY 240 * 320 */ /* Update shadow copy atomically */ local_irq_save(flags); fbi->reg_lcdcon1 = new_regs.lcdcon1; fbi->reg_lcdcon2 = new_regs.lcdcon2; fbi->reg_lcdcon3 = new_regs.lcdcon3; fbi->reg_lcdcon4 = new_regs.lcdcon4; fbi->reg_lcdcon5 = new_regs.lcdcon5; fbi->reg_lcdsaddr1 = new_regs.lcdsaddr1; fbi->reg_lcdsaddr2 = new_regs.lcdsaddr2; fbi->reg_lcdsaddr3 = new_regs.lcdsaddr3; fbi->reg_lpcsel = new_regs.lpcsel; local_irq_restore(flags); /* * Only update the registers if the controller is enabled * and something has changed. */ if( (LCDCON1 != fbi->reg_lcdcon1) || (LCDCON2 != fbi->reg_lcdcon2) || (LCDCON3 != fbi->reg_lcdcon3) || (LCDCON4 != fbi->reg_lcdcon4) || (LCDCON5 != fbi->reg_lcdcon5) || (LCDADDR1 != fbi->reg_lcdsaddr1)|| (LCDADDR2 != fbi->reg_lcdsaddr2) || (LCDADDR3 != fbi->reg_lcdsaddr3) ) { s3c2410fb_schedule_task(fbi, C_REENABLE); } return 0;}static void s3c2410fb_enable_controller(struct s3c2410fb_info *fbi){ DPRINTK("Enabling LCD controller\n"); /* * Make sure the mode bits are present in the first palette entry */ fbi->palette_cpu[0] &= 0xcfff; fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var); LCDCON1 =fbi->reg_lcdcon1; LCDCON2 =fbi->reg_lcdcon2; LCDCON3 =fbi->reg_lcdcon3; LCDCON4 =fbi->reg_lcdcon4; LCDCON5 =fbi->reg_lcdcon5; LCDADDR1=fbi->reg_lcdsaddr1; LCDADDR2=fbi->reg_lcdsaddr2; LCDADDR3=fbi->reg_lcdsaddr3; // LPCSEL &= (~(fbi->reg_lpcsel)); // LCDINTMSK |= fbi->reg_lcdintmsk; LCDINTMSK |= 3; TPAL=0; // temporary palette register, Disabled LCDLPCSEL &= ~(7);// LCDLPCSEL |= 7; LCDCON1|=1; // ENVID=ON FBuf = (struct FrameBuffer *)fbi->screen_cpu;#ifdef YOU_WANT_TO_DRAW_TETRAGON lcd_demo(); { unsigned long i ; for (i = 0; i < 0xc000000;i++); }#endif}static void s3c2410fb_disable_controller(struct s3c2410fb_info *fbi){ DECLARE_WAITQUEUE(wait, current); DPRINTK("Disabling LCD controller\n"); add_wait_queue(&fbi->ctrlr_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); LCDCON1=fbi->reg_lcdcon1; LCDCON2=fbi->reg_lcdcon2; LCDCON3=fbi->reg_lcdcon3; LCDCON4=fbi->reg_lcdcon4; LCDCON5=fbi->reg_lcdcon5; LCDADDR1=fbi->reg_lcdsaddr1; LCDADDR2=fbi->reg_lcdsaddr2; LCDADDR3=fbi->reg_lcdsaddr3; LCDLPCSEL = fbi->reg_lpcsel; LCDCON1 = LCDCON1&~(1); /* ENVID Clear */ schedule_timeout(20 * HZ / 1000); current->state = TASK_RUNNING; remove_wait_queue(&fbi->ctrlr_wait, &wait);}/* * This function must be called from task context only, since it will * sleep when disabling the LCD controller, or if we get two contending * processes trying to alter state. */static void set_ctrlr_state(struct s3c2410fb_info *fbi, u_int state){ u_int old_state; down(&fbi->ctrlr_sem); old_state = fbi->state; switch (state) { case C_DISABLE_CLKCHANGE: /* * Disable controller for clock change. If the * controller is already disabled, then do nothing. */ if (old_state != C_DISABLE) { fbi->state = state; s3c2410fb_disable_controller(fbi); } break; case C_DISABLE: /* * Disable controller */ if (old_state != C_DISABLE) { fbi->state = state; if (old_state != C_DISABLE_CLKCHANGE) s3c2410fb_disable_controller(fbi); } break; case C_ENABLE_CLKCHANGE: /* * Enable the controller after clock change. Only * do this if we were disabled for the clock change. */ if (old_state == C_DISABLE_CLKCHANGE) { fbi->state = C_ENABLE; s3c2410fb_enable_controller(fbi); } break; case C_REENABLE: /* * Re-enable the controller only if it was already * enabled. This is so we reprogram the control * registers. */ if (old_state == C_ENABLE) { s3c2410fb_disable_controller(fbi); s3c2410fb_enable_controller(fbi); } break; case C_ENABLE: /* * Power up the LCD screen, enable controller, and * turn on the backlight. */ if (old_state != C_ENABLE) { fbi->state = C_ENABLE; s3c2410fb_enable_controller(fbi); } break; } up(&fbi->ctrlr_sem);}/* * Our LCD controller task (which is called when we blank or unblank) * via keventd. */static void s3c2410fb_task(void *dummy){ struct s3c2410fb_info *fbi = dummy; u_int state = xchg(&fbi->task_state, -1);// set_ctrlr_state(fbi, state);}/* * s3c2410fb_map_video_memory(): * Allocates the DRAM memory for the frame buffer. This buffer is * remapped into a non-cached, non-buffered, memory region to * allow palette and pixel writes to occur without flushing the * cache. Once this area is remapped, all virtual memory * access to the video memory should occur at the new region. */static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi){ /* * We reserve one page for the palette, plus the size * of the framebuffer. * * fbi->map_dma is bus address (physical) * fbi->screen_dma = fbi->map_dma + PAGE_SIZE * fbi->map_cpu is virtual address * fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE * * S3C2400 Result * map_size is 0x00027000 * map_cpu is 0xC2800000 * smem_start is 0x0CFC1000 * palette_mem_size 0x20 */ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE ); fbi->map_cpu = consistent_alloc(GFP_KERNEL , fbi->map_size, &fbi->map_dma); if (fbi->map_cpu) { fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE ; fbi->screen_dma = fbi->map_dma + PAGE_SIZE ; fbi->fb.fix.smem_start = fbi->screen_dma; } return fbi->map_cpu ? 0 : -ENOMEM;}/* Fake monspecs to fill in fbinfo structure */static struct fb_monspecs monspecs __initdata = { 30000, 70000, 50, 65, 0 /* Generic */};static struct s3c2410fb_info * __init s3c2410fb_init_fbinfo(void){ struct s3c2410fb_info *fbi; fbi = kmalloc(sizeof(struct s3c2410fb_info) + sizeof(struct display) + sizeof(u16) * 16, GFP_KERNEL); if (!fbi) return NULL; memset(fbi, 0, sizeof(struct s3c2410fb_info) + sizeof(struct display)); fbi->currcon = -1; strcpy(fbi->fb.fix.id, S3C2410_NAME); fbi->fb.node = -1; /* What is this ? */ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; fbi->fb.fix.type_aux = 0; fbi->fb.fix.xpanstep = 0; fbi->fb.fix.ypanstep = 0; fbi->fb.fix.ywrapstep = 0; fbi->fb.fix.accel = FB_ACCEL_NONE; /* No hardware Accelerator */ fbi->fb.var.nonstd = 0; fbi->fb.var.activate = FB_ACTIVATE_NOW; fbi->fb.var.height = -1; fbi->fb.var.width = -1; fbi->fb.var.accel_flags = 0; fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; strcpy(fbi->fb.modename, S3C2410_NAME); strcpy(fbi->fb.fontname, "Acorn8x8"); fbi->fb.fbops = &s3c2410fb_ops; fbi->fb.changevar = NULL; fbi->fb.switch_con = s3c2410fb_switch; fbi->fb.updatevar = s3c2410fb_updatevar; fbi->fb.blank = s3c2410fb_blank; fbi->fb.flags = FBINFO_FLAG_DEFAULT; fbi->fb.node = -1; fbi->fb.monspecs = monspecs; fbi->fb.disp = (struct display *)(fbi + 1); /* golbal display */ fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1); fbi->rgb[RGB_8] = &rgb_8; fbi->rgb[RGB_16] = &def_rgb_16; s3c2410fb_get_machine_info(fbi); fbi->state = C_DISABLE; fbi->task_state = (u_char)-1; fbi->fb.fix.smem_len = (fbi->max_xres * fbi->max_yres * fbi->max_bpp) / 8; init_waitqueue_head(&fbi->ctrlr_wait); INIT_TQUEUE(&fbi->task, s3c2410fb_task, fbi); init_MUTEX(&fbi->ctrlr_sem); return fbi;}int __init s3c2410fb_init(void){ struct s3c2410fb_info *fbi; int ret; s3c2410fb_lcd_port_init(); s3c2410fb_lcd_On_Off(1); fbi = s3c2410fb_init_fbinfo(); ret = -ENOMEM; if (!fbi) goto failed; /* Initialize video memory */ ret = s3c2410fb_map_video_memory(fbi); if (ret) goto failed; s3c2410fb_set_var(&fbi->fb.var, -1, &fbi->fb); ret = register_framebuffer(&fbi->fb); if (ret < 0) goto failed; /* * Ok, now enable the LCD controller */ set_ctrlr_state(fbi, C_ENABLE); /* This driver cannot be unloaded at the moment */ MOD_INC_USE_COUNT; printk("s3c2410_init successful\n"); return 0;failed: printk("s3c2410_init failed\n"); if (fbi) kfree(fbi); return ret;}int __init s3c2410fb_setup(char *options){ return 0;}MODULE_DESCRIPTION("S3C2410/SAMSUNG framebuffer driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -