📄 sis_main.c
字号:
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;}#endif /* CONFIG_FB_SIS_300 */#ifdef CONFIG_FB_SIS_315 /* for SiS 315/550/650/740/330 */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 || ivideo.chip == SIS_740) {#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) || (pdev->device == PCI_DEVICE_ID_SI_740))) { 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, 330 */ 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; if(ivideo.chip == SIS_330) { if(reg) ivideo.video_size <<= 1; } else { 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 asymetric */ ivideo.video_size += (ivideo.video_size/2); break; } } return 0; } return -1; }#endif /* CONFIG_FB_SIS_315 *//* -------------- video bridge detection --------------- */static void sisfb_detect_VB_connect(){ u8 sr16, sr17, cr32, temp; if(sisvga_engine == SIS_300_VGA) { inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17); if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) { /* Old BIOSes store the detected CRT2 type in SR17 * instead of CR32. However, since our detection * routines store their results to CR32, we now copy * the remaining bits (for LCD and VGA) to CR32 for * unified usage. * SR17[0] CRT1 [1] LCD [2] TV [3] VGA2 * [4] AVIDEO [5] SVIDEO */ if (sr17 & 0x01) orSISIDXREG(SISCR, 0x32, SIS_CRT1); else andSISIDXREG(SISCR, 0x32, ~SIS_CRT1); if (sr17 & 0x02) orSISIDXREG(SISCR, 0x32, SIS_VB_LCD); else andSISIDXREG(SISCR, 0x32, ~SIS_VB_LCD); /* no HiVision and no DVI connector here */ andSISIDXREG(SISCR, 0x32, ~0xc0); /* PAL/NTSC is stored on SR16 on such machines */ if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) { inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16); if (sr16 & 0x20) ivideo.vbflags |= TV_PAL; else ivideo.vbflags |= TV_NTSC; } } } inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32); if (cr32 & SIS_CRT1) sisfb_crt1off = 0; else { if (cr32 & 0x5F) sisfb_crt1off = 1; else sisfb_crt1off = 0; } ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); if (cr32 & SIS_VB_TV) ivideo.vbflags |= CRT2_TV; if (cr32 & SIS_VB_LCD) ivideo.vbflags |= CRT2_LCD; if (cr32 & SIS_VB_CRT2) ivideo.vbflags |= CRT2_VGA; /* TW: Detect/set TV plug & type */ if(sisfb_tvplug != -1) ivideo.vbflags |= sisfb_tvplug; if (cr32 & SIS_VB_HIVISION) ivideo.vbflags |= (TV_HIVISION | TV_SVIDEO); else if (cr32 & SIS_VB_SVIDEO) ivideo.vbflags |= TV_SVIDEO; else if (cr32 & SIS_VB_COMPOSITE) ivideo.vbflags |= TV_AVIDEO; else if (cr32 & SIS_VB_SCART) ivideo.vbflags |= TV_SCART; if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) { if(sisvga_engine == SIS_300_VGA) { inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp); if (temp & 0x01) ivideo.vbflags |= TV_PAL; else ivideo.vbflags |= TV_NTSC; } else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip >= SIS_330)) { inSISIDXREG(SISCR, 0x38, temp); if(temp & 0x10) ivideo.vbflags |= TV_PAL; else ivideo.vbflags |= TV_NTSC; } else { inSISIDXREG(SISCR, 0x79, temp); if(temp & 0x20) ivideo.vbflags |= TV_PAL; else ivideo.vbflags |= TV_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; } if(enable_dstn) { ivideo.vbflags &= ~(CRT2_TV | CRT2_VGA); ivideo.vbflags |= CRT2_LCD; }}static void sisfb_get_VB_type(void){ u8 vb_chipid; u8 reg; ivideo.hasVB = HASVB_NONE; sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN; sishw_ext.Is301BDH = FALSE; sishw_ext.usExternalChip = 0; if(enable_dstn) { ivideo.hasVB = HASVB_LVDS; ivideo.vbflags |= VB_LVDS; sishw_ext.usExternalChip = 0x01; return; } inSISIDXREG(SISPART4, 0x00, vb_chipid); switch (vb_chipid) { case 0x01: ivideo.hasVB = HASVB_301; inSISIDXREG(SISPART4, 0x01, reg); if(reg < 0xb0) { ivideo.vbflags |= VB_301; sishw_ext.ujVBChipID = VB_CHIP_301; printk(KERN_INFO "sisfb: Detected SiS301 video bridge\n"); } else if(reg < 0xd0) { ivideo.vbflags |= VB_301B; sishw_ext.ujVBChipID = VB_CHIP_301B; printk(KERN_INFO "sisfb: Detected SiS301B video bridge\n"); } else if(reg < 0xe0) { ivideo.vbflags |= VB_301LV; sishw_ext.ujVBChipID = VB_CHIP_301LV; printk(KERN_INFO "sisfb: Detected SiS301LV video bridge\n"); } else if(reg <= 0xe1) { ivideo.vbflags |= VB_302LV; sishw_ext.ujVBChipID = VB_CHIP_302LV; printk(KERN_INFO "sisfb: Detected SiS302LV video bridge\n"); } break; case 0x02: ivideo.hasVB = HASVB_302; inSISIDXREG(SISPART4, 0x01, reg); if(reg < 0xd0) { ivideo.vbflags |= VB_302B; sishw_ext.ujVBChipID = VB_CHIP_302B; printk(KERN_INFO "sisfb: Detected SiS302B video bridge\n"); } else if(reg < 0xe0) { ivideo.vbflags |= VB_301LV; sishw_ext.ujVBChipID = VB_CHIP_301LV; printk(KERN_INFO "sisfb: Detected SiS301LV video bridge\n"); } else if(reg <= 0xe1) { ivideo.vbflags |= VB_302LV; sishw_ext.ujVBChipID = VB_CHIP_302LV; printk(KERN_INFO "sisfb: Detected SiS302LV video bridge\n"); } break; } if(ivideo.vbflags & (VB_301B | VB_302B)) { inSISIDXREG(SISPART4,0x23,reg); if(!(reg & 0x02)) { sishw_ext.Is301BDH = TRUE; ivideo.vbflags |= VB_30xBDH; } } if((!(ivideo.vbflags & VB_VIDEOBRIDGE)) && (ivideo.chip != SIS_300)) { inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg); reg &= SIS_EXTERNAL_CHIP_MASK; reg >>= 1; if(sisvga_engine == SIS_300_VGA) { switch (reg) { case SIS_EXTERNAL_CHIP_LVDS: ivideo.hasVB = HASVB_LVDS; ivideo.vbflags |= VB_LVDS; sishw_ext.usExternalChip = 0x01; printk(KERN_INFO "sisfb: Detected LVDS transmitter\n"); break; case SIS_EXTERNAL_CHIP_TRUMPION: ivideo.hasVB = HASVB_TRUMPION; ivideo.vbflags |= VB_TRUMPION; sishw_ext.usExternalChip = 0x02; printk(KERN_INFO "sisfb: Detected Trumpion LCD scaler\n"); break; case SIS_EXTERNAL_CHIP_CHRONTEL: ivideo.hasVB = HASVB_CHRONTEL; ivideo.vbflags |= VB_CHRONTEL; sishw_ext.usExternalChip = 0x04; printk(KERN_INFO "sisfb: Detected Chrontel TV encoder\n"); break; case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: ivideo.hasVB = HASVB_LVDS_CHRONTEL; ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL); sishw_ext.usExternalChip = 0x05; printk(KERN_INFO "sisfb: Detected LVDS transmitter and Chrontel TV encoder\n"); break; } } else { switch (reg) { case SIS310_EXTERNAL_CHIP_LVDS: ivideo.hasVB = HASVB_LVDS; ivideo.vbflags |= VB_LVDS; sishw_ext.usExternalChip = 0x01; printk(KERN_INFO "sisfb: Detected LVDS transmitter\n"); break; case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL: ivideo.hasVB = HASVB_LVDS_CHRONTEL; ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL); sishw_ext.usExternalChip = 0x05; printk(KERN_INFO "sisfb: Detected Chrontel LVDS transmitter and TV encoder\n"); break; } } } if(ivideo.vbflags & VB_SISBRIDGE) { SiS_Sense30x(); } else if(ivideo.vbflags & VB_CHRONTEL) { SiS_SenseCh(); } }/* ------------------ Sensing routines ------------------ *//* TW: Determine and detect attached devices on SiS30x */intSISDoSense(int tempbl, int tempbh, int tempcl, int tempch){ int temp,i; outSISIDXREG(SISPART4,0x11,tempbl); temp = tempbh | tempcl; setSISIDXREG(SISPART4,0x10,0xe0,temp); for(i=0; i<10; i++) SiS_LongWait(&SiS_Pr); tempch &= 0x7f; inSISIDXREG(SISPART4,0x03,temp); temp ^= 0x0e; temp &= tempch; return(temp);}voidSiS_Sense30x(void){ u8 backupP4_0d; u8 testsvhs_tempbl, testsvhs_tempbh; u8 testsvhs_tempcl, testsvhs_tempch; u8 testcvbs_tempbl, testcvbs_tempbh; u8 testcvbs_tempcl, testcvbs_tempch; u8 testvga2_tempbl, testvga2_tempbh; u8 testvga2_tempcl, testvga2_tempch; int myflag, result; inSISIDXREG(SISPART4,0x0d,backupP4_0d); outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04)); if(sisvga_engine == SIS_300_VGA) { if(ivideo.vbflags & (VB_301B|VB_302B|VB_301LV|VB_302LV)) { testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b; testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74; } else { testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; testsvhs_tempbh = 0x00;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -