patch for aty128fb.c

From: Paul Mackerras (paulus@samba.org)
Date: Wed Dec 11 2002 - 06:47:40 EST


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,
                         (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2);
- 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);
         } else {
                 /* Switch back PCI power management to D0 */
                 mdelay(100);
- pci_write_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, 0);
- mdelay(100);
- pci_read_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
+ pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0);
+ pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
                 mdelay(100);
         }
 }
@@ -2259,10 +2278,13 @@
 int
 aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
- int result = PBOOK_SLEEP_OK, nb;
- struct fb_info *info = info; /* FIXME!!! How do find which framebuffer */
- struct aty128fb_par *par = info->par;
+ int nb;
+ struct fb_info *info = aty128_fb;
+ struct aty128fb_par *par;
 
+ if (info == NULL)
+ return PBOOK_SLEEP_OK;
+ par = info->par;
         nb = info->var.yres * info->fix.line_length;
 
         switch (when) {
@@ -2311,17 +2333,23 @@
                 aty128fb_blank(0, info);
                 break;
         }
- return result;
+ return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
 int __init aty128fb_init(void)
 {
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_register_sleep_notifier(&aty128_sleep_notifier);
+#endif
         return pci_module_init(&aty128fb_driver);
 }
 
 static void __exit aty128fb_exit(void)
 {
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_unregister_sleep_notifier(&aty128_sleep_notifier);
+#endif
         pci_unregister_driver(&aty128fb_driver);
 }
 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Dec 15 2002 - 22:00:20 EST