Commit bc2ef884 authored by Mario Limonciello's avatar Mario Limonciello Committed by Matthew Garrett

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: default avatarMario Limonciello <mario_limonciello@dell.com>
Signed-off-by: default avatarMatthew Garrett <matthew.garrett@nebula.com>
parent b998680e
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define WMAX_METHOD_HDMI_STATUS 0x2 #define WMAX_METHOD_HDMI_STATUS 0x2
#define WMAX_METHOD_BRIGHTNESS 0x3 #define WMAX_METHOD_BRIGHTNESS 0x3
#define WMAX_METHOD_ZONE_CONTROL 0x4 #define WMAX_METHOD_ZONE_CONTROL 0x4
#define WMAX_METHOD_HDMI_CABLE 0x5
MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>"); MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>");
MODULE_DESCRIPTION("Alienware special feature control"); MODULE_DESCRIPTION("Alienware special feature control");
...@@ -422,41 +423,85 @@ static void alienware_zone_exit(struct platform_device *dev) ...@@ -422,41 +423,85 @@ static void alienware_zone_exit(struct platform_device *dev)
The HDMI mux sysfs node indicates the status of the HDMI input mux. The HDMI mux sysfs node indicates the status of the HDMI input mux.
It can toggle between standard system GPU output and HDMI input. It can toggle between standard system GPU output and HDMI input.
*/ */
static ssize_t show_hdmi(struct device *dev, struct device_attribute *attr, static acpi_status alienware_hdmi_command(struct hdmi_args *in_args,
char *buf) u32 command, int *out_data)
{ {
acpi_status status; acpi_status status;
struct acpi_buffer input;
union acpi_object *obj; union acpi_object *obj;
u32 tmp = 0; struct acpi_buffer input;
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer output;
input.length = (acpi_size) sizeof(*in_args);
input.pointer = in_args;
if (out_data != NULL) {
output.length = ACPI_ALLOCATE_BUFFER;
output.pointer = NULL;
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
command, &input, &output);
} else
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
command, &input, NULL);
if (ACPI_SUCCESS(status) && out_data != NULL) {
obj = (union acpi_object *)output.pointer;
if (obj && obj->type == ACPI_TYPE_INTEGER)
*out_data = (u32) obj->integer.value;
}
return status;
}
static ssize_t show_hdmi_cable(struct device *dev,
struct device_attribute *attr, char *buf)
{
acpi_status status;
u32 out_data;
struct hdmi_args in_args = { struct hdmi_args in_args = {
.arg = 0, .arg = 0,
}; };
input.length = (acpi_size) sizeof(in_args); status =
input.pointer = &in_args; alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_CABLE,
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, (u32 *) &out_data);
WMAX_METHOD_HDMI_STATUS, &input, &output); if (ACPI_SUCCESS(status)) {
if (out_data == 0)
return scnprintf(buf, PAGE_SIZE,
"[unconnected] connected unknown\n");
else if (out_data == 1)
return scnprintf(buf, PAGE_SIZE,
"unconnected [connected] unknown\n");
}
pr_err("alienware-wmi: unknown HDMI cable status: %d\n", status);
return scnprintf(buf, PAGE_SIZE, "unconnected connected [unknown]\n");
}
static ssize_t show_hdmi_source(struct device *dev,
struct device_attribute *attr, char *buf)
{
acpi_status status;
u32 out_data;
struct hdmi_args in_args = {
.arg = 0,
};
status =
alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_STATUS,
(u32 *) &out_data);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
obj = (union acpi_object *)output.pointer; if (out_data == 1)
if (obj && obj->type == ACPI_TYPE_INTEGER)
tmp = (u32) obj->integer.value;
if (tmp == 1)
return scnprintf(buf, PAGE_SIZE, return scnprintf(buf, PAGE_SIZE,
"[input] gpu unknown\n"); "[input] gpu unknown\n");
else if (tmp == 2) else if (out_data == 2)
return scnprintf(buf, PAGE_SIZE, return scnprintf(buf, PAGE_SIZE,
"input [gpu] unknown\n"); "input [gpu] unknown\n");
} }
pr_err("alienware-wmi: unknown HDMI status: %d\n", status); pr_err("alienware-wmi: unknown HDMI source status: %d\n", out_data);
return scnprintf(buf, PAGE_SIZE, "input gpu [unknown]\n"); return scnprintf(buf, PAGE_SIZE, "input gpu [unknown]\n");
} }
static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr, static ssize_t toggle_hdmi_source(struct device *dev,
const char *buf, size_t count) struct device_attribute *attr,
const char *buf, size_t count)
{ {
struct acpi_buffer input;
acpi_status status; acpi_status status;
struct hdmi_args args; struct hdmi_args args;
if (strcmp(buf, "gpu\n") == 0) if (strcmp(buf, "gpu\n") == 0)
...@@ -466,33 +511,46 @@ static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr, ...@@ -466,33 +511,46 @@ static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr,
else else
args.arg = 3; args.arg = 3;
pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
input.length = (acpi_size) sizeof(args);
input.pointer = &args; status = alienware_hdmi_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL);
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
WMAX_METHOD_HDMI_SOURCE, &input, NULL);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", pr_err("alienware-wmi: HDMI toggle failed: results: %u\n",
status); status);
return count; return count;
} }
static DEVICE_ATTR(hdmi, S_IRUGO | S_IWUSR, show_hdmi, toggle_hdmi); static DEVICE_ATTR(cable, S_IRUGO, show_hdmi_cable, NULL);
static DEVICE_ATTR(source, S_IRUGO | S_IWUSR, show_hdmi_source,
toggle_hdmi_source);
static struct attribute *hdmi_attrs[] = {
&dev_attr_cable.attr,
&dev_attr_source.attr,
NULL,
};
static void remove_hdmi(struct platform_device *device) static struct attribute_group hdmi_attribute_group = {
.name = "hdmi",
.attrs = hdmi_attrs,
};
static void remove_hdmi(struct platform_device *dev)
{ {
device_remove_file(&device->dev, &dev_attr_hdmi); sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group);
} }
static int create_hdmi(void) static int create_hdmi(struct platform_device *dev)
{ {
int ret = -ENOMEM; int ret;
ret = device_create_file(&platform_device->dev, &dev_attr_hdmi);
ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group);
if (ret) if (ret)
goto error_create_hdmi; goto error_create_hdmi;
return 0; return 0;
error_create_hdmi: error_create_hdmi:
remove_hdmi(platform_device); remove_hdmi(dev);
return ret; return ret;
} }
...@@ -526,7 +584,7 @@ static int __init alienware_wmi_init(void) ...@@ -526,7 +584,7 @@ static int __init alienware_wmi_init(void)
goto fail_platform_device2; goto fail_platform_device2;
if (interface == WMAX) { if (interface == WMAX) {
ret = create_hdmi(); ret = create_hdmi(platform_device);
if (ret) if (ret)
goto fail_prep_hdmi; goto fail_prep_hdmi;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment