Blame view
drivers/macintosh/via-pmu-backlight.c
4.45 KB
b24413180
|
1 |
// SPDX-License-Identifier: GPL-2.0 |
5474c120a
|
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * 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 |
acc2472ed
|
18 |
static const struct backlight_ops pmu_backlight_data; |
4efd587bf
|
19 |
static DEFINE_SPINLOCK(pmu_backlight_lock); |
fa19d6348
|
20 |
static int sleeping, uses_pmu_bl; |
d565dd3b0
|
21 |
static u8 bl_curve[FB_BACKLIGHT_LEVELS]; |
5474c120a
|
22 |
|
d565dd3b0
|
23 24 |
static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) { |
0094f2cdc
|
25 |
int i, flat, count, range = (max - min); |
d565dd3b0
|
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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) |
5474c120a
|
58 59 60 61 |
{ int pmulevel; /* Get and convert the value */ |
d565dd3b0
|
62 |
pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; |
5474c120a
|
63 64 65 66 67 68 69 |
if (pmulevel < 0) pmulevel = 0; else if (pmulevel > MAX_PMU_LEVEL) pmulevel = MAX_PMU_LEVEL; return pmulevel; } |
0094f2cdc
|
70 |
static int __pmu_backlight_update_status(struct backlight_device *bd) |
5474c120a
|
71 |
{ |
5474c120a
|
72 |
struct adb_request req; |
599a52d12
|
73 |
int level = bd->props.brightness; |
5474c120a
|
74 |
|
5474c120a
|
75 |
|
599a52d12
|
76 77 |
if (bd->props.power != FB_BLANK_UNBLANK || bd->props.fb_blank != FB_BLANK_UNBLANK) |
5474c120a
|
78 |
level = 0; |
4b755999d
|
79 |
if (level > 0) { |
d565dd3b0
|
80 |
int pmulevel = pmu_backlight_get_level_brightness(level); |
5474c120a
|
81 |
|
4b755999d
|
82 83 |
pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); pmu_wait_complete(&req); |
5474c120a
|
84 |
|
4b755999d
|
85 86 87 88 89 90 91 92 |
pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT | PMU_POW_ON); pmu_wait_complete(&req); } else { pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT | PMU_POW_OFF); pmu_wait_complete(&req); } |
5474c120a
|
93 94 |
return 0; } |
0094f2cdc
|
95 96 97 98 99 100 101 102 103 104 105 106 |
static int pmu_backlight_update_status(struct backlight_device *bd) { unsigned long flags; int rc = 0; spin_lock_irqsave(&pmu_backlight_lock, flags); /* Don't update brightness when sleeping */ if (!sleeping) rc = __pmu_backlight_update_status(bd); spin_unlock_irqrestore(&pmu_backlight_lock, flags); return rc; } |
acc2472ed
|
107 |
static const struct backlight_ops pmu_backlight_data = { |
5474c120a
|
108 |
.update_status = pmu_backlight_update_status, |
599a52d12
|
109 |
|
5474c120a
|
110 |
}; |
4b755999d
|
111 |
#ifdef CONFIG_PM |
d565dd3b0
|
112 |
void pmu_backlight_set_sleep(int sleep) |
4b755999d
|
113 114 115 116 |
{ unsigned long flags; spin_lock_irqsave(&pmu_backlight_lock, flags); |
d565dd3b0
|
117 |
sleeping = sleep; |
fa19d6348
|
118 |
if (pmac_backlight && uses_pmu_bl) { |
0094f2cdc
|
119 120 121 122 123 124 125 126 127 |
if (sleep) { struct adb_request req; pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT | PMU_POW_OFF); pmu_wait_complete(&req); } else __pmu_backlight_update_status(pmac_backlight); } |
4b755999d
|
128 |
spin_unlock_irqrestore(&pmu_backlight_lock, flags); |
4b755999d
|
129 |
} |
d565dd3b0
|
130 |
#endif /* CONFIG_PM */ |
4b755999d
|
131 |
|
00f7b29f6
|
132 |
void __init pmu_backlight_init(void) |
5474c120a
|
133 |
{ |
a19a6ee6c
|
134 |
struct backlight_properties props; |
5474c120a
|
135 |
struct backlight_device *bd; |
5474c120a
|
136 137 |
char name[10]; int level, autosave; |
5474c120a
|
138 139 |
/* Special case for the old PowerBook since I can't test on it */ autosave = |
71a157e8e
|
140 141 |
of_machine_is_compatible("AAPL,3400/2400") || of_machine_is_compatible("AAPL,3500"); |
5474c120a
|
142 143 144 |
if (!autosave && !pmac_has_backlight_type("pmu") && |
71a157e8e
|
145 146 |
!of_machine_is_compatible("AAPL,PowerBook1998") && !of_machine_is_compatible("PowerBook1,1")) |
5474c120a
|
147 |
return; |
d565dd3b0
|
148 |
snprintf(name, sizeof(name), "pmubl"); |
5474c120a
|
149 |
|
a19a6ee6c
|
150 |
memset(&props, 0, sizeof(struct backlight_properties)); |
bb7ca747f
|
151 |
props.type = BACKLIGHT_PLATFORM; |
a19a6ee6c
|
152 153 154 |
props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data, &props); |
5474c120a
|
155 |
if (IS_ERR(bd)) { |
0094f2cdc
|
156 157 158 |
printk(KERN_ERR "PMU Backlight registration failed "); return; |
5474c120a
|
159 |
} |
fa19d6348
|
160 |
uses_pmu_bl = 1; |
d565dd3b0
|
161 |
pmu_backlight_init_curve(0x7F, 0x46, 0x0E); |
5474c120a
|
162 |
|
599a52d12
|
163 |
level = bd->props.max_brightness; |
5474c120a
|
164 165 166 167 168 169 |
if (autosave) { /* read autosaved value if available */ struct adb_request req; pmu_request(&req, NULL, 2, 0xd9, 0); pmu_wait_complete(&req); |
d565dd3b0
|
170 |
level = pmu_backlight_curve_lookup( |
5474c120a
|
171 |
(req.reply[0] >> 4) * |
599a52d12
|
172 |
bd->props.max_brightness / 15); |
5474c120a
|
173 |
} |
599a52d12
|
174 175 |
bd->props.brightness = level; bd->props.power = FB_BLANK_UNBLANK; |
28ee086d5
|
176 |
backlight_update_status(bd); |
5474c120a
|
177 |
|
0094f2cdc
|
178 179 |
printk(KERN_INFO "PMU Backlight initialized (%s) ", name); |
5474c120a
|
180 |
} |