📄 viafbdev.c
字号:
/* * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE.See the GNU General Public License * for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifdef MODULE#include <linux/module.h>#endif#define _MASTER_FILE#include "global.h"static int MAX_CURS = 32;static struct fb_var_screeninfo default_var;static char *viafb_name = "Via";static u32 pseudo_pal[17];/* video mode */static char *viafb_mode = "640x480";static char *viafb_mode1 = "640x480";static int viafb_resMode = VIA_RES_640X480;/* Added for specifying active devices.*/char *viafb_active_dev = "";/* Added for specifying video on devices.*/char *viafb_video_dev = "";/*Added for specify lcd output port*/char *viafb_lcd_port = "";char *viafb_dvi_port = "";static int timer_on;struct timer_list timer_for3D;static void viafb_set_device(struct device_t active_dev);static int apply_device_setting(struct viafb_ioctl_setting setting_info, struct fb_info *info);static void apply_second_mode_setting(struct fb_var_screeninfo *sec_var);static void retrieve_device_setting(struct viafb_ioctl_setting *setting_info);static void viafb_set_video_device(u32 video_dev_info);static void viafb_get_video_device(u32 *video_dev_info);/* Mode information */static const struct viafb_modeinfo viafb_modentry[] = { {480, 640, VIA_RES_480X640, "480x640"}, {640, 480, VIA_RES_640X480, "640x480"}, {800, 480, VIA_RES_800X480, "800x480"}, {800, 600, VIA_RES_800X600, "800x600"}, {1024, 768, VIA_RES_1024X768, "1024x768"}, {1152, 864, VIA_RES_1152X864, "1152x864"}, {1280, 1024, VIA_RES_1280X1024, "1280x1024"}, {1600, 1200, VIA_RES_1600X1200, "1600x1200"}, {1440, 1050, VIA_RES_1440X1050, "1440x1050"}, {1280, 768, VIA_RES_1280X768, "1280x768"}, {1280, 800, VIA_RES_1280X800, "1280x800"}, {1280, 960, VIA_RES_1280X960, "1280x960"}, {1920, 1440, VIA_RES_1920X1440, "1920x1440"}, {848, 480, VIA_RES_848X480, "848x480"}, {1400, 1050, VIA_RES_1400X1050, "1400x1050"}, {720, 480, VIA_RES_720X480, "720x480"}, {720, 576, VIA_RES_720X576, "720x576"}, {1024, 512, VIA_RES_1024X512, "1024x512"}, {1024, 576, VIA_RES_1024X576, "1024x576"}, {1024, 600, VIA_RES_1024X600, "1024x600"}, {1280, 720, VIA_RES_1280X720, "1280x720"}, {1920, 1080, VIA_RES_1920X1080, "1920x1080"}, {1366, 768, VIA_RES_1368X768, "1368x768"}, {1680, 1050, VIA_RES_1680X1050, "1680x1050"}, {960, 600, VIA_RES_960X600, "960x600"}, {1000, 600, VIA_RES_1000X600, "1000x600"}, {1024, 576, VIA_RES_1024X576, "1024x576"}, {1024, 600, VIA_RES_1024X600, "1024x600"}, {1088, 612, VIA_RES_1088X612, "1088x612"}, {1152, 720, VIA_RES_1152X720, "1152x720"}, {1200, 720, VIA_RES_1200X720, "1200x720"}, {1280, 600, VIA_RES_1280X600, "1280x600"}, {1360, 768, VIA_RES_1360X768, "1360x768"}, {1440, 900, VIA_RES_1440X900, "1440x900"}, {1600, 900, VIA_RES_1600X900, "1600x900"}, {1600, 1024, VIA_RES_1600X1024, "1600x1024"}, {1792, 1344, VIA_RES_1792X1344, "1792x1344"}, {1856, 1392, VIA_RES_1856X1392, "1856x1392"}, {1920, 1200, VIA_RES_1920X1200, "1920x1200"}, {2048, 1536, VIA_RES_2048X1536, "2048x1536"}, {0, 0, VIA_RES_INVALID, "640x480"}};static struct fb_ops viafb_ops;static void get_panel_max_scal_size(struct _panel_size_pos_info *p_max_size){ switch (p_max_size->device_type) { case DVI_Device: p_max_size->x = p_max_size->y = 0; break; default: p_max_size->x = p_max_size->y = 0; }}static void get_panel_max_scal_pos(struct _panel_size_pos_info *p_para){ switch (p_para->device_type) { case DVI_Device: p_para->x = p_para->y = 0; break; default: p_para->x = p_para->y = 0; }}static void get_panel_scal_pos(struct _panel_size_pos_info *p_para){ switch (p_para->device_type) { case DVI_Device: p_para->x = p_para->y = 0; break; default: p_para->x = p_para->y = 0; }}static void get_panel_scal_size(struct _panel_size_pos_info *p_para){ switch (p_para->device_type) { case DVI_Device: p_para->x = p_para->y = 0; break; default: p_para->x = p_para->y = 0; }}static void set_panel_scal_pos(struct _panel_size_pos_info *p_para){ switch (p_para->device_type) { case DVI_Device: break; default: ; }}static void set_panel_scal_size(struct _panel_size_pos_info *p_para){ switch (p_para->device_type) { case DVI_Device: break; default: ; }}static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info){ struct viafb_par *ppar; ppar = info->par; DEBUG_MSG(KERN_INFO "viafb_update_fix!\n"); fix->visual = ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; fix->line_length = ppar->linelength; return 0;}static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, struct viafb_par *viaparinfo){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, viafb_name); fix->smem_start = viaparinfo->fbmem; fix->smem_len = viaparinfo->fbmem_free; fix->mmio_start = viaparinfo->mmio_base; fix->mmio_len = viaparinfo->mmio_len; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; /* Just tell the accel name */ viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;}static int viafb_open(struct fb_info *info, int user){ DEBUG_MSG(KERN_INFO "viafb_open!\n"); return 0;}static int viafb_release(struct fb_info *info, int user){ DEBUG_MSG(KERN_INFO "viafb_release!\n"); return 0;}static void viafb_update_viafb_par(struct fb_info *info){ struct viafb_par *ppar; ppar = info->par; ppar->bpp = info->var.bits_per_pixel; ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8; ppar->hres = info->var.xres; ppar->vres = info->var.yres; ppar->xoffset = info->var.xoffset; ppar->yoffset = info->var.yoffset;}static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ int vmode_index, htotal, vtotal; struct viafb_par *ppar; u32 long_refresh; ppar = info->par; DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ /* HW neither support interlacte nor double-scaned mode */ if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) return -EINVAL; vmode_index = viafb_get_mode_index(var->xres, var->yres, 0); if (vmode_index == VIA_RES_INVALID) { DEBUG_MSG(KERN_INFO "viafb: Mode %dx%dx%d not supported!!\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } if (24 == var->bits_per_pixel) var->bits_per_pixel = 32; if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && var->bits_per_pixel != 32) return -EINVAL; if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) /*32 pixel alignment */ var->xres_virtual = (var->xres_virtual + 31) & ~31; if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > ppar->memsize) return -EINVAL; /* Based on var passed in to calculate the refresh, * because our driver use some modes special. */ htotal = var->xres + var->left_margin + var->right_margin + var->hsync_len; vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; long_refresh = 1000000000UL / var->pixclock * 1000; long_refresh /= (htotal * vtotal); viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); /* Not supported by our driver, reutrn immediately */ if (!viafb_refresh) return -EINVAL; /* Adjust var according to our driver's own table */ viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); return 0;}static int viafb_set_par(struct fb_info *info){ int vmode_index; int vmode_index1 = 0; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); viafb_update_device_setting(info->var.xres, info->var.yres, info->var.bits_per_pixel, viafb_refresh, 0); vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0); if (viafb_SAMM_ON == 1) { DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", viafb_second_xres, viafb_second_yres, via_fb_bpp1); vmode_index1 = viafb_get_mode_index(viafb_second_xres, viafb_second_yres, 1); DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n", vmode_index1); viafb_update_device_setting(viafb_second_xres, viafb_second_yres, via_fb_bpp1, viafb_refresh1, 1); } if (vmode_index != VIA_RES_INVALID) { viafb_setmode(vmode_index, info->var.xres, info->var.yres, info->var.bits_per_pixel, vmode_index1, viafb_second_xres, viafb_second_yres, via_fb_bpp1); /*We should set memory offset according virtual_x */ /*Fix me:put this function into viafb_setmode */ viafb_memory_pitch_patch(info); /* Update ***fb_par information */ viafb_update_viafb_par(info); /* Update other fixed information */ viafb_update_fix(&info->fix, info); via_fb_bpp = info->var.bits_per_pixel; /* Update via_fb_accel, it is necessary to our 2D accelerate */ via_fb_accel = info->var.accel_flags; if (via_fb_accel) viafb_set_2d_color_depth(info->var.bits_per_pixel); } return 0;}static int viafb_get_cmap_len(struct fb_var_screeninfo *var){ DEBUG_MSG(KERN_INFO "viafb_get_cmap_len!\n"); return (var->bits_per_pixel == 8) ? 256 : 16;}/* Set one color register */static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,unsigned blue, unsigned transp, struct fb_info *info){ u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n"); if (regno >= viafb_get_cmap_len(&info->var)) return 1; if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { /* Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev. */ outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; } switch (info->var.bits_per_pixel) { case 8: outb(0x1A, 0x3C4); sr1a = inb(0x3C5); outb(0x1B, 0x3C4); sr1b = inb(0x3C5); outb(0x67, 0x3D4); cr67 = inb(0x3D5); outb(0x6A, 0x3D4); cr6a = inb(0x3D5); /* Map the 3C6/7/8/9 to the IGA2 */ outb(0x1A, 0x3C4); outb(sr1a | 0x01, 0x3C5); /* Second Display Engine colck always on */ outb(0x1B, 0x3C4); outb(sr1b | 0x80, 0x3C5); /* Second Display Color Depth 8 */ outb(0x67, 0x3D4); outb(cr67 & 0x3F, 0x3D5); outb(0x6A, 0x3D4); /* Second Display Channel Reset CR6A[6]) */ outb(cr6a & 0xBF, 0x3D5); /* Second Display Channel Enable CR6A[7] */ outb(cr6a | 0x80, 0x3D5); /* Second Display Channel stop reset) */ outb(cr6a | 0x40, 0x3D5); /* Bit mask of palette */ outb(0xFF, 0x3c6); /* Write one register of IGA2 */ outb(regno, 0x3C8); if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && rev >= 15) { shift = 8; viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); } else { shift = 10; viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); viafb_write_reg_mask(SR15, VIASR, 0, BIT7); } outb(red >> shift, 0x3C9); outb(green >> shift, 0x3C9); outb(blue >> shift, 0x3C9); /* Map the 3C6/7/8/9 to the IGA1 */ outb(0x1A, 0x3C4); outb(sr1a & 0xFE, 0x3C5); /* Bit mask of palette */ outb(0xFF, 0x3c6); /* Write one register of IGA1 */ outb(regno, 0x3C8); outb(red >> shift, 0x3C9); outb(green >> shift, 0x3C9); outb(blue >> shift, 0x3C9); outb(0x1A, 0x3C4); outb(sr1a, 0x3C5); outb(0x1B, 0x3C4); outb(sr1b, 0x3C5); outb(0x67, 0x3D4); outb(cr67, 0x3D5); outb(0x6A, 0x3D4); outb(cr6a, 0x3D5); break; case 16: ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); break; case 32: ((u32 *) info->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); break; } return 0;}/*CALLED BY: fb_set_cmap *//* fb_set_var, pass 256 colors *//*CALLED BY: fb_set_cmap *//* fbcon_set_palette, pass 16 colors */static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info){ u32 len = cmap->len; u32 i; u16 *pred = cmap->red; u16 *pgreen = cmap->green; u16 *pblue = cmap->blue; u16 *ptransp = cmap->transp; u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; if (len > 256) return 1; if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { /* Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip rev. */ outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; } switch (info->var.bits_per_pixel) { case 8: outb(0x1A, 0x3C4); sr1a = inb(0x3C5); outb(0x1B, 0x3C4); sr1b = inb(0x3C5); outb(0x67, 0x3D4); cr67 = inb(0x3D5); outb(0x6A, 0x3D4); cr6a = inb(0x3D5); /* Map the 3C6/7/8/9 to the IGA2 */ outb(0x1A, 0x3C4); outb(sr1a | 0x01, 0x3C5);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -