patch for aty128fb.c

Paul Mackerras (paulus@samba.org)
Wed, 11 Dec 2002 22:47:40 +1100


This patch gets aty128fb.c to compile and work on my G4 powerbook. I
have fixed the bug where the check_var routine would alter the par
structure, and I have fixed up the errors in the powerbook-specific
sleep/wakeup code.

Currently it can only put one rage 128 chip to sleep, but that is ok
for now since I've never seen a laptop with two rage 128 chips yet. :)
The generic device model will ultimately give us a better way to
handle sleep/wakeup.

Paul.

diff -urN linux-2.5/drivers/video/aty128fb.c pmac-2.5/drivers/video/aty128fb.c
--- linux-2.5/drivers/video/aty128fb.c 2002-12-10 15:20:32.000000000 +1100
+++ pmac-2.5/drivers/video/aty128fb.c 2002-12-11 22:41:38.000000000 +1100
@@ -65,10 +65,7 @@
#ifdef CONFIG_ALL_PPC
#include <asm/prom.h>
#include <asm/pci-bridge.h>
-#include <video/macmodes.h>
-#ifdef CONFIG_NVRAM
-#include <linux/nvram.h>
-#endif
+#include "macmodes.h"
#endif

#ifdef CONFIG_ADB_PMU
@@ -285,7 +282,6 @@

struct aty128_crtc {
u32 gen_cntl;
- u32 ext_cntl;
u32 h_total, h_sync_strt_wid;
u32 v_total, v_sync_strt_wid;
u32 pitch;
@@ -326,10 +322,13 @@
unsigned char *save_framebuffer;
int pm_reg;
int crt_on, lcd_on;
+ struct pci_dev *pdev;
+ struct fb_info *next;
#endif
- unsigned char red[64]; /* see comments in aty128fb_setcolreg */
- unsigned char green[64];
- unsigned char blue[64];
+ u8 red[32]; /* see aty128fb_setcolreg */
+ u8 green[64];
+ u8 blue[32];
+ u32 pseudo_palette[16]; /* used for TRUECOLOR */
};

#ifdef CONFIG_PMAC_PBOOK
@@ -337,6 +336,7 @@
static struct pmu_sleep_notifier aty128_sleep_notifier = {
aty128_sleep_notify, SLEEP_LEVEL_VIDEO,
};
+static struct fb_info *aty128_fb = NULL;
#endif

#define round_div(n, d) ((n+(d/2))/d)
@@ -1203,7 +1203,11 @@
{
struct aty128fb_par *par = info->par;
u32 config;
-
+ int err;
+
+ if ((err = aty128_decode_var(&info->var, par)) != 0)
+ return err;
+
if (par->blitter_may_be_busy)
wait_for_idle(par);

@@ -1271,15 +1275,22 @@
aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
{
int err;
+ struct aty128_crtc crtc;
+ struct aty128_pll pll;
+ struct aty128_ddafifo fifo_reg;

- if ((err = aty128_var_to_crtc(var, &par->crtc, par)))
+ if ((err = aty128_var_to_crtc(var, &crtc, par)))
return err;

- if ((err = aty128_var_to_pll(var->pixclock, &par->pll, par)))
+ if ((err = aty128_var_to_pll(var->pixclock, &pll, par)))
return err;

- if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.depth, par)))
+ if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
return err;
+
+ par->crtc = crtc;
+ par->pll = pll;
+ par->fifo_reg = fifo_reg;
par->accel_flags = var->accel_flags;

return 0;
@@ -1312,12 +1323,13 @@
static int
aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct aty128fb_par *par = info->par;
+ struct aty128fb_par par;
int err;

- if ((err = aty128_decode_var(var, par)) != 0)
+ par = *(struct aty128fb_par *)info->par;
+ if ((err = aty128_decode_var(var, &par)) != 0)
return err;
- aty128_encode_var(var, par);
+ aty128_encode_var(var, &par);
return 0;
}

@@ -1415,7 +1427,7 @@
}
#endif
#ifdef CONFIG_ALL_PPC
- /* vmode and cmode depreciated */
+ /* vmode and cmode deprecated */
if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
@@ -1602,7 +1614,12 @@
#endif /* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PMAC_PBOOK
par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
- pmu_register_sleep_notifier(&aty128_sleep_notifier);
+ if (aty128_fb == NULL) {
+ /* XXX can only put one chip to sleep */
+ aty128_fb = info;
+ } else
+ printk(KERN_WARNING "aty128fb: can only sleep one Rage 128\n");
+ par->pdev = pdev;
#endif

printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
@@ -1647,8 +1664,7 @@
}

/* We have the resources. Now virtualize them */
- size = sizeof(struct fb_info) + sizeof(struct aty128fb_par) +
- sizeof(u32)*16;
+ size = sizeof(struct fb_info) + sizeof(struct aty128fb_par);
if (!(info = kmalloc(size, GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_unmap_out;
@@ -1656,9 +1672,7 @@
memset(info, 0, size);

par = (struct aty128fb_par *)(info + 1);
- info->pseudo_palette = (void *) (par + 1);
-
- memset(info, 0, sizeof(struct fb_info));
+ info->pseudo_palette = par->pseudo_palette;

info->par = par;
info->fix = aty128fb_fix;
@@ -1758,6 +1772,10 @@
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
+#ifdef CONFIG_PMAC_PBOOK
+ if (info == aty128_fb)
+ aty128_fb = NULL;
+#endif
kfree(info);
}
#endif /* CONFIG_PCI */
@@ -2008,7 +2026,7 @@
}
}

- if (par->crtc.depth == 16) {
+ if (par->crtc.depth == 16 && regno > 0) {
/*
* With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
* have 32 slots for R and B values but 64 slots for G values.
@@ -2016,12 +2034,13 @@
* goes in a different slot, and we have to avoid disturbing
* the other fields in the slots we touch.
*/
- par->red[regno] = red;
par->green[regno] = green;
- par->blue[regno] = blue;
- if (regno > 0 && regno < 32)
+ if (regno < 32) {
+ par->red[regno] = red;
+ par->blue[regno] = blue;
aty128_st_pal(regno * 8, red, par->green[regno*2],
blue, par);
+ }
red = par->red[regno/2];
blue = par->blue[regno/2];
regno <<= 2;
@@ -2213,6 +2232,7 @@
{
u32 pmgt;
u16 pwr_command;
+ struct pci_dev *pdev = par->pdev;

if (!par->pm_reg)
return;
@@ -2237,17 +2257,16 @@
aty_st_le32(BUS_CNTL1, 0x00000010);
aty_st_le32(MEM_POWER_MISC, 0x0c830000);
mdelay(100);
- pci_read_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
+ pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
/* Switch PCI power management to D2 */
- pci_write_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL,
+ pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL,
(p