patch-2.1.124 linux/drivers/video/offb.c
Next file: linux/drivers/video/platinumfb.c
Previous file: linux/drivers/video/newport_con.c
Back to the patch index
Back to the overall index
- Lines: 585
- Date:
Thu Oct 1 10:03:16 1998
- Orig file:
v2.1.123/linux/drivers/video/offb.c
- Orig date:
Tue Jul 28 14:21:09 1998
diff -u --recursive --new-file v2.1.123/linux/drivers/video/offb.c linux/drivers/video/offb.c
@@ -31,10 +31,11 @@
#endif
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm/bootx.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "macmodes.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/macmodes.h>
static int currcon = 0;
@@ -91,6 +92,12 @@
struct vc_mode display_info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
+extern boot_infos_t *boot_infos;
+
+static int offb_init_driver(struct device_node *);
+static void offb_init_nodriver(struct device_node *);
+static void offb_init_fb(const char *name, const char *full_name, int width,
+ int height, int depth, int pitch, unsigned long address);
/*
* Interface to the low level console driver
@@ -175,7 +182,8 @@
struct fb_info *info)
{
struct display *display;
- int oldbpp = -1, err;
+ unsigned int oldbpp = 0;
+ int err;
int activate = var->activate;
struct fb_info_offb *info2 = (struct fb_info_offb *)info;
@@ -229,8 +237,7 @@
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, offb_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, offb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -258,8 +265,7 @@
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, offb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, offb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -279,12 +285,18 @@
#ifdef CONFIG_FB_S3TRIO
extern void s3triofb_init_of(struct device_node *dp);
#endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_IMSTT
+extern void imsttfb_of_init(struct device_node *dp);
+#endif
#ifdef CONFIG_FB_CT65550
extern void chips_of_init(struct device_node *dp);
#endif /* CONFIG_FB_CT65550 */
#ifdef CONFIG_FB_CONTROL
extern void control_of_init(struct device_node *dp);
#endif /* CONFIG_FB_CONTROL */
+#ifdef CONFIG_FB_VALKYRIE
+extern void valkyrie_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_VALKYRIE */
#ifdef CONFIG_FB_PLATINUM
extern void platinum_of_init(struct device_node *dp);
#endif /* CONFIG_FB_PLATINUM */
@@ -297,193 +309,298 @@
__initfunc(void offb_init(void))
{
struct device_node *dp;
- int dpy, i, *pp, len;
- unsigned *up, address;
- struct fb_fix_screeninfo *fix;
- struct fb_var_screeninfo *var;
- struct display *disp;
- struct fb_info_offb *info;
+ unsigned int dpy;
+ struct device_node *displays = find_type_devices("display");
+ struct device_node *macos_display = NULL;
+
+ /* If we're booted from BootX... */
+ if (prom_num_displays == 0 && boot_infos != 0) {
+ unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;
+ if (!ofonly) {
+ /* find the device node corresponding to the macos display */
+ for (dp = displays; dp != NULL; dp = dp->next) {
+ int i;
+ /*
+ * Grrr... It looks like the MacOS ATI driver
+ * munges the assigned-addresses property (but
+ * the AAPL,address value is OK).
+ */
+ if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
+ unsigned int *ap = (unsigned int *)
+ get_property(dp, "AAPL,address", NULL);
+ if (ap != NULL) {
+ dp->addrs[0].address = *ap;
+ dp->addrs[0].size = 0x01000000;
+ }
+ }
+ /*
+ * See if the display address is in one of the address
+ * ranges for this display.
+ */
+ for (i = 0; i < dp->n_addrs; ++i) {
+ if (dp->addrs[i].address <= addr
+ && addr < dp->addrs[i].address + dp->addrs[i].size)
+ break;
+ }
+ if (i < dp->n_addrs) {
+ printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
+ macos_display = dp;
+ break;
+ }
+ }
+ }
+
+ /* initialize it */
+ if (macos_display == NULL || !offb_init_driver(macos_display)) {
+ offb_init_fb("MacOS display", "MacOS display",
+ boot_infos->dispDeviceRect[2],
+ boot_infos->dispDeviceRect[3],
+ boot_infos->dispDeviceDepth,
+ boot_infos->dispDeviceRowBytes, addr);
+ }
+ }
for (dpy = 0; dpy < prom_num_displays; dpy++) {
- if (!(dp = find_path_device(prom_display_paths[dpy])))
- continue;
+ if ((dp = find_path_device(prom_display_paths[dpy])))
+ if (ofonly || !offb_init_driver(dp))
+ offb_init_nodriver(dp);
+ }
- if (!ofonly) {
+ if (!ofonly) {
+ for (dp = find_type_devices("display"); dp != NULL; dp = dp->next) {
+ for (dpy = 0; dpy < prom_num_displays; dpy++)
+ if (strcmp(dp->full_name, prom_display_paths[dpy]) == 0)
+ break;
+ if (dpy >= prom_num_displays && dp != macos_display)
+ offb_init_driver(dp);
+ }
+ }
+}
+
+__initfunc(static int offb_init_driver(struct device_node *dp))
+{
#ifdef CONFIG_FB_ATY
- if (!strncmp(dp->name, "ATY", 3)) {
- atyfb_of_init(dp);
- continue;
- }
+ if (!strncmp(dp->name, "ATY", 3)) {
+ atyfb_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_ATY */
#ifdef CONFIG_FB_S3TRIO
- if (s3triofb_init_of(dp))
- continue;
+ if (s3triofb_init_of(dp))
+ return 1;
#endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_IMSTT
+ if (!strncmp(dp->name, "IMS,tt128mb", 11)) {
+ imsttfb_of_init(dp);
+ return 1;
+ }
+#endif
#ifdef CONFIG_FB_CT65550
- if (!strcmp(dp->name, "chips65550")) {
- chips_of_init(dp);
- continue;
- }
+ if (!strcmp(dp->name, "chips65550")) {
+ chips_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_CT65550 */
#ifdef CONFIG_FB_CONTROL
- if(!strcmp(dp->name, "control")) {
- control_of_init(dp);
- continue;
- }
+ if(!strcmp(dp->name, "control")) {
+ control_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_CONTROL */
+#ifdef CONFIG_FB_VALKYRIE
+ if(!strcmp(dp->name, "valkyrie")) {
+ valkyrie_of_init(dp);
+ return 1;
+ }
+#endif /* CONFIG_FB_VALKYRIE */
#ifdef CONFIG_FB_PLATINUM
- if (!strncmp(dp->name, "platinum",8)) {
- printk("jonh: offb_init sees device node %s\n", dp->name);
- platinum_of_init(dp);
- continue;
- }
+ if (!strncmp(dp->name, "platinum",8)) {
+ platinum_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_PLATINUM */
- }
+ return 0;
+}
- info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
- fix = &info->fix;
- var = &info->var;
- disp = &info->disp;
-
- strcpy(fix->id, "OFfb ");
- strncat(fix->id, dp->name, sizeof(fix->id));
- fix->id[sizeof(fix->id)-1] = '\0';
-
- if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
- && len == sizeof(int) && *pp != 8) {
- printk("%s: can't use depth = %d\n", dp->full_name, *pp);
- kfree(info);
- continue;
- }
- if ((pp = (int *)get_property(dp, "width", &len)) != NULL
- && len == sizeof(int))
- var->xres = var->xres_virtual = *pp;
- if ((pp = (int *)get_property(dp, "height", &len)) != NULL
- && len == sizeof(int))
- var->yres = var->yres_virtual = *pp;
- if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
- && len == sizeof(int))
- fix->line_length = *pp;
- else
- fix->line_length = var->xres_virtual;
- fix->smem_len = fix->line_length*var->yres;
- if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
- && len == sizeof(unsigned))
- address = (u_long)*up;
- else {
- for (i = 0; i < dp->n_addrs; ++i)
- if (dp->addrs[i].size >= len)
- break;
- if (i >= dp->n_addrs) {
- printk("no framebuffer address found for %s\n", dp->full_name);
- kfree(info);
- continue;
- }
- address = (u_long)dp->addrs[i].address;
+__initfunc(static void offb_init_nodriver(struct device_node *dp))
+{
+ int *pp, i;
+ unsigned int len;
+ int width = 640, height = 480, depth = 8, pitch;
+ unsigned *up, address;
+
+ if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
+ && len == sizeof(int))
+ depth = *pp;
+ if ((pp = (int *)get_property(dp, "width", &len)) != NULL
+ && len == sizeof(int))
+ width = *pp;
+ if ((pp = (int *)get_property(dp, "height", &len)) != NULL
+ && len == sizeof(int))
+ height = *pp;
+ if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
+ && len == sizeof(int))
+ pitch = *pp;
+ else
+ pitch = width;
+ if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
+ && len == sizeof(unsigned))
+ address = (u_long)*up;
+ else {
+ for (i = 0; i < dp->n_addrs; ++i)
+ if (dp->addrs[i].size >= len)
+ break;
+ if (i >= dp->n_addrs) {
+ printk("no framebuffer address found for %s\n", dp->full_name);
+ return;
}
- fix->smem_start = (char *)address;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
+ address = (u_long)dp->addrs[i].address;
+
+ /* kludge for valkyrie */
+ if (strcmp(dp->name, "valkyrie") == 0)
+ address += 0x1000;
+ }
+ offb_init_fb(dp->name, dp->full_name, width, height, depth,
+ pitch, address);
+}
+
+__initfunc(static void offb_init_fb(const char *name, const char *full_name,
+ int width, int height, int depth,
+ int pitch, unsigned long address))
+{
+ int i;
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ struct display *disp;
+ struct fb_info_offb *info;
+
+ printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
+ width, height, name, address, depth, pitch);
+ if (depth != 8) {
+ printk("%s: can't use depth = %d\n", full_name, depth);
+ return;
+ }
+
+ info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
+ if (info == 0)
+ return;
+ memset(info, 0, sizeof(*info));
+
+ fix = &info->fix;
+ var = &info->var;
+ disp = &info->disp;
+
+ strcpy(fix->id, "OFfb ");
+ strncat(fix->id, name, sizeof(fix->id));
+ fix->id[sizeof(fix->id)-1] = '\0';
+
+ var->xres = var->xres_virtual = width;
+ var->yres = var->yres_virtual = height;
+ fix->line_length = pitch;
+
+ fix->smem_start = (char *)address;
+ fix->smem_len = pitch * height;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
/* XXX kludge for ati */
- if (strncmp(dp->name, "ATY,", 4) == 0) {
- info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
- info->cmap_data = info->cmap_adr + 1;
- }
+ if (strncmp(name, "ATY,", 4) == 0) {
+ info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
+ info->cmap_data = info->cmap_adr + 1;
+ }
- fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_STATIC_PSEUDOCOLOR;
+ fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR :
+ FB_VISUAL_STATIC_PSEUDOCOLOR;
- var->xoffset = var->yoffset = 0;
- var->bits_per_pixel = 8;
- var->grayscale = 0;
- var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
- var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
- var->transp.offset = var->transp.length = var->transp.msb_right = 0;
- var->nonstd = 0;
- var->activate = 0;
- var->height = var->width = -1;
- var->pixclock = 10000;
- var->left_margin = var->right_margin = 16;
- var->upper_margin = var->lower_margin = 16;
- var->hsync_len = var->vsync_len = 8;
- var->sync = 0;
- var->vmode = FB_VMODE_NONINTERLACED;
-
- disp->var = *var;
- disp->cmap.start = 0;
- disp->cmap.len = 0;
- disp->cmap.red = NULL;
- disp->cmap.green = NULL;
- disp->cmap.blue = NULL;
- disp->cmap.transp = NULL;
- disp->screen_base = ioremap(address, fix->smem_len);
- disp->visual = fix->visual;
- disp->type = fix->type;
- disp->type_aux = fix->type_aux;
- disp->ypanstep = 0;
- disp->ywrapstep = 0;
- disp->line_length = fix->line_length;
- disp->can_soft_blank = info->cmap_adr ? 1 : 0;
- disp->inverse = 0;
+ var->xoffset = var->yoffset = 0;
+ var->bits_per_pixel = 8;
+ var->grayscale = 0;
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+ var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+ var->nonstd = 0;
+ var->activate = 0;
+ var->height = var->width = -1;
+ var->pixclock = 10000;
+ var->left_margin = var->right_margin = 16;
+ var->upper_margin = var->lower_margin = 16;
+ var->hsync_len = var->vsync_len = 8;
+ var->sync = 0;
+ var->vmode = FB_VMODE_NONINTERLACED;
+
+ disp->var = *var;
+ disp->cmap.start = 0;
+ disp->cmap.len = 0;
+ disp->cmap.red = NULL;
+ disp->cmap.green = NULL;
+ disp->cmap.blue = NULL;
+ disp->cmap.transp = NULL;
+ disp->screen_base = ioremap(address, fix->smem_len);
+ disp->visual = fix->visual;
+ disp->type = fix->type;
+ disp->type_aux = fix->type_aux;
+ disp->ypanstep = 0;
+ disp->ywrapstep = 0;
+ disp->line_length = fix->line_length;
+ disp->can_soft_blank = info->cmap_adr ? 1 : 0;
+ disp->inverse = 0;
#ifdef FBCON_HAS_CFB8
- disp->dispsw = &fbcon_cfb8;
+ disp->dispsw = &fbcon_cfb8;
#else
- disp->dispsw = NULL;
+ disp->dispsw = &fbcon_dummy;
#endif
- disp->scrollmode = SCROLL_YREDRAW;
+ disp->scrollmode = SCROLL_YREDRAW;
- strcpy(info->info.modename, "OFfb ");
- strncat(info->info.modename, dp->full_name,
- sizeof(info->info.modename));
- info->info.node = -1;
- info->info.fbops = &offb_ops;
- info->info.disp = disp;
- info->info.fontname[0] = '\0';
- info->info.changevar = NULL;
- info->info.switch_con = &offbcon_switch;
- info->info.updatevar = &offbcon_updatevar;
- info->info.blank = &offbcon_blank;
-
- for (i = 0; i < 16; i++) {
- int j = color_table[i];
- info->palette[i].red = default_red[j];
- info->palette[i].green = default_grn[j];
- info->palette[i].blue = default_blu[j];
- }
- offb_set_var(var, -1, &info->info);
+ strcpy(info->info.modename, "OFfb ");
+ strncat(info->info.modename, full_name, sizeof(info->info.modename));
+ info->info.node = -1;
+ info->info.fbops = &offb_ops;
+ info->info.disp = disp;
+ info->info.fontname[0] = '\0';
+ info->info.changevar = NULL;
+ info->info.switch_con = &offbcon_switch;
+ info->info.updatevar = &offbcon_updatevar;
+ info->info.blank = &offbcon_blank;
+ info->info.flags = FBINFO_FLAG_DEFAULT;
+
+ for (i = 0; i < 16; i++) {
+ int j = color_table[i];
+ info->palette[i].red = default_red[j];
+ info->palette[i].green = default_grn[j];
+ info->palette[i].blue = default_blu[j];
+ }
+ offb_set_var(var, -1, &info->info);
- if (register_framebuffer(&info->info) < 0) {
- kfree(info);
- return;
- }
+ if (register_framebuffer(&info->info) < 0) {
+ kfree(info);
+ return;
+ }
- printk("fb%d: Open Firmware frame buffer device on %s\n",
- GET_FB_IDX(info->info.node), dp->full_name);
+ printk("fb%d: Open Firmware frame buffer device on %s\n",
+ GET_FB_IDX(info->info.node), full_name);
#ifdef CONFIG_FB_COMPAT_XPMAC
- if (!console_fb_info) {
- display_info.height = var->yres;
- display_info.width = var->xres;
- display_info.depth = 8;
- display_info.pitch = fix->line_length;
- display_info.mode = 0;
- strncpy(display_info.name, dp->name, sizeof(display_info.name));
- display_info.fb_address = address;
- display_info.cmap_adr_address = 0;
- display_info.cmap_data_address = 0;
- display_info.disp_reg_address = 0;
- /* XXX kludge for ati */
- if (strncmp(dp->name, "ATY,", 4) == 0) {
- display_info.disp_reg_address = address + 0x7ffc00;
- display_info.cmap_adr_address = address + 0x7ffcc0;
- display_info.cmap_data_address = address + 0x7ffcc1;
- }
- console_fb_info = &info->info;
+ if (!console_fb_info) {
+ display_info.height = var->yres;
+ display_info.width = var->xres;
+ display_info.depth = 8;
+ display_info.pitch = fix->line_length;
+ display_info.mode = 0;
+ strncpy(display_info.name, name, sizeof(display_info.name));
+ display_info.fb_address = address;
+ display_info.cmap_adr_address = 0;
+ display_info.cmap_data_address = 0;
+ display_info.disp_reg_address = 0;
+ /* XXX kludge for ati */
+ if (strncmp(name, "ATY,", 4) == 0) {
+ display_info.disp_reg_address = address + 0x7ffc00;
+ display_info.cmap_adr_address = address + 0x7ffcc0;
+ display_info.cmap_data_address = address + 0x7ffcc1;
}
-#endif /* CONFIG_FB_COMPAT_XPMAC) */
+ console_fb_info = &info->info;
}
+#endif /* CONFIG_FB_COMPAT_XPMAC) */
}
@@ -505,8 +622,7 @@
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- offb_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, offb_getcolreg, info);
currcon = con;
/* Install new colormap */
@@ -561,9 +677,11 @@
if (!info2->cmap_adr || regno > 255)
return 1;
- *red = info2->palette[regno].red;
- *green = info2->palette[regno].green;
- *blue = info2->palette[regno].blue;
+
+ *red = (info2->palette[regno].red<<8) | info2->palette[regno].red;
+ *green = (info2->palette[regno].green<<8) | info2->palette[regno].green;
+ *blue = (info2->palette[regno].blue<<8) | info2->palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -581,6 +699,10 @@
if (!info2->cmap_adr || regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
info2->palette[regno].red = red;
info2->palette[regno].green = green;
info2->palette[regno].blue = blue;
@@ -601,12 +723,10 @@
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- offb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, offb_setcolreg, info);
else
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, offb_setcolreg,
- info);
+ 1, offb_setcolreg, info);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov