* 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
#include <asm/pci-bridge.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/machdep.h>
#include <asm/backlight.h>
#endif
/*
* 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 */
/* ------------------------------------------------------------------------- *
*
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
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();
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
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;
err_release_region:
pci_release_regions(pd);
err_disable_device:
+ pci_disable_device(pd);
err_free_pixmap:
kfree(info->pixmap.addr);
err_framebuffer_release:
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);
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);