0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/backlight.h>
0010 #include <linux/fb.h>
0011 #include <linux/pci.h>
0012
0013 #ifdef CONFIG_PMAC_BACKLIGHT
0014 #include <asm/backlight.h>
0015 #endif
0016
0017 #include "nv_local.h"
0018 #include "nv_type.h"
0019 #include "nv_proto.h"
0020
0021
0022
0023
0024 #define MIN_LEVEL 0x158
0025 #define MAX_LEVEL 0x534
0026 #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
0027
0028 static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
0029 int level)
0030 {
0031 struct fb_info *info = pci_get_drvdata(par->pci_dev);
0032 int nlevel;
0033
0034
0035
0036 nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
0037
0038 if (nlevel < 0)
0039 nlevel = 0;
0040 else if (nlevel < MIN_LEVEL)
0041 nlevel = MIN_LEVEL;
0042 else if (nlevel > MAX_LEVEL)
0043 nlevel = MAX_LEVEL;
0044
0045 return nlevel;
0046 }
0047
0048 static int nvidia_bl_update_status(struct backlight_device *bd)
0049 {
0050 struct nvidia_par *par = bl_get_data(bd);
0051 u32 tmp_pcrt, tmp_pmc, fpcontrol;
0052 int level;
0053
0054 if (!par->FlatPanel)
0055 return 0;
0056
0057 if (bd->props.power != FB_BLANK_UNBLANK ||
0058 bd->props.fb_blank != FB_BLANK_UNBLANK)
0059 level = 0;
0060 else
0061 level = bd->props.brightness;
0062
0063 tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
0064 tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
0065 fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
0066
0067 if (level > 0) {
0068 tmp_pcrt |= 0x1;
0069 tmp_pmc |= (1 << 31);
0070 tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
0071 fpcontrol |= par->fpSyncs;
0072 } else
0073 fpcontrol |= 0x20000022;
0074
0075 NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
0076 NV_WR32(par->PMC, 0x10F0, tmp_pmc);
0077 NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
0078
0079 return 0;
0080 }
0081
0082 static const struct backlight_ops nvidia_bl_ops = {
0083 .update_status = nvidia_bl_update_status,
0084 };
0085
0086 void nvidia_bl_init(struct nvidia_par *par)
0087 {
0088 struct backlight_properties props;
0089 struct fb_info *info = pci_get_drvdata(par->pci_dev);
0090 struct backlight_device *bd;
0091 char name[12];
0092
0093 if (!par->FlatPanel)
0094 return;
0095
0096 #ifdef CONFIG_PMAC_BACKLIGHT
0097 if (!machine_is(powermac) ||
0098 !pmac_has_backlight_type("mnca"))
0099 return;
0100 #endif
0101
0102 snprintf(name, sizeof(name), "nvidiabl%d", info->node);
0103
0104 memset(&props, 0, sizeof(struct backlight_properties));
0105 props.type = BACKLIGHT_RAW;
0106 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
0107 bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
0108 &props);
0109 if (IS_ERR(bd)) {
0110 info->bl_dev = NULL;
0111 printk(KERN_WARNING "nvidia: Backlight registration failed\n");
0112 goto error;
0113 }
0114
0115 info->bl_dev = bd;
0116 fb_bl_default_curve(info, 0,
0117 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
0118 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
0119
0120 bd->props.brightness = bd->props.max_brightness;
0121 bd->props.power = FB_BLANK_UNBLANK;
0122 backlight_update_status(bd);
0123
0124 printk("nvidia: Backlight initialized (%s)\n", name);
0125
0126 error:
0127 return;
0128 }
0129
0130 void nvidia_bl_exit(struct nvidia_par *par)
0131 {
0132 struct fb_info *info = pci_get_drvdata(par->pci_dev);
0133 struct backlight_device *bd = info->bl_dev;
0134
0135 backlight_device_unregister(bd);
0136 printk("nvidia: Backlight unloaded\n");
0137 }