[PATCH] atyfb: Improve atyfb_atari_probe()
[sfrench/cifs-2.6.git] / drivers / video / aty / atyfb_base.c
index 510e4ea296ed14b8fa180dd1db62b53d2010d65b..a9c73c257f3ab446a5ea1e15b2557530b2d47425 100644 (file)
@@ -203,14 +203,6 @@ static void ATIReduceRatio(int *Numerator, int *Denominator)
      *  The Hardware parameters for each card
      */
 
-struct aty_cmap_regs {
-       u8 windex;
-       u8 lut;
-       u8 mask;
-       u8 rindex;
-       u8 cntl;
-};
-
 struct pci_mmap_map {
        unsigned long voff;
        unsigned long poff;
@@ -240,9 +232,6 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
 static int atyfb_blank(int blank, struct fb_info *info);
 static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
-extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
 #ifdef __sparc__
 static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
 #endif
@@ -252,7 +241,7 @@ static int atyfb_sync(struct fb_info *info);
      *  Internal routines
      */
 
-static int aty_init(struct fb_info *info, const char *name);
+static int aty_init(struct fb_info *info);
 #ifdef CONFIG_ATARI
 static int store_video_par(char *videopar, unsigned char m64_num);
 #endif
@@ -409,7 +398,7 @@ static struct {
        { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
        { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
        { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
-       { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+       { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 },
        { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
 
        { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
@@ -1535,7 +1524,7 @@ static int atyfb_open(struct fb_info *info, int user)
        return (0);
 }
 
-static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t aty_irq(int irq, void *dev_id)
 {
        struct atyfb_par *par = dev_id;
        int handled = 0;
@@ -1940,17 +1929,14 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter)
                aty_st_8(DAC_CNTL, tmp, par);
                aty_st_8(DAC_MASK, 0xff, par);
 
-               writeb(i, &par->aty_cmap_regs->rindex);
-               atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut);
-               atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut);
-               atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut);
-               writeb(i, &par->aty_cmap_regs->windex);
-               writeb(atyfb_save.r[1 - enter][i],
-                      &par->aty_cmap_regs->lut);
-               writeb(atyfb_save.g[1 - enter][i],
-                      &par->aty_cmap_regs->lut);
-               writeb(atyfb_save.b[1 - enter][i],
-                      &par->aty_cmap_regs->lut);
+               aty_st_8(DAC_R_INDEX, i, par);
+               atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par);
+               atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par);
+               atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par);
+               aty_st_8(DAC_W_INDEX, i, par);
+               aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par);
+               aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par);
+               aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par);
        }
 }
 
@@ -2199,14 +2185,15 @@ static struct backlight_properties aty_bl_data = {
 
 static void aty_bl_set_power(struct fb_info *info, int power)
 {
-       if (info->bl_dev == NULL)
-               return;
-
        mutex_lock(&info->bl_mutex);
-       up(&info->bl_dev->sem);
-       info->bl_dev->props->power = power;
-       __aty_bl_update_status(info->bl_dev);
-       down(&info->bl_dev->sem);
+
+       if (info->bl_dev) {
+               down(&info->bl_dev->sem);
+               info->bl_dev->props->power = power;
+               __aty_bl_update_status(info->bl_dev);
+               up(&info->bl_dev->sem);
+       }
+
        mutex_unlock(&info->bl_mutex);
 }
 
@@ -2237,11 +2224,11 @@ static void aty_bl_init(struct atyfb_par *par)
                0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
        mutex_unlock(&info->bl_mutex);
 
-       up(&bd->sem);
+       down(&bd->sem);
        bd->props->brightness = aty_bl_data.max_brightness;
        bd->props->power = FB_BLANK_UNBLANK;
        bd->props->update_status(bd);
-       down(&bd->sem);
+       up(&bd->sem);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
        mutex_lock(&pmac_backlight_mutex);
@@ -2346,24 +2333,17 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
 }
 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
 
