Path: blob/master/drivers/macintosh/via-pmu-backlight.c
15109 views
/*1* Backlight code for via-pmu2*3* Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.4* Copyright (C) 2001-2002 Benjamin Herrenschmidt5* Copyright (C) 2006 Michael Hanselmann <[email protected]>6*7*/89#include <asm/ptrace.h>10#include <linux/adb.h>11#include <linux/pmu.h>12#include <asm/backlight.h>13#include <asm/prom.h>1415#define MAX_PMU_LEVEL 0xFF1617static const struct backlight_ops pmu_backlight_data;18static DEFINE_SPINLOCK(pmu_backlight_lock);19static int sleeping, uses_pmu_bl;20static u8 bl_curve[FB_BACKLIGHT_LEVELS];2122static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)23{24int i, flat, count, range = (max - min);2526bl_curve[0] = off;2728for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)29bl_curve[flat] = min;3031count = FB_BACKLIGHT_LEVELS * 15 / 16;32for (i = 0; i < count; ++i)33bl_curve[flat + i] = min + (range * (i + 1) / count);34}3536static int pmu_backlight_curve_lookup(int value)37{38int level = (FB_BACKLIGHT_LEVELS - 1);39int i, max = 0;4041/* Look for biggest value */42for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)43max = max((int)bl_curve[i], max);4445/* Look for nearest value */46for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {47int diff = abs(bl_curve[i] - value);48if (diff < max) {49max = diff;50level = i;51}52}53return level;54}5556static int pmu_backlight_get_level_brightness(int level)57{58int pmulevel;5960/* Get and convert the value */61pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;62if (pmulevel < 0)63pmulevel = 0;64else if (pmulevel > MAX_PMU_LEVEL)65pmulevel = MAX_PMU_LEVEL;6667return pmulevel;68}6970static int __pmu_backlight_update_status(struct backlight_device *bd)71{72struct adb_request req;73int level = bd->props.brightness;747576if (bd->props.power != FB_BLANK_UNBLANK ||77bd->props.fb_blank != FB_BLANK_UNBLANK)78level = 0;7980if (level > 0) {81int pmulevel = pmu_backlight_get_level_brightness(level);8283pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);84pmu_wait_complete(&req);8586pmu_request(&req, NULL, 2, PMU_POWER_CTRL,87PMU_POW_BACKLIGHT | PMU_POW_ON);88pmu_wait_complete(&req);89} else {90pmu_request(&req, NULL, 2, PMU_POWER_CTRL,91PMU_POW_BACKLIGHT | PMU_POW_OFF);92pmu_wait_complete(&req);93}9495return 0;96}9798static int pmu_backlight_update_status(struct backlight_device *bd)99{100unsigned long flags;101int rc = 0;102103spin_lock_irqsave(&pmu_backlight_lock, flags);104/* Don't update brightness when sleeping */105if (!sleeping)106rc = __pmu_backlight_update_status(bd);107spin_unlock_irqrestore(&pmu_backlight_lock, flags);108return rc;109}110111112static int pmu_backlight_get_brightness(struct backlight_device *bd)113{114return bd->props.brightness;115}116117static const struct backlight_ops pmu_backlight_data = {118.get_brightness = pmu_backlight_get_brightness,119.update_status = pmu_backlight_update_status,120121};122123#ifdef CONFIG_PM124void pmu_backlight_set_sleep(int sleep)125{126unsigned long flags;127128spin_lock_irqsave(&pmu_backlight_lock, flags);129sleeping = sleep;130if (pmac_backlight && uses_pmu_bl) {131if (sleep) {132struct adb_request req;133134pmu_request(&req, NULL, 2, PMU_POWER_CTRL,135PMU_POW_BACKLIGHT | PMU_POW_OFF);136pmu_wait_complete(&req);137} else138__pmu_backlight_update_status(pmac_backlight);139}140spin_unlock_irqrestore(&pmu_backlight_lock, flags);141}142#endif /* CONFIG_PM */143144void __init pmu_backlight_init()145{146struct backlight_properties props;147struct backlight_device *bd;148char name[10];149int level, autosave;150151/* Special case for the old PowerBook since I can't test on it */152autosave =153of_machine_is_compatible("AAPL,3400/2400") ||154of_machine_is_compatible("AAPL,3500");155156if (!autosave &&157!pmac_has_backlight_type("pmu") &&158!of_machine_is_compatible("AAPL,PowerBook1998") &&159!of_machine_is_compatible("PowerBook1,1"))160return;161162snprintf(name, sizeof(name), "pmubl");163164memset(&props, 0, sizeof(struct backlight_properties));165props.type = BACKLIGHT_PLATFORM;166props.max_brightness = FB_BACKLIGHT_LEVELS - 1;167bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data,168&props);169if (IS_ERR(bd)) {170printk(KERN_ERR "PMU Backlight registration failed\n");171return;172}173uses_pmu_bl = 1;174pmu_backlight_init_curve(0x7F, 0x46, 0x0E);175176level = bd->props.max_brightness;177178if (autosave) {179/* read autosaved value if available */180struct adb_request req;181pmu_request(&req, NULL, 2, 0xd9, 0);182pmu_wait_complete(&req);183184level = pmu_backlight_curve_lookup(185(req.reply[0] >> 4) *186bd->props.max_brightness / 15);187}188189bd->props.brightness = level;190bd->props.power = FB_BLANK_UNBLANK;191backlight_update_status(bd);192193printk(KERN_INFO "PMU Backlight initialized (%s)\n", name);194}195196197