aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
authorMario Limonciello <mario_limonciello@dell.com>2014-05-07 16:08:10 -0400
committerMatthew Garrett <matthew.garrett@nebula.com>2014-06-10 19:04:17 -0400
commitbc2ef884320bdca8d2544d517ac5489bb1722896 (patch)
tree7b5555ad81590a3089a185aae941f591c5c9b43b /drivers/platform/x86
parentb998680e9adea22159b66bd59ecdf07624e201ed (diff)
alienware-wmi: For WMAX HDMI method, introduce a way to query HDMI cable status
Since there are now multiple HDMI attributes associated with the WMAX method, create a sysfs group for them instead. Signed-off-by: Mario Limonciello <mario_limonciello@dell.com> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/alienware-wmi.c118
1 files changed, 88 insertions, 30 deletions
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c
index e5329eac86b7..297b6640213f 100644
--- a/drivers/platform/x86/alienware-wmi.c
+++ b/drivers/platform/x86/alienware-wmi.c
@@ -32,6 +32,7 @@
32#define WMAX_METHOD_HDMI_STATUS 0x2 32#define WMAX_METHOD_HDMI_STATUS 0x2
33#define WMAX_METHOD_BRIGHTNESS 0x3 33#define WMAX_METHOD_BRIGHTNESS 0x3
34#define WMAX_METHOD_ZONE_CONTROL 0x4 34#define WMAX_METHOD_ZONE_CONTROL 0x4
35#define WMAX_METHOD_HDMI_CABLE 0x5
35 36
36MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>"); 37MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>");
37MODULE_DESCRIPTION("Alienware special feature control"); 38MODULE_DESCRIPTION("Alienware special feature control");
@@ -422,41 +423,85 @@ static void alienware_zone_exit(struct platform_device *dev)
422 The HDMI mux sysfs node indicates the status of the HDMI input mux. 423 The HDMI mux sysfs node indicates the status of the HDMI input mux.
423 It can toggle between standard system GPU output and HDMI input. 424 It can toggle between standard system GPU output and HDMI input.
424*/ 425*/
425static ssize_t show_hdmi(struct device *dev, struct device_attribute *attr, 426static acpi_status alienware_hdmi_command(struct hdmi_args *in_args,
426 char *buf) 427 u32 command, int *out_data)
427{ 428{
428 acpi_status status; 429 acpi_status status;
429 struct acpi_buffer input;
430 union acpi_object *obj; 430 union acpi_object *obj;
431 u32 tmp = 0; 431 struct acpi_buffer input;
432 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 432 struct acpi_buffer output;
433
434 input.length = (acpi_size) sizeof(*in_args);
435 input.pointer = in_args;
436 if (out_data != NULL) {
437 output.length = ACPI_ALLOCATE_BUFFER;
438 output.pointer = NULL;
439 status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
440 command, &input, &output);
441 } else
442 status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
443 command, &input, NULL);
444
445 if (ACPI_SUCCESS(status) && out_data != NULL) {
446 obj = (union acpi_object *)output.pointer;
447 if (obj && obj->type == ACPI_TYPE_INTEGER)
448 *out_data = (u32) obj->integer.value;
449 }
450 return status;
451
452}
453
454static ssize_t show_hdmi_cable(struct device *dev,
455 struct device_attribute *attr, char *buf)
456{
457 acpi_status status;
458 u32 out_data;
433 struct hdmi_args in_args = { 459 struct hdmi_args in_args = {
434 .arg = 0, 460 .arg = 0,
435 }; 461 };
436 input.length = (acpi_size) sizeof(in_args); 462 status =
437 input.pointer = &in_args; 463 alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_CABLE,
438 status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, 464 (u32 *) &out_data);
439 WMAX_METHOD_HDMI_STATUS, &input, &output); 465 if (ACPI_SUCCESS(status)) {
466 if (out_data == 0)
467 return scnprintf(buf, PAGE_SIZE,
468 "[unconnected] connected unknown\n");
469 else if (out_data == 1)
470 return scnprintf(buf, PAGE_SIZE,
471 "unconnected [connected] unknown\n");
472 }
473 pr_err("alienware-wmi: unknown HDMI cable status: %d\n", status);
474 return scnprintf(buf, PAGE_SIZE, "unconnected connected [unknown]\n");
475}
476
477static ssize_t show_hdmi_source(struct device *dev,
478 struct device_attribute *attr, char *buf)
479{
480 acpi_status status;
481 u32 out_data;
482 struct hdmi_args in_args = {
483 .arg = 0,
484 };
485 status =
486 alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_STATUS,
487 (u32 *) &out_data);
440 488
441 if (ACPI_SUCCESS(status)) { 489 if (ACPI_SUCCESS(status)) {
442 obj = (union acpi_object *)output.pointer; 490 if (out_data == 1)
443 if (obj && obj->type == ACPI_TYPE_INTEGER)
444 tmp = (u32) obj->integer.value;
445 if (tmp == 1)
446 return scnprintf(buf, PAGE_SIZE, 491 return scnprintf(buf, PAGE_SIZE,
447 "[input] gpu unknown\n"); 492 "[input] gpu unknown\n");
448 else if (tmp == 2) 493 else if (out_data == 2)
449 return scnprintf(buf, PAGE_SIZE, 494 return scnprintf(buf, PAGE_SIZE,
450 "input [gpu] unknown\n"); 495 "input [gpu] unknown\n");
451 } 496 }
452 pr_err("alienware-wmi: unknown HDMI status: %d\n", status); 497 pr_err("alienware-wmi: unknown HDMI source status: %d\n", out_data);
453 return scnprintf(buf, PAGE_SIZE, "input gpu [unknown]\n"); 498 return scnprintf(buf, PAGE_SIZE, "input gpu [unknown]\n");
454} 499}
455 500
456static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr, 501static ssize_t toggle_hdmi_source(struct device *dev,
457 const char *buf, size_t count) 502 struct device_attribute *attr,
503 const char *buf, size_t count)
458{ 504{
459 struct acpi_buffer input;
460 acpi_status status; 505 acpi_status status;
461 struct hdmi_args args; 506 struct hdmi_args args;
462 if (strcmp(buf, "gpu\n") == 0) 507 if (strcmp(buf, "gpu\n") == 0)
@@ -466,33 +511,46 @@ static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr,
466 else 511 else
467 args.arg = 3; 512 args.arg = 3;
468 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); 513 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
469 input.length = (acpi_size) sizeof(args); 514
470 input.pointer = &args; 515 status = alienware_hdmi_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL);
471 status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, 516
472 WMAX_METHOD_HDMI_SOURCE, &input, NULL);
473 if (ACPI_FAILURE(status)) 517 if (ACPI_FAILURE(status))
474 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", 518 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n",
475 status); 519 status);
476 return count; 520 return count;
477} 521}
478 522
479static DEVICE_ATTR(hdmi, S_IRUGO | S_IWUSR, show_hdmi, toggle_hdmi); 523static DEVICE_ATTR(cable, S_IRUGO, show_hdmi_cable, NULL);
524static DEVICE_ATTR(source, S_IRUGO | S_IWUSR, show_hdmi_source,
525 toggle_hdmi_source);
526
527static struct attribute *hdmi_attrs[] = {
528 &dev_attr_cable.attr,
529 &dev_attr_source.attr,
530 NULL,
531};
480 532
481static void remove_hdmi(struct platform_device *device) 533static struct attribute_group hdmi_attribute_group = {
534 .name = "hdmi",
535 .attrs = hdmi_attrs,
536};
537
538static void remove_hdmi(struct platform_device *dev)
482{ 539{
483 device_remove_file(&device->dev, &dev_attr_hdmi); 540 sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group);
484} 541}
485 542
486static int create_hdmi(void) 543static int create_hdmi(struct platform_device *dev)
487{ 544{
488 int ret = -ENOMEM; 545 int ret;
489 ret = device_create_file(&platform_device->dev, &dev_attr_hdmi); 546
547 ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group);
490 if (ret) 548 if (ret)
491 goto error_create_hdmi; 549 goto error_create_hdmi;
492 return 0; 550 return 0;
493 551
494error_create_hdmi: 552error_create_hdmi:
495 remove_hdmi(platform_device); 553 remove_hdmi(dev);
496 return ret; 554 return ret;
497} 555}
498 556
@@ -526,7 +584,7 @@ static int __init alienware_wmi_init(void)
526 goto fail_platform_device2; 584 goto fail_platform_device2;
527 585
528 if (interface == WMAX) { 586 if (interface == WMAX) {
529 ret = create_hdmi(); 587 ret = create_hdmi(platform_device);
530 if (ret) 588 if (ret)
531 goto fail_prep_hdmi; 589 goto fail_prep_hdmi;
532 } 590 }