-static int __devinit aty_init(struct fb_info *info, const char *name)
+static int __devinit aty_init(struct fb_info *info)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        const char *ramname = NULL, *xtal;
        int gtb_memsize, has_var = 0;
        struct fb_var_screeninfo var;
-       u8 pll_ref_div;
        u32 i;
-#if defined(CONFIG_PPC)
-       int sense;
-#endif
 
        init_waitqueue_head(&par->vblank.wait);
        spin_lock_init(&par->int_lock);
 
-       par->aty_cmap_regs =
-           (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0);
-
 #ifdef CONFIG_PPC_PMAC
        /* The Apple iBook1 uses non-standard memory frequencies. We detect it
         * and set the frequency manually. */
@@ -2466,18 +2446,21 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
                        par->pll_limits.mclk = 63;
        }
 
-       if (M64_HAS(GTB_DSP)
-           && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) {
-               int diff1, diff2;
-               diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
-               diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
-               if (diff1 < 0)
-                       diff1 = -diff1;
-               if (diff2 < 0)
-                       diff2 = -diff2;
-               if (diff2 < diff1) {
-                       par->ref_clk_per = 1000000000000ULL / 29498928;
-                       xtal = "29.498928";
+       if (M64_HAS(GTB_DSP)) {
+               u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+
+               if (pll_ref_div) {
+                       int diff1, diff2;
+                       diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
+                       diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
+                       if (diff1 < 0)
+                               diff1 = -diff1;
+                       if (diff2 < 0)
+                               diff2 = -diff2;
+                       if (diff2 < diff1) {
+                               par->ref_clk_per = 1000000000000ULL / 29498928;
+                               xtal = "29.498928";
+                       }
                }
        }
 #endif /* CONFIG_FB_ATY_CT */
@@ -2603,9 +2586,8 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
                par->pll_ops->init_pll(info, &par->pll);
 
        /*
-        *  Last page of 8 MB (4 MB on ISA) aperture is MMIO
-        *  FIXME: we should use the auxiliary aperture instead so we can access
-        *  the full 8 MB of video RAM on 8 MB boards
+        *  Last page of 8 MB (4 MB on ISA) aperture is MMIO,
+        *  unless the auxiliary register aperture is used.
         */
 
        if (!par->aux_start &&
@@ -2671,6 +2653,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
                                has_var = 1;
                } else {
                        if (default_vmode == VMODE_CHOOSE) {
+                               int sense;
                                if (M64_HAS(G3_PB_1024x768))
                                        /* G3 PowerBook with 1024x768 LCD */
                                        default_vmode = VMODE_1024_768_60;
@@ -2751,7 +2734,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
        fb_list = info;
 
        PRINTKI("fb%d: %s frame buffer device on %s\n",
-              info->node, info->fix.id, name);
+               info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
        return 0;
 
 aty_init_exit:
@@ -2828,9 +2811,9 @@ static int atyfb_blank(int blank, struct fb_info *info)
 #endif
 
        gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+       gen_cntl &= ~0x400004c;
        switch (blank) {
-               case FB_BLANK_UNBLANK:
-                       gen_cntl &= ~0x400004c;
+               case FB_BLANK_UNBLANK:
                        break;
                case FB_BLANK_NORMAL:
                        gen_cntl |= 0x4000040;
@@ -2865,17 +2848,10 @@ static int atyfb_blank(int blank, struct fb_info *info)
 static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
                       const struct atyfb_par *par)
 {
-#ifdef CONFIG_ATARI
-       out_8(&par->aty_cmap_regs->windex, regno);
-       out_8(&par->aty_cmap_regs->lut, red);
-       out_8(&par->aty_cmap_regs->lut, green);
-       out_8(&par->aty_cmap_regs->lut, blue);
-#else
-       writeb(regno, &par->aty_cmap_regs->windex);
-       writeb(red, &par->aty_cmap_regs->lut);
-       writeb(green, &par->aty_cmap_regs->lut);
-       writeb(blue, &par->aty_cmap_regs->lut);
-#endif
+       aty_st_8(DAC_W_INDEX, regno, par);
+       aty_st_8(DAC_DATA, red, par);
+       aty_st_8(DAC_DATA, green, par);
+       aty_st_8(DAC_DATA, blue, par);
 }
 
     /*
@@ -3184,7 +3160,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 
 #ifdef __i386__
 #ifdef CONFIG_FB_ATY_GENERIC_LCD
-static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
 {
        u32 driv_inf_tab, sig;
        u16 lcd_ofs;
@@ -3529,6 +3505,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i
 atyfb_setup_generic_fail:
        iounmap(par->ati_regbase);
        par->ati_regbase = NULL;
+       if (info->screen_base) {
+               iounmap(info->screen_base);
+               info->screen_base = NULL;
+       }
        return ret;
 }
 
@@ -3596,7 +3576,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
        pci_set_drvdata(pdev, info);
 
        /* Init chip & register framebuffer */
-       if (aty_init(info, "PCI"))
+       if (aty_init(info))
                goto err_release_io;
 
 #ifdef __sparc__
@@ -3643,12 +3623,13 @@ err_release_mem:
 
 #ifdef CONFIG_ATARI
 
-static int __devinit atyfb_atari_probe(void)
+static int __init atyfb_atari_probe(void)
 {
        struct atyfb_par *par;
        struct fb_info *info;
        int m64_num;
        u32 clock_r;
+       int num_found = 0;
 
        for (m64_num = 0; m64_num < mach64_count; m64_num++) {
                if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
@@ -3696,16 +3677,34 @@ static int __devinit atyfb_atari_probe(void)
                        break;
                }
 
-               if (aty_init(info, "ISA bus")) {
+               /* Fake pci_id for correct_chipset() */
+               switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
+               case 0x00d7:
+                       par->pci_id = PCI_CHIP_MACH64GX;
+                       break;
+               case 0x0057:
+                       par->pci_id = PCI_CHIP_MACH64CX;
+                       break;
+               default:
+                       break;
+               }
+
+               if (correct_chipset(par) || aty_init(info)) {
+                       iounmap(info->screen_base);
+                       iounmap(par->ati_regbase);
                        framebuffer_release(info);
-                       /* This is insufficient! kernel_map has added two large chunks!! */
-                       return -ENXIO;
+               } else {
+                       num_found++;
                }
        }
+
+       return num_found ? 0 : -ENXIO;
 }
 
 #endif /* CONFIG_ATARI */
 
+#ifdef CONFIG_PCI
+
 static void __devexit atyfb_remove(struct fb_info *info)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -3753,7 +3752,6 @@ static void __devexit atyfb_remove(struct fb_info *info)
        framebuffer_release(info);
 }
 
-#ifdef CONFIG_PCI
 
 static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
 {
@@ -3788,7 +3786,7 @@ static struct pci_driver atyfb_driver = {
 #endif /* CONFIG_PCI */
 
 #ifndef MODULE
-static int __devinit atyfb_setup(char *options)
+static int __init atyfb_setup(char *options)
 {
        char *this_opt;
 
@@ -3860,8 +3858,9 @@ static int __devinit atyfb_setup(char *options)
 }
 #endif  /*  MODULE  */
 
-static int __devinit atyfb_init(void)
+static int __init atyfb_init(void)
 {
+    int err1 = 1, err2 = 1;
 #ifndef MODULE
     char *option = NULL;
 
@@ -3871,12 +3870,13 @@ static int __devinit atyfb_init(void)
 #endif
 
 #ifdef CONFIG_PCI
-    pci_register_driver(&atyfb_driver);
+    err1 = pci_register_driver(&atyfb_driver);
 #endif
 #ifdef CONFIG_ATARI
-    atyfb_atari_probe();
+    err2 = atyfb_atari_probe();
 #endif
-    return 0;
+
+    return (err1 && err2) ? -ENODEV : 0;
 }
 
 static void __exit atyfb_exit(void)