📄 sis_main.c
字号:
#ifdef SISFB_PAN fb_pan_display: sisfb_pan_display,#endif fb_ioctl: sisfb_ioctl, fb_mmap: sisfb_mmap,};#endif/* ------------ Interface to the low level console driver -------------*/#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* --------- for 2.4 series --------- */static int sisfb_update_var(int con, struct fb_info *info){#ifdef SISFB_PAN sisfb_pan_var(&fb_display[con].var);#endif return 0;}static int sisfb_switch(int con, struct fb_info *info){ int cols, rows;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#define currcon info->currcon#endif if(fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info); fb_display[con].var.activate = FB_ACTIVATE_NOW; if(!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof(struct fb_var_screeninfo))) { currcon = con; return 1; } currcon = con; sisfb_do_set_var(&fb_display[con].var, 1, info); sisfb_set_disp(con, &fb_display[con].var, info); sisfb_do_install_cmap(con, info); cols = sisbios_mode[sisfb_mode_idx].cols; rows = sisbios_mode[sisfb_mode_idx].rows; vc_resize_con(rows, cols, fb_display[con].conp->vc_num); sisfb_update_var(con, info); return 1;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#undef currcon#endif}static void sisfb_blank(int blank, struct fb_info *info){ u8 reg; inSISIDXREG(SISCR, 0x17, reg); if(blank > 0) reg &= 0x7f; else reg |= 0x80; outSISIDXREG(SISCR, 0x17, reg);}#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* ---------- for 2.5 series -------- */static int sisfb_blank(int blank, struct fb_info *info){ u8 reg; inSISIDXREG(SISCR, 0x17, reg); if(blank > 0) reg &= 0x7f; else reg |= 0x80; outSISIDXREG(SISCR, 0x17, reg); return(0);}#endif/* --------------- 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 */ inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg); ivideo.video_size = ((unsigned int) ((reg & 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; 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; } outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); break; } } if (!pdev_valid) return -1; } return 0;}static void sisfb_detect_VB_connect_300(){ u8 sr16, sr17, cr32, temp; ivideo.TV_plug = ivideo.TV_type = 0; switch(ivideo.hasVB) { case HASVB_LVDS_CHRONTEL: case HASVB_CHRONTEL: SiS_SenseCh(); break; case HASVB_301: case HASVB_302: SiS_Sense30x(); break; } inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17); inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32); 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(sisfb_tvplug != -1) /* PR/TW: override detected TV type */ ivideo.TV_plug = sisfb_tvplug; else if (sr17 & 0x20) ivideo.TV_plug = TVPLUG_SVIDEO; else if (sr17 & 0x10) ivideo.TV_plug = TVPLUG_COMPOSITE; inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16); 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 */ if(sisfb_tvplug != -1) /* PR/TW: override with option */ ivideo.TV_plug = sisfb_tvplug;#ifdef oldHV else if (cr32 & SIS_VB_HIVISION) { ivideo.TV_type = TVMODE_HIVISION; ivideo.TV_plug = TVPLUG_SVIDEO; }#endif 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) { inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp); 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) { if(sisfb_forcecrt1) sisfb_crt1off = 0; else sisfb_crt1off = 1; }}static void sisfb_get_VB_type_300(void){ u8 reg; if(ivideo.chip != SIS_300) { if(!sisfb_has_VB_300()) { inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg); 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(); }}static int sisfb_has_VB_300(void){ u8 vb_chipid; inSISIDXREG(SISPART4, 0x00, vb_chipid); 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;}#endif /* CONFIG_FB_SIS_300 */#ifdef CONFIG_FB_SIS_315 /* for SiS 315/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" */ inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); reg &= 0xC0; switch (pci_data) { 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; } /* TODO: set Dual channel and bus width bits here */ outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); break; } } if (!pdev_valid) return -1;#else inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); 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; case SIS550_DRAM_SIZE_128MB: ivideo.video_size = 0x8000000; break; case SIS550_DRAM_SIZE_256MB: ivideo.video_size = 0x10000000; break; default: /* TW: Some 550 BIOSes don't seem to initialize SR14 correctly (if at all), * do it the hard way ourselves in this case. Unfortunately, we don't * support 24, 48, 96 and other "odd" amounts here. */ printk(KERN_INFO "sisfb: Warning: Could not determine memory size, " "now reading from PCI config\n"); pdev_valid = 0; pci_for_each_dev(pdev) { if ( (pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device == PCI_DEVICE_ID_SI_550) ) { 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=IND_SIS_DRAM_SIZE */ inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); reg &= 0xC0; switch (pci_data) { 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; default: printk(KERN_INFO "sisfb: Unable to determine memory size, giving up.\n"); return -1; } outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); } } if (!pdev_valid) { printk(KERN_INFO "sisfb: Total confusion - No SiS PCI VGA device found?!\n"); return -1; } return 0; }#endif return 0; } else { /* 315 */ inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg); switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) { case SIS315_DRAM_SIZE_2MB: ivideo.video_size = 0x200000; break; case SIS315_DRAM_SIZE_4MB: ivideo.video_size = 0x400000; break; case SIS315_DRAM_SIZE_8MB: ivideo.video_size = 0x800000; break; case SIS315_DRAM_SIZE_16MB: ivideo.video_size = 0x1000000; break; case SIS315_DRAM_SIZE_32MB: ivideo.video_size = 0x2000000; break; case SIS315_DRAM_SIZE_64MB: ivideo.video_size = 0x4000000; break; case SIS315_DRAM_SIZE_128MB: ivideo.video_size = 0x8000000; break; default: return -1; } } reg &= SIS315_DUAL_CHANNEL_MASK; reg >>= 2; switch (reg) { case SIS315_SINGLE_CHANNEL_2_RANK: ivideo.video_size <<= 1; break; case SIS315_DUAL_CHANNEL_1_RANK: ivideo.video_size <<= 1; break; case SIS315_ASYM_DDR: /* TW: DDR asymentric */ ivideo.video_size += (ivideo.video_size/2); break; } return 0;}static void sisfb_detect_VB_connect_315(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -