diff options
author | Corentin Chary <corentincj@iksaif.net> | 2011-11-26 04:59:58 -0500 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2012-03-20 12:02:05 -0400 |
commit | a6df48943a408b493d1aa141791d614a529d484e (patch) | |
tree | 3e5d9d88c76fa130f1f5f49967a57000c7a0f185 /drivers | |
parent | 73d99a224435f25976a29c3aef53590180cdb774 (diff) |
samsung-laptop: put all local variables in a single structure
Even if this driver can only be loaded once, it is still a good
idea to create some kind of context structure.
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/platform/x86/samsung-laptop.c | 291 |
1 files changed, 170 insertions, 121 deletions
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index fd73ea89b857..c2a74bfc017c 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c | |||
@@ -217,16 +217,23 @@ static const struct sabi_config sabi_configs[] = { | |||
217 | { }, | 217 | { }, |
218 | }; | 218 | }; |
219 | 219 | ||
220 | static const struct sabi_config *sabi_config; | 220 | struct samsung_laptop { |
221 | const struct sabi_config *config; | ||
221 | 222 | ||
222 | static void __iomem *sabi; | 223 | void __iomem *sabi; |
223 | static void __iomem *sabi_iface; | 224 | void __iomem *sabi_iface; |
224 | static void __iomem *f0000_segment; | 225 | void __iomem *f0000_segment; |
225 | static struct backlight_device *backlight_device; | 226 | |
226 | static struct mutex sabi_mutex; | 227 | struct mutex sabi_mutex; |
227 | static struct platform_device *sdev; | 228 | |
228 | static struct rfkill *rfk; | 229 | struct platform_device *pdev; |
229 | static bool has_stepping_quirk; | 230 | struct backlight_device *backlight_device; |
231 | struct rfkill *rfk; | ||
232 | |||
233 | bool has_stepping_quirk; | ||
234 | }; | ||
235 | |||
236 | static struct samsung_laptop *samsung; | ||
230 | 237 | ||
231 | static bool force; | 238 | static bool force; |
232 | module_param(force, bool, 0); | 239 | module_param(force, bool, 0); |
@@ -239,27 +246,28 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); | |||
239 | 246 | ||
240 | static int sabi_get_command(u8 command, struct sabi_retval *sretval) | 247 | static int sabi_get_command(u8 command, struct sabi_retval *sretval) |
241 | { | 248 | { |
249 | const struct sabi_config *config = samsung->config; | ||
242 | int retval = 0; | 250 | int retval = 0; |
243 | u16 port = readw(sabi + sabi_config->header_offsets.port); | 251 | u16 port = readw(samsung->sabi + config->header_offsets.port); |
244 | u8 complete, iface_data; | 252 | u8 complete, iface_data; |
245 | 253 | ||
246 | mutex_lock(&sabi_mutex); | 254 | mutex_lock(&samsung->sabi_mutex); |
247 | 255 | ||
248 | /* enable memory to be able to write to it */ | 256 | /* enable memory to be able to write to it */ |
249 | outb(readb(sabi + sabi_config->header_offsets.en_mem), port); | 257 | outb(readb(samsung->sabi + config->header_offsets.en_mem), port); |
250 | 258 | ||
251 | /* write out the command */ | 259 | /* write out the command */ |
252 | writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN); | 260 | writew(config->main_function, samsung->sabi_iface + SABI_IFACE_MAIN); |
253 | writew(command, sabi_iface + SABI_IFACE_SUB); | 261 | writew(command, samsung->sabi_iface + SABI_IFACE_SUB); |
254 | writeb(0, sabi_iface + SABI_IFACE_COMPLETE); | 262 | writeb(0, samsung->sabi_iface + SABI_IFACE_COMPLETE); |
255 | outb(readb(sabi + sabi_config->header_offsets.iface_func), port); | 263 | outb(readb(samsung->sabi + config->header_offsets.iface_func), port); |
256 | 264 | ||
257 | /* write protect memory to make it safe */ | 265 | /* write protect memory to make it safe */ |
258 | outb(readb(sabi + sabi_config->header_offsets.re_mem), port); | 266 | outb(readb(samsung->sabi + config->header_offsets.re_mem), port); |
259 | 267 | ||
260 | /* see if the command actually succeeded */ | 268 | /* see if the command actually succeeded */ |
261 | complete = readb(sabi_iface + SABI_IFACE_COMPLETE); | 269 | complete = readb(samsung->sabi_iface + SABI_IFACE_COMPLETE); |
262 | iface_data = readb(sabi_iface + SABI_IFACE_DATA); | 270 | iface_data = readb(samsung->sabi_iface + SABI_IFACE_DATA); |
263 | if (complete != 0xaa || iface_data == 0xff) { | 271 | if (complete != 0xaa || iface_data == 0xff) { |
264 | pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n", | 272 | pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n", |
265 | command, complete, iface_data); | 273 | command, complete, iface_data); |
@@ -272,107 +280,112 @@ static int sabi_get_command(u8 command, struct sabi_retval *sretval) | |||
272 | * There are commands that need more, but not for the ones we | 280 | * There are commands that need more, but not for the ones we |
273 | * currently care about. | 281 | * currently care about. |
274 | */ | 282 | */ |
275 | sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA); | 283 | sretval->retval[0] = readb(samsung->sabi_iface + SABI_IFACE_DATA); |
276 | sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1); | 284 | sretval->retval[1] = readb(samsung->sabi_iface + SABI_IFACE_DATA + 1); |
277 | sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2); | 285 | sretval->retval[2] = readb(samsung->sabi_iface + SABI_IFACE_DATA + 2); |
278 | sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3); | 286 | sretval->retval[3] = readb(samsung->sabi_iface + SABI_IFACE_DATA + 3); |
279 | 287 | ||
280 | exit: | 288 | exit: |
281 | mutex_unlock(&sabi_mutex); | 289 | mutex_unlock(&samsung->sabi_mutex); |
282 | return retval; | 290 | return retval; |
283 | 291 | ||
284 | } | 292 | } |
285 | 293 | ||
286 | static int sabi_set_command(u8 command, u8 data) | 294 | static int sabi_set_command(u8 command, u8 data) |
287 | { | 295 | { |
296 | const struct sabi_config *config = samsung->config; | ||
288 | int retval = 0; | 297 | int retval = 0; |
289 | u16 port = readw(sabi + sabi_config->header_offsets.port); | 298 | u16 port = readw(samsung->sabi + config->header_offsets.port); |
290 | u8 complete, iface_data; | 299 | u8 complete, iface_data; |
291 | 300 | ||
292 | mutex_lock(&sabi_mutex); | 301 | mutex_lock(&samsung->sabi_mutex); |
293 | 302 | ||
294 | /* enable memory to be able to write to it */ | 303 | /* enable memory to be able to write to it */ |
295 | outb(readb(sabi + sabi_config->header_offsets.en_mem), port); | 304 | outb(readb(samsung->sabi + config->header_offsets.en_mem), port); |
296 | 305 | ||
297 | /* write out the command */ | 306 | /* write out the command */ |
298 | writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN); | 307 | writew(config->main_function, samsung->sabi_iface + SABI_IFACE_MAIN); |
299 | writew(command, sabi_iface + SABI_IFACE_SUB); | 308 | writew(command, samsung->sabi_iface + SABI_IFACE_SUB); |
300 | writeb(0, sabi_iface + SABI_IFACE_COMPLETE); | 309 | writeb(0, samsung->sabi_iface + SABI_IFACE_COMPLETE); |
301 | writeb(data, sabi_iface + SABI_IFACE_DATA); | 310 | writeb(data, samsung->sabi_iface + SABI_IFACE_DATA); |
302 | outb(readb(sabi + sabi_config->header_offsets.iface_func), port); | 311 | outb(readb(samsung->sabi + config->header_offsets.iface_func), port); |
303 | 312 | ||
304 | /* write protect memory to make it safe */ | 313 | /* write protect memory to make it safe */ |
305 | outb(readb(sabi + sabi_config->header_offsets.re_mem), port); | 314 | outb(readb(samsung->sabi + config->header_offsets.re_mem), port); |
306 | 315 | ||
307 | /* see if the command actually succeeded */ | 316 | /* see if the command actually succeeded */ |
308 | complete = readb(sabi_iface + SABI_IFACE_COMPLETE); | 317 | complete = readb(samsung->sabi_iface + SABI_IFACE_COMPLETE); |
309 | iface_data = readb(sabi_iface + SABI_IFACE_DATA); | 318 | iface_data = readb(samsung->sabi_iface + SABI_IFACE_DATA); |
310 | if (complete != 0xaa || iface_data == 0xff) { | 319 | if (complete != 0xaa || iface_data == 0xff) { |
311 | pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n", | 320 | pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n", |
312 | command, complete, iface_data); | 321 | command, complete, iface_data); |
313 | retval = -EINVAL; | 322 | retval = -EINVAL; |
314 | } | 323 | } |
315 | 324 | ||
316 | mutex_unlock(&sabi_mutex); | 325 | mutex_unlock(&samsung->sabi_mutex); |
317 | return retval; | 326 | return retval; |
318 | } | 327 | } |
319 | 328 | ||
320 | static void test_backlight(void) | 329 | static void test_backlight(void) |
321 | { | 330 | { |
331 | const struct sabi_commands *commands = &samsung->config->commands; | ||
322 | struct sabi_retval sretval; | 332 | struct sabi_retval sretval; |
323 | 333 | ||
324 | sabi_get_command(sabi_config->commands.get_backlight, &sretval); | 334 | sabi_get_command(commands->get_backlight, &sretval); |
325 | printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); | 335 | printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); |
326 | 336 | ||
327 | sabi_set_command(sabi_config->commands.set_backlight, 0); | 337 | sabi_set_command(commands->set_backlight, 0); |
328 | printk(KERN_DEBUG "backlight should be off\n"); | 338 | printk(KERN_DEBUG "backlight should be off\n"); |
329 | 339 | ||
330 | sabi_get_command(sabi_config->commands.get_backlight, &sretval); | 340 | sabi_get_command(commands->get_backlight, &sretval); |
331 | printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); | 341 | printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); |
332 | 342 | ||
333 | msleep(1000); | 343 | msleep(1000); |
334 | 344 | ||
335 | sabi_set_command(sabi_config->commands.set_backlight, 1); | 345 | sabi_set_command(commands->set_backlight, 1); |
336 | printk(KERN_DEBUG "backlight should be on\n"); | 346 | printk(KERN_DEBUG "backlight should be on\n"); |
337 | 347 | ||
338 | sabi_get_command(sabi_config->commands.get_backlight, &sretval); | 348 | sabi_get_command(commands->get_backlight, &sretval); |
339 | printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); | 349 | printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); |
340 | } | 350 | } |
341 | 351 | ||
342 | static void test_wireless(void) | 352 | static void test_wireless(void) |
343 | { | 353 | { |
354 | const struct sabi_commands *commands = &samsung->config->commands; | ||
344 | struct sabi_retval sretval; | 355 | struct sabi_retval sretval; |
345 | 356 | ||
346 | sabi_get_command(sabi_config->commands.get_wireless_button, &sretval); | 357 | sabi_get_command(commands->get_wireless_button, &sretval); |
347 | printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); | 358 | printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); |
348 | 359 | ||
349 | sabi_set_command(sabi_config->commands.set_wireless_button, 0); | 360 | sabi_set_command(commands->set_wireless_button, 0); |
350 | printk(KERN_DEBUG "wireless led should be off\n"); | 361 | printk(KERN_DEBUG "wireless led should be off\n"); |
351 | 362 | ||
352 | sabi_get_command(sabi_config->commands.get_wireless_button, &sretval); | 363 | sabi_get_command(commands->get_wireless_button, &sretval); |
353 | printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); | 364 | printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); |
354 | 365 | ||
355 | msleep(1000); | 366 | msleep(1000); |
356 | 367 | ||
357 | sabi_set_command(sabi_config->commands.set_wireless_button, 1); | 368 | sabi_set_command(commands->set_wireless_button, 1); |
358 | printk(KERN_DEBUG "wireless led should be on\n"); | 369 | printk(KERN_DEBUG "wireless led should be on\n"); |
359 | 370 | ||
360 | sabi_get_command(sabi_config->commands.get_wireless_button, &sretval); | 371 | sabi_get_command(commands->get_wireless_button, &sretval); |
361 | printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); | 372 | printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); |
362 | } | 373 | } |
363 | 374 | ||
364 | static u8 read_brightness(void) | 375 | static u8 read_brightness(void) |
365 | { | 376 | { |
377 | const struct sabi_config *config = samsung->config; | ||
378 | const struct sabi_commands *commands = &samsung->config->commands; | ||
366 | struct sabi_retval sretval; | 379 | struct sabi_retval sretval; |
367 | int user_brightness = 0; | 380 | int user_brightness = 0; |
368 | int retval; | 381 | int retval; |
369 | 382 | ||
370 | retval = sabi_get_command(sabi_config->commands.get_brightness, | 383 | retval = sabi_get_command(commands->get_brightness, |
371 | &sretval); | 384 | &sretval); |
372 | if (!retval) { | 385 | if (!retval) { |
373 | user_brightness = sretval.retval[0]; | 386 | user_brightness = sretval.retval[0]; |
374 | if (user_brightness > sabi_config->min_brightness) | 387 | if (user_brightness > config->min_brightness) |
375 | user_brightness -= sabi_config->min_brightness; | 388 | user_brightness -= config->min_brightness; |
376 | else | 389 | else |
377 | user_brightness = 0; | 390 | user_brightness = 0; |
378 | } | 391 | } |
@@ -381,9 +394,11 @@ static u8 read_brightness(void) | |||
381 | 394 | ||
382 | static void set_brightness(u8 user_brightness) | 395 | static void set_brightness(u8 user_brightness) |
383 | { | 396 | { |
384 | u8 user_level = user_brightness + sabi_config->min_brightness; | 397 | const struct sabi_config *config = samsung->config; |
398 | const struct sabi_commands *commands = &samsung->config->commands; | ||
399 | u8 user_level = user_brightness + config->min_brightness; | ||
385 | 400 | ||
386 | if (has_stepping_quirk && user_level != 0) { | 401 | if (samsung->has_stepping_quirk && user_level != 0) { |
387 | /* | 402 | /* |
388 | * short circuit if the specified level is what's already set | 403 | * short circuit if the specified level is what's already set |
389 | * to prevent the screen from flickering needlessly | 404 | * to prevent the screen from flickering needlessly |
@@ -391,10 +406,10 @@ static void set_brightness(u8 user_brightness) | |||
391 | if (user_brightness == read_brightness()) | 406 | if (user_brightness == read_brightness()) |
392 | return; | 407 | return; |
393 | 408 | ||
394 | sabi_set_command(sabi_config->commands.set_brightness, 0); | 409 | sabi_set_command(commands->set_brightness, 0); |
395 | } | 410 | } |
396 | 411 | ||
397 | sabi_set_command(sabi_config->commands.set_brightness, user_level); | 412 | sabi_set_command(commands->set_brightness, user_level); |
398 | } | 413 | } |
399 | 414 | ||
400 | static int get_brightness(struct backlight_device *bd) | 415 | static int get_brightness(struct backlight_device *bd) |
@@ -425,11 +440,11 @@ static void check_for_stepping_quirk(void) | |||
425 | else | 440 | else |
426 | check_level = initial_level - 2; | 441 | check_level = initial_level - 2; |
427 | 442 | ||
428 | has_stepping_quirk = false; | 443 | samsung->has_stepping_quirk = false; |
429 | set_brightness(check_level); | 444 | set_brightness(check_level); |
430 | 445 | ||
431 | if (read_brightness() != check_level) { | 446 | if (read_brightness() != check_level) { |
432 | has_stepping_quirk = true; | 447 | samsung->has_stepping_quirk = true; |
433 | pr_info("enabled workaround for brightness stepping quirk\n"); | 448 | pr_info("enabled workaround for brightness stepping quirk\n"); |
434 | } | 449 | } |
435 | 450 | ||
@@ -438,12 +453,14 @@ static void check_for_stepping_quirk(void) | |||
438 | 453 | ||
439 | static int update_status(struct backlight_device *bd) | 454 | static int update_status(struct backlight_device *bd) |
440 | { | 455 | { |
456 | const struct sabi_commands *commands = &samsung->config->commands; | ||
457 | |||
441 | set_brightness(bd->props.brightness); | 458 | set_brightness(bd->props.brightness); |
442 | 459 | ||
443 | if (bd->props.power == FB_BLANK_UNBLANK) | 460 | if (bd->props.power == FB_BLANK_UNBLANK) |
444 | sabi_set_command(sabi_config->commands.set_backlight, 1); | 461 | sabi_set_command(commands->set_backlight, 1); |
445 | else | 462 | else |
446 | sabi_set_command(sabi_config->commands.set_backlight, 0); | 463 | sabi_set_command(commands->set_backlight, 0); |
447 | return 0; | 464 | return 0; |
448 | } | 465 | } |
449 | 466 | ||
@@ -454,15 +471,17 @@ static const struct backlight_ops backlight_ops = { | |||
454 | 471 | ||
455 | static int rfkill_set(void *data, bool blocked) | 472 | static int rfkill_set(void *data, bool blocked) |
456 | { | 473 | { |
474 | const struct sabi_commands *commands = &samsung->config->commands; | ||
475 | |||
457 | /* Do something with blocked...*/ | 476 | /* Do something with blocked...*/ |
458 | /* | 477 | /* |
459 | * blocked == false is on | 478 | * blocked == false is on |
460 | * blocked == true is off | 479 | * blocked == true is off |
461 | */ | 480 | */ |
462 | if (blocked) | 481 | if (blocked) |
463 | sabi_set_command(sabi_config->commands.set_wireless_button, 0); | 482 | sabi_set_command(commands->set_wireless_button, 0); |
464 | else | 483 | else |
465 | sabi_set_command(sabi_config->commands.set_wireless_button, 1); | 484 | sabi_set_command(commands->set_wireless_button, 1); |
466 | 485 | ||
467 | return 0; | 486 | return 0; |
468 | } | 487 | } |
@@ -471,18 +490,18 @@ static struct rfkill_ops rfkill_ops = { | |||
471 | .set_block = rfkill_set, | 490 | .set_block = rfkill_set, |
472 | }; | 491 | }; |
473 | 492 | ||
474 | static int init_wireless(struct platform_device *sdev) | 493 | static int init_wireless(struct platform_device *pdev) |
475 | { | 494 | { |
476 | int retval; | 495 | int retval; |
477 | 496 | ||
478 | rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN, | 497 | samsung->rfk = rfkill_alloc("samsung-wifi", &samsung->pdev->dev, RFKILL_TYPE_WLAN, |
479 | &rfkill_ops, NULL); | 498 | &rfkill_ops, NULL); |
480 | if (!rfk) | 499 | if (!samsung->rfk) |
481 | return -ENOMEM; | 500 | return -ENOMEM; |
482 | 501 | ||
483 | retval = rfkill_register(rfk); | 502 | retval = rfkill_register(samsung->rfk); |
484 | if (retval) { | 503 | if (retval) { |
485 | rfkill_destroy(rfk); | 504 | rfkill_destroy(samsung->rfk); |
486 | return -ENODEV; | 505 | return -ENODEV; |
487 | } | 506 | } |
488 | 507 | ||
@@ -491,27 +510,28 @@ static int init_wireless(struct platform_device *sdev) | |||
491 | 510 | ||
492 | static void destroy_wireless(void) | 511 | static void destroy_wireless(void) |
493 | { | 512 | { |
494 | rfkill_unregister(rfk); | 513 | rfkill_unregister(samsung->rfk); |
495 | rfkill_destroy(rfk); | 514 | rfkill_destroy(samsung->rfk); |
496 | } | 515 | } |
497 | 516 | ||
498 | static ssize_t get_performance_level(struct device *dev, | 517 | static ssize_t get_performance_level(struct device *dev, |
499 | struct device_attribute *attr, char *buf) | 518 | struct device_attribute *attr, char *buf) |
500 | { | 519 | { |
520 | const struct sabi_config *config = samsung->config; | ||
501 | struct sabi_retval sretval; | 521 | struct sabi_retval sretval; |
502 | int retval; | 522 | int retval; |
503 | int i; | 523 | int i; |
504 | 524 | ||
505 | /* Read the state */ | 525 | /* Read the state */ |
506 | retval = sabi_get_command(sabi_config->commands.get_performance_level, | 526 | retval = sabi_get_command(config->commands.get_performance_level, |
507 | &sretval); | 527 | &sretval); |
508 | if (retval) | 528 | if (retval) |
509 | return retval; | 529 | return retval; |
510 | 530 | ||
511 | /* The logic is backwards, yeah, lots of fun... */ | 531 | /* The logic is backwards, yeah, lots of fun... */ |
512 | for (i = 0; sabi_config->performance_levels[i].name; ++i) { | 532 | for (i = 0; config->performance_levels[i].name; ++i) { |
513 | if (sretval.retval[0] == sabi_config->performance_levels[i].value) | 533 | if (sretval.retval[0] == config->performance_levels[i].value) |
514 | return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name); | 534 | return sprintf(buf, "%s\n", config->performance_levels[i].name); |
515 | } | 535 | } |
516 | return sprintf(buf, "%s\n", "unknown"); | 536 | return sprintf(buf, "%s\n", "unknown"); |
517 | } | 537 | } |
@@ -520,18 +540,20 @@ static ssize_t set_performance_level(struct device *dev, | |||
520 | struct device_attribute *attr, const char *buf, | 540 | struct device_attribute *attr, const char *buf, |
521 | size_t count) | 541 | size_t count) |
522 | { | 542 | { |
543 | const struct sabi_config *config = samsung->config; | ||
544 | |||
523 | if (count >= 1) { | 545 | if (count >= 1) { |
524 | int i; | 546 | int i; |
525 | for (i = 0; sabi_config->performance_levels[i].name; ++i) { | 547 | for (i = 0; config->performance_levels[i].name; ++i) { |
526 | const struct sabi_performance_level *level = | 548 | const struct sabi_performance_level *level = |
527 | &sabi_config->performance_levels[i]; | 549 | &config->performance_levels[i]; |
528 | if (!strncasecmp(level->name, buf, strlen(level->name))) { | 550 | if (!strncasecmp(level->name, buf, strlen(level->name))) { |
529 | sabi_set_command(sabi_config->commands.set_performance_level, | 551 | sabi_set_command(config->commands.set_performance_level, |
530 | level->value); | 552 | level->value); |
531 | break; | 553 | break; |
532 | } | 554 | } |
533 | } | 555 | } |
534 | if (!sabi_config->performance_levels[i].name) | 556 | if (!config->performance_levels[i].name) |
535 | return -EINVAL; | 557 | return -EINVAL; |
536 | } | 558 | } |
537 | return count; | 559 | return count; |
@@ -805,6 +827,9 @@ static int find_signature(void __iomem *memcheck, const char *testStr) | |||
805 | 827 | ||
806 | static int __init samsung_init(void) | 828 | static int __init samsung_init(void) |
807 | { | 829 | { |
830 | const struct sabi_config *config = NULL; | ||
831 | const struct sabi_commands *commands; | ||
832 | struct backlight_device *bd; | ||
808 | struct backlight_properties props; | 833 | struct backlight_properties props; |
809 | struct sabi_retval sretval; | 834 | struct sabi_retval sretval; |
810 | unsigned int ifaceP; | 835 | unsigned int ifaceP; |
@@ -812,21 +837,26 @@ static int __init samsung_init(void) | |||
812 | int loca; | 837 | int loca; |
813 | int retval; | 838 | int retval; |
814 | 839 | ||
815 | mutex_init(&sabi_mutex); | ||
816 | |||
817 | if (!force && !dmi_check_system(samsung_dmi_table)) | 840 | if (!force && !dmi_check_system(samsung_dmi_table)) |
818 | return -ENODEV; | 841 | return -ENODEV; |
819 | 842 | ||
820 | f0000_segment = ioremap_nocache(0xf0000, 0xffff); | 843 | samsung = kzalloc(sizeof(*samsung), GFP_KERNEL); |
821 | if (!f0000_segment) { | 844 | if (!samsung) |
845 | return -ENOMEM; | ||
846 | |||
847 | mutex_init(&samsung->sabi_mutex); | ||
848 | |||
849 | samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff); | ||
850 | if (!samsung->f0000_segment) { | ||
822 | pr_err("Can't map the segment at 0xf0000\n"); | 851 | pr_err("Can't map the segment at 0xf0000\n"); |
823 | return -EINVAL; | 852 | goto error_cant_map; |
824 | } | 853 | } |
825 | 854 | ||
826 | /* Try to find one of the signatures in memory to find the header */ | 855 | /* Try to find one of the signatures in memory to find the header */ |
827 | for (i = 0; sabi_configs[i].test_string != 0; ++i) { | 856 | for (i = 0; sabi_configs[i].test_string != 0; ++i) { |
828 | sabi_config = &sabi_configs[i]; | 857 | samsung->config = &sabi_configs[i]; |
829 | loca = find_signature(f0000_segment, sabi_config->test_string); | 858 | loca = find_signature(samsung->f0000_segment, |
859 | samsung->config->test_string); | ||
830 | if (loca != 0xffff) | 860 | if (loca != 0xffff) |
831 | break; | 861 | break; |
832 | } | 862 | } |
@@ -836,51 +866,60 @@ static int __init samsung_init(void) | |||
836 | goto error_no_signature; | 866 | goto error_no_signature; |
837 | } | 867 | } |
838 | 868 | ||
869 | config = samsung->config; | ||
870 | commands = &config->commands; | ||
871 | |||
839 | /* point to the SMI port Number */ | 872 | /* point to the SMI port Number */ |
840 | loca += 1; | 873 | loca += 1; |
841 | sabi = (f0000_segment + loca); | 874 | samsung->sabi = (samsung->f0000_segment + loca); |
842 | 875 | ||
843 | if (debug) { | 876 | if (debug) { |
844 | printk(KERN_DEBUG "This computer supports SABI==%x\n", | 877 | printk(KERN_DEBUG "This computer supports SABI==%x\n", |
845 | loca + 0xf0000 - 6); | 878 | loca + 0xf0000 - 6); |
846 | printk(KERN_DEBUG "SABI header:\n"); | 879 | printk(KERN_DEBUG "SABI header:\n"); |
847 | printk(KERN_DEBUG " SMI Port Number = 0x%04x\n", | 880 | printk(KERN_DEBUG " SMI Port Number = 0x%04x\n", |
848 | readw(sabi + sabi_config->header_offsets.port)); | 881 | readw(samsung->sabi + |
882 | config->header_offsets.port)); | ||
849 | printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n", | 883 | printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n", |
850 | readb(sabi + sabi_config->header_offsets.iface_func)); | 884 | readb(samsung->sabi + |
885 | config->header_offsets.iface_func)); | ||
851 | printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n", | 886 | printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n", |
852 | readb(sabi + sabi_config->header_offsets.en_mem)); | 887 | readb(samsung->sabi + |
888 | config->header_offsets.en_mem)); | ||
853 | printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n", | 889 | printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n", |
854 | readb(sabi + sabi_config->header_offsets.re_mem)); | 890 | readb(samsung->sabi + |
891 | config->header_offsets.re_mem)); | ||
855 | printk(KERN_DEBUG " SABI data offset = 0x%04x\n", | 892 | printk(KERN_DEBUG " SABI data offset = 0x%04x\n", |
856 | readw(sabi + sabi_config->header_offsets.data_offset)); | 893 | readw(samsung->sabi + |
894 | config->header_offsets.data_offset)); | ||
857 | printk(KERN_DEBUG " SABI data segment = 0x%04x\n", | 895 | printk(KERN_DEBUG " SABI data segment = 0x%04x\n", |
858 | readw(sabi + sabi_config->header_offsets.data_segment)); | 896 | readw(samsung->sabi + |
897 | config->header_offsets.data_segment)); | ||
859 | } | 898 | } |
860 | 899 | ||
861 | /* Get a pointer to the SABI Interface */ | 900 | /* Get a pointer to the SABI Interface */ |
862 | ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4; | 901 | ifaceP = (readw(samsung->sabi + config->header_offsets.data_segment) & 0x0ffff) << 4; |
863 | ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff; | 902 | ifaceP += readw(samsung->sabi + config->header_offsets.data_offset) & 0x0ffff; |
864 | sabi_iface = ioremap_nocache(ifaceP, 16); | 903 | samsung->sabi_iface = ioremap_nocache(ifaceP, 16); |
865 | if (!sabi_iface) { | 904 | if (!samsung->sabi_iface) { |
866 | pr_err("Can't remap %x\n", ifaceP); | 905 | pr_err("Can't remap %x\n", ifaceP); |
867 | goto error_no_signature; | 906 | goto error_no_signature; |
868 | } | 907 | } |
869 | if (debug) { | 908 | if (debug) { |
870 | printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP); | 909 | printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP); |
871 | printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface); | 910 | printk(KERN_DEBUG "sabi_iface = %p\n", samsung->sabi_iface); |
872 | 911 | ||
873 | test_backlight(); | 912 | test_backlight(); |
874 | test_wireless(); | 913 | test_wireless(); |
875 | 914 | ||
876 | retval = sabi_get_command(sabi_config->commands.get_brightness, | 915 | retval = sabi_get_command(commands->get_brightness, |
877 | &sretval); | 916 | &sretval); |
878 | printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]); | 917 | printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]); |
879 | } | 918 | } |
880 | 919 | ||
881 | /* Turn on "Linux" mode in the BIOS */ | 920 | /* Turn on "Linux" mode in the BIOS */ |
882 | if (sabi_config->commands.set_linux != 0xff) { | 921 | if (commands->set_linux != 0xff) { |
883 | retval = sabi_set_command(sabi_config->commands.set_linux, | 922 | retval = sabi_set_command(commands->set_linux, |
884 | 0x81); | 923 | 0x81); |
885 | if (retval) { | 924 | if (retval) { |
886 | pr_warn("Linux mode was not set!\n"); | 925 | pr_warn("Linux mode was not set!\n"); |
@@ -892,30 +931,32 @@ static int __init samsung_init(void) | |||
892 | check_for_stepping_quirk(); | 931 | check_for_stepping_quirk(); |
893 | 932 | ||
894 | /* knock up a platform device to hang stuff off of */ | 933 | /* knock up a platform device to hang stuff off of */ |
895 | sdev = platform_device_register_simple("samsung", -1, NULL, 0); | 934 | samsung->pdev = platform_device_register_simple("samsung", -1, NULL, 0); |
896 | if (IS_ERR(sdev)) | 935 | if (IS_ERR(samsung->pdev)) |
897 | goto error_no_platform; | 936 | goto error_no_platform; |
898 | 937 | ||
899 | /* create a backlight device to talk to this one */ | 938 | /* create a backlight device to talk to this one */ |
900 | memset(&props, 0, sizeof(struct backlight_properties)); | 939 | memset(&props, 0, sizeof(struct backlight_properties)); |
901 | props.type = BACKLIGHT_PLATFORM; | 940 | props.type = BACKLIGHT_PLATFORM; |
902 | props.max_brightness = sabi_config->max_brightness - | 941 | props.max_brightness = config->max_brightness - |
903 | sabi_config->min_brightness; | 942 | config->min_brightness; |
904 | backlight_device = backlight_device_register("samsung", &sdev->dev, | 943 | bd = backlight_device_register("samsung", &samsung->pdev->dev, |
905 | NULL, &backlight_ops, | 944 | NULL, &backlight_ops, |
906 | &props); | 945 | &props); |
907 | if (IS_ERR(backlight_device)) | 946 | if (IS_ERR(bd)) |
908 | goto error_no_backlight; | 947 | goto error_no_backlight; |
909 | 948 | ||
910 | backlight_device->props.brightness = read_brightness(); | 949 | samsung->backlight_device = bd; |
911 | backlight_device->props.power = FB_BLANK_UNBLANK; | 950 | samsung->backlight_device->props.brightness = read_brightness(); |
912 | backlight_update_status(backlight_device); | 951 | samsung->backlight_device->props.power = FB_BLANK_UNBLANK; |
952 | backlight_update_status(samsung->backlight_device); | ||
913 | 953 | ||
914 | retval = init_wireless(sdev); | 954 | retval = init_wireless(samsung->pdev); |
915 | if (retval) | 955 | if (retval) |
916 | goto error_no_rfk; | 956 | goto error_no_rfk; |
917 | 957 | ||
918 | retval = device_create_file(&sdev->dev, &dev_attr_performance_level); | 958 | retval = device_create_file(&samsung->pdev->dev, |
959 | &dev_attr_performance_level); | ||
919 | if (retval) | 960 | if (retval) |
920 | goto error_file_create; | 961 | goto error_file_create; |
921 | 962 | ||
@@ -925,31 +966,39 @@ error_file_create: | |||
925 | destroy_wireless(); | 966 | destroy_wireless(); |
926 | 967 | ||
927 | error_no_rfk: | 968 | error_no_rfk: |
928 | backlight_device_unregister(backlight_device); | 969 | backlight_device_unregister(samsung->backlight_device); |
929 | 970 | ||
930 | error_no_backlight: | 971 | error_no_backlight: |
931 | platform_device_unregister(sdev); | 972 | platform_device_unregister(samsung->pdev); |
932 | 973 | ||
933 | error_no_platform: | 974 | error_no_platform: |
934 | iounmap(sabi_iface); | 975 | iounmap(samsung->sabi_iface); |
935 | 976 | ||
936 | error_no_signature: | 977 | error_no_signature: |
937 | iounmap(f0000_segment); | 978 | iounmap(samsung->f0000_segment); |
979 | |||
980 | error_cant_map: | ||
981 | kfree(samsung); | ||
982 | samsung = NULL; | ||
938 | return -EINVAL; | 983 | return -EINVAL; |
939 | } | 984 | } |
940 | 985 | ||
941 | static void __exit samsung_exit(void) | 986 | static void __exit samsung_exit(void) |
942 | { | 987 | { |
988 | const struct sabi_commands *commands = &samsung->config->commands; | ||
989 | |||
943 | /* Turn off "Linux" mode in the BIOS */ | 990 | /* Turn off "Linux" mode in the BIOS */ |
944 | if (sabi_config->commands.set_linux != 0xff) | 991 | if (commands->set_linux != 0xff) |
945 | sabi_set_command(sabi_config->commands.set_linux, 0x80); | 992 | sabi_set_command(commands->set_linux, 0x80); |
946 | 993 | ||
947 | device_remove_file(&sdev->dev, &dev_attr_performance_level); | 994 | device_remove_file(&samsung->pdev->dev, &dev_attr_performance_level); |
948 | backlight_device_unregister(backlight_device); | 995 | backlight_device_unregister(samsung->backlight_device); |
949 | destroy_wireless(); | 996 | destroy_wireless(); |
950 | iounmap(sabi_iface); | 997 | iounmap(samsung->sabi_iface); |
951 | iounmap(f0000_segment); | 998 | iounmap(samsung->f0000_segment); |
952 | platform_device_unregister(sdev); | 999 | platform_device_unregister(samsung->pdev); |
1000 | kfree(samsung); | ||
1001 | samsung = NULL; | ||
953 | } | 1002 | } |
954 | 1003 | ||
955 | module_init(samsung_init); | 1004 | module_init(samsung_init); |