?? au1200fb.patch
字號:
+ au1200_setpanel(NULL);+ break;+ default: + break;++ }+ return 0;+}++/* fb_mmap+ * Map video memory in user space. We don't use the generic fb_mmap method mainly+ * to allow the use of the TLB streaming flag (CCA=6)+ */+int au1200fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma)+{+ unsigned int len;+ unsigned long start=0, off;+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;++#ifdef CONFIG_PM+ au1xxx_pm_access(LCD_pm_dev);+#endif++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {+ return -EINVAL;+ }+ + start = fbdev->fb_phys & PAGE_MASK;+ len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);++ off = vma->vm_pgoff << PAGE_SHIFT;++ if ((vma->vm_end - vma->vm_start + off) > len) {+ return -EINVAL;+ }++ off += start;+ vma->vm_pgoff = off >> PAGE_SHIFT;++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);+ pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; //CCA=7++ vma->vm_flags |= VM_IO;+ + if (io_remap_page_range(vma, vma->vm_start, off,+ vma->vm_end - vma->vm_start,+ vma->vm_page_prot)) {+ return -EAGAIN;+ }++ return 0;+}++void set_global(u_int cmd, au1200_lcd_global_regs_t *pdata) {++ unsigned int hi1, divider;+ + /* SCREEN_SIZE: user cannot reset size, must switch panel choice */+ + if (pdata->flags & SCREEN_BACKCOLOR)+ lcd->backcolor = pdata->backcolor;+ + if (pdata->flags & SCREEN_BRIGHTNESS) {+ + // limit brightness pwm duty to >= 30/1600+ if (pdata->brightness < 30) {+ pdata->brightness = 30;+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;+ hi1 = (lcd->pwmhi >> 16) + 1;+ hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);+ lcd->pwmhi &= 0xFFFF;+ lcd->pwmhi |= (hi1 << 16);+ }+ + if (pdata->flags & SCREEN_COLORKEY)+ lcd->colorkey = pdata->colorkey;+ + if (pdata->flags & SCREEN_MASK)+ lcd->colorkeymsk = pdata->mask;+ au_sync();+}++void get_global(u_int cmd, au1200_lcd_global_regs_t *pdata) {+ unsigned int hi1, divider;+ + pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;+ pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;+ + pdata->backcolor = lcd->backcolor;+ pdata->colorkey = lcd->colorkey;+ pdata->mask = lcd->colorkeymsk;+ + // brightness+ hi1 = (lcd->pwmhi >> 16) + 1;+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;+ pdata->brightness = ((hi1 << 8) / divider) - 1;+ au_sync();+}++void print_global(au1200_lcd_global_regs_t *pdata) {++ printk("pdata->xsize %x\n", pdata->xsize);+ printk("pdata->ysize %x\n", pdata->ysize);+ printk("pdata->backcolor %x\n", pdata->backcolor);+ printk("pdata->brightness %x\n", pdata->brightness);+ printk("pdata->colorkey %x\n", pdata->colorkey);+ printk("pdata->mask %x\n", pdata->mask);+}++void set_window(unsigned int plane, au1200_lcd_window_regs_t *pdata) {+ + unsigned int val, bpp, move_window = 0;+ + /* Window control register 0 */+ if (pdata->flags & WIN_POSITION) {+ win->w[plane].xpos = pdata->xpos;+ win->w[plane].ypos = pdata->ypos;+ move_window = 1;+ }+ if (pdata->flags & WIN_ALPHA_COLOR) {+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);+ val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);+ lcd->window[plane].winctrl0 = val;+ }+ if (pdata->flags & WIN_ALPHA_MODE) {+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);+ val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);+ lcd->window[plane].winctrl0 = val;+ }+ + /* Window control register 1 */+ if (pdata->flags & WIN_PRIORITY) {+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);+ val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);+ lcd->window[plane].winctrl1 = val;+ }+ if (pdata->flags & WIN_CHANNEL) {+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);+ val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);+ lcd->window[plane].winctrl1 = val;+ }+ if (pdata->flags & WIN_BUFFER_FORMAT) {+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);+ val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);+ lcd->window[plane].winctrl1 = val;+ }+ if (pdata->flags & WIN_COLOR_ORDER) {+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);+ val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);+ lcd->window[plane].winctrl1 = val;+ }+ if (pdata->flags & WIN_PIXEL_ORDER) {+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);+ val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);+ lcd->window[plane].winctrl1 = val;+ }+ if (pdata->flags & WIN_SIZE) {+ win->w[plane].xres = pdata->xsize;+ win->w[plane].yres = pdata->ysize;+ move_window = 1;+ + /* program buffer line width */+ bpp = winbpp(lcd->window[plane].winctrl1) / 8;+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);+ val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);+ lcd->window[plane].winctrl2 = val;+ }+ + /* Window control register 2 */+ if (pdata->flags & WIN_COLORKEY_MODE) {+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);+ val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);+ lcd->window[plane].winctrl2 = val;+ }+ if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);+ val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);+ lcd->window[plane].winctrl2 = val;+ }+ if (pdata->flags & WIN_RAM_ARRAY_MODE) {+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);+ val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);+ lcd->window[plane].winctrl2 = val;+ + move_window = 1;+ if (pdata->ram_array_mode == 3) {+ _au1200fb_devices[plane].fb_phys = 0;+ }+ else {+ _au1200fb_devices[plane].fb_phys = virt_to_phys(_au1200fb_devices[plane].fb_mem);+ }+ }+ + if (pdata->flags & WIN_BUFFER_SCALE) {+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | LCD_WINCTRL2_SCY);+ val |= ((pdata->xscale << 4) & LCD_WINCTRL2_SCX);+ val |= ((pdata->yscale) & LCD_WINCTRL2_SCY);+ + /* program buffer line width */+ bpp = winbpp(lcd->window[plane].winctrl1) / 8;+ val &= ~(LCD_WINCTRL2_BX);+ + if (pdata->xscale == 1)+ val |= (((win->w[plane].xres * bpp / 2) << 8) & LCD_WINCTRL2_BX);+ else if (pdata->xscale == 2)+ val |= (((win->w[plane].xres * bpp / 4) << 8) & LCD_WINCTRL2_BX);+ else+ val |= (((win->w[plane].xres * bpp) << 8) & LCD_WINCTRL2_BX);+ lcd->window[plane].winctrl2 = val;+ + /* check off-screen and window size */+ move_window = 1;+ }+ + if (pdata->flags & WIN_ENABLE) {+ val = lcd->winenable;+ val &= ~(1<<plane);+ val |= (pdata->enable & 1) << plane;+ lcd->winenable = val;+ /* check for off-screen before enabling */+ move_window = 1;+ }+ au_sync();+ + if (move_window) {+ au1200_setlocation(&_au1200fb_devices[plane], plane, win->w[plane].xpos, win->w[plane].ypos);+ }+}++void get_window(unsigned int plane, au1200_lcd_window_regs_t *pdata) {++ /* Window control register 0 */+ pdata->xpos = win->w[plane].xpos;+ pdata->ypos = win->w[plane].ypos;+ pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;+ pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;+ + /* Window control register 1 */+ pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;+ pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;+ pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;+ pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;+ pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;+ pdata->xsize = win->w[plane].xres;+ pdata->ysize = win->w[plane].yres;+ + /* Window control register 2 */+ pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;+ pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;+ pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;+ pdata->xscale = ((lcd->window[plane].winctrl2 & LCD_WINCTRL2_SCX) >> 4);+ pdata->yscale = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_SCY);+ + pdata->enable = (lcd->winenable >> plane) & 1;+ au_sync();+}++static int au1200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,+ u_long arg, struct fb_info *info)+{+ int plane;+ int val;++#ifdef CONFIG_PM+ au1xxx_pm_access(LCD_pm_dev);+#endif+ + plane = fbinfo2index(info);+ print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);+ + if (cmd == AU1200_LCD_FB_IOCTL) {+ au1200_lcd_iodata_t iodata;+ + if (copy_from_user(&iodata, (void *) arg, sizeof(au1200_lcd_iodata_t)))+ return -EFAULT;+ + print_dbg("FB IOCTL called\n");+ + switch (iodata.subcmd)+ {+ + case AU1200_LCD_SET_SCREEN:+ print_dbg("AU1200_LCD_SET_SCREEN\n");+ set_global(cmd, &iodata.global);+ break;+ + case AU1200_LCD_GET_SCREEN:+ print_dbg("AU1200_LCD_GET_SCREEN\n");+ get_global(cmd, &iodata.global);+ break;+ + case AU1200_LCD_SET_WINDOW:+ print_dbg("AU1200_LCD_SET_WINDOW\n");+ set_window(plane, &iodata.window);+ break;+ + case AU1200_LCD_GET_WINDOW:+ print_dbg("AU1200_LCD_GET_WINDOW\n");+ get_window(plane, &iodata.window);+ break;+ + case AU1200_LCD_SET_PANEL:+ print_dbg("AU1200_LCD_SET_PANEL\n");+ if ((iodata.global.panel_choice >= 0) && (iodata.global.panel_choice < NUM_PANELS))+ {+ struct panel_settings *newpanel;+ panel_index = iodata.global.panel_choice;+ newpanel = &known_lcd_panels[panel_index];+ au1200_setpanel(newpanel);+ }+ break;+ + case AU1200_LCD_GET_PANEL:+ print_dbg("AU1200_LCD_GET_PANEL\n");+ iodata.global.panel_choice = panel_index;+ break;+ + default:+ return -EINVAL;+ }+ + val = copy_to_user((void *) arg, &iodata, sizeof(au1200_lcd_iodata_t));+ if (val) {+ print_dbg("error: could not copy %d bytes\n", val);+ return -EFAULT;+ }+ }+ +return 0;+}+++static struct fb_ops au1200fb_fb_ops = +{+ .owner = THIS_MODULE,+ .fb_open = au1200fb_fb_open,+ .fb_release = au1200fb_fb_release,+ .fb_check_var = au1200fb_fb_check_var,+ .fb_set_par = au1200fb_fb_set_par,+ .fb_setcolreg = au1200fb_fb_setcolreg,+ .fb_blank = au1200fb_fb_blank,+ .fb_fillrect = cfb_fillrect,+ .fb_copyarea = cfb_copyarea,+ .fb_imageblit = cfb_imageblit,+ .fb_cursor = soft_cursor,+ .fb_sync = NULL,+ .fb_ioctl = au1200fb_ioctl,+ .fb_mmap = au1200fb_fb_mmap, //NULL for fb_mmap ???+};++/*-------------------------------------------------------------------------*/++static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs)+{+ /* Nothing to do for now, just clear any pending interrupt */+ lcd->intstatus = lcd->intstatus;+ au_sync();+ return IRQ_HANDLED;+}++/*-------------------------------------------------------------------------*/++/* AU1200 LCD device probe helpers */++static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)+{+ struct fb_info *fbi = &fbdev->fb_info;+ int bpp;+ + memset(fbi, 0, sizeof(struct fb_info));+ fbi->fbops = &au1200fb_fb_ops;+ + bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);++ /* Copy monitor specs from panel data */+ /* FIX!!! we're setting up LCD controller windows, so these dont give a+ damn as to what the monitor specs are (the panel itself does, but that+ isnt done here...so maybe need a generic catchall monitor setting??? */+ memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));++ /* We first try the user mode passed in argument. If that failed, + * or if no one has been specified, we default to the first mode of the + * panel list. Note that after this call, var data will be set */+ if (!fb_find_mode(&fbi->var, + fbi, + NULL, //drv_info.opt_mode, + fbi->monspecs.modedb, + fbi->monspecs.modedb_len,+ fbi->monspecs.modedb, + bpp)) {++ print_err("Cannot find valid mode for panel %s", panel->name);+ return -EFAULT;+ }++ fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);+ if (!fbi->pseudo_palette) {+ return -ENOMEM;+ }+ memset(fbi->pseudo_palette, 0, sizeof(u32) * 16);++ if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {+ print_err("Fail to allocate colormap (%d entries)",+ AU1200_LCD_NBR_PALETTE_ENTRIES);+ kfree(fbi->pseudo_palette);+ return -EFAULT;+ }++ strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));+ fbi->fix.smem_start = fbdev->fb_phys;+ fbi->fix.smem_len = fbdev->fb_len;+ fbi->fix.type = FB_TYPE_PACKED_PIXELS;+ fbi->fix.xpanstep = 1;+ fbi->fix.ypanstep = 1;+ fbi->fix.mmio_start = 0;+ fbi->fix.mmio_len = 0;+ fbi->fix.accel = FB_ACCEL_NONE;++ fbi->screen_base = fbdev->fb_mem;++ au1200fb_update_fbinfo(fbi);++ return 0;+}++/*-------------------------------------------------------------------------*/++/* AU1200 LCD controller device driver */++int au1200fb_drv_probe(struct device *dev)+{+ struct au1200fb_device *fbdev;+ unsigned long page;+ int bpp, plane, ret;++ if (!dev)+ return -EINVAL;++ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -