Commit aa33924f authored by Marco Chiappero's avatar Marco Chiappero Committed by Matthew Garrett

sony-laptop: new keyboard backlight handle

Add support for handle 0x0143 (Vaio SA/SB/SC, CA/CB) and rework the code
to be hable to support different handles for the keyboard backlight
function.

[malattia@linux.it: group function specific variables in a struct]
Signed-off-by: default avatarMarco Chiappero <marco@absence.it>
Signed-off-by: default avatarMattia Dongili <malattia@linux.it>
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
parent 88bf1706
...@@ -141,8 +141,9 @@ MODULE_PARM_DESC(kbd_backlight_timeout, ...@@ -141,8 +141,9 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
"(default: 0)"); "(default: 0)");
static void sony_nc_kbd_backlight_resume(void); static void sony_nc_kbd_backlight_resume(void);
static void sony_nc_kbd_backlight_setup(struct platform_device *pd); static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd); unsigned int handle);
static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd);
static int sony_nc_battery_care_setup(struct platform_device *pd, static int sony_nc_battery_care_setup(struct platform_device *pd,
unsigned int handle); unsigned int handle);
...@@ -1315,7 +1316,11 @@ static void sony_nc_function_setup(struct acpi_device *device, ...@@ -1315,7 +1316,11 @@ static void sony_nc_function_setup(struct acpi_device *device,
sony_nc_rfkill_setup(device); sony_nc_rfkill_setup(device);
break; break;
case 0x0137: case 0x0137:
sony_nc_kbd_backlight_setup(pf_device); case 0x0143:
result = sony_nc_kbd_backlight_setup(pf_device, handle);
if (result)
pr_err("couldn't set up keyboard backlight function (%d)\n",
result);
break; break;
default: default:
continue; continue;
...@@ -1365,6 +1370,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) ...@@ -1365,6 +1370,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
sony_nc_rfkill_cleanup(); sony_nc_rfkill_cleanup();
break; break;
case 0x0137: case 0x0137:
case 0x0143:
sony_nc_kbd_backlight_cleanup(pd); sony_nc_kbd_backlight_cleanup(pd);
break; break;
default: default:
...@@ -1407,6 +1413,7 @@ static void sony_nc_function_resume(void) ...@@ -1407,6 +1413,7 @@ static void sony_nc_function_resume(void)
sony_nc_rfkill_update(); sony_nc_rfkill_update();
break; break;
case 0x0137: case 0x0137:
case 0x0143:
sony_nc_kbd_backlight_resume(); sony_nc_kbd_backlight_resume();
break; break;
default: default:
...@@ -1618,20 +1625,16 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) ...@@ -1618,20 +1625,16 @@ static void sony_nc_rfkill_setup(struct acpi_device *device)
} }
/* Keyboard backlight feature */ /* Keyboard backlight feature */
#define KBDBL_HANDLER 0x137
#define KBDBL_PRESENT 0xB00
#define SET_MODE 0xC00
#define SET_STATE 0xD00
#define SET_TIMEOUT 0xE00
struct kbd_backlight { struct kbd_backlight {
int mode; unsigned int handle;
int timeout; unsigned int base;
unsigned int mode;
unsigned int timeout;
struct device_attribute mode_attr; struct device_attribute mode_attr;
struct device_attribute timeout_attr; struct device_attribute timeout_attr;
}; };
static struct kbd_backlight *kbdbl_handle; static struct kbd_backlight *kbdbl_ctl;
static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
{ {
...@@ -1640,15 +1643,15 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) ...@@ -1640,15 +1643,15 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
if (value > 1) if (value > 1)
return -EINVAL; return -EINVAL;
if (sony_call_snc_handle(KBDBL_HANDLER, if (sony_call_snc_handle(kbdbl_ctl->handle,
(value << 0x10) | SET_MODE, &result)) (value << 0x10) | (kbdbl_ctl->base), &result))
return -EIO; return -EIO;
/* Try to turn the light on/off immediately */ /* Try to turn the light on/off immediately */
sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE, sony_call_snc_handle(kbdbl_ctl->handle,
&result); (value << 0x10) | (kbdbl_ctl->base + 0x100), &result);
kbdbl_handle->mode = value; kbdbl_ctl->mode = value;
return 0; return 0;
} }
...@@ -1677,7 +1680,7 @@ static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev, ...@@ -1677,7 +1680,7 @@ static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
struct device_attribute *attr, char *buffer) struct device_attribute *attr, char *buffer)
{ {
ssize_t count = 0; ssize_t count = 0;
count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode); count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode);
return count; return count;
} }
...@@ -1688,11 +1691,11 @@ static int __sony_nc_kbd_backlight_timeout_set(u8 value) ...@@ -1688,11 +1691,11 @@ static int __sony_nc_kbd_backlight_timeout_set(u8 value)
if (value > 3) if (value > 3)
return -EINVAL; return -EINVAL;
if (sony_call_snc_handle(KBDBL_HANDLER, if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) |
(value << 0x10) | SET_TIMEOUT, &result)) (kbdbl_ctl->base + 0x200), &result))
return -EIO; return -EIO;
kbdbl_handle->timeout = value; kbdbl_ctl->timeout = value;
return 0; return 0;
} }
...@@ -1721,85 +1724,107 @@ static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev, ...@@ -1721,85 +1724,107 @@ static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
struct device_attribute *attr, char *buffer) struct device_attribute *attr, char *buffer)
{ {
ssize_t count = 0; ssize_t count = 0;
count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout); count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout);
return count; return count;
} }
static void sony_nc_kbd_backlight_setup(struct platform_device *pd) static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
unsigned int handle)
{ {
int result; int result;
int ret = 0;
if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result)) /* verify the kbd backlight presence, these handles are not used for
return; * keyboard backlight only
if (!(result & 0x02)) */
return; ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100,
&result);
if (ret)
return ret;
kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL); if ((handle == 0x0137 && !(result & 0x02)) ||
if (!kbdbl_handle) !(result & 0x01)) {
return; dprintk("no backlight keyboard found\n");
return 0;
}
kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL);
if (!kbdbl_ctl)
return -ENOMEM;
kbdbl_ctl->handle = handle;
if (handle == 0x0137)
kbdbl_ctl->base = 0x0C00;
else
kbdbl_ctl->base = 0x4000;
sysfs_attr_init(&kbdbl_handle->mode_attr.attr); sysfs_attr_init(&kbdbl_ctl->mode_attr.attr);
kbdbl_handle->mode_attr.attr.name = "kbd_backlight"; kbdbl_ctl->mode_attr.attr.name = "kbd_backlight";
kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show; kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store; kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
sysfs_attr_init(&kbdbl_handle->timeout_attr.attr); sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr);
kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout"; kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout";
kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr)) ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr);
if (ret)
goto outkzalloc; goto outkzalloc;
if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr)) ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr);
if (ret)
goto outmode; goto outmode;
__sony_nc_kbd_backlight_mode_set(kbd_backlight); __sony_nc_kbd_backlight_mode_set(kbd_backlight);
__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout); __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
return; return 0;
outmode: outmode:
device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
outkzalloc: outkzalloc:
kfree(kbdbl_handle); kfree(kbdbl_ctl);
kbdbl_handle = NULL; kbdbl_ctl = NULL;
return; return ret;
} }
static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
{ {
if (kbdbl_handle) { if (kbdbl_ctl) {
int result; int result;
device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr); device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
/* restore the default hw behaviour */ /* restore the default hw behaviour */
sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result); sony_call_snc_handle(kbdbl_ctl->handle,
sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result); kbdbl_ctl->base | 0x10000, &result);
sony_call_snc_handle(kbdbl_ctl->handle,
kbdbl_ctl->base + 0x200, &result);
kfree(kbdbl_handle); kfree(kbdbl_ctl);
kbdbl_ctl = NULL;
} }
return 0;
} }
static void sony_nc_kbd_backlight_resume(void) static void sony_nc_kbd_backlight_resume(void)
{ {
int ignore = 0; int ignore = 0;
if (!kbdbl_handle) if (!kbdbl_ctl)
return; return;
if (kbdbl_handle->mode == 0) if (kbdbl_ctl->mode == 0)
sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore); sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base,
if (kbdbl_handle->timeout != 0)
sony_call_snc_handle(KBDBL_HANDLER,
(kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
&ignore); &ignore);
if (kbdbl_ctl->timeout != 0)
sony_call_snc_handle(kbdbl_ctl->handle,
(kbdbl_ctl->base + 0x200) |
(kbdbl_ctl->timeout << 0x10), &ignore);
} }
struct battery_care_control { struct battery_care_control {
......
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