linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / video / riva / fbdev.c
index 8ddb47a..6c19ab6 100644 (file)
  *     doublescan modes are broken
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/tty.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/backlight.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
@@ -48,7 +49,6 @@
 #include <asm/pci-bridge.h>
 #endif
 #ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/machdep.h>
 #include <asm/backlight.h>
 #endif
 
@@ -271,183 +271,34 @@ static const struct riva_regs reg_template = {
 /*
  * Backlight control
  */
-#ifdef CONFIG_FB_RIVA_BACKLIGHT
-/* We do not have any information about which values are allowed, thus
- * we used safe values.
- */
-#define MIN_LEVEL 0x158
-#define MAX_LEVEL 0x534
-#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
-
-static struct backlight_properties riva_bl_data;
-
-/* Call with fb_info->bl_mutex held */
-static int riva_bl_get_level_brightness(struct riva_par *par,
-               int level)
-{
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-       int nlevel;
-
-       /* Get and convert the value */
-       nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
-
-       if (nlevel < 0)
-               nlevel = 0;
-       else if (nlevel < MIN_LEVEL)
-               nlevel = MIN_LEVEL;
-       else if (nlevel > MAX_LEVEL)
-               nlevel = MAX_LEVEL;
-
-       return nlevel;
-}
-
-/* Call with fb_info->bl_mutex held */
-static int __riva_bl_update_status(struct backlight_device *bd)
-{
-       struct riva_par *par = class_get_devdata(&bd->class_dev);
-       U032 tmp_pcrt, tmp_pmc;
-       int level;
-
-       if (bd->props->power != FB_BLANK_UNBLANK ||
-           bd->props->fb_blank != FB_BLANK_UNBLANK)
-               level = 0;
-       else
-               level = bd->props->brightness;
-
-       tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
-       tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
-       if(level > 0) {
-               tmp_pcrt |= 0x1;
-               tmp_pmc |= (1 << 31); /* backlight bit */
-               tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
-       }
-       par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
-       par->riva.PMC[0x10F0/4] = tmp_pmc;
-
-       return 0;
-}
-
-static int riva_bl_update_status(struct backlight_device *bd)
-{
-       struct riva_par *par = class_get_devdata(&bd->class_dev);
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-       int ret;
-
-       mutex_lock(&info->bl_mutex);
-       ret = __riva_bl_update_status(bd);
-       mutex_unlock(&info->bl_mutex);
-
-       return ret;
-}
-
-static int riva_bl_get_brightness(struct backlight_device *bd)
-{
-       return bd->props->brightness;
-}
-
-static struct backlight_properties riva_bl_data = {
-       .owner    = THIS_MODULE,
-       .get_brightness = riva_bl_get_brightness,
-       .update_status  = riva_bl_update_status,
-       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
-};
-
-static void riva_bl_set_power(struct fb_info *info, int power)
-{
-       mutex_lock(&info->bl_mutex);
-
-       if (info->bl_dev) {
-               down(&info->bl_dev->sem);
-               info->bl_dev->props->power = power;
-               __riva_bl_update_status(info->bl_dev);
-               up(&info->bl_dev->sem);
-       }
-
-       mutex_unlock(&info->bl_mutex);
-}
-
-static void riva_bl_init(struct riva_par *par)
-{
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-       struct backlight_device *bd;
-       char name[12];
-
-       if (!par->FlatPanel)
-               return;
-
 #ifdef CONFIG_PMAC_BACKLIGHT
-       if (!machine_is(powermac) ||
-           !pmac_has_backlight_type("mnca"))
-               return;
-#endif
-
-       snprintf(name, sizeof(name), "rivabl%d", info->node);
 
-       bd = backlight_device_register(name, par, &riva_bl_data);
-       if (IS_ERR(bd)) {
-               info->bl_dev = NULL;
-               printk(KERN_WARNING "riva: Backlight registration failed\n");
-               goto error;
-       }
-
-       mutex_lock(&info->bl_mutex);
-       info->bl_dev = bd;
-       fb_bl_default_curve(info, 0,
-               0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
-               0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-       mutex_unlock(&info->bl_mutex);
-
-       down(&bd->sem);
-       bd->props->brightness = riva_bl_data.max_brightness;
-       bd->props->power = FB_BLANK_UNBLANK;
-       bd->props->update_status(bd);
-       up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-       if (!pmac_backlight)
-               pmac_backlight = bd;
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
-
-       printk("riva: Backlight initialized (%s)\n", name);
-
-       return;
-
-error:
-       return;
-}
-
-static void riva_bl_exit(struct riva_par *par)
-{
-       struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_lock(&pmac_backlight_mutex);
-#endif
-
-       mutex_lock(&info->bl_mutex);
-       if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-               if (pmac_backlight == info->bl_dev)
-                       pmac_backlight = NULL;
-#endif
-
-               backlight_device_unregister(info->bl_dev);
-
-               printk("riva: Backlight unloaded\n");
-       }
-       mutex_unlock(&info->bl_mutex);
+static int riva_backlight_levels[] = {
+    0x158,
+    0x192,
+    0x1c6,
+    0x200,
+    0x234,
+    0x268,
+    0x2a2,
+    0x2d6,
+    0x310,
+    0x344,
+    0x378,
+    0x3b2,
+    0x3e6,
+    0x41a,
+    0x454,
+    0x534,
+};
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-       mutex_unlock(&pmac_backlight_mutex);
-#endif
-}
-#else
-static inline void riva_bl_init(struct riva_par *par) {}
-static inline void riva_bl_exit(struct riva_par *par) {}
-static inline void riva_bl_set_power(struct fb_info *info, int power) {}
-#endif /* CONFIG_FB_RIVA_BACKLIGHT */
+static int riva_set_backlight_enable(int on, int level, void *data);
+static int riva_set_backlight_level(int level, void *data);
+static struct backlight_controller riva_backlight_controller = {
+       riva_set_backlight_enable,
+       riva_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
 /* ------------------------------------------------------------------------- *
  *
@@ -1119,6 +970,36 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
        return rc;
 }
 
+/* ------------------------------------------------------------------------- *
+ *
+ * Backlight operations
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int riva_set_backlight_enable(int on, int level, void *data)
+{
+       struct riva_par *par = data;
+       U032 tmp_pcrt, tmp_pmc;
+
+       tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
+       tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
+       if(on && (level > BACKLIGHT_OFF)) {
+               tmp_pcrt |= 0x1;
+               tmp_pmc |= (1 << 31); // backlight bit
+               tmp_pmc |= riva_backlight_levels[level-1] << 16; // level
+       }
+       par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
+       par->riva.PMC[0x10F0/4] = tmp_pmc;
+       return 0;
+}
+
+static int riva_set_backlight_level(int level, void *data)
+{
+       return riva_set_backlight_enable(1, level, data);
+}
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
 /* ------------------------------------------------------------------------- *
  *
  * framebuffer operations
@@ -1365,7 +1246,11 @@ static int rivafb_blank(int blank, struct fb_info *info)
        SEQout(par, 0x01, tmp);
        CRTCout(par, 0x1a, vesa);
 
-       riva_bl_set_power(info, blank);
+#ifdef CONFIG_PMAC_BACKLIGHT
+       if ( par->FlatPanel && _machine == _MACH_Pmac) {
+               set_backlight_enable(!blank);
+       }
+#endif
 
        NVTRACE_LEAVE();
 
@@ -2136,9 +2021,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 
        fb_destroy_modedb(info->monspecs.modedb);
        info->monspecs.modedb = NULL;
-
-       pci_set_drvdata(pd, info);
-       riva_bl_init(info->par);
        ret = register_framebuffer(info);
        if (ret < 0) {
                printk(KERN_ERR PFX
@@ -2146,13 +2028,19 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
                goto err_iounmap_screen_base;
        }
 
+       pci_set_drvdata(pd, info);
+
        printk(KERN_INFO PFX
                "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
                info->fix.id,
                RIVAFB_VERSION,
                info->fix.smem_len / (1024 * 1024),
                info->fix.smem_start);
-
+#ifdef CONFIG_PMAC_BACKLIGHT
+       if (default_par->FlatPanel && _machine == _MACH_Pmac)
+       register_backlight_controller(&riva_backlight_controller,
+                                               default_par, "mnca");
+#endif
        NVTRACE_LEAVE();
        return 0;
 
@@ -2169,6 +2057,7 @@ err_iounmap_ctrl_base:
 err_release_region:
        pci_release_regions(pd);
 err_disable_device:
+       pci_disable_device(pd);
 err_free_pixmap:
        kfree(info->pixmap.addr);
 err_framebuffer_release:
@@ -2183,8 +2072,8 @@ static void __exit rivafb_remove(struct pci_dev *pd)
        struct riva_par *par = info->par;
        
        NVTRACE_ENTER();
-
-       riva_bl_exit(par);
+       if (!info)
+               return;
 
 #ifdef CONFIG_FB_RIVA_I2C
        riva_delete_i2c_busses(par);
@@ -2203,6 +2092,7 @@ static void __exit rivafb_remove(struct pci_dev *pd)
        if (par->riva.Architecture == NV_ARCH_03)
                iounmap(par->riva.PRAMIN);
        pci_release_regions(pd);
+       pci_disable_device(pd);
        kfree(info->pixmap.addr);
        framebuffer_release(info);
        pci_set_drvdata(pd, NULL);