📄 au1200fb.c
字号:
iodata.winsize.hsz = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11; iodata.winsize.vsz = (lcd->window[plane].winctrl0 & LCD_WINCTRL1_SZY) >> 0; break; case AU1200_LCD_SET_WINSIZE: au1200_setsize(plane, iodata.winsize.hsz, iodata.winsize.vsz); break; case AU1200_LCD_GET_BACKCOLOR: iodata.backcolor.color = lcd->backcolor; break; case AU1200_LCD_SET_BACKCOLOR: lcd->backcolor = iodata.backcolor.color; break; case AU1200_LCD_GET_COLORKEY: iodata.colorkey.key = lcd->colorkey; iodata.colorkey.mask = lcd->colorkeymsk; break; case AU1200_LCD_SET_COLORKEY: lcd->colorkey = iodata.colorkey.key; lcd->colorkeymsk = iodata.colorkey.mask; break; case AU1200_LCD_GET_PANEL: iodata.panel.panel = panel_index; break; case AU1200_LCD_SET_PANEL: if ((iodata.panel.panel >= 0) && (iodata.panel.panel < NUM_PANELS)) { struct panel_settings *newpanel; panel_index = iodata.panel.panel; newpanel = &panels[panel_index]; au1200_setpanel(newpanel); } break; } return copy_to_user((void *) arg, &iodata, sizeof(au1200_lcd_getset_t)) ? -EFAULT : 0; } return -EINVAL;}static struct fbgen_hwswitch au1200_switch = { au1200_detect, au1200_encode_fix, au1200_decode_var, au1200_encode_var, au1200_get_par, au1200_set_par, au1200_getcolreg, au1200_setcolreg, au1200_pan_display, au1200_blank, au1200_set_disp};static void au1200_setpanel (struct panel_settings *newpanel){ /* * Perform global setup/init of LCD controller */ uint32 winenable; /* Make sure all windows disabled */ winenable = lcd->winenable; lcd->winenable = 0; /* * Ensure everything is disabled before reconfiguring */ if (lcd->screen & LCD_SCREEN_SEN) { /* Wait for vertical sync period */ lcd->intstatus = LCD_INT_SS; while ((lcd->intstatus & LCD_INT_SS) == 0) ; lcd->screen &= ~LCD_SCREEN_SEN; //disable the controller do { lcd->intstatus = lcd->intstatus; //clear interrupts } while ((lcd->intstatus & LCD_INT_SD) == 0); //wait for controller to shut down /* Call shutdown of current panel (if up) */ /* this must occur last, because if an external clock is driving the controller, the clock cannot be turned off before first shutting down the controller. */ if (panel->device_shutdown != NULL) panel->device_shutdown(); } panel = newpanel; printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); /* * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) */// if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) { uint32 sys_clksrc; au_writel(panel->mode_auxpll, SYS_AUXPLL); sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; sys_clksrc |= panel->mode_toyclksrc; au_writel(sys_clksrc, SYS_CLKSRC); } /* * Configure panel timings */ lcd->screen = panel->mode_screen; lcd->horztiming = panel->mode_horztiming; lcd->verttiming = panel->mode_verttiming; lcd->clkcontrol = panel->mode_clkcontrol; lcd->pwmdiv = panel->mode_pwmdiv; lcd->pwmhi = panel->mode_pwmhi; lcd->outmask = panel->mode_outmask; lcd->fifoctrl = panel->mode_fifoctrl; au_sync(); /* FIX!!! Check window settings to make sure still valid for new geometry */ au1200_setlocation(0, win->w[0].xpos, win->w[0].ypos); au1200_setlocation(1, win->w[1].xpos, win->w[1].ypos); au1200_setlocation(2, win->w[2].xpos, win->w[2].ypos); au1200_setlocation(3, win->w[3].xpos, win->w[3].ypos); lcd->winenable = winenable; /* * Re-enable screen now that it is configured */ lcd->screen |= LCD_SCREEN_SEN; au_sync(); /* Call init of panel */ if (panel->device_init != NULL) panel->device_init();#if 0#define D(X) printk("%25s: %08X\n", #X, X) D(lcd->screen); D(lcd->horztiming); D(lcd->verttiming); D(lcd->clkcontrol); D(lcd->pwmdiv); D(lcd->pwmhi); D(lcd->outmask); D(lcd->fifoctrl); D(lcd->window[0].winctrl0); D(lcd->window[0].winctrl1); D(lcd->window[0].winctrl2); D(lcd->window[0].winbuf0); D(lcd->window[0].winbuf1); D(lcd->window[0].winbufctrl); D(lcd->window[1].winctrl0); D(lcd->window[1].winctrl1); D(lcd->window[1].winctrl2); D(lcd->window[1].winbuf0); D(lcd->window[1].winbuf1); D(lcd->window[1].winbufctrl); D(lcd->window[2].winctrl0); D(lcd->window[2].winctrl1); D(lcd->window[2].winctrl2); D(lcd->window[2].winbuf0); D(lcd->window[2].winbuf1); D(lcd->window[2].winbufctrl); D(lcd->window[3].winctrl0); D(lcd->window[3].winctrl1); D(lcd->window[3].winctrl2); D(lcd->window[3].winbuf0); D(lcd->window[3].winbuf1); D(lcd->window[3].winbufctrl); D(lcd->winenable); D(lcd->intenable); D(lcd->intstatus); D(lcd->backcolor); D(lcd->winenable); D(lcd->colorkey); D(lcd->colorkeymsk); D(lcd->hwc.cursorctrl); D(lcd->hwc.cursorpos); D(lcd->hwc.cursorcolor0); D(lcd->hwc.cursorcolor1); D(lcd->hwc.cursorcolor2); D(lcd->hwc.cursorcolor3);#endif}static int au1200_setsize (int plane, int xres, int yres){ uint32 winctrl0, winctrl1, winenable; int xsz, ysz; // FIX!!! x*Y can not surpass allocated memoryprintk("setsize: x %d y %d\n", xres, yres); winctrl1 = lcd->window[plane].winctrl1;printk("org winctrl1 %08X\n", winctrl1); winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); xres -= 1; yres -= 1; winctrl1 |= (xres << 11); winctrl1 |= (yres << 0);printk("new winctrl1 %08X\n", winctrl1);// winenable = lcd->winenable & (1 << plane);// lcd->winenable &= ~(1 << plane); lcd->window[plane].winctrl1 = winctrl1;// lcd->winenable |= winenable;}static int au1200_setlocation (int plane, int xpos, int ypos){ uint32 winctrl0, winctrl1, winenable, fb_offset = 0; int xsz, ysz; /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ winctrl0 = lcd->window[plane].winctrl0; winctrl1 = lcd->window[plane].winctrl1; winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); /* Check for off-screen adjustments */ xsz = win->w[plane].xres; ysz = win->w[plane].yres; if ((xpos + win->w[plane].xres) > panel->Xres) { /* Off-screen to the right */ xsz = panel->Xres - xpos; /* off by 1 ??? */ printk("off screen right\n"); } if ((ypos + win->w[plane].yres) > panel->Yres) { /* Off-screen to the bottom */ ysz = panel->Yres - ypos; /* off by 1 ??? */ printk("off screen bottom\n"); } if (xpos < 0) { /* Off-screen to the left */ xsz = win->w[plane].xres + xpos; fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); xpos = 0; printk("off screen left\n"); } if (ypos < 0) { /* Off-screen to the top */ ysz = win->w[plane].yres + ypos; fb_offset += ((0 - ypos) * fb_pars[plane].line_length); ypos = 0; printk("off screen top\n"); } /* record settings */ win->w[plane].xpos = xpos; win->w[plane].ypos = ypos; xsz -= 1; ysz -= 1; winctrl0 |= (xpos << 21); winctrl0 |= (ypos << 10); winctrl1 |= (xsz << 11); winctrl1 |= (ysz << 0); /* Disable the window while making changes, then restore WINEN */ winenable = lcd->winenable & (1 << plane); lcd->winenable &= ~(1 << plane); lcd->window[plane].winctrl0 = winctrl0; lcd->window[plane].winctrl1 = winctrl1; lcd->window[plane].winbuf0 = lcd->window[plane].winbuf1 = fb_infos[plane].fb_phys + fb_offset; lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ lcd->winenable |= winenable; return 0;}static void au1200_setmode(int plane){ /* Window/plane setup */ lcd->window[plane].winctrl1 = ( 0 | LCD_WINCTRL1_PRI_N(plane) | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ ) ; au1200_setlocation(plane, win->w[plane].xpos, win->w[plane].ypos); lcd->window[plane].winctrl2 = ( 0 | LCD_WINCTRL2_CKMODE_00 | LCD_WINCTRL2_DBM/* | LCD_WINCTRL2_RAM */ | LCD_WINCTRL2_BX_N(fb_pars[plane].line_length) | LCD_WINCTRL2_SCX_1 | LCD_WINCTRL2_SCY_1 ) ; lcd->winenable |= win->w[plane].mode_winenable; au_sync();}static unsigned longau1200fb_alloc_fbmem (unsigned long size){ /* __get_free_pages() fulfills a max request of 2MB */ /* do multiple requests to obtain large contigous mem */#define MAX_GFP 0x00200000 unsigned long mem, amem, alloced = 0, allocsize; size += 0x1000; allocsize = (size < MAX_GFP) ? size : MAX_GFP; /* Get first chunk */ mem = (unsigned long ) __get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(allocsize)); if (mem != 0) alloced = allocsize; /* Get remaining, contiguous chunks */ while (alloced < size) { amem = (unsigned long ) __get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(allocsize)); if (amem != 0) alloced += allocsize; /* check for contiguous mem alloced */ if ((amem == 0) || (amem + allocsize) != mem) break; else mem = amem; } return mem;}int __init au1200fb_init(void){ struct au1200fb_info *fb_info; struct display *disp; struct au1200fb_par *par; unsigned long page; int plane, bpp; /* * Get the panel information/display mode */ panel = &panels[panel_index]; win = &windows[window_index]; printk("au1200fb: Panel %d %s\n", panel_index, panel->name); printk("au1200fb: Win %d %s\n", window_index, win->name); /* Global setup/init */ au1200_setpanel(panel); lcd->intenable = 0; lcd->intstatus = ~0; lcd->backcolor = win->mode_backcolor; lcd->winenable = 0; /* Setup Color Key - FIX!!! */ lcd->colorkey = win->mode_colorkey; lcd->colorkeymsk = win->mode_colorkeymsk; /* Setup HWCursor - FIX!!! Need to support this eventually */ lcd->hwc.cursorctrl = 0; lcd->hwc.cursorpos = 0; lcd->hwc.cursorcolor0 = 0; lcd->hwc.cursorcolor1 = 0; lcd->hwc.cursorcolor2 = 0; lcd->hwc.cursorcolor3 = 0; /* Register each plane as a frame buffer device */ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { fb_info = &fb_infos[plane]; disp = &disps[plane]; par = &fb_pars[plane]; bpp = winbpp(win->w[plane].mode_winctrl1); if (win->w[plane].xres == 0) win->w[plane].xres = panel->Xres; if (win->w[plane].yres == 0) win->w[plane].yres = panel->Yres; par->var.xres = par->var.xres_virtual = win->w[plane].xres; par->var.yres = par->var.yres_virtual = win->w[plane].yres; par->var.bits_per_pixel = bpp; par->line_length = win->w[plane].xres * bpp / 8; /* in bytes */ /* * Allocate LCD framebuffer from system memory * Set page reserved so that mmap will work. This is necessary * since we'll be remapping normal memory. */ fb_info->fb_size = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; fb_info->fb_virt_start = au1200fb_alloc_fbmem(fb_info->fb_size); if (!fb_info->fb_virt_start) { printk("Unable to allocate fb memory\n"); return -ENOMEM; } fb_info->fb_phys = virt_to_bus((void *)fb_info->fb_virt_start); for (page = fb_info->fb_virt_start; page < PAGE_ALIGN(fb_info->fb_virt_start + fb_info->fb_size); page += PAGE_SIZE) { SetPageReserved(virt_to_page(page)); } /* Convert to kseg1 */ fb_info->fb_virt_start = (void *)((u32)fb_info->fb_virt_start | 0xA0000000); // FIX!!! may wish to avoid this to save startup time??? memset((void *)fb_info->fb_virt_start, 0, fb_info->fb_size); fb_info->gen.parsize = sizeof(struct au1200fb_par); fb_info->gen.fbhw = &au1200_switch; strcpy(fb_info->gen.info.modename, "Au1200 LCD"); fb_info->gen.info.changevar = NULL; fb_info->gen.info.node = -1; fb_info->gen.info.fbops = &au1200fb_ops; fb_info->gen.info.disp = disp; fb_info->gen.info.switch_con = &fbgen_switch; fb_info->gen.info.updatevar = &fbgen_update_var; fb_info->gen.info.blank = &fbgen_blank; fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT; fb_info->nohwcursor = 1; fb_info->noblanking = 1; /* This should give a reasonable default video mode */ fbgen_get_var(&disp->var, -1, &fb_info->gen.info); fbgen_do_set_var(&disp->var, 1, &fb_info->gen); fbgen_set_disp(-1, &fb_info->gen); fbgen_install_cmap(0, &fb_info->gen); /* Turn on plane */ au1200_setmode(plane); if (register_framebuffer(&fb_info->gen.info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s plane %d @ %08X (%d x %d x %d)\n", GET_FB_IDX(fb_info->gen.info.node), fb_info->gen.info.modename, plane, fb_info->fb_phys, win->w[plane].xres, win->w[plane].yres, bpp); } /* uncomment this if your driver cannot be unloaded */ /* MOD_INC_USE_COUNT; */ return 0;}void au1200fb_setup(char *options, int *ints){ char* this_opt; int i; int num_panels = sizeof(panels)/sizeof(struct panel_settings); if (!options || !*options) return; for(this_opt=strtok(options, ","); this_opt; this_opt=strtok(NULL, ",")) { if (!strncmp(this_opt, "panel:", 6)) {#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200) /* Read Pb1200 Rotary Switch S11 to obtain default panel */#ifdef CONFIG_MIPS_PB1200 if (!strncmp(this_opt+6, "s11", 3))#endif#ifdef CONFIG_MIPS_DB1200 if (!strncmp(this_opt+6, "s7", 3))#endif { BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; int p; p = bcsr->switches; p >>= 8; p &= 0x0F; if (p >= num_panels) p = 0; panel_index = p; } else#elif defined(CONFIG_MIPS_FICMMP) au1xxx_gpio_tristate(6); if(au1xxx_gpio_read(12) == 0) panel_index = 8; else panel_index = 7;#endif /* Get the panel name, everything else if fixed */ for (i=0; i<num_panels; i++) { if (!strncmp(this_opt+6, panels[i].name, strlen(this_opt))) { panel_index = i; break; } } } else if (!strncmp(this_opt, "nohwcursor", 10)) { printk("nohwcursor\n"); fb_infos[0].nohwcursor = 1; } } panel_index = 3; // Tengfei@ Debug printk("au1200fb: Panel %d %s\n", panel_index, panels[panel_index].name);}#ifdef MODULEMODULE_LICENSE("GPL");MODULE_DESCRIPTION("Au1200 LCD framebuffer driver");void au1200fb_cleanup(struct fb_info *info){ unregister_framebuffer(info);}module_init(au1200fb_init);module_exit(au1200fb_cleanup);#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -