diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index d3f8d75bcbb4..4397fac55ba0 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c @@ -18,17 +18,48 @@ static struct backlight_properties pmu_backlight_data; static spinlock_t pmu_backlight_lock; static int sleeping; +static u8 bl_curve[FB_BACKLIGHT_LEVELS]; -static int pmu_backlight_get_level_brightness(struct fb_info *info, - int level) +static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) +{ + unsigned int i, flat, count, range = (max - min); + + bl_curve[0] = off; + + for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) + bl_curve[flat] = min; + + count = FB_BACKLIGHT_LEVELS * 15 / 16; + for (i = 0; i < count; ++i) + bl_curve[flat + i] = min + (range * (i + 1) / count); +} + +static int pmu_backlight_curve_lookup(int value) +{ + int level = (FB_BACKLIGHT_LEVELS - 1); + int i, max = 0; + + /* Look for biggest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) + max = max((int)bl_curve[i], max); + + /* Look for nearest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { + int diff = abs(bl_curve[i] - value); + if (diff < max) { + max = diff; + level = i; + } + } + return level; +} + +static int pmu_backlight_get_level_brightness(int level) { int pmulevel; /* Get and convert the value */ - mutex_lock(&info->bl_mutex); - pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; - mutex_unlock(&info->bl_mutex); - + pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; if (pmulevel < 0) pmulevel = 0; else if (pmulevel > MAX_PMU_LEVEL) @@ -39,7 +70,6 @@ static int pmu_backlight_get_level_brightness(struct fb_info *info, static int pmu_backlight_update_status(struct backlight_device *bd) { - struct fb_info *info = class_get_devdata(&bd->class_dev); struct adb_request req; unsigned long flags; int level = bd->props->brightness; @@ -55,7 +85,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd) level = 0; if (level > 0) { - int pmulevel = pmu_backlight_get_level_brightness(info, level); + int pmulevel = pmu_backlight_get_level_brightness(level); pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); pmu_wait_complete(&req); @@ -88,35 +118,19 @@ static struct backlight_properties pmu_backlight_data = { }; #ifdef CONFIG_PM -static int pmu_backlight_sleep_call(struct pmu_sleep_notifier *self, int when) +void pmu_backlight_set_sleep(int sleep) { unsigned long flags; spin_lock_irqsave(&pmu_backlight_lock, flags); - - switch (when) { - case PBOOK_SLEEP_REQUEST: - sleeping = 1; - break; - case PBOOK_WAKE: - sleeping = 0; - break; - } - + sleeping = sleep; spin_unlock_irqrestore(&pmu_backlight_lock, flags); - - return PBOOK_SLEEP_OK; } - -static struct pmu_sleep_notifier pmu_backlight_sleep_notif = { - .notifier_call = pmu_backlight_sleep_call, -}; -#endif +#endif /* CONFIG_PM */ void __init pmu_backlight_init() { struct backlight_device *bd; - struct fb_info *info; char name[10]; int level, autosave; @@ -131,27 +145,14 @@ void __init pmu_backlight_init() !machine_is_compatible("PowerBook1,1")) return; - /* Actually, this is a hack, but I don't know of a better way - * to get the first framebuffer device. - */ - info = registered_fb[0]; - if (!info) { - printk("pmubl: No framebuffer found\n"); - goto error; - } + snprintf(name, sizeof(name), "pmubl"); - snprintf(name, sizeof(name), "pmubl%d", info->node); - - bd = backlight_device_register(name, info, &pmu_backlight_data); + bd = backlight_device_register(name, NULL, &pmu_backlight_data); if (IS_ERR(bd)) { printk("pmubl: Backlight registration failed\n"); goto error; } - - mutex_lock(&info->bl_mutex); - info->bl_dev = bd; - fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); - mutex_unlock(&info->bl_mutex); + pmu_backlight_init_curve(0x7F, 0x46, 0x0E); level = pmu_backlight_data.max_brightness; @@ -161,11 +162,9 @@ void __init pmu_backlight_init() pmu_request(&req, NULL, 2, 0xd9, 0); pmu_wait_complete(&req); - mutex_lock(&info->bl_mutex); - level = pmac_backlight_curve_lookup(info, + level = pmu_backlight_curve_lookup( (req.reply[0] >> 4) * pmu_backlight_data.max_brightness / 15); - mutex_unlock(&info->bl_mutex); } up(&bd->sem); @@ -179,10 +178,6 @@ void __init pmu_backlight_init() pmac_backlight = bd; mutex_unlock(&pmac_backlight_mutex); -#ifdef CONFIG_PM - pmu_register_sleep_notifier(&pmu_backlight_sleep_notif); -#endif - printk("pmubl: Backlight initialized (%s)\n", name); return; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index ea386801e215..14610a63f580 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -1995,6 +1995,8 @@ restore_via_state(void) out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } +extern void pmu_backlight_set_sleep(int sleep); + static int pmac_suspend_devices(void) { @@ -2032,6 +2034,11 @@ pmac_suspend_devices(void) return -EBUSY; } +#ifdef CONFIG_PMAC_BACKLIGHT + /* Tell backlight code not to muck around with the chip anymore */ + pmu_backlight_set_sleep(1); +#endif + /* Call platform functions marked "on sleep" */ pmac_pfunc_i2c_suspend(); pmac_pfunc_base_suspend(); @@ -2090,6 +2097,11 @@ pmac_wakeup_devices(void) { mdelay(100); +#ifdef CONFIG_PMAC_BACKLIGHT + /* Tell backlight code it can use the chip again */ + pmu_backlight_set_sleep(0); +#endif + /* Power back up system devices (including the PIC) */ device_power_up();