📄 sis_main.c
字号:
#endif } return 0;}static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info){ unsigned int htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; unsigned int vtotal = 0; /* TW */ /* var->upper_margin + var->yres + var->lower_margin + var->vsync_len; */ double drate = 0, hrate = 0; int found_mode = 0; int old_mode; if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* TW */ vtotal <<= 1; } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* TW */ vtotal <<= 2; } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { vtotal = var->upper_margin + (var->yres/2) + var->lower_margin + var->vsync_len; /* TW */ /* var->yres <<= 1; */ /* TW */ } else vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; if (!(htotal) || !(vtotal)) { DPRINTK("sisfb: Invalid 'var' information\n"); return -EINVAL; } drate = 1E12 / var->pixclock; hrate = drate / htotal; ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5); DPRINTK("sisfb: Change mode to %dx%dx%d-%dMHz\n", var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate); old_mode = sisfb_mode_idx; sisfb_mode_idx = 0; while ((sisbios_mode[sisfb_mode_idx].mode_no != 0) && (sisbios_mode[sisfb_mode_idx].xres <= var->xres)) { if ((sisbios_mode[sisfb_mode_idx].xres == var->xres) && (sisbios_mode[sisfb_mode_idx].yres == var->yres) && (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) { sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no; found_mode = 1; break; } sisfb_mode_idx++; } if (found_mode) sisfb_validate_mode(); else sisfb_mode_idx = -1; if (sisfb_mode_idx < 0) { DPRINTK("sisfb: sisfb does not support mode %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel); sisfb_mode_idx = old_mode; return -EINVAL; } if (sisfb_search_refresh_rate(ivideo.refresh_rate) == 0) { sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx; ivideo.refresh_rate = 60; } if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) { sisfb_pre_setmode(); if (SiSSetMode(&sishw_ext, sisfb_mode_no) == 0) { DPRINTK("sisfb: Setting mode[0x%x]: failed\n", sisfb_mode_no); return -1; } vgawb(SEQ_ADR, IND_SIS_PASSWORD); vgawb(SEQ_DATA, SIS_PASSWORD); sisfb_post_setmode(); DPRINTK("sisfb: Set new mode: %dx%dx%d-%d \n", sisbios_mode[sisfb_mode_idx].xres, sisbios_mode[sisfb_mode_idx].yres, sisbios_mode[sisfb_mode_idx].bpp, ivideo.refresh_rate); ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp; ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres; ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres; ivideo.org_x = ivideo.org_y = 0; video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3); } return 0;}static void sisfb_set_disp(int con, struct fb_var_screeninfo *var){ struct fb_fix_screeninfo fix; struct display *display; struct display_switch *sw; u32 flags; if (con >= 0) display = &fb_display[con]; else display = &disp; sisfb_get_fix(&fix, con, 0); display->screen_base = ivideo.video_vbase; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; display->ypanstep = fix.ypanstep; display->ywrapstep = fix.ywrapstep; display->line_length = fix.line_length; display->next_line = fix.line_length; display->can_soft_blank = 0; display->inverse = sisfb_inverse; display->var = *var; save_flags(flags); switch (ivideo.video_bpp) {#ifdef FBCON_HAS_CFB8 case 8: sw = &fbcon_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case 15: case 16: sw = &fbcon_cfb16; display->dispsw_data = fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: sw = &fbcon_cfb24; display->dispsw_data = fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: sw = &fbcon_cfb32; display->dispsw_data = fbcon_cmap.cfb32; break;#endif default: sw = &fbcon_dummy; return; } memcpy(&sisfb_sw, sw, sizeof(*sw)); display->dispsw = &sisfb_sw; restore_flags(flags); display->scrollmode = SCROLL_YREDRAW; sisfb_sw.bmove = fbcon_redraw_bmove;}static void sisfb_do_install_cmap(int con, struct fb_info *info){ if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, 1, sis_setcolreg, info); else fb_set_cmap(fb_default_cmap(video_cmap_len), 1, sis_setcolreg, info);}/* --------------- Chip-dependent Routines --------------------------- */#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */static int sisfb_get_dram_size_300(void){ struct pci_dev *pdev = NULL; int pdev_valid = 0; u8 pci_data, reg; u16 nbridge_id; switch (ivideo.chip) { case SIS_540: nbridge_id = PCI_DEVICE_ID_SI_540; break; case SIS_630: nbridge_id = PCI_DEVICE_ID_SI_630; break; case SIS_730: nbridge_id = PCI_DEVICE_ID_SI_730; break; default: nbridge_id = 0; break; } if (nbridge_id == 0) { /* 300 */ vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE); ivideo.video_size = ((unsigned int) ((vgarb(SEQ_DATA) & SIS_DRAM_SIZE_MASK) + 1) << 20); } else { /* 540, 630, 730 */ pci_for_each_dev(pdev) { if ((pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device == nbridge_id)) { pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data); pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4; ivideo.video_size = (unsigned int)(1 << (pci_data+21)); pdev_valid = 1; reg = SIS_DATA_BUS_64 << 6; vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE); switch (pci_data) { case BRI_DRAM_SIZE_2MB: reg |= SIS_DRAM_SIZE_2MB; break; case BRI_DRAM_SIZE_4MB: reg |= SIS_DRAM_SIZE_4MB; break; case BRI_DRAM_SIZE_8MB: reg |= SIS_DRAM_SIZE_8MB; break; case BRI_DRAM_SIZE_16MB: reg |= SIS_DRAM_SIZE_16MB; break; case BRI_DRAM_SIZE_32MB: reg |= SIS_DRAM_SIZE_32MB; break; case BRI_DRAM_SIZE_64MB: reg |= SIS_DRAM_SIZE_64MB; break; } vgawb(SEQ_DATA, reg); break; } } if (!pdev_valid) return -1; } return 0;}static void sisfb_detect_VB_connect_300(){ u8 sr16, sr17, cr32, temp; vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_17); sr17 = vgarb(SEQ_DATA); vgawb(CRTC_ADR, IND_SIS_SCRATCH_REG_CR32); cr32 = vgarb(CRTC_DATA); ivideo.TV_plug = ivideo.TV_type = 0; if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) { if ((sr17 & 0x01) && !sisfb_crt1off) sisfb_crt1off = 0; else { if (sr17 & 0x0E) sisfb_crt1off = 1; else sisfb_crt1off = 0; } if (sisfb_crt2type != -1) /* TW: override detected CRT2 type */ ivideo.disp_state = sisfb_crt2type; else if (sr17 & 0x08 ) ivideo.disp_state = DISPTYPE_CRT2; else if (sr17 & 0x02) ivideo.disp_state = DISPTYPE_LCD; else if (sr17 & 0x04) ivideo.disp_state = DISPTYPE_TV; else ivideo.disp_state = 0; if (sr17 & 0x20) ivideo.TV_plug = TVPLUG_SVIDEO; else if (sr17 & 0x10) ivideo.TV_plug = TVPLUG_COMPOSITE; vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_16); sr16 = vgarb(SEQ_DATA); if (sr16 & 0x20) ivideo.TV_type = TVMODE_PAL; else ivideo.TV_type = TVMODE_NTSC; } else { if ((cr32 & SIS_CRT1) && !sisfb_crt1off) sisfb_crt1off = 0; else { if (cr32 & 0x5F) sisfb_crt1off = 1; else sisfb_crt1off = 0; } if (sisfb_crt2type != -1) /* TW: override detected CRT2 type */ ivideo.disp_state = sisfb_crt2type; else if (cr32 & SIS_VB_CRT2) ivideo.disp_state = DISPTYPE_CRT2; else if (cr32 & SIS_VB_LCD) ivideo.disp_state = DISPTYPE_LCD; else if (cr32 & SIS_VB_TV) ivideo.disp_state = DISPTYPE_TV; else ivideo.disp_state = 0; /* TW: Detect TV plug & type anyway */ if (cr32 & SIS_VB_HIVISION) { ivideo.TV_type = TVMODE_HIVISION; ivideo.TV_plug = TVPLUG_SVIDEO; } else if (cr32 & SIS_VB_SVIDEO) ivideo.TV_plug = TVPLUG_SVIDEO; else if (cr32 & SIS_VB_COMPOSITE) ivideo.TV_plug = TVPLUG_COMPOSITE; else if (cr32 & SIS_VB_SCART) ivideo.TV_plug = TVPLUG_SCART; if (ivideo.TV_type == 0) { // Eden Chen //temp = *((u8 *)(sishw_ext.VirtualRomBase+0x52)); //if (temp&0x40) { // temp=*((u8 *)(sishw_ext.VirtualRomBase+0x53)); //} else { vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP); temp = vgarb(SEQ_DATA); //} // ~Eden Chen if (temp & 0x01) ivideo.TV_type = TVMODE_PAL; else ivideo.TV_type = TVMODE_NTSC; } } /* TW: Copy forceCRT1 option to CRT1off if option is given */ if (sisfb_forcecrt1 != -1) { vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_17); sr17 = vgarb(SEQ_DATA); if (sisfb_forcecrt1) { sisfb_crt1off=0; sr17 |= 0x80; } else { sisfb_crt1off=1; sr17 &= ~0x80; } vgawb(SEQ_DATA, sr17); }}static void sisfb_get_VB_type_300(void){ u8 reg; if (ivideo.chip != SIS_300) { if (!sisfb_has_VB_300()) { vgawb(CRTC_ADR, IND_SIS_SCRATCH_REG_CR37); reg = vgarb(CRTC_DATA); switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) { case SIS_EXTERNAL_CHIP_SIS301: ivideo.hasVB = HASVB_301; break; case SIS_EXTERNAL_CHIP_LVDS: ivideo.hasVB = HASVB_LVDS; break; case SIS_EXTERNAL_CHIP_TRUMPION: ivideo.hasVB = HASVB_TRUMPION; break; case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: ivideo.hasVB = HASVB_LVDS_CHRONTEL; break; case SIS_EXTERNAL_CHIP_CHRONTEL: ivideo.hasVB = HASVB_CHRONTEL; break; default: break; } } } else { sisfb_has_VB_300(); } //sishw_ext.hasVB = ivideo.hasVB;}static int sisfb_has_VB_300(void){ // Eden Chen //u8 sr38, sr39, vb_chipid; u8 vb_chipid; //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP); //sr38 = vgarb(SEQ_DATA); //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP2); //sr39 = vgarb(SEQ_DATA); vgawb(VB_PART4_ADR, 0x0); vb_chipid = vgarb(VB_PART4_DATA); switch (vb_chipid) { case 0x01: ivideo.hasVB = HASVB_301; break; case 0x02: ivideo.hasVB = HASVB_302; break; case 0x03: ivideo.hasVB = HASVB_303; break; default: ivideo.hasVB = HASVB_NONE; return FALSE; } return TRUE; //if ( // ( (ivideo.chip == SIS_300) && (sr38 & 0x20) ) // || // ( (ivideo.chip == SIS_540) && (sr38 & 0x20) && (!(sr39 & 0x80)) ) // || // ( (ivideo.chip == SIS_630 ) && (sr38 & 0x20) && (!(sr39 & 0x80)) && // ((ivideo.revision_id & 0xf0) < 0x30) && (vb_chipid == 1) ) // || // ( (ivideo.chip == SIS_630 ) && ((ivideo.revision_id & 0xf0) >= 0x30) && // (vb_chipid == 1) ) // || // ( (ivideo.chip == SIS_730) && (vb_chipid == 1) ) /* 730 */ //) { // ivideo.hasVB = HASVB_301; // return TRUE; //} else { // ivideo.hasVB = HASVB_NONE; // return FALSE; //} // ~Eden Chen}#endif /* CONFIG_FB_SIS_300 */#ifdef CONFIG_FB_SIS_315 /* for SiS 315H/315PRO/550/650/740 */static int sisfb_get_dram_size_315(void){ struct pci_dev *pdev = NULL; int pdev_valid = 0; u8 pci_data; u8 reg = 0; if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650) {#ifdef LINUXBIOS pci_for_each_dev(pdev) { if ( (pdev->vendor == PCI_VENDOR_ID_SI) && ( (pdev->device == PCI_DEVICE_ID_SI_550) || (pdev->device == PCI_DEVICE_ID_SI_650))) { pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data); pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4; ivideo.video_size = (unsigned int)(1 << (pci_data+21)); pdev_valid = 1; /* TW: Initialize SR14 "by hand" */ vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE); reg = vgarb(SEQ_DATA) & 0xC0; switch (pci_data) { //case BRI_DRAM_SIZE_2MB: // reg |= (SIS315_DRAM_SIZE_2MB << 4); break; case BRI_DRAM_SIZE_4MB: reg |= SIS550_DRAM_SIZE_4MB; break; case BRI_DRAM_SIZE_8MB: reg |= SIS550_DRAM_SIZE_8MB; break; case BRI_DRAM_SIZE_16MB: reg |= SIS550_DRAM_SIZE_16MB; break; case BRI_DRAM_SIZE_32MB: reg |= SIS550_DRAM_SIZE_32MB; break; case BRI_DRAM_SIZE_64MB: reg |= SIS550_DRAM_SIZE_64MB; break; /* case BRI_DRAM_SIZE_128MB: reg |= (SIS315_DRAM_SIZE_128MB << 4); break; */ } /* TODO : set Dual channel and bus width bits here */ vgawb(SEQ_DATA, reg); break; } } if (!pdev_valid) return -1;#else vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE); reg = vgarb(SEQ_DATA); switch (reg & SIS550_DRAM_SIZE_MASK) { case SIS550_DRAM_SIZE_4MB: ivideo.video_size = 0x400000; break; case SIS550_DRAM_SIZE_8MB: ivideo.video_size = 0x800000; break; case SIS550_DRAM_SIZE_16MB: ivideo.video_size = 0x1000000; break; case SIS550_DRAM_SIZE_24MB: ivideo.video_size = 0x1800000; break; case SIS550_DRAM_SIZE_32MB: ivideo.video_size = 0x2000000; break; case SIS550_DRAM_SIZE_64MB: ivideo.video_size = 0x4000000; break; case SIS550_DRAM_SIZE_96MB: ivideo.video_size = 0x6000000; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -