mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
[PATCH] Rewritten backlight infrastructure for portable Apple computers
This patch contains a total rewrite of the backlight infrastructure for portable Apple computers. Backward compatibility is retained. A sysfs interface allows userland to control the brightness with more steps than before. Userland is allowed to upload a brightness curve for different monitors, similar to Mac OS X. [[email protected]: add needed exports] Signed-off-by: Michael Hanselmann <[email protected]> Acked-by: Benjamin Herrenschmidt <[email protected]> Cc: Richard Purdie <[email protected]> Cc: "Antonino A. Daplas" <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
17660bdd5c
commit
5474c120aa
26 changed files with 1529 additions and 711 deletions
|
|
@ -99,17 +99,22 @@ config PMAC_MEDIABAY
|
|||
devices are not fully supported in the bay as I never had one to
|
||||
try with
|
||||
|
||||
# made a separate option since backlight may end up beeing used
|
||||
# on non-powerbook machines (but only on PMU based ones AFAIK)
|
||||
config PMAC_BACKLIGHT
|
||||
bool "Backlight control for LCD screens"
|
||||
depends on ADB_PMU && (BROKEN || !PPC64)
|
||||
help
|
||||
Say Y here to build in code to manage the LCD backlight on a
|
||||
Macintosh PowerBook. With this code, the backlight will be turned
|
||||
on and off appropriately on power-management and lid-open/lid-closed
|
||||
events; also, the PowerBook button device will be enabled so you can
|
||||
change the screen brightness.
|
||||
Say Y here to enable Macintosh specific extensions of the generic
|
||||
backlight code. With this enabled, the brightness keys on older
|
||||
PowerBooks will be enabled so you can change the screen brightness.
|
||||
Newer models should use an userspace daemon like pbbuttonsd.
|
||||
|
||||
config PMAC_BACKLIGHT_LEGACY
|
||||
bool "Provide legacy ioctl's on /dev/pmu for the backlight"
|
||||
depends on PMAC_BACKLIGHT && (BROKEN || !PPC64)
|
||||
help
|
||||
Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for
|
||||
programs which use this old interface. New and updated programs
|
||||
should use the backlight classes in sysfs.
|
||||
|
||||
config ADB_MACIO
|
||||
bool "Include MacIO (CHRP) ADB driver"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o
|
|||
obj-$(CONFIG_ANSLCD) += ans-lcd.o
|
||||
|
||||
obj-$(CONFIG_ADB_PMU) += via-pmu.o
|
||||
obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o
|
||||
obj-$(CONFIG_ADB_CUDA) += via-cuda.o
|
||||
obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o
|
||||
obj-$(CONFIG_PMAC_SMU) += smu.o
|
||||
|
|
|
|||
|
|
@ -503,9 +503,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
|
|||
case 0x1f: /* Powerbook button device */
|
||||
{
|
||||
int down = (data[1] == (data[1] & 0xf));
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
int backlight = get_backlight_level();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX: Where is the contrast control for the passive?
|
||||
* -- Cort
|
||||
|
|
@ -530,29 +528,17 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
|
|||
|
||||
case 0xa: /* brightness decrease */
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
if (!disable_kernel_backlight) {
|
||||
if (down && backlight >= 0) {
|
||||
if (backlight > BACKLIGHT_OFF)
|
||||
set_backlight_level(backlight-1);
|
||||
else
|
||||
set_backlight_level(BACKLIGHT_OFF);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
if (!disable_kernel_backlight && down)
|
||||
pmac_backlight_key_down();
|
||||
#endif
|
||||
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
|
||||
break;
|
||||
|
||||
case 0x9: /* brightness increase */
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
if (!disable_kernel_backlight) {
|
||||
if (down && backlight >= 0) {
|
||||
if (backlight < BACKLIGHT_MAX)
|
||||
set_backlight_level(backlight+1);
|
||||
else
|
||||
set_backlight_level(BACKLIGHT_MAX);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
if (!disable_kernel_backlight && down)
|
||||
pmac_backlight_key_up();
|
||||
#endif
|
||||
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
|
||||
break;
|
||||
|
||||
|
|
|
|||
150
drivers/macintosh/via-pmu-backlight.c
Normal file
150
drivers/macintosh/via-pmu-backlight.c
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Backlight code for via-pmu
|
||||
*
|
||||
* Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
|
||||
* Copyright (C) 2001-2002 Benjamin Herrenschmidt
|
||||
* Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <linux/adb.h>
|
||||
#include <linux/pmu.h>
|
||||
#include <asm/backlight.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#define MAX_PMU_LEVEL 0xFF
|
||||
|
||||
static struct device_node *vias;
|
||||
static struct backlight_properties pmu_backlight_data;
|
||||
|
||||
static int pmu_backlight_get_level_brightness(struct fb_info *info,
|
||||
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);
|
||||
|
||||
if (pmulevel < 0)
|
||||
pmulevel = 0;
|
||||
else if (pmulevel > MAX_PMU_LEVEL)
|
||||
pmulevel = MAX_PMU_LEVEL;
|
||||
|
||||
return pmulevel;
|
||||
}
|
||||
|
||||
static int pmu_backlight_update_status(struct backlight_device *bd)
|
||||
{
|
||||
struct fb_info *info = class_get_devdata(&bd->class_dev);
|
||||
struct adb_request req;
|
||||
int pmulevel, level = bd->props->brightness;
|
||||
|
||||
if (vias == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (bd->props->power != FB_BLANK_UNBLANK ||
|
||||
bd->props->fb_blank != FB_BLANK_UNBLANK)
|
||||
level = 0;
|
||||
|
||||
pmulevel = pmu_backlight_get_level_brightness(info, level);
|
||||
|
||||
pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
|
||||
pmu_wait_complete(&req);
|
||||
|
||||
pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
|
||||
PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
|
||||
pmu_wait_complete(&req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmu_backlight_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
return bd->props->brightness;
|
||||
}
|
||||
|
||||
static struct backlight_properties pmu_backlight_data = {
|
||||
.owner = THIS_MODULE,
|
||||
.get_brightness = pmu_backlight_get_brightness,
|
||||
.update_status = pmu_backlight_update_status,
|
||||
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
|
||||
};
|
||||
|
||||
void __init pmu_backlight_init(struct device_node *in_vias)
|
||||
{
|
||||
struct backlight_device *bd;
|
||||
struct fb_info *info;
|
||||
char name[10];
|
||||
int level, autosave;
|
||||
|
||||
vias = in_vias;
|
||||
|
||||
/* Special case for the old PowerBook since I can't test on it */
|
||||
autosave =
|
||||
machine_is_compatible("AAPL,3400/2400") ||
|
||||
machine_is_compatible("AAPL,3500");
|
||||
|
||||
if (!autosave &&
|
||||
!pmac_has_backlight_type("pmu") &&
|
||||
!machine_is_compatible("AAPL,PowerBook1998") &&
|
||||
!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%d", info->node);
|
||||
|
||||
bd = backlight_device_register(name, info, &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);
|
||||
|
||||
level = pmu_backlight_data.max_brightness;
|
||||
|
||||
if (autosave) {
|
||||
/* read autosaved value if available */
|
||||
struct adb_request req;
|
||||
pmu_request(&req, NULL, 2, 0xd9, 0);
|
||||
pmu_wait_complete(&req);
|
||||
|
||||
mutex_lock(&info->bl_mutex);
|
||||
level = pmac_backlight_curve_lookup(info,
|
||||
(req.reply[0] >> 4) *
|
||||
pmu_backlight_data.max_brightness / 15);
|
||||
mutex_unlock(&info->bl_mutex);
|
||||
}
|
||||
|
||||
up(&bd->sem);
|
||||
bd->props->brightness = level;
|
||||
bd->props->power = FB_BLANK_UNBLANK;
|
||||
bd->props->update_status(bd);
|
||||
down(&bd->sem);
|
||||
|
||||
mutex_lock(&pmac_backlight_mutex);
|
||||
if (!pmac_backlight)
|
||||
pmac_backlight = bd;
|
||||
mutex_unlock(&pmac_backlight_mutex);
|
||||
|
||||
printk("pmubl: Backlight initialized (%s)\n", name);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
return;
|
||||
}
|
||||
|
|
@ -144,7 +144,6 @@ static int data_index;
|
|||
static int data_len;
|
||||
static volatile int adb_int_pending;
|
||||
static volatile int disable_poll;
|
||||
static struct adb_request bright_req_1, bright_req_2;
|
||||
static struct device_node *vias;
|
||||
static int pmu_kind = PMU_UNKNOWN;
|
||||
static int pmu_fully_inited = 0;
|
||||
|
|
@ -161,7 +160,7 @@ static int drop_interrupts;
|
|||
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
|
||||
static int option_lid_wakeup = 1;
|
||||
#endif /* CONFIG_PM && CONFIG_PPC32 */
|
||||
#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT)
|
||||
#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
|
||||
static int sleep_in_progress;
|
||||
#endif
|
||||
static unsigned long async_req_locks;
|
||||
|
|
@ -208,10 +207,6 @@ static int proc_get_info(char *page, char **start, off_t off,
|
|||
int count, int *eof, void *data);
|
||||
static int proc_get_irqstats(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data);
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
static int pmu_set_backlight_level(int level, void* data);
|
||||
static int pmu_set_backlight_enable(int on, int level, void* data);
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
static void pmu_pass_intr(unsigned char *data, int len);
|
||||
static int proc_get_batt(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data);
|
||||
|
|
@ -292,13 +287,6 @@ static char *pbook_type[] = {
|
|||
"Core99"
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
static struct backlight_controller pmu_backlight_controller = {
|
||||
pmu_set_backlight_enable,
|
||||
pmu_set_backlight_level
|
||||
};
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
|
||||
int __init find_via_pmu(void)
|
||||
{
|
||||
u64 taddr;
|
||||
|
|
@ -417,8 +405,6 @@ static int __init via_pmu_start(void)
|
|||
if (vias == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
bright_req_1.complete = 1;
|
||||
bright_req_2.complete = 1;
|
||||
batt_req.complete = 1;
|
||||
|
||||
#ifndef CONFIG_PPC_MERGE
|
||||
|
|
@ -483,9 +469,9 @@ static int __init via_pmu_dev_init(void)
|
|||
return -ENODEV;
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
/* Enable backlight */
|
||||
register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
/* Initialize backlight */
|
||||
pmu_backlight_init(vias);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
if (machine_is_compatible("AAPL,3400/2400") ||
|
||||
|
|
@ -1424,7 +1410,7 @@ next:
|
|||
#ifdef CONFIG_INPUT_ADBHID
|
||||
if (!disable_kernel_backlight)
|
||||
#endif /* CONFIG_INPUT_ADBHID */
|
||||
set_backlight_level(data[1] >> 4);
|
||||
pmac_backlight_set_legacy_brightness(data[1] >> 4);
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
}
|
||||
/* Tick interrupt */
|
||||
|
|
@ -1674,61 +1660,6 @@ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
static int backlight_to_bright[] = {
|
||||
0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
|
||||
0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
|
||||
};
|
||||
|
||||
static int
|
||||
pmu_set_backlight_enable(int on, int level, void* data)
|
||||
{
|
||||
struct adb_request req;
|
||||
|
||||
if (vias == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (on) {
|
||||
pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
|
||||
backlight_to_bright[level]);
|
||||
pmu_wait_complete(&req);
|
||||
}
|
||||
pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
|
||||
PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
|
||||
pmu_wait_complete(&req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pmu_bright_complete(struct adb_request *req)
|
||||
{
|
||||
if (req == &bright_req_1)
|
||||
clear_bit(1, &async_req_locks);
|
||||
if (req == &bright_req_2)
|
||||
clear_bit(2, &async_req_locks);
|
||||
}
|
||||
|
||||
static int
|
||||
pmu_set_backlight_level(int level, void* data)
|
||||
{
|
||||
if (vias == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (test_and_set_bit(1, &async_req_locks))
|
||||
return -EAGAIN;
|
||||
pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT,
|
||||
backlight_to_bright[level]);
|
||||
if (test_and_set_bit(2, &async_req_locks))
|
||||
return -EAGAIN;
|
||||
pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL,
|
||||
PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ?
|
||||
PMU_POW_ON : PMU_POW_OFF));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
|
||||
void
|
||||
pmu_enable_irled(int on)
|
||||
{
|
||||
|
|
@ -2145,9 +2076,8 @@ pmac_suspend_devices(void)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Wait for completion of async backlight requests */
|
||||
while (!bright_req_1.complete || !bright_req_2.complete ||
|
||||
!batt_req.complete)
|
||||
/* Wait for completion of async requests */
|
||||
while (!batt_req.complete)
|
||||
pmu_poll();
|
||||
|
||||
/* Giveup the lazy FPU & vec so we don't have to back them
|
||||
|
|
@ -2678,26 +2608,34 @@ pmu_ioctl(struct inode * inode, struct file *filp,
|
|||
return put_user(1, argp);
|
||||
#endif /* CONFIG_PM && CONFIG_PPC32 */
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
/* Backlight should have its own device or go via
|
||||
* the fbdev
|
||||
*/
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
|
||||
/* Compatibility ioctl's for backlight */
|
||||
case PMU_IOC_GET_BACKLIGHT:
|
||||
{
|
||||
int brightness;
|
||||
|
||||
if (sleep_in_progress)
|
||||
return -EBUSY;
|
||||
error = get_backlight_level();
|
||||
if (error < 0)
|
||||
return error;
|
||||
return put_user(error, argp);
|
||||
|
||||
brightness = pmac_backlight_get_legacy_brightness();
|
||||
if (brightness < 0)
|
||||
return brightness;
|
||||
else
|
||||
return put_user(brightness, argp);
|
||||
|
||||
}
|
||||
case PMU_IOC_SET_BACKLIGHT:
|
||||
{
|
||||
__u32 value;
|
||||
int brightness;
|
||||
|
||||
if (sleep_in_progress)
|
||||
return -EBUSY;
|
||||
error = get_user(value, argp);
|
||||
if (!error)
|
||||
error = set_backlight_level(value);
|
||||
break;
|
||||
|
||||
error = get_user(brightness, argp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return pmac_backlight_set_legacy_brightness(brightness);
|
||||
}
|
||||
#ifdef CONFIG_INPUT_ADBHID
|
||||
case PMU_IOC_GRAB_BACKLIGHT: {
|
||||
|
|
@ -2713,7 +2651,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
|
|||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_INPUT_ADBHID */
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT */
|
||||
#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
|
||||
case PMU_IOC_GET_MODEL:
|
||||
return put_user(pmu_kind, argp);
|
||||
case PMU_IOC_HAS_ADB:
|
||||
|
|
|
|||
Loading…
Reference in a new issue