extractedLnx/linux-2.6.20/drivers/video/sis/sis_main.c_sisfb_probe.c
static int __devinit
sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
struct sis_video_info *ivideo = NULL;
struct fb_info *sis_fb_info = NULL;
u16 reg16;
u8 reg;
int i, ret;
if(sisfb_off)
return -ENXIO;
sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
if(!sis_fb_info)
return -ENOMEM;
ivideo = (struct sis_video_info *)sis_fb_info->par;
ivideo->memyselfandi = sis_fb_info;
ivideo->sisfb_id = SISFB_ID;
if(card_list == NULL) {
ivideo->cardnumber = 0;
} else {
struct sis_video_info *countvideo = card_list;
ivideo->cardnumber = 1;
while((countvideo = countvideo->next) != 0)
ivideo->cardnumber++;
}
strncpy(ivideo->myid, chipinfo->chip_name, 30);
ivideo->warncount = 0;
ivideo->chip_id = pdev->device;
ivideo->chip_vendor = pdev->vendor;
pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
pci_read_config_word(pdev, PCI_COMMAND, ®16);
ivideo->sisvga_enabled = reg16 & 0x01;
ivideo->pcibus = pdev->bus->number;
ivideo->pcislot = PCI_SLOT(pdev->devfn);
ivideo->pcifunc = PCI_FUNC(pdev->devfn);
ivideo->subsysvendor = pdev->subsystem_vendor;
ivideo->subsysdevice = pdev->subsystem_device;
#ifdef SIS_OLD_CONFIG_COMPAT
ivideo->ioctl32registered = 0;
#endif
#ifndef MODULE
if(sisfb_mode_idx == -1) {
sisfb_get_vga_mode_from_kernel();
}
#endif
ivideo->chip = chipinfo->chip;
ivideo->sisvga_engine = chipinfo->vgaengine;
ivideo->hwcursor_size = chipinfo->hwcursor_size;
ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
ivideo->mni = chipinfo->mni;
ivideo->detectedpdc = 0xff;
ivideo->detectedpdca = 0xff;
ivideo->detectedlcda = 0xff;
ivideo->sisfb_thismonitor.datavalid = FALSE;
ivideo->current_base = 0;
ivideo->engineok = 0;
ivideo->sisfb_was_boot_device = 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
if(ivideo->sisvga_enabled)
ivideo->sisfb_was_boot_device = 1;
else {
printk(KERN_DEBUG "sisfb: PCI device is disabled, "
"but marked as boot video device ???\n");
printk(KERN_DEBUG "sisfb: I will not accept this "
"as the primary VGA device\n");
}
}
#endif
ivideo->sisfb_parm_mem = sisfb_parm_mem;
ivideo->sisfb_accel = sisfb_accel;
ivideo->sisfb_ypan = sisfb_ypan;
ivideo->sisfb_max = sisfb_max;
ivideo->sisfb_userom = sisfb_userom;
ivideo->sisfb_useoem = sisfb_useoem;
ivideo->sisfb_mode_idx = sisfb_mode_idx;
ivideo->sisfb_parm_rate = sisfb_parm_rate;
ivideo->sisfb_crt1off = sisfb_crt1off;
ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
ivideo->sisfb_crt2type = sisfb_crt2type;
ivideo->sisfb_crt2flags = sisfb_crt2flags;
/* pdc(a), scalelcd, special timing, lvdshl handled below */
ivideo->sisfb_dstn = sisfb_dstn;
ivideo->sisfb_fstn = sisfb_fstn;
ivideo->sisfb_tvplug = sisfb_tvplug;
ivideo->sisfb_tvstd = sisfb_tvstd;
ivideo->tvxpos = sisfb_tvxposoffset;
ivideo->tvypos = sisfb_tvyposoffset;
ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
ivideo->refresh_rate = 0;
if(ivideo->sisfb_parm_rate != -1) {
ivideo->refresh_rate = ivideo->sisfb_parm_rate;
}
ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
ivideo->SiS_Pr.CenterScreen = -1;
ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
ivideo->SiS_Pr.SiS_CHOverScan = -1;
ivideo->SiS_Pr.SiS_ChSW = FALSE;
ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
ivideo->SiS_Pr.HaveEMI = FALSE;
ivideo->SiS_Pr.HaveEMILCD = FALSE;
ivideo->SiS_Pr.OverruleEMI = FALSE;
ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
ivideo->SiS_Pr.PDC = -1;
ivideo->SiS_Pr.PDCA = -1;
ivideo->SiS_Pr.DDCPortMixup = FALSE;
#ifdef CONFIG_FB_SIS_315
if(ivideo->chip >= SIS_330) {
ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
if(ivideo->chip >= SIS_661) {
ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
}
}
#endif
memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
pci_set_drvdata(pdev, ivideo);
/* Patch special cases */
if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
switch(ivideo->nbridge->device) {
#ifdef CONFIG_FB_SIS_300
case PCI_DEVICE_ID_SI_730:
ivideo->chip = SIS_730;
strcpy(ivideo->myid, "SiS 730");
break;
#endif
#ifdef CONFIG_FB_SIS_315
case PCI_DEVICE_ID_SI_651:
/* ivideo->chip is ok */
strcpy(ivideo->myid, "SiS 651");
break;
case PCI_DEVICE_ID_SI_740:
ivideo->chip = SIS_740;
strcpy(ivideo->myid, "SiS 740");
break;
case PCI_DEVICE_ID_SI_661:
ivideo->chip = SIS_661;
strcpy(ivideo->myid, "SiS 661");
break;
case PCI_DEVICE_ID_SI_741:
ivideo->chip = SIS_741;
strcpy(ivideo->myid, "SiS 741");
break;
case PCI_DEVICE_ID_SI_760:
ivideo->chip = SIS_760;
strcpy(ivideo->myid, "SiS 760");
break;
case PCI_DEVICE_ID_SI_761:
ivideo->chip = SIS_761;
strcpy(ivideo->myid, "SiS 761");
break;
#endif
default:
break;
}
}
ivideo->SiS_Pr.ChipType = ivideo->chip;
ivideo->SiS_Pr.ivideo = (void *)ivideo;
#ifdef CONFIG_FB_SIS_315
if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
(ivideo->SiS_Pr.ChipType == SIS_315)) {
ivideo->SiS_Pr.ChipType = SIS_315H;
}
#endif
if(!ivideo->sisvga_enabled) {
if(pci_enable_device(pdev)) {
if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
pci_set_drvdata(pdev, NULL);
kfree(sis_fb_info);
return -EIO;
}
}
ivideo->video_base = pci_resource_start(pdev, 0);
ivideo->mmio_base = pci_resource_start(pdev, 1);
ivideo->mmio_size = pci_resource_len(pdev, 1);
ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
#ifdef CONFIG_FB_SIS_300
/* Find PCI systems for Chrontel/GPIO communication setup */
if(ivideo->chip == SIS_630) {
i = 0;
do {
if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
mychswtable[i].subsysCard == ivideo->subsysdevice) {
ivideo->SiS_Pr.SiS_ChSW = TRUE;
printk(KERN_DEBUG "sisfb: Identified [%s %s] "
"requiring Chrontel/GPIO setup\n",
mychswtable[i].vendorName,
mychswtable[i].cardName);
ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
break;
}
i++;
} while(mychswtable[i].subsysVendor != 0);
}
#endif
#ifdef CONFIG_FB_SIS_315
if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
}
#endif
outSISIDXREG(SISSR, 0x05, 0x86);
if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
|| (sisfb_resetcard)
#endif
) {
for(i = 0x30; i <= 0x3f; i++) {
outSISIDXREG(SISCR, i, 0x00);
}
}
/* Find out about current video mode */
ivideo->modeprechange = 0x03;
inSISIDXREG(SISCR, 0x34, reg);
if(reg & 0x7f) {
ivideo->modeprechange = reg & 0x7f;
} else if(ivideo->sisvga_enabled) {
#if defined(__i386__) || defined(__x86_64__)
unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
if(tt) {
ivideo->modeprechange = readb(tt + 0x49);
iounmap(tt);
}
#endif
}
/* Search and copy ROM image */
ivideo->bios_abase = NULL;
ivideo->SiS_Pr.VirtualRomBase = NULL;
ivideo->SiS_Pr.UseROM = FALSE;
ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
if(ivideo->sisfb_userom) {
ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
printk(KERN_INFO "sisfb: Video ROM %sfound\n",
ivideo->SiS_Pr.UseROM ? "" : "not ");
if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
ivideo->SiS_Pr.UseROM = FALSE;
ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
if( (ivideo->revision_id == 2) &&
(!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
ivideo->SiS_Pr.DDCPortMixup = TRUE;
}
}
} else {
printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
}
/* Find systems for special custom timing */
if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
sisfb_detect_custom_timing(ivideo);
}
/* POST card in case this has not been done by the BIOS */
if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
|| (sisfb_resetcard)
#endif
) {
#ifdef CONFIG_FB_SIS_300
if(ivideo->sisvga_engine == SIS_300_VGA) {
if(ivideo->chip == SIS_300) {
sisfb_post_sis300(pdev);
ivideo->sisfb_can_post = 1;
}
}
#endif
#ifdef CONFIG_FB_SIS_315
if(ivideo->sisvga_engine == SIS_315_VGA) {
int result = 1;
/* if((ivideo->chip == SIS_315H) ||
(ivideo->chip == SIS_315) ||
(ivideo->chip == SIS_315PRO) ||
(ivideo->chip == SIS_330)) {
sisfb_post_sis315330(pdev);
} else */ if(ivideo->chip == XGI_20) {
result = sisfb_post_xgi(pdev);
ivideo->sisfb_can_post = 1;
} else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
result = sisfb_post_xgi(pdev);
ivideo->sisfb_can_post = 1;
} else {
printk(KERN_INFO "sisfb: Card is not "
"POSTed and sisfb can't do this either.\n");
}
if(!result) {
printk(KERN_ERR "sisfb: Failed to POST card\n");
ret = -ENODEV;
goto error_3;
}
}
#endif
}
ivideo->sisfb_card_posted = 1;
/* Find out about RAM size */
if(sisfb_get_dram_size(ivideo)) {
printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
ret = -ENODEV;
goto error_3;
}
/* Enable PCI addressing and MMIO */
if((ivideo->sisfb_mode_idx < 0) ||
((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
/* Enable 2D accelerator engine */
orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
}
if(sisfb_pdc != 0xff) {
if(ivideo->sisvga_engine == SIS_300_VGA)
sisfb_pdc &= 0x3c;
else
sisfb_pdc &= 0x1f;
ivideo->SiS_Pr.PDC = sisfb_pdc;
}
#ifdef CONFIG_FB_SIS_315
if(ivideo->sisvga_engine == SIS_315_VGA) {
if(sisfb_pdca != 0xff)
ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
}
#endif
if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
(int)(ivideo->video_size >> 20));
printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
ret = -ENODEV;
goto error_3;
}
if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
ret = -ENODEV;
goto error_2;
}
ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
if(!ivideo->video_vbase) {
printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
ret = -ENODEV;
goto error_1;
}
ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
if(!ivideo->mmio_vbase) {
printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
ret = -ENODEV;
error_0: iounmap(ivideo->video_vbase);
error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
error_3: vfree(ivideo->bios_abase);
if(ivideo->lpcdev)
SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
if(ivideo->nbridge)
SIS_PCI_PUT_DEVICE(ivideo->nbridge);
pci_set_drvdata(pdev, NULL);
if(!ivideo->sisvga_enabled)
pci_disable_device(pdev);
kfree(sis_fb_info);
return ret;
}
printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
if(ivideo->video_offset) {
printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
ivideo->video_offset / 1024);
}
printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
/* Determine the size of the command queue */
if(ivideo->sisvga_engine == SIS_300_VGA) {
ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
} else {
if(ivideo->chip == XGI_20) {
ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
} else {
ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
}
}
/* Engines are no longer initialized here; this is
* now done after the first mode-switch (if the
* submitted var has its acceleration flags set).
*/
/* Calculate the base of the (unused) hw cursor */
ivideo->hwcursor_vbase = ivideo->video_vbase
+ ivideo->video_size
- ivideo->cmdQueueSize
- ivideo->hwcursor_size;
ivideo->caps |= HW_CURSOR_CAP;
/* Initialize offscreen memory manager */
if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
}
/* Used for clearing the screen only, therefore respect our mem limit */
ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
ivideo->mtrr = -1;
ivideo->vbflags = 0;
ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
ivideo->tvdefmodeidx = DEFAULT_TVMODE;
ivideo->defmodeidx = DEFAULT_MODE;
ivideo->newrom = 0;
if(ivideo->chip < XGI_20) {
if(ivideo->bios_abase) {
ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
}
}
if((ivideo->sisfb_mode_idx < 0) ||
((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
sisfb_sense_crt1(ivideo);
sisfb_get_VB_type(ivideo);
if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
sisfb_detect_VB_connect(ivideo);
}
ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
/* Decide on which CRT2 device to use */
if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
if(ivideo->sisfb_crt2type != -1) {
if((ivideo->sisfb_crt2type == CRT2_LCD) &&
(ivideo->vbflags & CRT2_LCD)) {
ivideo->currentvbflags |= CRT2_LCD;
} else if(ivideo->sisfb_crt2type != CRT2_LCD) {
ivideo->currentvbflags |= ivideo->sisfb_crt2type;
}
} else {
/* Chrontel 700x TV detection often unreliable, therefore
* use a different default order on such machines
*/
if((ivideo->sisvga_engine == SIS_300_VGA) &&
(ivideo->vbflags2 & VB2_CHRONTEL)) {
if(ivideo->vbflags & CRT2_LCD)
ivideo->currentvbflags |= CRT2_LCD;
else if(ivideo->vbflags & CRT2_TV)
ivideo->currentvbflags |= CRT2_TV;
else if(ivideo->vbflags & CRT2_VGA)
ivideo->currentvbflags |= CRT2_VGA;
} else {
if(ivideo->vbflags & CRT2_TV)
ivideo->currentvbflags |= CRT2_TV;
else if(ivideo->vbflags & CRT2_LCD)
ivideo->currentvbflags |= CRT2_LCD;
else if(ivideo->vbflags & CRT2_VGA)
ivideo->currentvbflags |= CRT2_VGA;
}
}
}
if(ivideo->vbflags & CRT2_LCD) {
sisfb_detect_lcd_type(ivideo);
}
sisfb_save_pdc_emi(ivideo);
if(!ivideo->sisfb_crt1off) {
sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
} else {
if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
(ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
}
}
if(ivideo->sisfb_mode_idx >= 0) {
int bu = ivideo->sisfb_mode_idx;
ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
ivideo->sisfb_mode_idx, ivideo->currentvbflags);
if(bu != ivideo->sisfb_mode_idx) {
printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
sisbios_mode[bu].xres,
sisbios_mode[bu].yres,
sisbios_mode[bu].bpp);
}
}
if(ivideo->sisfb_mode_idx < 0) {
switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
case CRT2_LCD:
ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
break;
case CRT2_TV:
ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
break;
default:
ivideo->sisfb_mode_idx = ivideo->defmodeidx;
break;
}
}
ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
if(ivideo->refresh_rate != 0) {
sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
ivideo->sisfb_mode_idx);
}
if(ivideo->rate_idx == 0) {
ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
ivideo->refresh_rate = 60;
}
if(ivideo->sisfb_thismonitor.datavalid) {
if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
ivideo->sisfb_mode_idx,
ivideo->rate_idx,
ivideo->refresh_rate)) {
printk(KERN_INFO "sisfb: WARNING: Refresh rate "
"exceeds monitor specs!\n");
}
}
ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
sisfb_set_vparms(ivideo);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/* ---------------- For 2.4: Now switch the mode ------------------ */
printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
ivideo->refresh_rate);
/* Determine whether or not acceleration is to be
* used. Need to know before pre/post_set_mode()
*/
ivideo->accel = 0;
ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
if(ivideo->sisfb_accel) {
ivideo->accel = -1;
ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
}
/* Now switch the mode */
sisfb_pre_setmode(ivideo);
if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
ivideo->mode_no);
ret = -EINVAL;
iounmap(ivideo->mmio_vbase);
goto error_0;
}
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
sisfb_post_setmode(ivideo);
/* Maximize regardless of sisfb_max at startup */
ivideo->default_var.yres_virtual = 32767;
/* Force reset of x virtual in crtc_to_var */
ivideo->default_var.xres_virtual = 0;
/* Copy mode timing to var */
sisfb_crtc_to_var(ivideo, &ivideo->default_var);
/* Find out about screen pitch */
sisfb_calc_pitch(ivideo, &ivideo->default_var);
sisfb_set_pitch(ivideo);
/* Init the accelerator (does nothing currently) */
sisfb_initaccel(ivideo);
/* Init some fbinfo entries */
sis_fb_info->node = -1;
sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
sis_fb_info->fbops = &sisfb_ops;
sis_fb_info->disp = &ivideo->sis_disp;
sis_fb_info->blank = &sisfb_blank;
sis_fb_info->switch_con = &sisfb_switch;
sis_fb_info->updatevar = &sisfb_update_var;
sis_fb_info->changevar = NULL;
strcpy(sis_fb_info->fontname, sisfb_fontname);
sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
ivideo->refresh_rate);
/* Set up the default var according to chosen default display mode */
ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
sisfb_bpp_to_var(ivideo, &ivideo->default_var);
ivideo->default_var.pixclock = (u32) (1000000000 /
sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
ivideo->rate_idx, &ivideo->default_var)) {
if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
ivideo->default_var.pixclock <<= 1;
}
}
if(ivideo->sisfb_ypan) {
/* Maximize regardless of sisfb_max at startup */
ivideo->default_var.yres_virtual =
sisfb_calc_maxyres(ivideo, &ivideo->default_var);
if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
ivideo->default_var.yres_virtual = ivideo->default_var.yres;
}
}
sisfb_calc_pitch(ivideo, &ivideo->default_var);
ivideo->accel = 0;
if(ivideo->sisfb_accel) {
ivideo->accel = -1;
#ifdef STUPID_ACCELF_TEXT_SHIT
ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
#endif
}
sisfb_initaccel(ivideo);
#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
sis_fb_info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN |
FBINFO_HWACCEL_XPAN |
FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_FILLRECT |
((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
#else
sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
#endif
sis_fb_info->var = ivideo->default_var;
sis_fb_info->fix = ivideo->sisfb_fix;
sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
sis_fb_info->fbops = &sisfb_ops;
sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
#endif /* 2.6 */
printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
#ifdef CONFIG_MTRR
ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
MTRR_TYPE_WRCOMB, 1);
if(ivideo->mtrr < 0) {
printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
}
#endif
if(register_framebuffer(sis_fb_info) < 0) {
printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
ret = -EINVAL;
iounmap(ivideo->mmio_vbase);
goto error_0;
}
ivideo->registered = 1;
/* Enlist us */
ivideo->next = card_list;
card_list = ivideo;
#ifdef SIS_OLD_CONFIG_COMPAT
{
int ret;
/* Our ioctls are all "32/64bit compatible" */
ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
if(ret)
printk(KERN_ERR
"sisfb: Error registering ioctl32 translations\n");
else
ivideo->ioctl32registered = 1;
}
#endif
printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
ivideo->sisfb_accel ? "enabled" : "disabled",
ivideo->sisfb_ypan ?
(ivideo->sisfb_max ? "enabled (auto-max)" :
"enabled (no auto-max)") :
"disabled");
printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
} /* if mode = "none" */
return 0;
}
Generated by GNU enscript 1.6.4.