18
18
#include <linux/pnp.h>
19
19
#include <linux/apple_bl.h>
20
20
#include <linux/slab.h>
21
+ #include <linux/delay.h>
21
22
#include <acpi/video.h>
22
23
#include <asm/io.h>
23
24
24
25
struct apple_gmux_data {
25
26
unsigned long iostart ;
26
27
unsigned long iolen ;
28
+ bool indexed ;
29
+ struct mutex index_lock ;
27
30
28
31
struct backlight_device * bdev ;
29
32
};
@@ -45,6 +48,9 @@ struct apple_gmux_data {
45
48
#define GMUX_PORT_DISCRETE_POWER 0x50
46
49
#define GMUX_PORT_MAX_BRIGHTNESS 0x70
47
50
#define GMUX_PORT_BRIGHTNESS 0x74
51
+ #define GMUX_PORT_VALUE 0xc2
52
+ #define GMUX_PORT_READ 0xd0
53
+ #define GMUX_PORT_WRITE 0xd4
48
54
49
55
#define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4)
50
56
@@ -59,24 +65,24 @@ struct apple_gmux_data {
59
65
#define GMUX_BRIGHTNESS_MASK 0x00ffffff
60
66
#define GMUX_MAX_BRIGHTNESS GMUX_BRIGHTNESS_MASK
61
67
62
- static inline u8 gmux_read8 (struct apple_gmux_data * gmux_data , int port )
68
+ static u8 gmux_pio_read8 (struct apple_gmux_data * gmux_data , int port )
63
69
{
64
70
return inb (gmux_data -> iostart + port );
65
71
}
66
72
67
- static inline void gmux_write8 (struct apple_gmux_data * gmux_data , int port ,
73
+ static void gmux_pio_write8 (struct apple_gmux_data * gmux_data , int port ,
68
74
u8 val )
69
75
{
70
76
outb (val , gmux_data -> iostart + port );
71
77
}
72
78
73
- static inline u32 gmux_read32 (struct apple_gmux_data * gmux_data , int port )
79
+ static u32 gmux_pio_read32 (struct apple_gmux_data * gmux_data , int port )
74
80
{
75
81
return inl (gmux_data -> iostart + port );
76
82
}
77
83
78
- static inline u32 gmux_write32 (struct apple_gmux_data * gmux_data , int port ,
79
- u32 val )
84
+ static void gmux_pio_write32 (struct apple_gmux_data * gmux_data , int port ,
85
+ u32 val )
80
86
{
81
87
int i ;
82
88
u8 tmpval ;
@@ -87,6 +93,144 @@ static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port,
87
93
}
88
94
}
89
95
96
+ static int gmux_index_wait_ready (struct apple_gmux_data * gmux_data )
97
+ {
98
+ int i = 200 ;
99
+ u8 gwr = inb (gmux_data -> iostart + GMUX_PORT_WRITE );
100
+
101
+ while (i && (gwr & 0x01 )) {
102
+ inb (gmux_data -> iostart + GMUX_PORT_READ );
103
+ gwr = inb (gmux_data -> iostart + GMUX_PORT_WRITE );
104
+ udelay (100 );
105
+ i -- ;
106
+ }
107
+
108
+ return !!i ;
109
+ }
110
+
111
+ static int gmux_index_wait_complete (struct apple_gmux_data * gmux_data )
112
+ {
113
+ int i = 200 ;
114
+ u8 gwr = inb (gmux_data -> iostart + GMUX_PORT_WRITE );
115
+
116
+ while (i && !(gwr & 0x01 )) {
117
+ gwr = inb (gmux_data -> iostart + GMUX_PORT_WRITE );
118
+ udelay (100 );
119
+ i -- ;
120
+ }
121
+
122
+ if (gwr & 0x01 )
123
+ inb (gmux_data -> iostart + GMUX_PORT_READ );
124
+
125
+ return !!i ;
126
+ }
127
+
128
+ static u8 gmux_index_read8 (struct apple_gmux_data * gmux_data , int port )
129
+ {
130
+ u8 val ;
131
+
132
+ mutex_lock (& gmux_data -> index_lock );
133
+ outb ((port & 0xff ), gmux_data -> iostart + GMUX_PORT_READ );
134
+ gmux_index_wait_ready (gmux_data );
135
+ val = inb (gmux_data -> iostart + GMUX_PORT_VALUE );
136
+ mutex_unlock (& gmux_data -> index_lock );
137
+
138
+ return val ;
139
+ }
140
+
141
+ static void gmux_index_write8 (struct apple_gmux_data * gmux_data , int port ,
142
+ u8 val )
143
+ {
144
+ mutex_lock (& gmux_data -> index_lock );
145
+ outb (val , gmux_data -> iostart + GMUX_PORT_VALUE );
146
+ gmux_index_wait_ready (gmux_data );
147
+ outb (port & 0xff , gmux_data -> iostart + GMUX_PORT_WRITE );
148
+ gmux_index_wait_complete (gmux_data );
149
+ mutex_unlock (& gmux_data -> index_lock );
150
+ }
151
+
152
+ static u32 gmux_index_read32 (struct apple_gmux_data * gmux_data , int port )
153
+ {
154
+ u32 val ;
155
+
156
+ mutex_lock (& gmux_data -> index_lock );
157
+ outb ((port & 0xff ), gmux_data -> iostart + GMUX_PORT_READ );
158
+ gmux_index_wait_ready (gmux_data );
159
+ val = inl (gmux_data -> iostart + GMUX_PORT_VALUE );
160
+ mutex_unlock (& gmux_data -> index_lock );
161
+
162
+ return val ;
163
+ }
164
+
165
+ static void gmux_index_write32 (struct apple_gmux_data * gmux_data , int port ,
166
+ u32 val )
167
+ {
168
+ int i ;
169
+ u8 tmpval ;
170
+
171
+ mutex_lock (& gmux_data -> index_lock );
172
+
173
+ for (i = 0 ; i < 4 ; i ++ ) {
174
+ tmpval = (val >> (i * 8 )) & 0xff ;
175
+ outb (tmpval , gmux_data -> iostart + GMUX_PORT_VALUE + i );
176
+ }
177
+
178
+ gmux_index_wait_ready (gmux_data );
179
+ outb (port & 0xff , gmux_data -> iostart + GMUX_PORT_WRITE );
180
+ gmux_index_wait_complete (gmux_data );
181
+ mutex_unlock (& gmux_data -> index_lock );
182
+ }
183
+
184
+ static u8 gmux_read8 (struct apple_gmux_data * gmux_data , int port )
185
+ {
186
+ if (gmux_data -> indexed )
187
+ return gmux_index_read8 (gmux_data , port );
188
+ else
189
+ return gmux_pio_read8 (gmux_data , port );
190
+ }
191
+
192
+ static void gmux_write8 (struct apple_gmux_data * gmux_data , int port , u8 val )
193
+ {
194
+ if (gmux_data -> indexed )
195
+ gmux_index_write8 (gmux_data , port , val );
196
+ else
197
+ gmux_pio_write8 (gmux_data , port , val );
198
+ }
199
+
200
+ static u32 gmux_read32 (struct apple_gmux_data * gmux_data , int port )
201
+ {
202
+ if (gmux_data -> indexed )
203
+ return gmux_index_read32 (gmux_data , port );
204
+ else
205
+ return gmux_pio_read32 (gmux_data , port );
206
+ }
207
+
208
+ static void gmux_write32 (struct apple_gmux_data * gmux_data , int port ,
209
+ u32 val )
210
+ {
211
+ if (gmux_data -> indexed )
212
+ gmux_index_write32 (gmux_data , port , val );
213
+ else
214
+ gmux_pio_write32 (gmux_data , port , val );
215
+ }
216
+
217
+ static bool gmux_is_indexed (struct apple_gmux_data * gmux_data )
218
+ {
219
+ u16 val ;
220
+
221
+ outb (0xaa , gmux_data -> iostart + 0xcc );
222
+ outb (0x55 , gmux_data -> iostart + 0xcd );
223
+ outb (0x00 , gmux_data -> iostart + 0xce );
224
+
225
+ val = inb (gmux_data -> iostart + 0xcc ) |
226
+ (inb (gmux_data -> iostart + 0xcd ) << 8 );
227
+
228
+ if (val == 0x55aa )
229
+ return true;
230
+
231
+ return false;
232
+ }
233
+
90
234
static int gmux_get_brightness (struct backlight_device * bd )
91
235
{
92
236
struct apple_gmux_data * gmux_data = bl_get_data (bd );
@@ -150,22 +294,29 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,
150
294
}
151
295
152
296
/*
153
- * On some machines the gmux is in ACPI even thought the machine
154
- * doesn 't really have a gmux. Check for invalid version information
155
- * to detect this.
297
+ * Invalid version information may indicate either that the gmux
298
+ * device isn 't present or that it's a new one that uses indexed
299
+ * io
156
300
*/
301
+
157
302
ver_major = gmux_read8 (gmux_data , GMUX_PORT_VERSION_MAJOR );
158
303
ver_minor = gmux_read8 (gmux_data , GMUX_PORT_VERSION_MINOR );
159
304
ver_release = gmux_read8 (gmux_data , GMUX_PORT_VERSION_RELEASE );
160
305
if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff ) {
161
- pr_info ("gmux device not present\n" );
162
- ret = - ENODEV ;
163
- goto err_release ;
306
+ if (gmux_is_indexed (gmux_data )) {
307
+ mutex_init (& gmux_data -> index_lock );
308
+ gmux_data -> indexed = true;
309
+ } else {
310
+ pr_info ("gmux device not present\n" );
311
+ ret = - ENODEV ;
312
+ goto err_release ;
313
+ }
314
+ pr_info ("Found indexed gmux\n" );
315
+ } else {
316
+ pr_info ("Found gmux version %d.%d.%d\n" , ver_major , ver_minor ,
317
+ ver_release );
164
318
}
165
319
166
- pr_info ("Found gmux version %d.%d.%d\n" , ver_major , ver_minor ,
167
- ver_release );
168
-
169
320
memset (& props , 0 , sizeof (props ));
170
321
props .type = BACKLIGHT_PLATFORM ;
171
322
props .max_brightness = gmux_read32 (gmux_data , GMUX_PORT_MAX_BRIGHTNESS );
0 commit comments