📄 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 (LCD_TYPE == TFT240_320)// 240 x 320 * 16bpp 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<0); 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 = 0x02; /* Enable LPC3600 */ //new_regs.tpal = 0x0;#endif#if (LCD_TYPE == TFT640_480)// 640 x 480 * 16bpp true color new_regs.lcdcon1=(CLKVAL_TFT<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0; //MVAL_USED=0 /* TFT LCD panel,16bpp TFT,ENVID=off */ new_regs.lcdcon2=(VBPD<<24)|(VFPD<<6)|(VSPW)|((var->yres-1)<<14); new_regs.lcdcon3=(HBPD<<19)|(HFPD)|((var->xres-1)<<8); new_regs.lcdcon4=(HSPW)|(MVAL<<8); new_regs.lcdcon5=(1<<11)|(1<<9)|(1<<8)|(1<<3)|1; 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 &= (~7); /* 0x0;Disable LPC3600 zjm */ new_regs.tpal = 0x0;#endif /* 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( (rLCDCON1 != fbi->reg_lcdcon1) || (rLCDCON2 != fbi->reg_lcdcon2) || (rLCDCON3 != fbi->reg_lcdcon3) || (rLCDCON4 != fbi->reg_lcdcon4) || (rLCDCON5 != fbi->reg_lcdcon5) || (rLCDSADDR1 != fbi->reg_lcdsaddr1)|| (rLCDSADDR2 != fbi->reg_lcdsaddr2) || (rLCDSADDR3 != 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); rLCDCON1 =fbi->reg_lcdcon1; rLCDCON2 =fbi->reg_lcdcon2; rLCDCON3 =fbi->reg_lcdcon3; rLCDCON4 =fbi->reg_lcdcon4; rLCDCON5 =fbi->reg_lcdcon5; rLCDSADDR1=fbi->reg_lcdsaddr1; rLCDSADDR2=fbi->reg_lcdsaddr2; rLCDSADDR3=fbi->reg_lcdsaddr3; // rLPCSEL &= (~(fbi->reg_lpcsel)); // rLCDINTMSK |= fbi->reg_lcdintmsk; rLCDINTMSK |= 3; rTPAL=0; // temporary palette register, Disabled#if (LCD_TYPE == TFT240_320) rLPCSEL |= 2;#endif#if (LCD_TYPE == TFT640_480) rLPCSEL &= ~(7);#endif rLCDCON1|=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); rLCDCON1=fbi->reg_lcdcon1; rLCDCON2=fbi->reg_lcdcon2; rLCDCON3=fbi->reg_lcdcon3; rLCDCON4=fbi->reg_lcdcon4; rLCDCON5=fbi->reg_lcdcon5; rLCDSADDR1=fbi->reg_lcdsaddr1; rLCDSADDR2=fbi->reg_lcdsaddr2; rLCDSADDR3=fbi->reg_lcdsaddr3; rLPCSEL = fbi->reg_lpcsel; rLCDCON1 = rLCDCON1&~(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; printk(KERN_NOTICE "\n map_size:%x\n map_cpu:%x\n screen_cpu:%x\n screen_dma:%x\n",fbi->map_size,fbi->map_cpu,fbi->screen_cpu,fbi->screen_dma);//lee } 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(); 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; return 0;failed: 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 + -