📄 sis_main.c
字号:
if((xres >= 640) && (yres >= 480)) { for(j = 0; j < 8; j++) { if((xres == sisfb_ddcfmodes[j].x) && (yres == sisfb_ddcfmodes[j].y) && (refresh == sisfb_ddcfmodes[j].v)) { if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h; if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1; if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v; if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v; if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d; } } } index += 2; } if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) { monitor->datavalid = true; } } return monitor->datavalid;}static void __devinitsisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno){ unsigned short temp, i, realcrtno = crtno; unsigned char buffer[256]; monitor->datavalid = false; if(crtno) { if(ivideo->vbflags & CRT2_LCD) realcrtno = 1; else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2; else return; } if((ivideo->sisfb_crt1off) && (!crtno)) return; temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, realcrtno, 0, &buffer[0], ivideo->vbflags2); if((!temp) || (temp == 0xffff)) { printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1); return; } else { printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1); printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n", crtno + 1, (temp & 0x1a) ? "" : "[none of the supported]", (temp & 0x02) ? "2 " : "", (temp & 0x08) ? "D&P" : "", (temp & 0x10) ? "FPDI-2" : ""); if(temp & 0x02) { i = 3; /* Number of retrys */ do { temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, realcrtno, 1, &buffer[0], ivideo->vbflags2); } while((temp) && i--); if(!temp) { if(sisfb_interpret_edid(monitor, &buffer[0])) { printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n", monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax, monitor->dclockmax / 1000); } else { printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1); } } else { printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1); } } else { printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n"); } }}/* -------------- Mode validation --------------- */static boolsisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate){ int htotal, vtotal; unsigned int dclock, hsync; if(!monitor->datavalid) return true; if(mode_idx < 0) return false; /* Skip for 320x200, 320x240, 640x400 */ switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) { case 0x59: case 0x41: case 0x4f: case 0x50: case 0x56: case 0x53: case 0x2f: case 0x5d: case 0x5e: return true;#ifdef CONFIG_FB_SIS_315 case 0x5a: case 0x5b: if(ivideo->sisvga_engine == SIS_315_VGA) return true;#endif } if(rate < (monitor->vmin - 1)) return false; if(rate > (monitor->vmax + 1)) return false; if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, sisbios_mode[mode_idx].mode_no[ivideo->mni], &htotal, &vtotal, rate_idx)) { dclock = (htotal * vtotal * rate) / 1000; if(dclock > (monitor->dclockmax + 1000)) return false; hsync = dclock / htotal; if(hsync < (monitor->hmin - 1)) return false; if(hsync > (monitor->hmax + 1)) return false; } else { return false; } return true;}static intsisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags){ u16 xres=0, yres, myres;#ifdef CONFIG_FB_SIS_300 if(ivideo->sisvga_engine == SIS_300_VGA) { if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return -1 ; }#endif#ifdef CONFIG_FB_SIS_315 if(ivideo->sisvga_engine == SIS_315_VGA) { if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return -1; }#endif myres = sisbios_mode[myindex].yres; switch(vbflags & VB_DISPTYPE_DISP2) { case CRT2_LCD: xres = ivideo->lcdxres; yres = ivideo->lcdyres; if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) && (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) { if(sisbios_mode[myindex].xres > xres) return -1; if(myres > yres) return -1; } if(ivideo->sisfb_fstn) { if(sisbios_mode[myindex].xres == 320) { if(myres == 240) { switch(sisbios_mode[myindex].mode_no[1]) { case 0x50: myindex = MODE_FSTN_8; break; case 0x56: myindex = MODE_FSTN_16; break; case 0x53: return -1; } } } } if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) { return -1; } break; case CRT2_TV: if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) { return -1; } break; case CRT2_VGA: if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) { return -1; } break; } return myindex;}static u8sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx){ int i = 0; u16 xres = sisbios_mode[mode_idx].xres; u16 yres = sisbios_mode[mode_idx].yres; ivideo->rate_idx = 0; while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) { if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) { if(sisfb_vrate[i].refresh == rate) { ivideo->rate_idx = sisfb_vrate[i].idx; break; } else if(sisfb_vrate[i].refresh > rate) { if((sisfb_vrate[i].refresh - rate) <= 3) { DPRINTK("sisfb: Adjusting rate from %d up to %d\n", rate, sisfb_vrate[i].refresh); ivideo->rate_idx = sisfb_vrate[i].idx; ivideo->refresh_rate = sisfb_vrate[i].refresh; } else if(((rate - sisfb_vrate[i-1].refresh) <= 2) && (sisfb_vrate[i].idx != 1)) { DPRINTK("sisfb: Adjusting rate from %d down to %d\n", rate, sisfb_vrate[i-1].refresh); ivideo->rate_idx = sisfb_vrate[i-1].idx; ivideo->refresh_rate = sisfb_vrate[i-1].refresh; } break; } else if((rate - sisfb_vrate[i].refresh) <= 2) { DPRINTK("sisfb: Adjusting rate from %d down to %d\n", rate, sisfb_vrate[i].refresh); ivideo->rate_idx = sisfb_vrate[i].idx; break; } } i++; } if(ivideo->rate_idx > 0) { return ivideo->rate_idx; } else { printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres); return 0; }}static boolsisfb_bridgeisslave(struct sis_video_info *ivideo){ unsigned char P1_00; if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) return false; inSISIDXREG(SISPART1,0x00,P1_00); if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { return true; } else { return false; }}static boolsisfballowretracecrt1(struct sis_video_info *ivideo){ u8 temp; inSISIDXREG(SISCR,0x17,temp); if(!(temp & 0x80)) return false; inSISIDXREG(SISSR,0x1f,temp); if(temp & 0xc0) return false; return true;}static boolsisfbcheckvretracecrt1(struct sis_video_info *ivideo){ if(!sisfballowretracecrt1(ivideo)) return false; if(inSISREG(SISINPSTAT) & 0x08) return true; else return false;}static voidsisfbwaitretracecrt1(struct sis_video_info *ivideo){ int watchdog; if(!sisfballowretracecrt1(ivideo)) return; watchdog = 65536; while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); watchdog = 65536; while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);}static boolsisfbcheckvretracecrt2(struct sis_video_info *ivideo){ unsigned char temp, reg; switch(ivideo->sisvga_engine) { case SIS_300_VGA: reg = 0x25; break; case SIS_315_VGA: reg = 0x30; break; default: return false; } inSISIDXREG(SISPART1, reg, temp); if(temp & 0x02) return true; else return false;}static boolsisfb_CheckVBRetrace(struct sis_video_info *ivideo){ if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { if(!sisfb_bridgeisslave(ivideo)) { return sisfbcheckvretracecrt2(ivideo); } } return sisfbcheckvretracecrt1(ivideo);}static u32sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount){ u8 idx, reg1, reg2, reg3, reg4; u32 ret = 0; (*vcount) = (*hcount) = 0; if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) { ret |= (FB_VBLANK_HAVE_VSYNC | FB_VBLANK_HAVE_HBLANK | FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_HCOUNT); switch(ivideo->sisvga_engine) { case SIS_300_VGA: idx = 0x25; break; default: case SIS_315_VGA: idx = 0x30; break; } inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; (*vcount) = reg3 | ((reg4 & 0x70) << 4); (*hcount) = reg2 | ((reg4 & 0x0f) << 8); } else if(sisfballowretracecrt1(ivideo)) { ret |= (FB_VBLANK_HAVE_VSYNC | FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_HCOUNT); reg1 = inSISREG(SISINPSTAT); if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; inSISIDXREG(SISCR,0x20,reg1); inSISIDXREG(SISCR,0x1b,reg1); inSISIDXREG(SISCR,0x1c,reg2); inSISIDXREG(SISCR,0x1d,reg3); (*vcount) = reg2 | ((reg3 & 0x07) << 8); (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; } return ret;}static intsisfb_myblank(struct sis_video_info *ivideo, int blank){ u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13; bool backlight = true; switch(blank) { case FB_BLANK_UNBLANK: /* on */ sr01 = 0x00; sr11 = 0x00; sr1f = 0x00; cr63 = 0x00; p2_0 = 0x20; p1_13 = 0x00; backlight = true; break; case FB_BLANK_NORMAL: /* blank */ sr01 = 0x20; sr11 = 0x00; sr1f = 0x00; cr63 = 0x00; p2_0 = 0x20; p1_13 = 0x00; backlight = true; break; case FB_BLANK_VSYNC_SUSPEND: /* no vsync */ sr01 = 0x20; sr11 = 0x08; sr1f = 0x80; cr63 = 0x40; p2_0 = 0x40; p1_13 = 0x80; backlight = false; break; case FB_BLANK_HSYNC_SUSPEND: /* no hsync */ sr01 = 0x20; sr11 = 0x08; sr1f = 0x40; cr63 = 0x40; p2_0 = 0x80; p1_13 = 0x40; backlight = false; break; case FB_BLANK_POWERDOWN: /* off */ sr01 = 0x20; sr11 = 0x08; sr1f = 0xc0; cr63 = 0x40; p2_0 = 0xc0; p1_13 = 0xc0; backlight = false; break; default: return 1; } if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { if( (!ivideo->sisfb_thismonitor.datavalid) || ((ivideo->sisfb_thismonitor.datavalid) && (ivideo->sisfb_thismonitor.feature & 0xe0))) { if(ivideo->sisvga_engine == SIS_315_VGA) { setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); } if(!(sisfb_bridgeisslave(ivideo))) { setSISIDXREG(SISSR, 0x01, ~0x20, sr01); setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); } } } if(ivideo->currentvbflags & CRT2_LCD) { if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { if(backlight) { SiS_SiS30xBLOn(&ivideo->SiS_Pr); } else { SiS_SiS30xBLOff(&ivideo->SiS_Pr); } } else if(ivideo->sisvga_engine == SIS_315_VGA) {#ifdef CONFIG_FB_SIS_315 if(ivideo->vbflags2 & VB2_CHRONTEL) { if(backlight) { SiS_Chrontel701xBLOn(&ivideo->SiS_Pr); } else { SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); } }#endif } if(((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) || ((ivideo->sisvga_engine == SIS_315_VGA) && ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) { setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -