summaryrefslogtreecommitdiffstats
path: root/drivers/video/chipsfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/chipsfb.c')
-rw-r--r--drivers/video/chipsfb.c127
1 files changed, 72 insertions, 55 deletions
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 699ae96ff..eb5d8931c 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -53,11 +53,14 @@ struct fb_info_chips {
struct {
__u8 red, green, blue;
} palette[256];
+ unsigned long frame_buffer_phys;
__u8 *frame_buffer;
- __u8 *blitter_regs;
+ unsigned long blitter_regs_phys;
+ __u32 *blitter_regs;
+ unsigned long blitter_data_phys;
+ __u8 *blitter_data;
+ unsigned long io_base_phys;
__u8 *io_base;
- unsigned long chips_base_phys;
- unsigned long chips_io_phys;
struct fb_info_chips *next;
#ifdef CONFIG_PMAC_PBOOK
unsigned char *save_framebuffer;
@@ -214,27 +217,28 @@ static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
if (con == currcon) /* current console? */
return fb_get_cmap(cmap, kspc, chipsfb_getcolreg, info);
if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
- else
- fb_copy_cmap(fb_default_cmap(256), cmap, kspc? 0: 2);
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else {
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+ }
return 0;
}
static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- struct display *disp = &fb_display[con];
int err;
- if (disp->cmap.len == 0) {
- err = fb_alloc_cmap(&disp->cmap, 256, 0);
- if (err)
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
return err;
}
-
- if (con == currcon)
+ if (con == currcon) /* current console? */
return fb_set_cmap(cmap, kspc, chipsfb_setcolreg, info);
- fb_copy_cmap(cmap, &disp->cmap, kspc==0);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
}
@@ -244,24 +248,21 @@ static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
return -EINVAL;
}
-static int chipsfb_switch(int con, struct fb_info *info)
+static int chipsfbcon_switch(int con, struct fb_info *info)
{
struct fb_info_chips *p = (struct fb_info_chips *) info;
- struct display* old_disp = &fb_display[currcon];
- struct display* new_disp = &fb_display[con];
- int bit_depth;
+ int new_bpp, old_bpp;
+ /* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&old_disp->cmap, 1, chipsfb_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, chipsfb_getcolreg, info);
- bit_depth = new_disp->var.bits_per_pixel;
- if (old_disp->var.bits_per_pixel != bit_depth)
- {
- currcon = con;
- chips_set_bitdepth(p, new_disp, con, bit_depth);
- }
- else
- currcon = con;
+ new_bpp = fb_display[con].var.bits_per_pixel;
+ old_bpp = fb_display[currcon].var.bits_per_pixel;
+ currcon = con;
+
+ if (new_bpp != old_bpp)
+ chips_set_bitdepth(p, &fb_display[con], con, new_bpp);
do_install_cmap(con, info);
return 0;
@@ -277,9 +278,10 @@ static void chipsfb_blank(int blank, struct fb_info *info)
struct fb_info_chips *p = (struct fb_info_chips *) info;
int i;
- if (blank > 1) {
+ // used to disable backlight only for blank > 1, but it seems
+ // useful at blank = 1 too (saves battery, extends backlight life)
+ if (blank) {
pmu_enable_backlight(0);
- } else if (blank) {
for (i = 0; i < 256; ++i) {
out_8(p->io_base + 0x3c8, i);
udelay(1);
@@ -311,10 +313,8 @@ static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct fb_info_chips *p = (struct fb_info_chips *) info;
- int hr;
- hr = (p->fix.visual != FB_VISUAL_PSEUDOCOLOR)? (regno << 3): regno;
- if (hr > 255)
+ if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
@@ -322,18 +322,18 @@ static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
p->palette[regno].red = red;
p->palette[regno].green = green;
p->palette[regno].blue = blue;
- out_8(p->io_base + 0x3c8, hr);
+ out_8(p->io_base + 0x3c8, regno);
udelay(1);
out_8(p->io_base + 0x3c9, red);
out_8(p->io_base + 0x3c9, green);
out_8(p->io_base + 0x3c9, blue);
#ifdef FBCON_HAS_CFB16
- if (regno < 16)
- p->fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;
+ if (regno < 16) p->fbcon_cfb16_cmap[regno] =
+ ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | ((blue & 0xf8) >> 3);
#endif
- return 0;
+ return 0;
}
static void do_install_cmap(int con, struct fb_info *info)
@@ -356,13 +356,14 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
if (bpp == 16) {
if (con == currcon) {
- write_cr(0x13, 200); // 16 bit display width (decimal)
- write_xr(0x81, 0x14); // 15 bit (TrueColor) color mode
+ write_cr(0x13, 200); // Set line length (doublewords)
+ write_xr(0x81, 0x14); // 15 bit (555) color mode
+ write_xr(0x82, 0x00); // Disable palettes
write_xr(0x20, 0x10); // 16 bit blitter mode
}
fix->line_length = 800*2;
- fix->visual = FB_VISUAL_DIRECTCOLOR;
+ fix->visual = FB_VISUAL_TRUECOLOR;
var->red.offset = 10;
var->green.offset = 5;
@@ -377,8 +378,9 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
#endif
} else if (bpp == 8) {
if (con == currcon) {
- write_cr(0x13, 100); // 8 bit display width (decimal)
+ write_cr(0x13, 100); // Set line length (doublewords)
write_xr(0x81, 0x12); // 8 bit color mode
+ write_xr(0x82, 0x08); // Graphics gamma enable
write_xr(0x20, 0x00); // 8 bit blitter mode
}
@@ -400,7 +402,7 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
disp->visual = fix->visual;
disp->var = *var;
-#ifdef CONFIG_PMAC_PBOOK
+#if (defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_FB_COMPAT_XPMAC))
display_info.depth = bpp;
display_info.pitch = fix->line_length;
#endif
@@ -547,9 +549,17 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
int i;
strcpy(p->fix.id, "C&T 65550");
- p->fix.smem_start = (char *) p->chips_base_phys;
- p->fix.smem_len = 800 * 600;
- p->fix.mmio_start = (char *) p->chips_io_phys;
+ p->fix.smem_start = (char *) p->frame_buffer_phys;
+
+// FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
+// * "3500" PowerBook G3 (the original PB G3) has 2MB.
+// * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
+// Motherboard actually supports 2MB -- there are two blank locations
+// for a second pair of DRAMs. (Thanks, Apple!)
+// * 3400 has 1MB (I think). Don't know if it's expandable.
+// -- Tim Seufert
+ p->fix.smem_len = 0x100000; // 1MB
+ p->fix.mmio_start = (char *) p->io_base_phys;
p->fix.type = FB_TYPE_PACKED_PIXELS;
p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
p->fix.line_length = 800;
@@ -572,7 +582,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
p->disp.cmap.green = NULL;
p->disp.cmap.blue = NULL;
p->disp.cmap.transp = NULL;
- p->disp.screen_base = (char *) p->frame_buffer;
+ p->disp.screen_base = p->frame_buffer;
p->disp.visual = p->fix.visual;
p->disp.type = p->fix.type;
p->disp.type_aux = p->fix.type_aux;
@@ -587,7 +597,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
p->info.disp = &p->disp;
p->info.fontname[0] = 0;
p->info.changevar = NULL;
- p->info.switch_con = &chipsfb_switch;
+ p->info.switch_con = &chipsfbcon_switch;
p->info.updatevar = &chipsfb_updatevar;
p->info.blank = &chipsfb_blank;
p->info.flags = FBINFO_FLAG_DEFAULT;
@@ -604,7 +614,8 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
return;
}
- printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node));
+ printk("fb%d: Chips 65550 frame buffer (%dK RAM detected)\n",
+ GET_FB_IDX(p->info.node), p->fix.smem_len / 1024);
chips_hw_init(p);
@@ -617,10 +628,10 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
display_info.mode = VMODE_800_600_60;
strncpy(display_info.name, "chips65550",
sizeof(display_info.name));
- display_info.fb_address = p->chips_base_phys + 0x800000;
- display_info.cmap_adr_address = p->chips_io_phys + 0x3c8;
- display_info.cmap_data_address = p->chips_io_phys + 0x3c9;
- display_info.disp_reg_address = p->chips_base_phys + 0xc00000;
+ display_info.fb_address = p->frame_buffer_phys;
+ display_info.cmap_adr_address = p->io_base_phys + 0x3c8;
+ display_info.cmap_data_address = p->io_base_phys + 0x3c9;
+ display_info.disp_reg_address = p->blitter_regs_phys;
console_fb_info = &p->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
@@ -659,17 +670,23 @@ __initfunc(void chips_of_init(struct device_node *dp))
return;
memset(p, 0, sizeof(*p));
addr = dp->addrs[0].address;
- p->chips_base_phys = addr;
- p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_NO_CACHE);
- p->blitter_regs = ioremap(addr + 0xC00000, 0x1000);
+#ifdef __BIG_ENDIAN
+ addr += 0x800000; // Use big-endian aperture
+#endif
+ p->frame_buffer_phys = addr;
+ p->frame_buffer = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
+ p->blitter_regs_phys = addr + 0x400000;
+ p->blitter_regs = ioremap(addr + 0x400000, 0x1000);
+ p->blitter_data_phys = addr + 0x410000;
+ p->blitter_data = ioremap(addr + 0x410000, 0x10000);
if (pci_device_loc(dp, &bus, &devfn) == 0) {
pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
cmd |= 3; /* enable memory and IO space */
pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
- p->io_base = (unsigned char *) pci_io_base(bus);
+ p->io_base = (__u8 *) pci_io_base(bus);
/* XXX really want the physical address here */
- p->chips_io_phys = (unsigned long) pci_io_base(bus);
+ p->io_base_phys = (unsigned long) pci_io_base(bus);
}
/* Clear the entire framebuffer */