> >XFree86 4.01 debs won't be out for a while, and they probably won't > >include the experimental PPC stuff. No idea on the Pismo, but the Lombard
[The Pismo doesn't have the braindead OF overlap mapping, so no problem there ...] > If someone wants to make XF4.0.1 debs for PPC, I beleive they should be > done from Franz Sirl source base (devel.linuxppc.org/users/fsirl/xf4/ > SRPMS). This archive contains the latest fixes, patches, etc... for PPC The latest changes from Ani Joshi's rsync server? That would save me cleaning up my mess of 16 bit Mach64 hacks ... > BTW Michael, can you send me the PCI patch ? Attached. The first part is experimental code to make atyfb handle 16 bit 565 color which needs a bit more work, including bastardizing a reserved field in the fb var struct to pass the actual depth as opposed to bpp. The way it's #if'ed out it shouldn't hurt, it was just too much of a hassle to take out again. The other stuff (patch to atyfb_of_init) is the PCI overlap related one, I've changed it to either remap the MMIO region into the LE aperture, or right past the BE framebuffer aperture depending on whether there's enough space. I'm sure it can be done in less than 100 lines of code and it's too verbose for release purpose but it happens to work (please note that mapping MMIO right adjacent to the IO aperture, i.e. 0x80882000, would cause a hard crash. Apparently ATY decodes MMIO at both 0x81fff000 and 0x80fff000 regardless of what the PCI bridge is configured to, and setting up a PCI mapping at 0x80882000 leaves both MMIO apertures unmapped. Was that what PCI resource mapping was about, a new and improved way to shoot yourself in the foot??) Michael
--- drivers/video/atyfb.c.org Mon Apr 3 20:20:24 2000 +++ drivers/video/atyfb.c Thu Jul 27 21:25:42 2000 @@ -1061,6 +1061,7 @@ u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; u32 pix_width, dp_pix_width, dp_chain_mask; + u32 depth; /* input */ xres = var->xres; @@ -1070,6 +1071,7 @@ xoffset = var->xoffset; yoffset = var->yoffset; bpp = var->bits_per_pixel; + depth = var->red.length + var->green.length + var->blue.length + var->transp.length; left = var->left_margin; right = var->right_margin; upper = var->upper_margin; @@ -1118,6 +1120,9 @@ c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0; + if (depth > bpp+1) + depth = bpp; + if (bpp <= 8) { bpp = 8; pix_width = CRTC_PIX_WIDTH_8BPP; @@ -1125,10 +1130,24 @@ dp_chain_mask = 0x8080; } else if (bpp <= 16) { bpp = 16; +#if 1 pix_width = CRTC_PIX_WIDTH_15BPP; dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = 0x4210; +#else + if (depth == 15) { + pix_width = CRTC_PIX_WIDTH_15BPP; + dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | + BYTE_ORDER_LSB_TO_MSB; + dp_chain_mask = 0x4210; + } else { + pix_width = CRTC_PIX_WIDTH_16BPP; + dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP | + BYTE_ORDER_LSB_TO_MSB; + dp_chain_mask = 0x8410; + } +#endif } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) { bpp = 24; pix_width = CRTC_PIX_WIDTH_24BPP; @@ -1285,7 +1304,7 @@ var->transp.offset = 0; var->transp.length = 0; break; -#if 0 +#if 1 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */ bpp = 16; var->red.offset = 11; @@ -3176,7 +3195,7 @@ u8 bus, devfn; u16 cmd; struct fb_info_aty *info; - int i; + int i, i_frame, i_regs, i_io, naddr; if (device_is_compatible(dp, "ATY,264LTPro")) { /* XXX kludge for now */ @@ -3204,6 +3223,13 @@ return; } + printk("atyfb: of_init got %d OF adresses for ATY:\n", dp->n_addrs); + for (i = 0; i < dp->n_addrs; i++) + printk(" %08x-%08x", dp->addrs[i].address, + dp->addrs[i].address+dp->addrs[i].size-1); + if (dp->n_addrs) + printk("\n"); + info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); if (!info) { printk("atyfb_of_init: can't alloc fb_info_aty\n"); @@ -3215,6 +3241,8 @@ info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys, 0x1000); + printk("atyfb: regbase phys 0x%lx virt 0x%lx\n", info->ati_regbase_phys, info->ati_regbase); + if(! info->ati_regbase) { printk("atyfb_init: ioremap() returned NULL\n"); kfree(info); @@ -3226,6 +3254,53 @@ /* enable memory-space accesses using config-space command register */ if (pci_device_loc(dp, &bus, &devfn) == 0) { + + for (i = 0; i < dp->n_addrs + 2; i++) { + int io, breg = PCI_BASE_ADDRESS_0 + (i << 2); + unsigned long base; + u32 size, pbase; + + base = dp->addrs[i].address; + + pcibios_read_config_dword(bus, devfn, breg, &pbase); + pcibios_write_config_dword(bus, devfn, breg, 0xffffffff); + pcibios_read_config_dword(bus, devfn, breg, &size); + pcibios_write_config_dword(bus, devfn, breg, pbase); + + io = (pbase & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; + + if (io) { + size &= ~1; + i_io = i; + } + + size = ~(size) + 1; + + if (size == 0) + break; + + printk("atyfb: chunk %d ofbase 0x%lx breg %d io %d pbase 0x%lx size 0x%lx \n", + i, base, breg, io, pbase, size); + + if (!base) { + printk("atyfb: chunk %d assigning ofbase 0x%lx \n", i, pbase); + dp->addrs[i].address = pbase; + dp->addrs[i].size = size; + } + if (pbase == addr) { + printk("atyfb: chunk %d assigned as VRAM aperture! \n", i); + i_frame = i; + } + if (size == 0x1000) { + printk("atyfb: chunk %d assigned as MMIO aperture! \n", i); + i_regs = i; + } + + } + + naddr = i; + printk("atyfb: found %d PCI addresses total. \n", i); + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); if (cmd != 0xffff) { cmd |= PCI_COMMAND_MEMORY; @@ -3242,12 +3317,88 @@ info->frame_buffer_phys = addr; info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); + printk("atyfb: framebuffer phys 0x%lx virt 0x%lx\n", info->frame_buffer_phys, info->frame_buffer); + if(! info->frame_buffer) { printk("atyfb_init: ioremap() returned NULL\n"); kfree(info); return; } + /* + * Fix MMIO mapping if MMIO and VRAM overlap + * Note that we can't move the VRAM base address to the BE aperture (this would move the whole + * VRAM region, not resize it) so it's easier to remap MMIO someplace else. + */ + if ( (dp->addrs[i_frame].address < dp->addrs[i_regs].address+dp->addrs[i_regs].size + && dp->addrs[i_frame].address+dp->addrs[i_frame].size >= dp->addrs[i_regs].address) + || (dp->addrs[i_regs].address < dp->addrs[i_frame].address+dp->addrs[i_frame].size + && dp->addrs[i_regs].address+dp->addrs[i_regs].size >= dp->addrs[i_frame].address) ) { + + struct pci_dev *pdev = pci_find_slot(bus, devfn); + int io, breg = PCI_BASE_ADDRESS_0 + (i_regs << 2); + int flags; + unsigned long base; + u32 size, pbase, new; + + base = dp->addrs[i_regs].address; + + pcibios_read_config_dword(bus, devfn, breg, &pbase); + pcibios_write_config_dword(bus, devfn, breg, 0xffffffff); + pcibios_read_config_dword(bus, devfn, breg, &size); + pcibios_write_config_dword(bus, devfn, breg, pbase); + + io = (pbase & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; + flags = (pbase & PCI_BASE_ADDRESS_MEM_MASK); + + if (io) + size &= ~1; + size = ~(size) + 1; + + printk("atyfb: chunk %d ofbase 0x%lx breg %d io %d pbase 0x%lx size 0x%lx needs reassigning! \n", + i_regs, base, breg, io, pbase, size); + +#if 0 + /* move MMIO past frame buffer for now. Need to walk PCI resources to find safe place */ + new = (dp->addrs[i_frame].address+dp->addrs[i_frame].size) | (flags & 0x0f); +#else + /* move MMIO before frame buffer and past I/O for now. Need to walk PCI resources to find safe place */ + if (dp->addrs[i_io].address+dp->addrs[i_io].size+dp->addrs[i_regs].size < dp->addrs[i_frame].address) + new = (dp->addrs[i_io].address&0xff000000) | (dp->addrs[i_regs].address&0x00ffffff) | (flags & 0x0f); + else + new = (dp->addrs[i_frame].address+dp->addrs[i_frame].size) | (flags & 0x0f); +#endif + + pcibios_write_config_dword(bus, devfn, breg, new); + + pcibios_read_config_dword(bus, devfn, breg, &pbase); + pcibios_write_config_dword(bus, devfn, breg, 0xffffffff); + pcibios_read_config_dword(bus, devfn, breg, &size); + pcibios_write_config_dword(bus, devfn, breg, pbase); + + if (new != pbase) + printk("atyfb: failed to remap MMIO region! \n"); + + /* update PCI struct */ + if (!pdev) + printk("atyfb: no pci_dev registered for device!\n"); + else + pdev->base_address[i_regs] = pbase; + + io = (pbase & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; + flags = (pbase & ~PCI_BASE_ADDRESS_MEM_MASK); + + if (io) + size &= ~1; + size = ~(size) + 1; + + printk("atyfb: chunk %d ofbase 0x%lx breg %d io %d reassigned to pbase 0x%lx size 0x%lx ! \n", + i_regs, base, breg, io, pbase, size); + + /* update OF device tree */ + dp->addrs[i_regs].address = dp->addrs[i_frame].address+dp->addrs[i_frame].size; + } + if (!aty_init(info, dp->full_name)) { kfree(info); return;