in fbdev/matrox/matroxfb_base.c [1633:1962]
static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
{
unsigned long ctrlptr_phys = 0;
unsigned long video_base_phys = 0;
unsigned int memsize;
int err;
static const struct pci_device_id intel_82437[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437) },
{ },
};
DBG(__func__)
/* set default values... */
vesafb_defined.accel_flags = FB_ACCELF_TEXT;
minfo->hw_switch = b->base->lowlevel;
minfo->devflags.accelerator = b->base->accelID;
minfo->max_pixel_clock = b->maxclk;
printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
minfo->capable.plnwt = 1;
minfo->chip = b->chip;
minfo->capable.srcorg = b->flags & DEVF_SRCORG;
minfo->devflags.video64bits = b->flags & DEVF_VIDEO64BIT;
if (b->flags & DEVF_TEXT4B) {
minfo->devflags.vgastep = 4;
minfo->devflags.textmode = 4;
minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
} else if (b->flags & DEVF_TEXT16B) {
minfo->devflags.vgastep = 16;
minfo->devflags.textmode = 1;
minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
} else {
minfo->devflags.vgastep = 8;
minfo->devflags.textmode = 1;
minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP8;
}
minfo->devflags.support32MB = (b->flags & DEVF_SUPPORT32MB) != 0;
minfo->devflags.precise_width = !(b->flags & DEVF_ANY_VXRES);
minfo->devflags.crtc2 = (b->flags & DEVF_CRTC2) != 0;
minfo->devflags.maven_capable = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
minfo->devflags.dualhead = (b->flags & DEVF_DUALHEAD) != 0;
minfo->devflags.dfp_type = dfp_type;
minfo->devflags.g450dac = (b->flags & DEVF_G450DAC) != 0;
minfo->devflags.textstep = minfo->devflags.vgastep * minfo->devflags.textmode;
minfo->devflags.textvram = 65536 / minfo->devflags.textmode;
setDefaultOutputs(minfo);
if (b->flags & DEVF_PANELLINK_CAPABLE) {
minfo->outputs[2].data = minfo;
minfo->outputs[2].output = &panellink_output;
minfo->outputs[2].src = minfo->outputs[2].default_src;
minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
minfo->devflags.panellink = 1;
}
if (minfo->capable.cross4MB < 0)
minfo->capable.cross4MB = b->flags & DEVF_CROSS4MB;
if (b->flags & DEVF_SWAPS) {
ctrlptr_phys = pci_resource_start(minfo->pcidev, 1);
video_base_phys = pci_resource_start(minfo->pcidev, 0);
minfo->devflags.fbResource = PCI_BASE_ADDRESS_0;
} else {
ctrlptr_phys = pci_resource_start(minfo->pcidev, 0);
video_base_phys = pci_resource_start(minfo->pcidev, 1);
minfo->devflags.fbResource = PCI_BASE_ADDRESS_1;
}
err = -EINVAL;
if (!ctrlptr_phys) {
printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
goto fail;
}
if (!video_base_phys) {
printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
goto fail;
}
memsize = b->base->maxvram;
if (!request_mem_region(ctrlptr_phys, 16384, "matroxfb MMIO")) {
goto fail;
}
if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
goto failCtrlMR;
}
minfo->video.len_maximum = memsize;
/* convert mem (autodetect k, M) */
if (mem < 1024) mem *= 1024;
if (mem < 0x00100000) mem *= 1024;
if (mem && (mem < memsize))
memsize = mem;
err = -ENOMEM;
minfo->mmio.vbase.vaddr = ioremap(ctrlptr_phys, 16384);
if (!minfo->mmio.vbase.vaddr) {
printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
goto failVideoMR;
}
minfo->mmio.base = ctrlptr_phys;
minfo->mmio.len = 16384;
minfo->video.base = video_base_phys;
minfo->video.vbase.vaddr = ioremap_wc(video_base_phys, memsize);
if (!minfo->video.vbase.vaddr) {
printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
video_base_phys, memsize);
goto failCtrlIO;
}
{
u_int32_t cmd;
u_int32_t mga_option;
pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &mga_option);
pci_read_config_dword(minfo->pcidev, PCI_COMMAND, &cmd);
mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
mga_option |= MX_OPTION_BSWAP;
/* disable palette snooping */
cmd &= ~PCI_COMMAND_VGA_PALETTE;
if (pci_dev_present(intel_82437)) {
if (!(mga_option & 0x20000000) && !minfo->devflags.nopciretry) {
printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
}
mga_option |= 0x20000000;
minfo->devflags.nopciretry = 1;
}
pci_write_config_dword(minfo->pcidev, PCI_COMMAND, cmd);
pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mga_option);
minfo->hw.MXoptionReg = mga_option;
/* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
/* maybe preinit() candidate, but it is same... for all devices... at this time... */
pci_write_config_dword(minfo->pcidev, PCI_MGA_INDEX, 0x00003C00);
}
err = -ENXIO;
matroxfb_read_pins(minfo);
if (minfo->hw_switch->preinit(minfo)) {
goto failVideoIO;
}
err = -ENOMEM;
if (!matroxfb_getmemory(minfo, memsize, &minfo->video.len) || !minfo->video.len) {
printk(KERN_ERR "matroxfb: cannot determine memory size\n");
goto failVideoIO;
}
minfo->devflags.ydstorg = 0;
minfo->video.base = video_base_phys;
minfo->video.len_usable = minfo->video.len;
if (minfo->video.len_usable > b->base->maxdisplayable)
minfo->video.len_usable = b->base->maxdisplayable;
if (mtrr)
minfo->wc_cookie = arch_phys_wc_add(video_base_phys,
minfo->video.len);
if (!minfo->devflags.novga)
request_region(0x3C0, 32, "matrox");
matroxfb_g450_connect(minfo);
minfo->hw_switch->reset(minfo);
minfo->fbcon.monspecs.hfmin = 0;
minfo->fbcon.monspecs.hfmax = fh;
minfo->fbcon.monspecs.vfmin = 0;
minfo->fbcon.monspecs.vfmax = fv;
minfo->fbcon.monspecs.dpms = 0; /* TBD */
/* static settings */
vesafb_defined.red = colors[depth-1].red;
vesafb_defined.green = colors[depth-1].green;
vesafb_defined.blue = colors[depth-1].blue;
vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
vesafb_defined.grayscale = grayscale;
vesafb_defined.vmode = 0;
if (noaccel)
vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
minfo->fbops = matroxfb_ops;
minfo->fbcon.fbops = &minfo->fbops;
minfo->fbcon.pseudo_palette = minfo->cmap;
minfo->fbcon.flags = FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */
FBINFO_HWACCEL_COPYAREA | /* We have hw-assisted bmove */
FBINFO_HWACCEL_FILLRECT | /* And fillrect */
FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
FBINFO_HWACCEL_XPAN | /* And we support both horizontal */
FBINFO_HWACCEL_YPAN | /* And vertical panning */
FBINFO_READS_FAST;
minfo->video.len_usable &= PAGE_MASK;
fb_alloc_cmap(&minfo->fbcon.cmap, 256, 1);
#ifndef MODULE
/* mode database is marked __init!!! */
if (!hotplug) {
fb_find_mode(&vesafb_defined, &minfo->fbcon, videomode[0] ? videomode : NULL,
NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
}
#endif /* !MODULE */
/* mode modifiers */
if (hslen)
vesafb_defined.hsync_len = hslen;
if (vslen)
vesafb_defined.vsync_len = vslen;
if (left != ~0)
vesafb_defined.left_margin = left;
if (right != ~0)
vesafb_defined.right_margin = right;
if (upper != ~0)
vesafb_defined.upper_margin = upper;
if (lower != ~0)
vesafb_defined.lower_margin = lower;
if (xres)
vesafb_defined.xres = xres;
if (yres)
vesafb_defined.yres = yres;
if (sync != -1)
vesafb_defined.sync = sync;
else if (vesafb_defined.sync == ~0) {
vesafb_defined.sync = 0;
if (yres < 400)
vesafb_defined.sync |= FB_SYNC_HOR_HIGH_ACT;
else if (yres < 480)
vesafb_defined.sync |= FB_SYNC_VERT_HIGH_ACT;
}
/* fv, fh, maxclk limits was specified */
{
unsigned int tmp;
if (fv) {
tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
+ vesafb_defined.lower_margin + vesafb_defined.vsync_len);
if ((tmp < fh) || (fh == 0)) fh = tmp;
}
if (fh) {
tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
+ vesafb_defined.right_margin + vesafb_defined.hsync_len);
if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
}
tmp = (maxclk + 499) / 500;
if (tmp) {
tmp = (2000000000 + tmp) / tmp;
if (tmp > pixclock) pixclock = tmp;
}
}
if (pixclock) {
if (pixclock < 2000) /* > 500MHz */
pixclock = 4000; /* 250MHz */
if (pixclock > 1000000)
pixclock = 1000000; /* 1MHz */
vesafb_defined.pixclock = pixclock;
}
/* FIXME: Where to move this?! */
#if defined(CONFIG_PPC_PMAC)
#ifndef MODULE
if (machine_is(powermac)) {
struct fb_var_screeninfo var;
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
#if defined(CONFIG_PPC32)
if (IS_REACHABLE(CONFIG_NVRAM) && default_cmode == CMODE_NVRAM)
default_cmode = nvram_read_byte(NV_CMODE);
#endif
if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
default_cmode = CMODE_8;
if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
var.accel_flags = vesafb_defined.accel_flags;
var.xoffset = var.yoffset = 0;
/* Note: mac_vmode_to_var() does not set all parameters */
vesafb_defined = var;
}
}
#endif /* !MODULE */
#endif /* CONFIG_PPC_PMAC */
vesafb_defined.xres_virtual = vesafb_defined.xres;
if (nopan) {
vesafb_defined.yres_virtual = vesafb_defined.yres;
} else {
vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
to yres_virtual * xres_virtual < 2^32 */
}
matroxfb_init_fix(minfo);
minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase);
/* Normalize values (namely yres_virtual) */
matroxfb_check_var(&vesafb_defined, &minfo->fbcon);
/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
* vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
* and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
* anyway. But we at least tried... */
minfo->fbcon.var = vesafb_defined;
err = -EINVAL;
printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
minfo->video.base, vaddr_va(minfo->video.vbase), minfo->video.len);
/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
* and we do not want currcon == 0 for subsequent framebuffers */
minfo->fbcon.device = &minfo->pcidev->dev;
if (register_framebuffer(&minfo->fbcon) < 0) {
goto failVideoIO;
}
fb_info(&minfo->fbcon, "%s frame buffer device\n", minfo->fbcon.fix.id);
/* there is no console on this fb... but we have to initialize hardware
* until someone tells me what is proper thing to do */
if (!minfo->initialized) {
fb_info(&minfo->fbcon, "initializing hardware\n");
/* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
* already before, so register_framebuffer works correctly. */
vesafb_defined.activate |= FB_ACTIVATE_FORCE;
fb_set_var(&minfo->fbcon, &vesafb_defined);
}
return 0;
failVideoIO:;
matroxfb_g450_shutdown(minfo);
iounmap(minfo->video.vbase.vaddr);
failCtrlIO:;
iounmap(minfo->mmio.vbase.vaddr);
failVideoMR:;
release_mem_region(video_base_phys, minfo->video.len_maximum);
failCtrlMR:;
release_mem_region(ctrlptr_phys, 16384);
fail:;
return err;
}