X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Facpi%2Fvideo.c;h=baa4419297209efd6d79aaedb2dae13c2d1a6f92;hb=9f15fc666ef54afc7aff31dfa31edecf00e0d81a;hp=eab9c4213b49625a800c42b581b0e6931cb9c39a;hpb=702ed512de9c8a67a69a981c73b7337c2131f198;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index eab9c42..baa4419 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -41,7 +41,6 @@ #include #include -#define ACPI_VIDEO_COMPONENT 0x08000000 #define ACPI_VIDEO_CLASS "video" #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" @@ -57,8 +56,6 @@ #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 -#define ACPI_VIDEO_HEAD_INVALID (~0u - 1) -#define ACPI_VIDEO_HEAD_END (~0u) #define MAX_NAME_LEN 20 #define ACPI_VIDEO_DISPLAY_CRT 1 @@ -73,8 +70,12 @@ MODULE_AUTHOR("Bruno Ducrot"); MODULE_DESCRIPTION("ACPI Video Driver"); MODULE_LICENSE("GPL"); +static int brightness_switch_enabled = 1; +module_param(brightness_switch_enabled, bool, 0644); + static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); +static int acpi_video_resume(struct acpi_device *device); static const struct acpi_device_id video_device_ids[] = { {ACPI_VIDEO_HID, 0}, @@ -89,6 +90,7 @@ static struct acpi_driver acpi_video_bus = { .ops = { .add = acpi_video_bus_add, .remove = acpi_video_bus_remove, + .resume = acpi_video_resume, }, }; @@ -187,6 +189,7 @@ struct acpi_video_device { /* bus */ static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_bus_info_fops = { + .owner = THIS_MODULE, .open = acpi_video_bus_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -195,6 +198,7 @@ static struct file_operations acpi_video_bus_info_fops = { static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_bus_ROM_fops = { + .owner = THIS_MODULE, .open = acpi_video_bus_ROM_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -204,6 +208,7 @@ static struct file_operations acpi_video_bus_ROM_fops = { static int acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_bus_POST_info_fops = { + .owner = THIS_MODULE, .open = acpi_video_bus_POST_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -212,6 +217,7 @@ static struct file_operations acpi_video_bus_POST_info_fops = { static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_bus_POST_fops = { + .owner = THIS_MODULE, .open = acpi_video_bus_POST_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -220,6 +226,7 @@ static struct file_operations acpi_video_bus_POST_fops = { static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_bus_DOS_fops = { + .owner = THIS_MODULE, .open = acpi_video_bus_DOS_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -230,6 +237,7 @@ static struct file_operations acpi_video_bus_DOS_fops = { static int acpi_video_device_info_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_device_info_fops = { + .owner = THIS_MODULE, .open = acpi_video_device_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -239,6 +247,7 @@ static struct file_operations acpi_video_device_info_fops = { static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_device_state_fops = { + .owner = THIS_MODULE, .open = acpi_video_device_state_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -248,6 +257,7 @@ static struct file_operations acpi_video_device_state_fops = { static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_device_brightness_fops = { + .owner = THIS_MODULE, .open = acpi_video_device_brightness_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -257,6 +267,7 @@ static struct file_operations acpi_video_device_brightness_fops = { static int acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_video_device_EDID_fops = { + .owner = THIS_MODULE, .open = acpi_video_device_EDID_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -275,37 +286,44 @@ static void acpi_video_device_rebind(struct acpi_video_bus *video); static void acpi_video_device_bind(struct acpi_video_bus *video, struct acpi_video_device *device); static int acpi_video_device_enumerate(struct acpi_video_bus *video); -static int acpi_video_switch_output(struct acpi_video_bus *video, int event); static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level); static int acpi_video_device_lcd_get_level_current( struct acpi_video_device *device, - unsigned long *level); + unsigned long long *level); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); static void acpi_video_switch_brightness(struct acpi_video_device *device, int event); static int acpi_video_device_get_state(struct acpi_video_device *device, - unsigned long *state); + unsigned long long *state); static int acpi_video_output_get(struct output_device *od); static int acpi_video_device_set_state(struct acpi_video_device *device, int state); /*backlight device sysfs support*/ static int acpi_video_get_brightness(struct backlight_device *bd) { - unsigned long cur_level; + unsigned long long cur_level; + int i; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); acpi_video_device_lcd_get_level_current(vd, &cur_level); - return (int) cur_level; + for (i = 2; i < vd->brightness->count; i++) { + if (vd->brightness->levels[i] == cur_level) + /* The first two entries are special - see page 575 + of the ACPI spec 3.0 */ + return i-2; + } + return 0; } static int acpi_video_set_brightness(struct backlight_device *bd) { - int request_level = bd->props.brightness; + int request_level = bd->props.brightness+2; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - acpi_video_device_lcd_set_level(vd, request_level); + acpi_video_device_lcd_set_level(vd, + vd->brightness->levels[request_level]); return 0; } @@ -317,7 +335,7 @@ static struct backlight_ops acpi_backlight_ops = { /*video output device sysfs support*/ static int acpi_video_output_get(struct output_device *od) { - unsigned long state; + unsigned long long state; struct acpi_video_device *vd = (struct acpi_video_device *)dev_get_drvdata(&od->dev); acpi_video_device_get_state(vd, &state); @@ -351,7 +369,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) { struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); - unsigned long level; + unsigned long long level; int state; acpi_video_device_lcd_get_level_current(video, &level); @@ -391,7 +409,7 @@ static struct thermal_cooling_device_ops video_cooling_ops = { /* device */ static int -acpi_video_device_query(struct acpi_video_device *device, unsigned long *state) +acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state) { int status; @@ -402,7 +420,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state) static int acpi_video_device_get_state(struct acpi_video_device *device, - unsigned long *state) + unsigned long long *state) { int status; @@ -417,7 +435,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state) int status; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; - unsigned long ret; + unsigned long long ret; arg0.integer.value = state; @@ -476,7 +494,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, - unsigned long *level) + unsigned long long *level) { if (device->cap._BQC) return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, @@ -530,7 +548,7 @@ static int acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) { int status; - unsigned long tmp; + unsigned long long tmp; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; @@ -545,7 +563,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) } static int -acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id) +acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) { int status; @@ -556,7 +574,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id) static int acpi_video_bus_POST_options(struct acpi_video_bus *video, - unsigned long *options) + unsigned long long *options) { int status; @@ -612,6 +630,76 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) * device : video output device (LCD, CRT, ..) * * Return Value: + * Maximum brightness level + * + * Allocate and initialize device->brightness. + */ + +static int +acpi_video_init_brightness(struct acpi_video_device *device) +{ + union acpi_object *obj = NULL; + int i, max_level = 0, count = 0; + union acpi_object *o; + struct acpi_video_device_brightness *br = NULL; + + if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " + "LCD brightness level\n")); + goto out; + } + + if (obj->package.count < 2) + goto out; + + br = kzalloc(sizeof(*br), GFP_KERNEL); + if (!br) { + printk(KERN_ERR "can't allocate memory\n"); + goto out; + } + + br->levels = kmalloc(obj->package.count * sizeof *(br->levels), + GFP_KERNEL); + if (!br->levels) + goto out_free; + + for (i = 0; i < obj->package.count; i++) { + o = (union acpi_object *)&obj->package.elements[i]; + if (o->type != ACPI_TYPE_INTEGER) { + printk(KERN_ERR PREFIX "Invalid data\n"); + continue; + } + br->levels[count] = (u32) o->integer.value; + + if (br->levels[count] > max_level) + max_level = br->levels[count]; + count++; + } + + if (count < 2) + goto out_free_levels; + + br->count = count; + device->brightness = br; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); + kfree(obj); + return max_level; + +out_free_levels: + kfree(br->levels); +out_free: + kfree(br); +out: + device->brightness = NULL; + kfree(obj); + return 0; +} + +/* + * Arg: + * device : video output device (LCD, CRT, ..) + * + * Return Value: * None * * Find out all required AML methods defined under the output @@ -621,10 +709,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) static void acpi_video_device_find_cap(struct acpi_video_device *device) { acpi_handle h_dummy1; - int i; u32 max_level = 0; - union acpi_object *obj = NULL; - struct acpi_video_device_brightness *br = NULL; memset(&device->cap, 0, sizeof(device->cap)); @@ -653,56 +738,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cap._DSS = 1; } - if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { - - if (obj->package.count >= 2) { - int count = 0; - union acpi_object *o; - - br = kzalloc(sizeof(*br), GFP_KERNEL); - if (!br) { - printk(KERN_ERR "can't allocate memory\n"); - } else { - br->levels = kmalloc(obj->package.count * - sizeof *(br->levels), GFP_KERNEL); - if (!br->levels) - goto out; - - for (i = 0; i < obj->package.count; i++) { - o = (union acpi_object *)&obj->package. - elements[i]; - if (o->type != ACPI_TYPE_INTEGER) { - printk(KERN_ERR PREFIX "Invalid data\n"); - continue; - } - br->levels[count] = (u32) o->integer.value; - - if (br->levels[count] > max_level) - max_level = br->levels[count]; - count++; - } - out: - if (count < 2) { - kfree(br->levels); - kfree(br); - } else { - br->count = count; - device->brightness = br; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "found %d brightness levels\n", - count)); - } - } - } + if (acpi_video_backlight_support()) + max_level = acpi_video_init_brightness(device); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n")); - } - - kfree(obj); - - if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ - unsigned long tmp; + if (device->cap._BCL && device->cap._BCM && max_level > 0) { int result; static int count = 0; char *name; @@ -711,44 +750,56 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) return; sprintf(name, "acpi_video%d", count++); - acpi_video_device_lcd_get_level_current(device, &tmp); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - device->backlight->props.max_brightness = max_level; - device->backlight->props.brightness = (int)tmp; + device->backlight->props.max_brightness = device->brightness->count-3; + /* + * If there exists the _BQC object, the _BQC object will be + * called to get the current backlight brightness. Otherwise + * the brightness will be set to the maximum. + */ + if (device->cap._BQC) + device->backlight->props.brightness = + acpi_video_get_brightness(device->backlight); + else + device->backlight->props.brightness = + device->backlight->props.max_brightness; backlight_update_status(device->backlight); kfree(name); device->cdev = thermal_cooling_device_register("LCD", device->dev, &video_cooling_ops); - if (device->cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev->dev.bus_id, device->cdev->id); - result = sysfs_create_link(&device->dev->dev.kobj, - &device->cdev->device.kobj, - "thermal_cooling"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cdev->device.kobj, - &device->dev->dev.kobj, - "device"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - } - } - if (device->cap._DCS && device->cap._DSS){ - static int count = 0; - char *name; - name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); - if (!name) + if (IS_ERR(device->cdev)) return; - sprintf(name, "acpi_video%d", count++); - device->output_dev = video_output_register(name, - NULL, device, &acpi_output_properties); - kfree(name); + + dev_info(&device->dev->dev, "registered as cooling_device%d\n", + device->cdev->id); + result = sysfs_create_link(&device->dev->dev.kobj, + &device->cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&device->cdev->device.kobj, + &device->dev->dev.kobj, "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + + } + + if (acpi_video_display_switch_support()) { + + if (device->cap._DCS && device->cap._DSS) { + static int count; + char *name; + name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); + if (!name) + return; + sprintf(name, "acpi_video%d", count++); + device->output_dev = video_output_register(name, + NULL, device, &acpi_output_properties); + kfree(name); + } } - return; } /* @@ -794,11 +845,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) static int acpi_video_bus_check(struct acpi_video_bus *video) { acpi_status status = -ENOENT; - + struct device *dev; if (!video) return -EINVAL; + dev = acpi_get_physical_pci_device(video->device->handle); + if (!dev) + return -ENODEV; + put_device(dev); + /* Since there is no HID, CID and so on for VGA driver, we have * to check well known required nodes. */ @@ -870,7 +926,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) { int status; struct acpi_video_device *dev = seq->private; - unsigned long state; + unsigned long long state; if (!dev) @@ -879,14 +935,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) status = acpi_video_device_get_state(dev, &state); seq_printf(seq, "state: "); if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02lx\n", state); + seq_printf(seq, "0x%02llx\n", state); else seq_printf(seq, "\n"); status = acpi_video_device_query(dev, &state); seq_printf(seq, "query: "); if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02lx\n", state); + seq_printf(seq, "0x%02llx\n", state); else seq_printf(seq, "\n"); @@ -1037,87 +1093,82 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) static int acpi_video_device_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *entry, *device_dir; struct acpi_video_device *vid_dev; - - if (!device) - return -ENODEV; - vid_dev = acpi_driver_data(device); if (!vid_dev) return -ENODEV; - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - vid_dev->video->dir); - if (!acpi_device_dir(device)) - return -ENODEV; - acpi_device_dir(device)->owner = THIS_MODULE; - } + device_dir = proc_mkdir(acpi_device_bid(device), + vid_dev->video->dir); + if (!device_dir) + return -ENOMEM; + + device_dir->owner = THIS_MODULE; /* 'info' [R] */ - entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); + entry = proc_create_data("info", S_IRUGO, device_dir, + &acpi_video_device_info_fops, acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_device_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_dir; /* 'state' [R/W] */ - entry = - create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); + acpi_video_device_state_fops.write = acpi_video_device_write_state; + entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR, + device_dir, + &acpi_video_device_state_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - acpi_video_device_state_fops.write = acpi_video_device_write_state; - entry->proc_fops = &acpi_video_device_state_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_info; /* 'brightness' [R/W] */ - entry = - create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); + acpi_video_device_brightness_fops.write = + acpi_video_device_write_brightness; + entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR, + device_dir, + &acpi_video_device_brightness_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness; - entry->proc_fops = &acpi_video_device_brightness_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_state; /* 'EDID' [R] */ - entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device)); + entry = proc_create_data("EDID", S_IRUGO, device_dir, + &acpi_video_device_EDID_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_device_EDID_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_brightness; + + acpi_device_dir(device) = device_dir; return 0; + + err_remove_brightness: + remove_proc_entry("brightness", device_dir); + err_remove_state: + remove_proc_entry("state", device_dir); + err_remove_info: + remove_proc_entry("info", device_dir); + err_remove_dir: + remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); + return -ENOMEM; } static int acpi_video_device_remove_fs(struct acpi_device *device) { struct acpi_video_device *vid_dev; + struct proc_dir_entry *device_dir; vid_dev = acpi_driver_data(device); if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) return -ENODEV; - if (acpi_device_dir(device)) { - remove_proc_entry("info", acpi_device_dir(device)); - remove_proc_entry("state", acpi_device_dir(device)); - remove_proc_entry("brightness", acpi_device_dir(device)); - remove_proc_entry("EDID", acpi_device_dir(device)); + device_dir = acpi_device_dir(device); + if (device_dir) { + remove_proc_entry("info", device_dir); + remove_proc_entry("state", device_dir); + remove_proc_entry("brightness", device_dir); + remove_proc_entry("EDID", device_dir); remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); acpi_device_dir(device) = NULL; } @@ -1159,7 +1210,7 @@ static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) if (!video) goto end; - printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__); + printk(KERN_INFO PREFIX "Please implement %s\n", __func__); seq_printf(seq, "\n"); end: @@ -1174,7 +1225,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) { struct acpi_video_bus *video = seq->private; - unsigned long options; + unsigned long long options; int status; @@ -1189,7 +1240,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) printk(KERN_WARNING PREFIX "This indicates a BIOS bug. Please contact the manufacturer.\n"); } - printk("%lx\n", options); + printk("%llx\n", options); seq_printf(seq, "can POST: "); if (options & 2) seq_printf(seq, " "); @@ -1213,7 +1264,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) { struct acpi_video_bus *video = seq->private; int status; - unsigned long id; + unsigned long long id; if (!video) @@ -1260,7 +1311,7 @@ acpi_video_bus_write_POST(struct file *file, struct seq_file *m = file->private_data; struct acpi_video_bus *video = m->private; char str[12] = { 0 }; - unsigned long opt, options; + unsigned long long opt, options; if (!video || count + 1 > sizeof str) @@ -1324,94 +1375,81 @@ acpi_video_bus_write_DOS(struct file *file, static int acpi_video_bus_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; - struct acpi_video_bus *video; + struct acpi_video_bus *video = acpi_driver_data(device); + struct proc_dir_entry *device_dir; + struct proc_dir_entry *entry; + device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); + if (!device_dir) + return -ENOMEM; - video = acpi_driver_data(device); - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_video_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - video->dir = acpi_device_dir(device); - acpi_device_dir(device)->owner = THIS_MODULE; - } + device_dir->owner = THIS_MODULE; /* 'info' [R] */ - entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); + entry = proc_create_data("info", S_IRUGO, device_dir, + &acpi_video_bus_info_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_dir; /* 'ROM' [R] */ - entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device)); + entry = proc_create_data("ROM", S_IRUGO, device_dir, + &acpi_video_bus_ROM_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_ROM_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_info; /* 'POST_info' [R] */ - entry = - create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device)); + entry = proc_create_data("POST_info", S_IRUGO, device_dir, + &acpi_video_bus_POST_info_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_POST_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_rom; /* 'POST' [R/W] */ - entry = - create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR, - acpi_device_dir(device)); + acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; + entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, + device_dir, + &acpi_video_bus_POST_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; - entry->proc_fops = &acpi_video_bus_POST_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_post_info; /* 'DOS' [R/W] */ - entry = - create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR, - acpi_device_dir(device)); + acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; + entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, + device_dir, + &acpi_video_bus_DOS_fops, + acpi_driver_data(device)); if (!entry) - return -ENODEV; - else { - acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; - entry->proc_fops = &acpi_video_bus_DOS_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_post; + video->dir = acpi_device_dir(device) = device_dir; return 0; + + err_remove_post: + remove_proc_entry("POST", device_dir); + err_remove_post_info: + remove_proc_entry("POST_info", device_dir); + err_remove_rom: + remove_proc_entry("ROM", device_dir); + err_remove_info: + remove_proc_entry("info", device_dir); + err_remove_dir: + remove_proc_entry(acpi_device_bid(device), acpi_video_dir); + return -ENOMEM; } static int acpi_video_bus_remove_fs(struct acpi_device *device) { - struct acpi_video_bus *video; - + struct proc_dir_entry *device_dir = acpi_device_dir(device); - video = acpi_driver_data(device); - - if (acpi_device_dir(device)) { - remove_proc_entry("info", acpi_device_dir(device)); - remove_proc_entry("ROM", acpi_device_dir(device)); - remove_proc_entry("POST_info", acpi_device_dir(device)); - remove_proc_entry("POST", acpi_device_dir(device)); - remove_proc_entry("DOS", acpi_device_dir(device)); + if (device_dir) { + remove_proc_entry("info", device_dir); + remove_proc_entry("ROM", device_dir); + remove_proc_entry("POST_info", device_dir); + remove_proc_entry("POST", device_dir); + remove_proc_entry("DOS", device_dir); remove_proc_entry(acpi_device_bid(device), acpi_video_dir); acpi_device_dir(device) = NULL; } @@ -1427,11 +1465,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) static struct acpi_video_device_attrib* acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) { - int count; + struct acpi_video_enumerated_device *ids; + int i; + + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if ((ids->value.int_val & 0xffff) == device_id) + return &ids->value.attrib; + } - for(count = 0; count < video->attached_count; count++) - if((video->attached_array[count].value.int_val & 0xffff) == device_id) - return &(video->attached_array[count].value.attrib); return NULL; } @@ -1439,7 +1481,7 @@ static int acpi_video_bus_get_one_device(struct acpi_device *device, struct acpi_video_bus *video) { - unsigned long device_id; + unsigned long long device_id; int status; struct acpi_video_device *data; struct acpi_video_device_attrib* attribute; @@ -1457,7 +1499,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device, strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - acpi_driver_data(device) = data; + device->driver_data = data; data->device_id = device_id; data->video = video; @@ -1496,8 +1538,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, acpi_video_device_notify, data); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); + printk(KERN_ERR PREFIX + "Error installing notify handler\n"); if(data->brightness) kfree(data->brightness->levels); kfree(data->brightness); @@ -1558,20 +1600,16 @@ static void acpi_video_device_bind(struct acpi_video_bus *video, struct acpi_video_device *device) { + struct acpi_video_enumerated_device *ids; int i; -#define IDS_VAL(i) video->attached_array[i].value.int_val -#define IDS_BIND(i) video->attached_array[i].bind_info - - for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID && - i < video->attached_count; i++) { - if (device->device_id == (IDS_VAL(i) & 0xffff)) { - IDS_BIND(i) = device; + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if (device->device_id == (ids->value.int_val & 0xffff)) { + ids->bind_info = device; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); } } -#undef IDS_VAL -#undef IDS_BIND } /* @@ -1590,7 +1628,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) int status; int count; int i; - struct acpi_video_enumerated_device *active_device_list; + struct acpi_video_enumerated_device *active_list; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *dod = NULL; union acpi_object *obj; @@ -1611,13 +1649,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", dod->package.count)); - active_device_list = kmalloc((1 + - dod->package.count) * - sizeof(struct - acpi_video_enumerated_device), - GFP_KERNEL); - - if (!active_device_list) { + active_list = kcalloc(1 + dod->package.count, + sizeof(struct acpi_video_enumerated_device), + GFP_KERNEL); + if (!active_list) { status = -ENOMEM; goto out; } @@ -1627,82 +1662,25 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) obj = &dod->package.elements[i]; if (obj->type != ACPI_TYPE_INTEGER) { - printk(KERN_ERR PREFIX "Invalid _DOD data\n"); - active_device_list[i].value.int_val = - ACPI_VIDEO_HEAD_INVALID; + printk(KERN_ERR PREFIX + "Invalid _DOD data in element %d\n", i); + continue; } - active_device_list[i].value.int_val = obj->integer.value; - active_device_list[i].bind_info = NULL; + + active_list[count].value.int_val = obj->integer.value; + active_list[count].bind_info = NULL; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int)obj->integer.value)); count++; } - active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END; kfree(video->attached_array); - video->attached_array = active_device_list; + video->attached_array = active_list; video->attached_count = count; - out: - kfree(buffer.pointer); - return status; -} - -/* - * Arg: - * video : video bus device - * event : notify event - * - * Return: - * < 0 : error - * - * 1. Find out the current active output device. - * 2. Identify the next output device to switch to. - * 3. call _DSS to do actual switch. - */ - -static int acpi_video_switch_output(struct acpi_video_bus *video, int event) -{ - struct list_head *node; - struct acpi_video_device *dev = NULL; - struct acpi_video_device *dev_next = NULL; - struct acpi_video_device *dev_prev = NULL; - unsigned long state; - int status = 0; - - mutex_lock(&video->device_list_lock); - - list_for_each(node, &video->video_device_list) { - dev = container_of(node, struct acpi_video_device, entry); - status = acpi_video_device_get_state(dev, &state); - if (state & 0x2) { - dev_next = container_of(node->next, - struct acpi_video_device, entry); - dev_prev = container_of(node->prev, - struct acpi_video_device, entry); - goto out; - } - } - - dev_next = container_of(node->next, struct acpi_video_device, entry); - dev_prev = container_of(node->prev, struct acpi_video_device, entry); out: - mutex_unlock(&video->device_list_lock); - - switch (event) { - case ACPI_VIDEO_NOTIFY_CYCLE: - case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: - acpi_video_device_set_state(dev, 0); - acpi_video_device_set_state(dev_next, 0x80000001); - break; - case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: - acpi_video_device_set_state(dev, 0); - acpi_video_device_set_state(dev_prev, 0x80000001); - default: - break; - } - + kfree(buffer.pointer); return status; } @@ -1754,7 +1732,9 @@ acpi_video_get_next_level(struct acpi_video_device *device, static void acpi_video_switch_brightness(struct acpi_video_device *device, int event) { - unsigned long level_current, level_next; + unsigned long long level_current, level_next; + if (!device->brightness) + return; acpi_video_device_lcd_get_level_current(device, &level_current); level_next = acpi_video_get_next_level(device, level_current, event); acpi_video_device_lcd_set_level(device, level_next); @@ -1773,7 +1753,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, status = acpi_video_bus_get_one_device(dev, video); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); + printk(KERN_WARNING PREFIX + "Cant attach device"); continue; } } @@ -1873,23 +1854,19 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) * connector. */ acpi_video_device_enumerate(video); acpi_video_device_rebind(video); - acpi_video_switch_output(video, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_SWITCHVIDEOMODE; break; case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ - acpi_video_switch_output(video, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_SWITCHVIDEOMODE; break; case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ - acpi_video_switch_output(video, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_VIDEO_NEXT; break; case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ - acpi_video_switch_output(video, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_VIDEO_PREV; break; @@ -1901,6 +1878,7 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) break; } + acpi_notifier_call_chain(device, event, 0); input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); @@ -1926,27 +1904,32 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESS_CYCLE; break; case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESSUP; break; case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESSDOWN; break; case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESS_ZERO; break; case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_DISPLAY_OFF; break; @@ -1957,6 +1940,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) break; } + acpi_notifier_call_chain(device, event, 0); input_report_key(input, keycode, 1); input_sync(input); input_report_key(input, keycode, 0); @@ -1966,6 +1950,25 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) } static int instance; +static int acpi_video_resume(struct acpi_device *device) +{ + struct acpi_video_bus *video; + struct acpi_video_device *video_device; + int i; + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + video = acpi_driver_data(device); + + for (i = 0; i < video->attached_count; i++) { + video_device = video->attached_array[i].bind_info; + if (video_device && video_device->backlight) + acpi_video_set_brightness(video_device->backlight); + } + return AE_OK; +} + static int acpi_video_bus_add(struct acpi_device *device) { acpi_status status; @@ -1987,7 +1990,7 @@ static int acpi_video_bus_add(struct acpi_device *device) video->device = device; strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - acpi_driver_data(device) = video; + device->driver_data = video; acpi_video_bus_find_cap(video); error = acpi_video_bus_check(video); @@ -2008,8 +2011,8 @@ static int acpi_video_bus_add(struct acpi_device *device) ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); + printk(KERN_ERR PREFIX + "Error installing notify handler\n"); error = -ENODEV; goto err_stop_video; } @@ -2063,7 +2066,7 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_video_bus_remove_fs(device); err_free_video: kfree(video); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return error; } @@ -2099,12 +2102,6 @@ static int __init acpi_video_init(void) { int result = 0; - - /* - acpi_dbg_level = 0xFFFFFFFF; - acpi_dbg_layer = 0x08000000; - */ - acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); if (!acpi_video_dir) return -ENODEV;