diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-02-13 15:31:38 +0200 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-04-17 08:10:19 +0300 |
commit | f7018c21350204c4cf628462f229d44d03545254 (patch) | |
tree | 408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/matrox/matroxfb_crtc2.c | |
parent | c26ef3eb3c11274bad1b64498d0a134f85755250 (diff) |
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related
files, directories for backlight, console, linux logo, lots of fbdev
device drivers, fbdev framework files.
Make some order into the chaos by creating drivers/video/fbdev
directory, and move all fbdev related files there.
No functionality is changed, although I guess it is possible that some
subtle Makefile build order related issue could be created by this
patch.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/matrox/matroxfb_crtc2.c')
-rw-r--r-- | drivers/video/matrox/matroxfb_crtc2.c | 739 |
1 files changed, 0 insertions, 739 deletions
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c deleted file mode 100644 index 02796a4317a..00000000000 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * - * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450. - * - * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> - * - * Portions Copyright (c) 2001 Matrox Graphics Inc. - * - * Version: 1.65 2002/08/14 - * - */ - -#include "matroxfb_maven.h" -#include "matroxfb_crtc2.h" -#include "matroxfb_misc.h" -#include "matroxfb_DAC1064.h" -#include <linux/matroxfb.h> -#include <linux/slab.h> -#include <linux/uaccess.h> - -/* **************************************************** */ - -static int mem = 8192; - -module_param(mem, int, 0); -MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)"); - -/* **************************************************** */ - -static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info* info) { - u_int32_t col; -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - - if (regno >= 16) - return 1; - if (m2info->fbcon.var.grayscale) { - /* gray = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - } - red = CNVT_TOHW(red, m2info->fbcon.var.red.length); - green = CNVT_TOHW(green, m2info->fbcon.var.green.length); - blue = CNVT_TOHW(blue, m2info->fbcon.var.blue.length); - transp = CNVT_TOHW(transp, m2info->fbcon.var.transp.length); - - col = (red << m2info->fbcon.var.red.offset) | - (green << m2info->fbcon.var.green.offset) | - (blue << m2info->fbcon.var.blue.offset) | - (transp << m2info->fbcon.var.transp.offset); - - switch (m2info->fbcon.var.bits_per_pixel) { - case 16: - m2info->cmap[regno] = col | (col << 16); - break; - case 32: - m2info->cmap[regno] = col; - break; - } - return 0; -#undef m2info -} - -static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, - struct my_timming* mt, - int mode, - unsigned int pos) { - u_int32_t tmp; - u_int32_t datactl; - struct matrox_fb_info *minfo = m2info->primary_dev; - - switch (mode) { - case 15: - tmp = 0x00200000; - break; - case 16: - tmp = 0x00400000; - break; -/* case 32: */ - default: - tmp = 0x00800000; - break; - } - tmp |= 0x00000001; /* enable CRTC2 */ - datactl = 0; - if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) { - if (minfo->devflags.g450dac) { - tmp |= 0x00000006; /* source from secondary pixel PLL */ - /* no vidrst when in monitor mode */ - if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) { - tmp |= 0xC0001000; /* Enable H/V vidrst */ - } - } else { - tmp |= 0x00000002; /* source from VDOCLK */ - tmp |= 0xC0000000; /* enable vvidrst & hvidrst */ - /* MGA TVO is our clock source */ - } - } else if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) { - tmp |= 0x00000004; /* source from pixclock */ - /* PIXPLL is our clock source */ - } - if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) { - tmp |= 0x00100000; /* connect CRTC2 to DAC */ - } - if (mt->interlaced) { - tmp |= 0x02000000; /* interlaced, second field is bigger, as G450 apparently ignores it */ - mt->VDisplay >>= 1; - mt->VSyncStart >>= 1; - mt->VSyncEnd >>= 1; - mt->VTotal >>= 1; - } - if ((mt->HTotal & 7) == 2) { - datactl |= 0x00000010; - mt->HTotal &= ~7; - } - tmp |= 0x10000000; /* 0x10000000 is VIDRST polarity */ - mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8)); - mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8)); - mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1)); - mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1)); - mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart)); /* preload */ - { - u_int32_t linelen = m2info->fbcon.var.xres_virtual * (m2info->fbcon.var.bits_per_pixel >> 3); - if (tmp & 0x02000000) { - /* field #0 is smaller, so... */ - mga_outl(0x3C2C, pos); /* field #1 vmemory start */ - mga_outl(0x3C28, pos + linelen); /* field #0 vmemory start */ - linelen <<= 1; - m2info->interlaced = 1; - } else { - mga_outl(0x3C28, pos); /* vmemory start */ - m2info->interlaced = 0; - } - mga_outl(0x3C40, linelen); - } - mga_outl(0x3C4C, datactl); /* data control */ - if (tmp & 0x02000000) { - int i; - - mga_outl(0x3C10, tmp & ~0x02000000); - for (i = 0; i < 2; i++) { - unsigned int nl; - unsigned int lastl = 0; - - while ((nl = mga_inl(0x3C48) & 0xFFF) >= lastl) { - lastl = nl; - } - } - } - mga_outl(0x3C10, tmp); - minfo->hw.crtc2.ctl = tmp; - - tmp = mt->VDisplay << 16; /* line compare */ - if (mt->sync & FB_SYNC_HOR_HIGH_ACT) - tmp |= 0x00000100; - if (mt->sync & FB_SYNC_VERT_HIGH_ACT) - tmp |= 0x00000200; - mga_outl(0x3C44, tmp); -} - -static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) { - struct matrox_fb_info *minfo = m2info->primary_dev; - - mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */ - minfo->hw.crtc2.ctl = 0x00000004; -} - -static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, - struct fb_var_screeninfo* var) { - unsigned int pos; - unsigned int linelen; - unsigned int pixelsize; - struct matrox_fb_info *minfo = m2info->primary_dev; - - m2info->fbcon.var.xoffset = var->xoffset; - m2info->fbcon.var.yoffset = var->yoffset; - pixelsize = m2info->fbcon.var.bits_per_pixel >> 3; - linelen = m2info->fbcon.var.xres_virtual * pixelsize; - pos = m2info->fbcon.var.yoffset * linelen + m2info->fbcon.var.xoffset * pixelsize; - pos += m2info->video.offbase; - if (m2info->interlaced) { - mga_outl(0x3C2C, pos); - mga_outl(0x3C28, pos + linelen); - } else { - mga_outl(0x3C28, pos); - } -} - -static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info, - struct fb_var_screeninfo* var, - int *visual, - int *video_cmap_len, - int *mode) { - unsigned int mask; - unsigned int memlen; - unsigned int vramlen; - - switch (var->bits_per_pixel) { - case 16: mask = 0x1F; - break; - case 32: mask = 0x0F; - break; - default: return -EINVAL; - } - vramlen = m2info->video.len_usable; - if (var->yres_virtual < var->yres) - var->yres_virtual = var->yres; - if (var->xres_virtual < var->xres) - var->xres_virtual = var->xres; - var->xres_virtual = (var->xres_virtual + mask) & ~mask; - if (var->yres_virtual > 32767) - return -EINVAL; - memlen = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel >> 3); - if (memlen > vramlen) - return -EINVAL; - if (var->xoffset + var->xres > var->xres_virtual) - var->xoffset = var->xres_virtual - var->xres; - if (var->yoffset + var->yres > var->yres_virtual) - var->yoffset = var->yres_virtual - var->yres; - - var->xres &= ~7; - var->left_margin &= ~7; - var->right_margin &= ~7; - var->hsync_len &= ~7; - - *mode = var->bits_per_pixel; - if (var->bits_per_pixel == 16) { - if (var->green.length == 5) { - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 15; - var->transp.length = 1; - *mode = 15; - } else { - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - } - } else { - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 24; - var->transp.length = 8; - } - *visual = FB_VISUAL_TRUECOLOR; - *video_cmap_len = 16; - return 0; -} - -static int matroxfb_dh_open(struct fb_info* info, int user) { -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - struct matrox_fb_info *minfo = m2info->primary_dev; - - if (minfo) { - int err; - - if (minfo->dead) { - return -ENXIO; - } - err = minfo->fbops.fb_open(&minfo->fbcon, user); - if (err) { - return err; - } - } - return 0; -#undef m2info -} - -static int matroxfb_dh_release(struct fb_info* info, int user) { -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - int err = 0; - struct matrox_fb_info *minfo = m2info->primary_dev; - - if (minfo) { - err = minfo->fbops.fb_release(&minfo->fbcon, user); - } - return err; -#undef m2info -} - -/* - * This function is called before the register_framebuffer so - * no locking is needed. - */ -static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) -{ - struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; - - strcpy(fix->id, "MATROX DH"); - - fix->smem_start = m2info->video.base; - fix->smem_len = m2info->video.len_usable; - fix->ypanstep = 1; - fix->ywrapstep = 0; - fix->xpanstep = 8; /* TBD */ - fix->mmio_start = m2info->mmio.base; - fix->mmio_len = m2info->mmio.len; - fix->accel = 0; /* no accel... */ -} - -static int matroxfb_dh_check_var(struct fb_var_screeninfo* var, struct fb_info* info) { -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - int visual; - int cmap_len; - int mode; - - return matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode); -#undef m2info -} - -static int matroxfb_dh_set_par(struct fb_info* info) { -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - int visual; - int cmap_len; - int mode; - int err; - struct fb_var_screeninfo* var = &info->var; - struct matrox_fb_info *minfo = m2info->primary_dev; - - if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0) - return err; - /* cmap */ - { - m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase); - m2info->fbcon.fix.visual = visual; - m2info->fbcon.fix.type = FB_TYPE_PACKED_PIXELS; - m2info->fbcon.fix.type_aux = 0; - m2info->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3; - } - { - struct my_timming mt; - unsigned int pos; - int out; - int cnt; - - matroxfb_var2my(&m2info->fbcon.var, &mt); - mt.crtc = MATROXFB_SRC_CRTC2; - /* CRTC2 delay */ - mt.delay = 34; - - pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3; - pos += m2info->video.offbase; - cnt = 0; - down_read(&minfo->altout.lock); - for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) { - cnt++; - if (minfo->outputs[out].output->compute) { - minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt); - } - } - } - minfo->crtc2.pixclock = mt.pixclock; - minfo->crtc2.mnp = mt.mnp; - up_read(&minfo->altout.lock); - if (cnt) { - matroxfb_dh_restore(m2info, &mt, mode, pos); - } else { - matroxfb_dh_disable(m2info); - } - DAC1064_global_init(minfo); - DAC1064_global_restore(minfo); - down_read(&minfo->altout.lock); - for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 && - minfo->outputs[out].output->program) { - minfo->outputs[out].output->program(minfo->outputs[out].data); - } - } - for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 && - minfo->outputs[out].output->start) { - minfo->outputs[out].output->start(minfo->outputs[out].data); - } - } - up_read(&minfo->altout.lock); - } - m2info->initialized = 1; - return 0; -#undef m2info -} - -static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, struct fb_info* info) { -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - matroxfb_dh_pan_var(m2info, var); - return 0; -#undef m2info -} - -static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) { - struct matrox_fb_info *minfo = m2info->primary_dev; - - matroxfb_enable_irq(minfo, 0); - memset(vblank, 0, sizeof(*vblank)); - vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK; - /* mask out reserved bits + field number (odd/even) */ - vblank->vcount = mga_inl(0x3C48) & 0x000007FF; - /* compatibility stuff */ - if (vblank->vcount >= m2info->fbcon.var.yres) - vblank->flags |= FB_VBLANK_VBLANKING; - if (test_bit(0, &minfo->irq_flags)) { - vblank->flags |= FB_VBLANK_HAVE_COUNT; - /* Only one writer, aligned int value... - it should work without lock and without atomic_t */ - vblank->count = minfo->crtc2.vsync.cnt; - } - return 0; -} - -static int matroxfb_dh_ioctl(struct fb_info *info, - unsigned int cmd, - unsigned long arg) -{ -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - struct matrox_fb_info *minfo = m2info->primary_dev; - - DBG(__func__) - - switch (cmd) { - case FBIOGET_VBLANK: - { - struct fb_vblank vblank; - int err; - - err = matroxfb_dh_get_vblank(m2info, &vblank); - if (err) - return err; - if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank))) - return -EFAULT; - return 0; - } - case FBIO_WAITFORVSYNC: - { - u_int32_t crt; - - if (get_user(crt, (u_int32_t __user *)arg)) - return -EFAULT; - - if (crt != 0) - return -ENODEV; - return matroxfb_wait_for_sync(minfo, 1); - } - case MATROXFB_SET_OUTPUT_MODE: - case MATROXFB_GET_OUTPUT_MODE: - case MATROXFB_GET_ALL_OUTPUTS: - { - return minfo->fbcon.fbops->fb_ioctl(&minfo->fbcon, cmd, arg); - } - case MATROXFB_SET_OUTPUT_CONNECTION: - { - u_int32_t tmp; - int out; - int changes; - - if (get_user(tmp, (u_int32_t __user *)arg)) - return -EFAULT; - for (out = 0; out < 32; out++) { - if (tmp & (1 << out)) { - if (out >= MATROXFB_MAX_OUTPUTS) - return -ENXIO; - if (!minfo->outputs[out].output) - return -ENXIO; - switch (minfo->outputs[out].src) { - case MATROXFB_SRC_NONE: - case MATROXFB_SRC_CRTC2: - break; - default: - return -EBUSY; - } - } - } - if (minfo->devflags.panellink) { - if (tmp & MATROXFB_OUTPUT_CONN_DFP) - return -EINVAL; - if ((minfo->outputs[2].src == MATROXFB_SRC_CRTC1) && tmp) - return -EBUSY; - } - changes = 0; - for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (tmp & (1 << out)) { - if (minfo->outputs[out].src != MATROXFB_SRC_CRTC2) { - changes = 1; - minfo->outputs[out].src = MATROXFB_SRC_CRTC2; - } - } else if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) { - changes = 1; - minfo->outputs[out].src = MATROXFB_SRC_NONE; - } - } - if (!changes) - return 0; - matroxfb_dh_set_par(info); - return 0; - } - case MATROXFB_GET_OUTPUT_CONNECTION: - { - u_int32_t conn = 0; - int out; - - for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) { - conn |= 1 << out; - } - } - if (put_user(conn, (u_int32_t __user *)arg)) - return -EFAULT; - return 0; - } - case MATROXFB_GET_AVAILABLE_OUTPUTS: - { - u_int32_t tmp = 0; - int out; - - for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (minfo->outputs[out].output) { - switch (minfo->outputs[out].src) { - case MATROXFB_SRC_NONE: - case MATROXFB_SRC_CRTC2: - tmp |= 1 << out; - break; - } - } - } - if (minfo->devflags.panellink) { - tmp &= ~MATROXFB_OUTPUT_CONN_DFP; - if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) { - tmp = 0; - } - } - if (put_user(tmp, (u_int32_t __user *)arg)) - return -EFAULT; - return 0; - } - } - return -ENOTTY; -#undef m2info -} - -static int matroxfb_dh_blank(int blank, struct fb_info* info) { -#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - switch (blank) { - case 1: - case 2: - case 3: - case 4: - default:; - } - /* do something... */ - return 0; -#undef m2info -} - -static struct fb_ops matroxfb_dh_ops = { - .owner = THIS_MODULE, - .fb_open = matroxfb_dh_open, - .fb_release = matroxfb_dh_release, - .fb_check_var = matroxfb_dh_check_var, - .fb_set_par = matroxfb_dh_set_par, - .fb_setcolreg = matroxfb_dh_setcolreg, - .fb_pan_display =matroxfb_dh_pan_display, - .fb_blank = matroxfb_dh_blank, - .fb_ioctl = matroxfb_dh_ioctl, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, -}; - -static struct fb_var_screeninfo matroxfb_dh_defined = { - 640,480,640,480,/* W,H, virtual W,H */ - 0,0, /* offset */ - 32, /* depth */ - 0, /* gray */ - {0,0,0}, /* R */ - {0,0,0}, /* G */ - {0,0,0}, /* B */ - {0,0,0}, /* alpha */ - 0, /* nonstd */ - FB_ACTIVATE_NOW, - -1,-1, /* display size */ - 0, /* accel flags */ - 39721L,48L,16L,33L,10L, - 96L,2,0, /* no sync info */ - FB_VMODE_NONINTERLACED, -}; - -static int matroxfb_dh_regit(const struct matrox_fb_info *minfo, - struct matroxfb_dh_fb_info *m2info) -{ -#define minfo (m2info->primary_dev) - void* oldcrtc2; - - m2info->fbcon.fbops = &matroxfb_dh_ops; - m2info->fbcon.flags = FBINFO_FLAG_DEFAULT; - m2info->fbcon.flags |= FBINFO_HWACCEL_XPAN | - FBINFO_HWACCEL_YPAN; - m2info->fbcon.pseudo_palette = m2info->cmap; - fb_alloc_cmap(&m2info->fbcon.cmap, 256, 1); - - if (mem < 64) - mem *= 1024; - if (mem < 64*1024) - mem *= 1024; - mem &= ~0x00000FFF; /* PAGE_MASK? */ - if (minfo->video.len_usable + mem <= minfo->video.len) - m2info->video.offbase = minfo->video.len - mem; - else if (minfo->video.len < mem) { - return -ENOMEM; - } else { /* check yres on first head... */ - m2info->video.borrowed = mem; - minfo->video.len_usable -= mem; - m2info->video.offbase = minfo->video.len_usable; - } - m2info->video.base = minfo->video.base + m2info->video.offbase; - m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem; - m2info->video.vbase.vaddr = vaddr_va(minfo->video.vbase) + m2info->video.offbase; - m2info->mmio.base = minfo->mmio.base; - m2info->mmio.vbase = minfo->mmio.vbase; - m2info->mmio.len = minfo->mmio.len; - - matroxfb_dh_init_fix(m2info); - if (register_framebuffer(&m2info->fbcon)) { - return -ENXIO; - } - if (!m2info->initialized) - fb_set_var(&m2info->fbcon, &matroxfb_dh_defined); - down_write(&minfo->crtc2.lock); - oldcrtc2 = minfo->crtc2.info; - minfo->crtc2.info = m2info; - up_write(&minfo->crtc2.lock); - if (oldcrtc2) { - printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n", - oldcrtc2); - } - return 0; -#undef minfo -} - -/* ************************** */ - -static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) { -#define minfo (m2info->primary_dev) - if (matroxfb_dh_regit(minfo, m2info)) { - printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n"); - return -1; - } - printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n", - minfo->fbcon.node, m2info->fbcon.node); - m2info->fbcon_registered = 1; - return 0; -#undef minfo -} - -static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) { -#define minfo (m2info->primary_dev) - if (m2info->fbcon_registered) { - int id; - struct matroxfb_dh_fb_info* crtc2; - - down_write(&minfo->crtc2.lock); - crtc2 = minfo->crtc2.info; - if (crtc2 == m2info) - minfo->crtc2.info = NULL; - up_write(&minfo->crtc2.lock); - if (crtc2 != m2info) { - printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n", - crtc2, m2info); - printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n"); - return; - } - id = m2info->fbcon.node; - unregister_framebuffer(&m2info->fbcon); - /* return memory back to primary head */ - minfo->video.len_usable += m2info->video.borrowed; - printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id); - m2info->fbcon_registered = 0; - } -#undef minfo -} - -static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) { - struct matroxfb_dh_fb_info* m2info; - - /* hardware is CRTC2 incapable... */ - if (!minfo->devflags.crtc2) - return NULL; - m2info = kzalloc(sizeof(*m2info), GFP_KERNEL); - if (!m2info) { - printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n"); - return NULL; - } - m2info->primary_dev = minfo; - if (matroxfb_dh_registerfb(m2info)) { - kfree(m2info); - printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n"); - return NULL; - } - return m2info; -} - -static void matroxfb_crtc2_remove(struct matrox_fb_info* minfo, void* crtc2) { - matroxfb_dh_deregisterfb(crtc2); - kfree(crtc2); -} - -static struct matroxfb_driver crtc2 = { - .name = "Matrox G400 CRTC2", - .probe = matroxfb_crtc2_probe, - .remove = matroxfb_crtc2_remove }; - -static int matroxfb_crtc2_init(void) { - if (fb_get_options("matrox_crtc2fb", NULL)) - return -ENODEV; - - matroxfb_register_driver(&crtc2); - return 0; -} - -static void matroxfb_crtc2_exit(void) { - matroxfb_unregister_driver(&crtc2); -} - -MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>"); -MODULE_DESCRIPTION("Matrox G400 CRTC2 driver"); -MODULE_LICENSE("GPL"); -module_init(matroxfb_crtc2_init); -module_exit(matroxfb_crtc2_exit); -/* we do not have __setup() yet */ |