Subject: [PATCH] [acpi video] Add helper for enumerating devices on the video bus - Add enumerate_bus() and call from video_bus_init() - Add helpers to assist that function - get_int_array() to get a list of ints from a package - get_package() to simply extract a package Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/video/bus-device.c | 99 +++++++++++++++++++++++++++++++ 1 files changed, 99 insertions(+), 0 deletions(-) applies-to: c3b9c5bc31cf92ab815f641fdcb534a2be680d18 f3d125468a74a1abd2eecd19fcdbc6a9eacae680 diff --git a/drivers/acpi/drivers/video/bus-device.c b/drivers/acpi/drivers/video/bus-device.c index b7e48de..c9dbd7b 100644 --- a/drivers/acpi/drivers/video/bus-device.c +++ b/drivers/acpi/drivers/video/bus-device.c @@ -67,6 +67,71 @@ static int set_int(struct acpi_dev * ad, } +static int get_package(struct acpi_dev * ad, char * method, + union acpi_object ** package) +{ + struct acpi_buffer buffer = { + .length = ACPI_ALLOCATE_BUFFER, + }; + union acpi_object * obj; + acpi_status status; + + status = acpi_evaluate_object(ad->acpi_device->handle, + method, NULL, &buffer); + if (ACPI_FAILURE(status)) { + err("Evaluating %s", method); + return -ENODEV; + } + + obj = buffer.pointer; + if (!(obj && obj->type == ACPI_TYPE_PACKAGE)) { + err("Invalid %s data", method); + kfree(buffer.pointer); + return -EFAULT; + } + *package = obj; + return 0; +} + +static int get_int_array(struct acpi_dev * ad, char * method, + u32 * values, u32 * num) +{ + union acpi_object * package; + int ret; + int i; + + /* + * Get the package from the namespace + */ + ret = get_package(ad, method, &package); + if (ret) + return ret; + + /* + * Modify the count, based on passed limits + */ + if (package->package.count <= *num) + *num = package->package.count; + else + err("Ignoring elements from %s: Have room for %d, need %d", + method, *num, package->package.count); + + /* + * Fill the array with the package contents + */ + for (i = 0; i < *num; i++) { + union acpi_object * o = &package->package.elements[i]; + + if (o->type != ACPI_TYPE_INTEGER) { + err("Invalid %s data at [%d]", method, i); + } + values[i] = o->integer.value; + } + kfree(package); + return 0; +} + + /** * can_switch - Check if a video bus supports video switching * @ad: The ACPI device representing the video bus @@ -254,6 +319,36 @@ static int get_post_info(struct acpi_vid } +/** + * enumerate_bus - Discover and count video devices for a bus + * @vb: The ACPI video bus + * + * + * NOTE: The ACPI spec implies that a maximum of 8 devices can be + * attached to a video bus (based on the fact that they reserve + * 3 bits for the "head/pipe ID" field in the video device attribute. + * Having 8 attached displays seems unlikely in 2006, but it is a + * hard-coded limit in the future when we all have 64 monitors plugged + * into our laptops.. + */ + +static int enumerate_bus(struct acpi_video_bus * vb) +{ + u32 dod_values[VIDEO_DEVICE_MAX]; + int ret; + int i; + + ret = get_int_array(vb->v_ad, "_DOD", dod_values, &vb->v_dev_num); + if (ret) + return ret; + + dbg("Found %d video heads in _DOD", vb->v_dev_num); + + for (i = 0; i < vb->v_dev_num; i++) + vb->v_dev[i].v_attrib = dod_values[i]; + return 0; +} + int video_bus_init(struct acpi_video_bus * vb) { int ret = 0; @@ -279,6 +374,10 @@ int video_bus_init(struct acpi_video_bus return ret; } + if (vb->v_can_switch) { + ret = enumerate_bus(vb); + } + return ret; } --- 0.99.9.GIT