Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/powermac/backlight.c
10818 views
1
/*
2
* Miscellaneous procedures for dealing with the PowerMac hardware.
3
* Contains support for the backlight.
4
*
5
* Copyright (C) 2000 Benjamin Herrenschmidt
6
* Copyright (C) 2006 Michael Hanselmann <[email protected]>
7
*
8
*/
9
10
#include <linux/kernel.h>
11
#include <linux/fb.h>
12
#include <linux/backlight.h>
13
#include <linux/adb.h>
14
#include <linux/pmu.h>
15
#include <asm/atomic.h>
16
#include <asm/prom.h>
17
#include <asm/backlight.h>
18
19
#define OLD_BACKLIGHT_MAX 15
20
21
static void pmac_backlight_key_worker(struct work_struct *work);
22
static void pmac_backlight_set_legacy_worker(struct work_struct *work);
23
24
static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker);
25
static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker);
26
27
/* Although these variables are used in interrupt context, it makes no sense to
28
* protect them. No user is able to produce enough key events per second and
29
* notice the errors that might happen.
30
*/
31
static int pmac_backlight_key_queued;
32
static int pmac_backlight_set_legacy_queued;
33
34
/* The via-pmu code allows the backlight to be grabbed, in which case the
35
* in-kernel control of the brightness needs to be disabled. This should
36
* only be used by really old PowerBooks.
37
*/
38
static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
39
40
/* Protect the pmac_backlight variable below.
41
You should hold this lock when using the pmac_backlight pointer to
42
prevent its potential removal. */
43
DEFINE_MUTEX(pmac_backlight_mutex);
44
45
/* Main backlight storage
46
*
47
* Backlight drivers in this variable are required to have the "ops"
48
* attribute set and to have an update_status function.
49
*
50
* We can only store one backlight here, but since Apple laptops have only one
51
* internal display, it doesn't matter. Other backlight drivers can be used
52
* independently.
53
*
54
*/
55
struct backlight_device *pmac_backlight;
56
57
int pmac_has_backlight_type(const char *type)
58
{
59
struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");
60
61
if (bk_node) {
62
const char *prop = of_get_property(bk_node,
63
"backlight-control", NULL);
64
if (prop && strncmp(prop, type, strlen(type)) == 0) {
65
of_node_put(bk_node);
66
return 1;
67
}
68
of_node_put(bk_node);
69
}
70
71
return 0;
72
}
73
74
int pmac_backlight_curve_lookup(struct fb_info *info, int value)
75
{
76
int level = (FB_BACKLIGHT_LEVELS - 1);
77
78
if (info && info->bl_dev) {
79
int i, max = 0;
80
81
/* Look for biggest value */
82
for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
83
max = max((int)info->bl_curve[i], max);
84
85
/* Look for nearest value */
86
for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
87
int diff = abs(info->bl_curve[i] - value);
88
if (diff < max) {
89
max = diff;
90
level = i;
91
}
92
}
93
94
}
95
96
return level;
97
}
98
99
static void pmac_backlight_key_worker(struct work_struct *work)
100
{
101
if (atomic_read(&kernel_backlight_disabled))
102
return;
103
104
mutex_lock(&pmac_backlight_mutex);
105
if (pmac_backlight) {
106
struct backlight_properties *props;
107
int brightness;
108
109
props = &pmac_backlight->props;
110
111
brightness = props->brightness +
112
((pmac_backlight_key_queued?-1:1) *
113
(props->max_brightness / 15));
114
115
if (brightness < 0)
116
brightness = 0;
117
else if (brightness > props->max_brightness)
118
brightness = props->max_brightness;
119
120
props->brightness = brightness;
121
backlight_update_status(pmac_backlight);
122
}
123
mutex_unlock(&pmac_backlight_mutex);
124
}
125
126
/* This function is called in interrupt context */
127
void pmac_backlight_key(int direction)
128
{
129
if (atomic_read(&kernel_backlight_disabled))
130
return;
131
132
/* we can receive multiple interrupts here, but the scheduled work
133
* will run only once, with the last value
134
*/
135
pmac_backlight_key_queued = direction;
136
schedule_work(&pmac_backlight_key_work);
137
}
138
139
static int __pmac_backlight_set_legacy_brightness(int brightness)
140
{
141
int error = -ENXIO;
142
143
mutex_lock(&pmac_backlight_mutex);
144
if (pmac_backlight) {
145
struct backlight_properties *props;
146
147
props = &pmac_backlight->props;
148
props->brightness = brightness *
149
(props->max_brightness + 1) /
150
(OLD_BACKLIGHT_MAX + 1);
151
152
if (props->brightness > props->max_brightness)
153
props->brightness = props->max_brightness;
154
else if (props->brightness < 0)
155
props->brightness = 0;
156
157
backlight_update_status(pmac_backlight);
158
159
error = 0;
160
}
161
mutex_unlock(&pmac_backlight_mutex);
162
163
return error;
164
}
165
166
static void pmac_backlight_set_legacy_worker(struct work_struct *work)
167
{
168
if (atomic_read(&kernel_backlight_disabled))
169
return;
170
171
__pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);
172
}
173
174
/* This function is called in interrupt context */
175
void pmac_backlight_set_legacy_brightness_pmu(int brightness) {
176
if (atomic_read(&kernel_backlight_disabled))
177
return;
178
179
pmac_backlight_set_legacy_queued = brightness;
180
schedule_work(&pmac_backlight_set_legacy_work);
181
}
182
183
int pmac_backlight_set_legacy_brightness(int brightness)
184
{
185
return __pmac_backlight_set_legacy_brightness(brightness);
186
}
187
188
int pmac_backlight_get_legacy_brightness()
189
{
190
int result = -ENXIO;
191
192
mutex_lock(&pmac_backlight_mutex);
193
if (pmac_backlight) {
194
struct backlight_properties *props;
195
196
props = &pmac_backlight->props;
197
198
result = props->brightness *
199
(OLD_BACKLIGHT_MAX + 1) /
200
(props->max_brightness + 1);
201
}
202
mutex_unlock(&pmac_backlight_mutex);
203
204
return result;
205
}
206
207
void pmac_backlight_disable()
208
{
209
atomic_inc(&kernel_backlight_disabled);
210
}
211
212
void pmac_backlight_enable()
213
{
214
atomic_dec(&kernel_backlight_disabled);
215
}
216
217
EXPORT_SYMBOL_GPL(pmac_backlight);
218
EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
219
EXPORT_SYMBOL_GPL(pmac_has_backlight_type);
220
221