au1200fb.c
来自「Linux环境下视频显示卡设备的驱动程序源代码」· C语言 代码 · 共 1,922 行 · 第 1/4 页
C
1,922 行
| LCD_WINCTRL2_DBM | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | LCD_WINCTRL2_SCX_1 | LCD_WINCTRL2_SCY_1 ) ; lcd->winenable |= win->w[plane].mode_winenable; au_sync();}/* Inline helpers *//*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*//*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)/* Bitfields format supported by the controller. */static struct fb_bitfield rgb_bitfields[][4] = { /* Red, Green, Blue, Transp */ [LCD_WINCTRL1_FRM_16BPP655 >> 25] = { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, [LCD_WINCTRL1_FRM_16BPP565 >> 25] = { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, [LCD_WINCTRL1_FRM_16BPP556 >> 25] = { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, [LCD_WINCTRL1_FRM_24BPP >> 25] = { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, [LCD_WINCTRL1_FRM_32BPP >> 25] = { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },};/*-------------------------------------------------------------------------*//* Helpers */static void au1200fb_update_fbinfo(struct fb_info *fbi){ /* FIX!!!! This also needs to take the window pixel format into account!!! */ /* Update var-dependent FB info */ if (panel_is_color(panel)) { if (fbi->var.bits_per_pixel <= 8) { /* palettized */ fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; fbi->fix.line_length = fbi->var.xres_virtual / (8/fbi->var.bits_per_pixel); } else { /* non-palettized */ fbi->fix.visual = FB_VISUAL_TRUECOLOR; fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); } } else { /* mono FIX!!! mono 8 and 4 bits */ fbi->fix.visual = FB_VISUAL_MONO10; fbi->fix.line_length = fbi->var.xres_virtual / 8; } fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; print_dbg("line length: %d\n", fbi->fix.line_length); print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);}/*-------------------------------------------------------------------------*//* AU1200 framebuffer driver *//* fb_check_var * Validate var settings with hardware restrictions and modify it if necessary */static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi){ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; u32 pixclock; int screen_size, plane; plane = fbdev->plane; /* Make sure that the mode respect all LCD controller and * panel restrictions. */ var->xres = win->w[plane].xres; var->yres = win->w[plane].yres; /* No need for virtual resolution support */ var->xres_virtual = var->xres; var->yres_virtual = var->yres; var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); screen_size = var->xres_virtual * var->yres_virtual; if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); else screen_size /= (8/var->bits_per_pixel); if (fbdev->fb_len < screen_size) return -EINVAL; /* Virtual screen is to big, abort */ /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel * clock can only be obtain by dividing this value by an even integer. * Fallback to a slower pixel clock if necessary. */ pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); if (AU1200_LCD_MAX_CLK % pixclock) { int diff = AU1200_LCD_MAX_CLK % pixclock; pixclock -= diff; } var->pixclock = KHZ2PICOS(pixclock/1000);#if 0 if (!panel_is_active(panel)) { int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; if (!panel_is_color(panel) && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { /* STN 8bit mono panel support is up to 6MHz pixclock */ var->pixclock = KHZ2PICOS(6000); } else if (!pcd) { /* Other STN panel support is up to 12MHz */ var->pixclock = KHZ2PICOS(12000); } }#endif /* Set bitfield accordingly */ switch (var->bits_per_pixel) { case 16: { /* 16bpp True color. * These must be set to MATCH WINCTRL[FORM] */ int idx; idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; var->red = rgb_bitfields[idx][0]; var->green = rgb_bitfields[idx][1]; var->blue = rgb_bitfields[idx][2]; var->transp = rgb_bitfields[idx][3]; break; } case 32: { /* 32bpp True color. * These must be set to MATCH WINCTRL[FORM] */ int idx; idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; var->red = rgb_bitfields[idx][0]; var->green = rgb_bitfields[idx][1]; var->blue = rgb_bitfields[idx][2]; var->transp = rgb_bitfields[idx][3]; break; } default: print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); return -EINVAL; } return 0;}/* fb_set_par * Set hardware with var settings. This will enable the controller with a * specific mode, normally validated with the fb_check_var method */static int au1200fb_fb_set_par(struct fb_info *fbi){ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; au1200fb_update_fbinfo(fbi); au1200_setmode(fbdev); return 0;}/* fb_setcolreg * Set color in LCD palette. */static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi){ volatile u32 *palette = lcd->palette; u32 value; if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) return -EINVAL; if (fbi->var.grayscale) { /* Convert color to grayscale */ red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16; } if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { /* Place color in the pseudopalette */ if (regno > 16) return -EINVAL; palette = (u32*) fbi->pseudo_palette; red >>= (16 - fbi->var.red.length); green >>= (16 - fbi->var.green.length); blue >>= (16 - fbi->var.blue.length); value = (red << fbi->var.red.offset) | (green << fbi->var.green.offset)| (blue << fbi->var.blue.offset); value &= 0xFFFF; } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { /* COLOR TFT PALLETTIZED (use RGB 565) */ value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F); value &= 0xFFFF; } else if (0 /*panel_is_color(fbdev->panel)*/) { /* COLOR STN MODE */ value = 0x1234; value &= 0xFFF; } else { /* MONOCHROME MODE */ value = (green >> 12) & 0x000F; value &= 0xF; } palette[regno] = value; return 0;}/* fb_blank * Blank the screen. Depending on the mode, the screen will be * activated with the backlight color, or desactivated */static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi){ /* Short-circuit screen blanking */ if (noblanking) return 0; switch (blank_mode) { case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL: /* printk("turn on panel\n"); */ au1200_setpanel(panel); break; case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: /* printk("turn off panel\n"); */ au1200_setpanel(NULL); break; default: break; } /* FB_BLANK_NORMAL is a soft blank */ return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 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) */static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma){ unsigned int len; unsigned long start=0, off; struct au1200fb_device *fbdev = (struct au1200fb_device *) info;#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; return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); return 0;}static void set_global(u_int cmd, struct 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();}static void get_global(u_int cmd, struct 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();}static void set_window(unsigned int plane, struct au1200_lcd_window_regs_t *pdata){ unsigned int val, bpp; /* Window control register 0 */ if (pdata->flags & WIN_POSITION) { val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | LCD_WINCTRL0_OY); val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); lcd->window[plane].winctrl0 = val; } 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) { val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); lcd->window[plane].winctrl1 = val; /* program buffer line width */ bpp = winbpp(val) / 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; } /* Buffer line width programmed with WIN_SIZE */ if (pdata->flags & WIN_BUFFER_SCALE) { val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | LCD_WINCTRL2_SCY); val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); lcd->window[plane].winctrl2 = val; } if (pdata->flags & WIN_ENABLE) { val = lcd->winenable; val &= ~(1<<plane); val |= (pdata->enable & 1) << plane; lcd->winenable = val; } au_sync();}static void get_window(unsigned int plane, struct au1200_lcd_window_regs_t *pdata){ /* Window control register 0 */ pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?