diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 01bed937d387..f15a58f7403f 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -3000,12 +3000,16 @@ static struct backlight_ops ibm_backlight_data = { | |||
3000 | .update_status = brightness_update_status, | 3000 | .update_status = brightness_update_status, |
3001 | }; | 3001 | }; |
3002 | 3002 | ||
3003 | static struct mutex brightness_mutex; | ||
3004 | |||
3003 | static int __init brightness_init(struct ibm_init_struct *iibm) | 3005 | static int __init brightness_init(struct ibm_init_struct *iibm) |
3004 | { | 3006 | { |
3005 | int b; | 3007 | int b; |
3006 | 3008 | ||
3007 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); | 3009 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); |
3008 | 3010 | ||
3011 | mutex_init(&brightness_mutex); | ||
3012 | |||
3009 | if (!brightness_mode) { | 3013 | if (!brightness_mode) { |
3010 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) | 3014 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) |
3011 | brightness_mode = 2; | 3015 | brightness_mode = 2; |
@@ -3092,27 +3096,44 @@ static int brightness_get(struct backlight_device *bd) | |||
3092 | 3096 | ||
3093 | static int brightness_set(int value) | 3097 | static int brightness_set(int value) |
3094 | { | 3098 | { |
3095 | int cmos_cmd, inc, i; | 3099 | int cmos_cmd, inc, i, res; |
3096 | int current_value = brightness_get(NULL); | 3100 | int current_value; |
3097 | 3101 | ||
3098 | if (value > 7) | 3102 | if (value > 7) |
3099 | return -EINVAL; | 3103 | return -EINVAL; |
3100 | 3104 | ||
3105 | res = mutex_lock_interruptible(&brightness_mutex); | ||
3106 | if (res < 0) | ||
3107 | return res; | ||
3108 | |||
3109 | current_value = brightness_get(NULL); | ||
3110 | if (current_value < 0) { | ||
3111 | res = current_value; | ||
3112 | goto errout; | ||
3113 | } | ||
3114 | |||
3101 | cmos_cmd = value > current_value ? | 3115 | cmos_cmd = value > current_value ? |
3102 | TP_CMOS_BRIGHTNESS_UP : | 3116 | TP_CMOS_BRIGHTNESS_UP : |
3103 | TP_CMOS_BRIGHTNESS_DOWN; | 3117 | TP_CMOS_BRIGHTNESS_DOWN; |
3104 | inc = value > current_value ? 1 : -1; | 3118 | inc = value > current_value ? 1 : -1; |
3105 | 3119 | ||
3120 | res = 0; | ||
3106 | for (i = current_value; i != value; i += inc) { | 3121 | for (i = current_value; i != value; i += inc) { |
3107 | if ((brightness_mode & 2) && | 3122 | if ((brightness_mode & 2) && |
3108 | issue_thinkpad_cmos_command(cmos_cmd)) | 3123 | issue_thinkpad_cmos_command(cmos_cmd)) { |
3109 | return -EIO; | 3124 | res = -EIO; |
3125 | goto errout; | ||
3126 | } | ||
3110 | if ((brightness_mode & 1) && | 3127 | if ((brightness_mode & 1) && |
3111 | !acpi_ec_write(brightness_offset, i + inc)) | 3128 | !acpi_ec_write(brightness_offset, i + inc)) { |
3112 | return -EIO; | 3129 | res = -EIO; |
3130 | goto errout;; | ||
3131 | } | ||
3113 | } | 3132 | } |
3114 | 3133 | ||
3115 | return 0; | 3134 | errout: |
3135 | mutex_unlock(&brightness_mutex); | ||
3136 | return res; | ||
3116 | } | 3137 | } |
3117 | 3138 | ||
3118 | static int brightness_read(char *p) | 3139 | static int brightness_read(char *p) |