patch-2.3.13 linux/drivers/video/atyfb.c
Next file: linux/drivers/video/cgfourteenfb.c
Previous file: linux/drivers/video/aty.h
Back to the patch index
Back to the overall index
- Lines: 657
- Date:
Mon Aug 9 11:40:29 1999
- Orig file:
v2.3.12/linux/drivers/video/atyfb.c
- Orig date:
Wed Jun 9 14:44:25 1999
diff -u --recursive --new-file v2.3.12/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.107 1999/06/08 19:59:03 geert Exp $
+/* $Id: atyfb.c,v 1.109 1999/08/08 01:38:05 davem Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -72,8 +72,8 @@
#ifdef __sparc__
#include <asm/pbm.h>
#include <asm/fbio.h>
-#include <asm/uaccess.h>
#endif
+#include <asm/uaccess.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
@@ -136,6 +136,8 @@
u8 pll_ext_cntl;
u32 dsp_config; /* Mach64 GTB DSP */
u32 dsp_on_off; /* Mach64 GTB DSP */
+ u8 mclk_post_div_real;
+ u8 vclk_post_div_real;
};
@@ -189,6 +191,7 @@
struct fb_info_aty {
struct fb_info fb_info;
+ struct fb_info_aty *next;
unsigned long ati_regbase_phys;
unsigned long ati_regbase;
unsigned long frame_buffer_phys;
@@ -340,16 +343,19 @@
const struct pll_gx *pll);
static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll);
static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
-static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per,
+static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
const struct fb_info_aty *info);
static void aty_set_pll_ct(const struct fb_info_aty *info,
const struct pll_ct *pll);
-static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
- u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div,
- u8 bpp, struct pll_ct *pll);
+static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ struct pll_ct *pll);
+static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
+ struct pll_ct *pll);
+static void aty_calc_pll_ct(const struct fb_info_aty *info,
+ struct pll_ct *pll);
static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
u8 bpp, struct pll_ct *pll);
-static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per,
+static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
const struct fb_info_aty *info);
static void atyfb_set_par(const struct atyfb_par *par,
struct fb_info_aty *info);
@@ -465,7 +471,7 @@
};
-static inline u32 aty_ld_le32(volatile unsigned int regindex,
+static inline u32 aty_ld_le32(unsigned int regindex,
const struct fb_info_aty *info)
{
unsigned long temp;
@@ -473,7 +479,7 @@
#if defined(__powerpc__)
temp = info->ati_regbase;
- asm("lwbrx %0,%1,%2" : "=r"(val) : "r" (regindex), "r" (temp));
+ asm("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
#elif defined(__sparc_v9__)
temp = info->ati_regbase + regindex;
asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
@@ -484,14 +490,14 @@
return val;
}
-static inline void aty_st_le32(volatile unsigned int regindex, u32 val,
+static inline void aty_st_le32(unsigned int regindex, u32 val,
const struct fb_info_aty *info)
{
unsigned long temp;
#if defined(__powerpc__)
temp = info->ati_regbase;
- asm("stwbrx %0,%1,%2" : : "r" (val), "r" (regindex), "r" (temp) :
+ asm("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
"memory");
#elif defined(__sparc_v9__)
temp = info->ati_regbase + regindex;
@@ -502,13 +508,13 @@
#endif
}
-static inline u8 aty_ld_8(volatile unsigned int regindex,
+static inline u8 aty_ld_8(unsigned int regindex,
const struct fb_info_aty *info)
{
return *(volatile u8 *)(info->ati_regbase+regindex);
}
-static inline void aty_st_8(volatile unsigned int regindex, u8 val,
+static inline void aty_st_8(unsigned int regindex, u8 val,
const struct fb_info_aty *info)
{
*(volatile u8 *)(info->ati_regbase+regindex) = val;
@@ -941,8 +947,10 @@
}
}
-__initfunc(static struct aty_cursor *
-aty_init_cursor(struct fb_info_aty *fb))
+static struct fb_info_aty *fb_list = NULL;
+
+static struct aty_cursor * __init
+aty_init_cursor(struct fb_info_aty *fb)
{
struct aty_cursor *cursor;
unsigned long addr;
@@ -1452,7 +1460,7 @@
/* FIXME: ATI18818?? */
-static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per,
+static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
const struct fb_info_aty *info)
{
u8 df, vco_div_count, ref_div_count;
@@ -1461,9 +1469,7 @@
vco_div_count = pll->m & 0x3f;
ref_div_count = pll->n;
- *vclk_per = ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
-
- return 0;
+ return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
}
@@ -1495,16 +1501,15 @@
}
}
-static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
- u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div,
- u8 bpp, struct pll_ct *pll)
+static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
+ struct pll_ct *pll)
{
u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
/* xclocks_per_row<<11 */
- xclks_per_row = (mclk_fb_div*vclk_post_div*64<<11)/
- (vclk_fb_div*mclk_post_div*bpp);
+ xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
+ (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
if (xclks_per_row < (1<<11))
FAIL("Dotclock to high");
if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
@@ -1564,63 +1569,59 @@
return 0;
}
-static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
- u8 bpp, struct pll_ct *pll)
+static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ struct pll_ct *pll)
{
u32 q, x; /* x is a workaround for sparc64-linux-gcc */
- u8 pll_ref_div, pll_gen_cntl, pll_ext_cntl;
- u8 mclk_fb_div, mclk_post_div, mpostdiv = 0;
- u8 vclk_fb_div, vclk_post_div, vpostdiv = 0;
- int err;
-
x = x; /* x is a workaround for sparc64-linux-gcc */
- pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
-
- pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
+ pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
- q = info->ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */
+ q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */
if (q < 16*8 || q > 255*8)
FAIL("mclk out of range");
else if (q < 32*8)
- mclk_post_div = 8;
+ pll->mclk_post_div_real = 8;
else if (q < 64*8)
- mclk_post_div = 4;
+ pll->mclk_post_div_real = 4;
else if (q < 128*8)
- mclk_post_div = 2;
+ pll->mclk_post_div_real = 2;
else
- mclk_post_div = 1;
- mclk_fb_div = q*mclk_post_div/8;
+ pll->mclk_post_div_real = 1;
+ pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
- q = info->ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */
+ q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */
if (q < 16*8 || q > 255*8)
FAIL("vclk out of range");
else if (q < 32*8)
- vclk_post_div = 8;
+ pll->vclk_post_div_real = 8;
else if (q < 64*8)
- vclk_post_div = 4;
+ pll->vclk_post_div_real = 4;
else if (q < 128*8)
- vclk_post_div = 2;
+ pll->vclk_post_div_real = 2;
else
- vclk_post_div = 1;
- vclk_fb_div = q*vclk_post_div/8;
+ pll->vclk_post_div_real = 1;
+ pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
+ return 0;
+}
- if ((err = aty_dsp_gt(info, mclk_fb_div, mclk_post_div, vclk_fb_div,
- vclk_post_div, bpp, pll)))
- return err;
+static void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
+{
+ u8 mpostdiv = 0;
+ u8 vpostdiv = 0;
if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
(Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
(Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
(Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
(Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
- pll_gen_cntl = 0x04;
+ pll->pll_gen_cntl = 0x04;
else
- pll_gen_cntl = 0x84;
+ pll->pll_gen_cntl = 0x84;
- switch (mclk_post_div) {
+ switch (pll->mclk_post_div_real) {
case 1:
mpostdiv = 0;
break;
@@ -1637,61 +1638,64 @@
mpostdiv = 3;
break;
}
- pll_gen_cntl |= mpostdiv<<4; /* mclk */
+ pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */
if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))
- pll_ext_cntl = 0;
+ pll->pll_ext_cntl = 0;
else
- pll_ext_cntl = mpostdiv; /* xclk == mclk */
+ pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
- switch (vclk_post_div) {
+ switch (pll->vclk_post_div_real) {
case 2:
vpostdiv = 1;
break;
case 3:
- pll_ext_cntl |= 0x10;
+ pll->pll_ext_cntl |= 0x10;
case 1:
vpostdiv = 0;
break;
case 6:
- pll_ext_cntl |= 0x10;
+ pll->pll_ext_cntl |= 0x10;
case 4:
vpostdiv = 2;
break;
case 12:
- pll_ext_cntl |= 0x10;
+ pll->pll_ext_cntl |= 0x10;
case 8:
vpostdiv = 3;
break;
}
- vclk_post_div = vpostdiv;
- pll->pll_ref_div = pll_ref_div;
- pll->pll_gen_cntl = pll_gen_cntl;
- pll->mclk_fb_div = mclk_fb_div;
- pll->vclk_post_div = vclk_post_div;
- pll->vclk_fb_div = vclk_fb_div;
- pll->pll_ext_cntl = pll_ext_cntl;
+ pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
+ pll->vclk_post_div = vpostdiv;
+}
+
+static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ u8 bpp, struct pll_ct *pll)
+{
+ int err;
+
+ if ((err = aty_valid_pll_ct(info, vclk_per, pll)))
+ return err;
+ if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
+ Gx == ET_CHIP_ID ||
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
+ if ((err = aty_dsp_gt(info, bpp, pll)))
+ return err;
+ }
+ aty_calc_pll_ct(info, pll);
return 0;
}
-static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per,
+static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
const struct fb_info_aty *info)
{
+ u32 ref_clk_per = info->ref_clk_per;
u8 pll_ref_div = pll->pll_ref_div;
u8 vclk_fb_div = pll->vclk_fb_div;
- u8 vclk_post_div = pll->vclk_post_div;
- u8 pll_ext_cntl = pll->pll_ext_cntl;
- static u8 vclk_post_div_tab[] = {
- 1, 2, 4, 8,
- 3, 0, 6, 12
- };
- u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 2) |
- (vclk_post_div & 3)];
- if (vpostdiv == 0)
- return -EINVAL;
- *vclk_per = pll_ref_div*vpostdiv*info->ref_clk_per/vclk_fb_div/2;
- return 0;
+ u8 vclk_post_div = pll->vclk_post_div_real;
+
+ return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2;
}
/* ------------------------------------------------------------------------- */
@@ -1739,7 +1743,7 @@
} else {
aty_set_pll_ct(info, &par->pll.ct);
- i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff;
+ i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
i |= info->mem_refresh_rate << 20;
switch (par->crtc.bpp) {
@@ -1844,11 +1848,9 @@
if ((err = aty_crtc_to_var(&par->crtc, var)))
return err;
if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
- err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock, info);
+ var->pixclock = aty_pll_gx_to_var(&par->pll.gx, info);
else
- err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock, info);
- if (err)
- return err;
+ var->pixclock = aty_pll_ct_to_var(&par->pll.ct, info);
var->height = -1;
var->width = -1;
@@ -2194,36 +2196,101 @@
}
+#ifdef DEBUG
+#define ATYIO_CLKR 0x41545900 /* ATY\00 */
+#define ATYIO_CLKW 0x41545901 /* ATY\01 */
+
+struct atyclk {
+ u32 ref_clk_per;
+ u8 pll_ref_div;
+ u8 mclk_fb_div;
+ u8 mclk_post_div; /* 1,2,3,4,8 */
+ u8 vclk_fb_div;
+ u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
+ u32 dsp_xclks_per_row; /* 0-16383 */
+ u32 dsp_loop_latency; /* 0-15 */
+ u32 dsp_precision; /* 0-7 */
+ u32 dsp_on; /* 0-2047 */
+ u32 dsp_off; /* 0-2047 */
+};
+#endif
+
static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info)
+ u_long arg, int con, struct fb_info *info2)
{
+ struct fb_info_aty *info = (struct fb_info_aty *)info2;
#ifdef __sparc__
- struct fb_info_aty *fb = (struct fb_info_aty *)info;
struct fbtype fbtyp;
struct display *disp;
if (con >= 0)
disp = &fb_display[con];
else
- disp = info->disp;
+ disp = info2->disp;
+#endif
switch (cmd) {
+#ifdef __sparc__
case FBIOGTYPE:
fbtyp.fb_type = FBTYPE_PCI_GENERIC;
- fbtyp.fb_width = fb->current_par.crtc.vxres;
- fbtyp.fb_height = fb->current_par.crtc.vyres;
- fbtyp.fb_depth = fb->current_par.crtc.bpp;
+ fbtyp.fb_width = info->current_par.crtc.vxres;
+ fbtyp.fb_height = info->current_par.crtc.vyres;
+ fbtyp.fb_depth = info->current_par.crtc.bpp;
fbtyp.fb_cmsize = disp->cmap.len;
- fbtyp.fb_size = fb->total_vram;
+ fbtyp.fb_size = info->total_vram;
copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
break;
+#endif /* __sparc__ */
+#ifdef DEBUG
+ case ATYIO_CLKR:
+ if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
+ struct atyclk clk;
+ struct pll_ct *pll = &info->current_par.pll.ct;
+ u32 dsp_config = pll->dsp_config;
+ u32 dsp_on_off = pll->dsp_on_off;
+ clk.ref_clk_per = info->ref_clk_per;
+ clk.pll_ref_div = pll->pll_ref_div;
+ clk.mclk_fb_div = pll->mclk_fb_div;
+ clk.mclk_post_div = pll->mclk_post_div_real;
+ clk.vclk_fb_div = pll->vclk_fb_div;
+ clk.vclk_post_div = pll->vclk_post_div_real;
+ clk.dsp_xclks_per_row = dsp_config & 0x3fff;
+ clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
+ clk.dsp_precision = (dsp_config>>20) & 7;
+ clk.dsp_on = dsp_on_off & 0x7ff;
+ clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
+ copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk),
+ -EFAULT);
+ } else
+ return -EINVAL;
+ break;
+ case ATYIO_CLKW:
+ if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
+ struct atyclk clk;
+ struct pll_ct *pll = &info->current_par.pll.ct;
+ copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk),
+ -EFAULT);
+ info->ref_clk_per = clk.ref_clk_per;
+ pll->pll_ref_div = clk.pll_ref_div;
+ pll->mclk_fb_div = clk.mclk_fb_div;
+ pll->mclk_post_div_real = clk.mclk_post_div;
+ pll->vclk_fb_div = clk.vclk_fb_div;
+ pll->vclk_post_div_real = clk.vclk_post_div;
+ pll->dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
+ ((clk.dsp_loop_latency & 0xf)<<16) |
+ ((clk.dsp_precision & 7)<<20);
+ pll->dsp_on_off = (clk.dsp_on & 0x7ff) |
+ ((clk.dsp_off & 0x7ff)<<16);
+ aty_calc_pll_ct(info, pll);
+ aty_set_pll_ct(info, pll);
+ } else
+ return -EINVAL;
+ break;
+#endif /* DEBUG */
default:
return -EINVAL;
}
return 0;
-#else
- return -EINVAL;
-#endif
}
#ifdef __sparc__
@@ -2424,7 +2491,7 @@
* Initialisation
*/
-__initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
+static int __init aty_init(struct fb_info_aty *info, const char *name)
{
u32 chip_id;
u32 i;
@@ -2746,12 +2813,15 @@
if (register_framebuffer(&info->fb_info) < 0)
return 0;
+ info->next = fb_list;
+ fb_list = info;
+
printk("fb%d: %s frame buffer device on %s\n",
GET_FB_IDX(info->fb_info.node), atyfb_name, name);
return 1;
}
-__initfunc(void atyfb_init(void))
+void __init atyfb_init(void)
{
#if defined(CONFIG_FB_OF)
/* We don't want to be called like this. */
@@ -2779,6 +2849,7 @@
for (pdev = pci_devices; pdev; pdev = pdev->next) {
if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
(pdev->vendor == PCI_VENDOR_ID_ATI)) {
+ struct resource *rp;
info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
if (!info) {
@@ -2787,12 +2858,12 @@
}
memset(info, 0, sizeof(struct fb_info_aty));
- addr = pdev->base_address[0];
- if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
- addr = pdev->base_address[1];
+ rp = &pdev->resource[0];
+ if (rp->flags & IORESOURCE_IOPORT)
+ rp = &pdev->resource[1];
+ addr = rp->start;
if (!addr)
continue;
- addr &= PCI_BASE_ADDRESS_MEM_MASK;
#ifdef __sparc__
/*
@@ -2811,7 +2882,7 @@
* Figure mmap addresses from PCI config space.
* Split Framebuffer in big- and little-endian halfs.
*/
- for (i = 0; i < 6 && pdev->base_address[i]; i++)
+ for (i = 0; i < 6 && pdev->resource[i].start; i++)
/* nothing */;
j = i + 4;
@@ -2823,14 +2894,15 @@
}
memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
- for (i = 0, j = 2; i < 6 && pdev->base_address[i]; i++) {
+ for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
+ struct resource *rp = &pdev->resource[i];
int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
unsigned long base;
u32 size, pbase;
- base = pdev->base_address[i];
+ base = rp->start;
- io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
+ io = (rp->flags & IORESOURCE_IOPORT);
pci_read_config_dword(pdev, breg, &pbase);
pci_write_config_dword(pdev, breg, 0xffffffff);
@@ -3096,7 +3168,7 @@
}
#ifdef CONFIG_FB_OF
-__initfunc(void atyfb_of_init(struct device_node *dp))
+void __init atyfb_of_init(struct device_node *dp)
{
unsigned long addr;
u8 bus, devfn;
@@ -3135,7 +3207,7 @@
0x1000);
if(! info->ati_regbase) {
- printk("atyfb_init: ioremap() returned NULL\n");
+ printk("atyfb_of_init: ioremap() returned NULL\n");
kfree(info);
return;
}
@@ -3162,7 +3234,7 @@
info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
if(! info->frame_buffer) {
- printk("atyfb_init: ioremap() returned NULL\n");
+ printk("atyfb_of_init: ioremap() returned NULL\n");
kfree(info);
return;
}
@@ -3180,7 +3252,7 @@
#endif /* CONFIG_FB_OF */
-__initfunc(void atyfb_setup(char *options, int *ints))
+void __init atyfb_setup(char *options, int *ints)
{
char *this_opt;
@@ -3251,7 +3323,7 @@
}
#ifdef CONFIG_ATARI
-__initfunc(static int store_video_par(char *video_str, unsigned char m64_num))
+static int __init store_video_par(char *video_str, unsigned char m64_num)
{
char *p;
unsigned long vmembase, size, guiregbase;
@@ -3280,7 +3352,7 @@
return -1;
}
-__initfunc(static char *strtoke(char *s, const char *ct))
+static char __init *strtoke(char *s, const char *ct)
{
static char *ssave = NULL;
char *sbegin, *send;
@@ -3869,4 +3941,45 @@
fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
+#endif
+
+#ifdef MODULE
+int __init init_module(void)
+{
+ atyfb_init();
+ return fb_list ? 0 : -ENXIO;
+}
+
+void cleanup_module(void)
+{
+ while (fb_list) {
+ struct fb_info_aty *info = fb_list;
+ fb_list = info->next;
+
+ unregister_framebuffer(&info->fb_info);
+
+#ifndef __sparc__
+ if (info->ati_regbase)
+ iounmap((void *)info->ati_regbase);
+ if (info->frame_buffer)
+ iounmap((void *)info->frame_buffer);
+#ifdef __BIG_ENDIAN
+ if (info->cursor && info->cursor->ram)
+ iounmap(info->cursor->ram);
+#endif
+#endif
+
+ if (info->cursor) {
+ if (info->cursor->timer)
+ kfree(info->cursor->timer);
+ kfree(info->cursor);
+ }
+#ifdef __sparc__
+ if (info->mmap_map)
+ kfree(info->mmap_map);
+#endif
+ kfree(info);
+ }
+}
+
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)