sony-laptop for 2.6.39
Subsystems (3)
Mattia Dongili
maintainercover sony-laptop for 2.6.39
Hi Matthew,
here's finally some cleanup and new features implemented for sony-laptop. There is more brewing here (i.e. ALS for which for now sysfs files will be added as platform attrbutes of the driver and mostly rework of the code to make it cleaner) but I wanted to start getting this out to hopefully give it some broader testing.
Hopefully in patch 8 I gave sufficient attribution to Javier and Marco who kindly figured most of the details to use the new backlight handlers. Let me know if there is a proper git meta-header instead.
Please apply for 2.6.39, I'll send the additional patches soon.
I'm also thinking it may be time to deprecate and start removing sonypi from the tree, sony-laptop is still not 100% compatible (jogdial events are half broken at least on my ancient GR and I think some very old vaio V wouldn't work properly with sony-laptop, I'll find out details) but very little is known of the SPIC device (that was driven by sonypi) and recent models have no additional functionality provided via that device.
Any thoughts?
Thanks!
--- Documentation/laptops/sony-laptop.txt | 37 ++- drivers/platform/x86/sony-laptop.c | 492 ++++++++++++++++++++++++++------- include/linux/sonypi.h | 1 + 3 files changed, 421 insertions(+), 109 deletions(-)
Signature · 2 lines
mattia :wq
Mattia Dongili
maintainerPATCH 1/8 sony-laptop: add some debug printk useful for bug reports
--- drivers/platform/x86/sony-laptop.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-)
drivers/platform/x86/sony-laptop.c +11 -3
@@ -733,22 +733,30 @@ static int sony_find_snc_handle(int handle)for (i =0x20 ; i <0x30 ; i++) {acpi_callsetfunc (sony_nc_acpi_handle,"SN00" , i, &result); -if (result == handle) +if (result == handle) { +dprintk ("found handle 0x%.4x (offset: 0x%.2x)\n" , + handle, i -0x20 );return i-0x20 ; + } } +dprintk ("handle 0x%.4x not found\n" , handle);return -1 ; }static int sony_call_snc_handle (int handle,int argument,int *result) { +int ret =0 ;int offset =sony_find_snc_handle (handle);if (offset <0 )return -1 ; -return acpi_callsetfunc (sony_nc_acpi_handle,"SN07" , offset | argument, - result); + ret =acpi_callsetfunc (sony_nc_acpi_handle,"SN07" , offset | argument, + result); +dprintk ("called SN07 with 0x%.4x (result: 0x%.4x)\n" , offset | argument, + *result); +return ret; }/*
Signature · 1 line
1.7.2.3
Mattia Dongili
maintainerPATCH 2/8 sony-laptop: documentation updates
In reply to Mattia Dongili--- Documentation/laptops/sony-laptop.txt | 37 ++++++++++++++++++++++++++------ 1 files changed, 30 insertions(+), 7 deletions(-)
Documentation/laptops/sony-laptop.txt +30 -7
@@ -14,7 +14,8 @@ Some models report hotkeys through the SNC or SPIC devices, such events are reported both through the ACPI subsystem as acpi events and through the INPUT subsystem. See the logs of acpid or /proc/acpi/event and /proc/bus/input/devices to find out what those events are and which input -devices are created by the driver. +devices are created by the driver. Additionally, loading the driver with the +debug option will report all events in the kernel log. Backlight control: ------------------
@@ -64,6 +65,16 @@ powers off the sound card, # echo "1" > /sys/devices/platform/sony-laptop/audiopower powers on the sound card. + +RFkill control: +--------------- +More recent Vaio models expose a consistent set of ACPI methods to +control radio frequency emitting devices. If you are a lucky owner of +such a laptop you will find the necessary rfkill devices under +/sys/class/rfkill. Check those starting with sony-* in + # grep . /sys/class/rfkill/*/{state,name} + + Development: ------------
@@ -75,8 +86,21 @@ pass the option 'debug=1'. REPEAT: DON'T DO THIS IF YOU DON'T LIKE RISKY BUSINESS. In your kernel logs you will find the list of all ACPI methods -the SNC device has on your laptop. You can see the GCDP/GCDP methods -used to pwer on/off the CD drive, but there are others. +the SNC device has on your laptop. + +* For new models you will see a long list of meaningless method names, +reading the DSDT table source should reveal that: +(1) the SNC device uses an internal capability lookup table +(2) SN00 is used to find values in the lookup table +(3) SN06 and SN07 are used to call into the real methods based on + offsets you can obtain iterating the table using SN00 +(4) SN02 used to enable events. +Some values in the capability lookup table are more or less known, see +the code for all sony_call_snc_handle calls, others are more obscure. + +* For old models you can see the GCDP/GCDP methods used to pwer on/off +the CD drive, but there are others and they are usually different from +model to model. I HAVE NO IDEA WHAT THOSE METHODS DO.
@@ -108,9 +132,8 @@ Bugs/Limitations: laptop, including permanent damage. * The sony-laptop and sonypi drivers do not interact at all. In the - future, sonypi could use sony-laptop to do (part of) its business. + future, sonypi will be removed and replaced by sony-laptop. * spicctrl, which is the userspace tool used to communicate with the - sonypi driver (through /dev/sonypi) does not try to use the - sony-laptop driver. In the future, spicctrl could try sonypi first, - and if it isn't present, try sony-laptop instead. + sonypi driver (through /dev/sonypi) is deprecated as well since all + its features are now available under the sysfs tree via sony-laptop.
Signature · 1 line
1.7.2.3
Mattia Dongili
maintainerPATCH 3/8 sony-laptop: ignore hard switch rfkill events (SPIC)
In reply to Mattia DongiliThere is not much use for these events in userspace and handling the events themselves seems to get in the way of the actual activation of the rf devices. The SNC device doesn't expose them already.
https://bugzilla.kernel.org/show_bug.cgi?id=15303
--- drivers/platform/x86/sony-laptop.c | 8 +++++--- include/linux/sonypi.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-)
drivers/platform/x86/sony-laptop.c +5 -3
@@ -1591,8 +1591,8 @@ static struct sonypi_event sonypi_blueev[] = {/* The set of possible wireless events */ static struct sonypi_event sonypi_wlessev[] = { - {0x59 ,SONYPI_EVENT_WIRELESS_ON }, - {0x5a ,SONYPI_EVENT_WIRELESS_OFF }, + {0x59 ,SONYPI_EVENT_IGNORE }, + {0x5a ,SONYPI_EVENT_IGNORE }, {0 ,0 } };
@@ -2732,6 +2732,9 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)if (ev == dev->event_types[i].events[j].data) { device_event = dev->event_types[i].events[j].event; +/* some events may require ignoring */ +if (!device_event) +return IRQ_HANDLED ; goto found; } }
@@ -2751,7 +2754,6 @@ found:sony_laptop_report_input_event (device_event);acpi_bus_generate_proc_event (dev->acpi_dev,1 , device_event);sonypi_compat_report_event (device_event); -return IRQ_HANDLED ; }
include/linux/sonypi.h +1 -0
@@ -40,6 +40,7 @@/* events the user application reading /dev/sonypi can use */ +#define SONYPI_EVENT_IGNORE 0#define SONYPI_EVENT_JOGDIAL_DOWN 1#define SONYPI_EVENT_JOGDIAL_UP 2#define SONYPI_EVENT_JOGDIAL_DOWN_PRESSED 3
Signature · 1 line
1.7.2.3
Re: [PATCH 3/8] sony-laptop: ignore hard switch rfkill events (SPIC)
Do you possibly want to catch these and make sure the kernel rfkill state matches the hardware?
Signature · 1 line
Matthew Garrett | [email protected]
Mattia Dongili
maintainerRe: [PATCH 3/8] sony-laptop: ignore hard switch rfkill events (SPIC)
Quoted 2 lines · Matthew Garrett
Do you possibly want to catch these and make sure the kernel rfkill state matches the hardware?
hmmmm, to be honest I'm not entirely sure what the actual problem is. Maybe it's just a timing issue that is made better by avoiding the input/acpi event generation. For now drop this patch (there is a different workaround using the mask parameter).
Thomas,
do you still have that TX laptop that had the problem? would you be available to test a couple of other patches?
Thanks
Signature · 2 lines
mattia :wq!
Re: [PATCH 3/8] sony-laptop: ignore hard switch rfkill events (SPIC)
Am Samstag, den 19.02.2011, 21:46 +0900 schrieb Mattia Dongili:
Quoted 3 lines
Thomas,
do you still have that TX laptop that had the problem? would you be available to test a couple of other patches?
Yes the TX laptop is still around and is available for testing.
Regards, Thomas
Re: [PATCH 3/8] sony-laptop: ignore hard switch rfkill events (SPIC)
In reply to Mattia DongiliQuoted 8 lines · Mattia Dongili
Quoted 2 lines · Matthew Garrett
Do you possibly want to catch these and make sure the kernel rfkill state matches the hardware?
hmmmm, to be honest I'm not entirely sure what the actual problem is. Maybe it's just a timing issue that is made better by avoiding the input/acpi event generation. For now drop this patch (there is a different workaround using the mask parameter).
Delivering it to userspace can be racy - rfkill-input will try to toggle the state as well. So I think this is the right thing to do, but you might also want to use it to check the current hardware state and update the state of the rfkill device.
Signature · 1 line
Matthew Garrett | [email protected]
Mattia Dongili
maintainerRe: [PATCH 3/8] sony-laptop: ignore hard switch rfkill events (SPIC)
Quoted 10 lines · Matthew Garrett
Quoted 8 lines · Mattia Dongili
Quoted 2 lines · Matthew Garrett
Do you possibly want to catch these and make sure the kernel rfkill state matches the hardware?
hmmmm, to be honest I'm not entirely sure what the actual problem is. Maybe it's just a timing issue that is made better by avoiding the input/acpi event generation. For now drop this patch (there is a different workaround using the mask parameter).
Quoted 4 lines
Delivering it to userspace can be racy - rfkill-input will try to toggle the state as well. So I think this is the right thing to do, but you might also want to use it to check the current hardware state and update the state of the rfkill device.
Ah, alright. This makes a lot of sense with what was seen on Thomas' laptop.
Then if you are ok to keep this patch as is, I'll work on matching/flipping the rfkill device state separately.
Thanks
Signature · 2 lines
mattia :wq!
Mattia Dongili
maintainerPATCH 4/8 sony-laptop: use pr_<level> for messages
In reply to Mattia Dongili--- drivers/platform/x86/sony-laptop.c | 102 ++++++++++++++++------------------- 1 files changed, 47 insertions(+), 55 deletions(-)
drivers/platform/x86/sony-laptop.c +47 -55
@@ -71,8 +71,9 @@#endif #define DRV_PFX "sony-laptop: " -#define dprintk(msg...) do { \ - if (debug) printk(KERN_WARNING DRV_PFX msg); \ +#define dprintk(msg...) do { \ + if (debug) \ + pr_warn(DRV_PFX msg); \ } while (0)#define SONY_LAPTOP_DRIVER_VERSION "0.6"
@@ -402,7 +403,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) error =kfifo_alloc (&sony_laptop_input.fifo,SONY_LAPTOP_BUF_SIZE ,GFP_KERNEL );if (error) { - printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); +pr_err (DRV_PFX "kfifo_alloc failed\n" ); goto err_dec_users; }
@@ -686,7 +687,7 @@ static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)return 0 ; } - printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n"); +pr_warn (DRV_PFX "acpi_callreadfunc failed\n" );return -1 ; }
@@ -712,7 +713,7 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,if (status ==AE_OK ) {if (result !=NULL ) {if (out_obj.type !=ACPI_TYPE_INTEGER ) { - printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad " +pr_warn (DRV_PFX "acpi_evaluate_object bad " "return type\n" );return -1 ; }
@@ -721,7 +722,7 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,return 0 ; } - printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n"); +pr_warn (DRV_PFX "acpi_evaluate_object failed\n" );return -1 ; }
@@ -980,7 +981,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) }if (!key_event->data) - printk(KERN_INFO DRV_PFX +pr_info (DRV_PFX "Unknown event: 0x%x 0x%x\n" , key_handle, ev);
@@ -1004,7 +1005,7 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,struct acpi_device_info *info;if (ACPI_SUCCESS (acpi_get_object_info (handle, &info))) { - printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", +pr_warn (DRV_PFX "method: name: %4.4s, args %X\n" , (char *)&info->name, info->param_count);kfree (info);
@@ -1045,7 +1046,7 @@ static int sony_nc_resume(struct acpi_device *device) ret =acpi_callsetfunc (sony_nc_acpi_handle, *item->acpiset, item->value,NULL );if (ret <0 ) { -printk ("%s: %d\n" , __func__, ret); +pr_err (DRV_PFX "%s: %d\n" , __func__, ret);break ; } }
@@ -1065,7 +1066,7 @@ static int sony_nc_resume(struct acpi_device *device)/* set the last requested brightness level */ if (sony_backlight_device &&sony_backlight_update_status (sony_backlight_device) <0 ) - printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); +pr_warn (DRV_PFX "unable to restore brightness level\n" );/* re-read rfkill state */ sony_nc_rfkill_update ();
@@ -1213,13 +1214,9 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) } device_enum = (union acpi_object *) buffer.pointer; -if (!device_enum) { -pr_err ("Invalid SN06 return object\n" ); - goto out_no_enum; - } -if (device_enum->type !=ACPI_TYPE_BUFFER ) { -pr_err ("Invalid SN06 return object type 0x%.2x\n" , - device_enum->type); +if (!device_enum || device_enum->type !=ACPI_TYPE_BUFFER ) { +pr_err (DRV_PFX "Invalid SN06 return object 0x%.2x\n" , + device_enum->type); goto out_no_enum; }
@@ -1260,8 +1257,8 @@ static int sony_nc_add(struct acpi_device *device)acpi_handle handle;struct sony_nc_value *item; - printk(KERN_INFO DRV_PFX "%s v%s.\n", - SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); +pr_info (DRV_PFX "%s v%s.\n" ,SONY_NC_DRIVER_NAME , +SONY_LAPTOP_DRIVER_VERSION ); sony_nc_acpi_device = device;strcpy (acpi_device_class (device),"sony/hotkey" );
@@ -1278,10 +1275,11 @@ static int sony_nc_add(struct acpi_device *device) }if (debug) { - status =acpi_walk_namespace (ACPI_TYPE_METHOD , sony_nc_acpi_handle, -1 , sony_walk_callback,NULL ,NULL ,NULL ); + status =acpi_walk_namespace (ACPI_TYPE_METHOD , + sony_nc_acpi_handle,1 , sony_walk_callback, +NULL ,NULL ,NULL );if (ACPI_FAILURE (status)) { - printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); +pr_warn (DRV_PFX "unable to walk acpi resources\n" ); result = -ENODEV ; goto outwalk; }
@@ -1303,17 +1301,16 @@ static int sony_nc_add(struct acpi_device *device)/* setup input devices and helper fifo */ result =sony_laptop_setup_input (device);if (result) { - printk(KERN_ERR DRV_PFX - "Unable to create input devices.\n"); +pr_err (DRV_PFX "Unable to create input devices.\n" ); goto outwalk; }if (acpi_video_backlight_support ()) { - printk(KERN_INFO DRV_PFX "brightness ignored, must be " +pr_info (DRV_PFX "brightness ignored, must be " "controlled by ACPI video driver\n" ); }else if (ACPI_SUCCESS (acpi_get_handle (sony_nc_acpi_handle,"GBRT" , &handle))) { -struct backlight_properties props; +struct backlight_properties props;memset (&props,0 ,sizeof (struct backlight_properties )); props.max_brightness =SONY_MAX_BRIGHTNESS -1 ; sony_backlight_device = backlight_device_register("sony", NULL,
@@ -1322,7 +1319,7 @@ static int sony_nc_add(struct acpi_device *device) &props);if (IS_ERR (sony_backlight_device)) { - printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); +pr_warning (DRV_PFX "unable to register backlight device\n" ); sony_backlight_device =NULL ; }else { sony_backlight_device->props.brightness =
@@ -1849,7 +1846,7 @@ out:if (pcidev)pci_dev_put (pcidev); - printk(KERN_INFO DRV_PFX "detected Type%d model\n", +pr_info (DRV_PFX "detected Type%d model\n" , dev->model ==SONYPI_DEVICE_TYPE1 ?1 : dev->model ==SONYPI_DEVICE_TYPE2 ?2 :3 ); }
@@ -1897,7 +1894,7 @@ static int __sony_pic_camera_ready(void)static int __sony_pic_camera_off (void ) {if (!camera) { - printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); +pr_warn (DRV_PFX "camera control not enabled\n" );return -ENODEV ; }
@@ -1917,7 +1914,7 @@ static int __sony_pic_camera_on(void)int i, j, x;if (!camera) { - printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); +pr_warn (DRV_PFX "camera control not enabled\n" );return -ENODEV ; }
@@ -1940,7 +1937,7 @@ static int __sony_pic_camera_on(void) }if (j ==0 ) { - printk(KERN_WARNING DRV_PFX "failed to power on camera\n"); +pr_warn (DRV_PFX "failed to power on camera\n" );return -ENODEV ; }
@@ -1996,7 +1993,7 @@ int sony_pic_camera_command(int command, u8 value) ITERATIONS_SHORT);break ;default : - printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n", +pr_err (DRV_PFX "sony_pic_camera_command invalid: %d\n" , command);break ; }
@@ -2403,7 +2400,7 @@ static int sonypi_compat_init(void) error =kfifo_alloc (&sonypi_compat.fifo,SONY_LAPTOP_BUF_SIZE ,GFP_KERNEL );if (error) { - printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); +pr_err (DRV_PFX "kfifo_alloc failed\n" );return error; }
@@ -2413,11 +2410,11 @@ static int sonypi_compat_init(void) sonypi_misc_device.minor = minor; error =misc_register (&sonypi_misc_device);if (error) { - printk(KERN_ERR DRV_PFX "misc_register failed\n"); +pr_err (DRV_PFX "misc_register failed\n" ); goto err_free_kfifo; }if (minor ==-1 ) - printk(KERN_INFO DRV_PFX "device allocated minor is %d\n", +pr_info (DRV_PFX "device allocated minor is %d\n" , sonypi_misc_device.minor);return 0 ;
@@ -2477,8 +2474,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) }for (i =0 ; i < p->interrupt_count; i++) {if (!p->interrupts[i]) { - printk(KERN_WARNING DRV_PFX -"Invalid IRQ %d\n" , +pr_warn (DRV_PFX "Invalid IRQ %d\n" , p->interrupts[i]);continue ; }
@@ -2517,7 +2513,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) ioport->io2.address_length); }else { - printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n"); +pr_err (DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n" );return AE_ERROR ; }return AE_OK ;
@@ -2545,7 +2541,7 @@ static int sony_pic_possible_resources(struct acpi_device *device)dprintk ("Evaluating _STA\n" ); result =acpi_bus_get_status (device);if (result) { - printk(KERN_WARNING DRV_PFX "Unable to read status\n"); +pr_warn (DRV_PFX "Unable to read status\n" ); goto end; }
@@ -2561,8 +2557,7 @@ static int sony_pic_possible_resources(struct acpi_device *device) status =acpi_walk_resources (device->handle,METHOD_NAME__PRS , sony_pic_read_possible_resource, &spic_dev);if (ACPI_FAILURE (status)) { - printk(KERN_WARNING DRV_PFX -"Failure evaluating %s\n" , +pr_warn (DRV_PFX "Failure evaluating %s\n" ,METHOD_NAME__PRS ); result = -ENODEV ; }
@@ -2676,7 +2671,7 @@ static int sony_pic_enable(struct acpi_device *device,/* check for total failure */ if (ACPI_FAILURE (status)) { - printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n"); +pr_err (DRV_PFX "Error evaluating _SRS\n" ); result = -ENODEV ; goto end; }
@@ -2768,7 +2763,7 @@ static int sony_pic_remove(struct acpi_device *device, int type)struct sony_pic_irq *irq, *tmp_irq;if (sony_pic_disable (device)) { - printk(KERN_ERR DRV_PFX "Couldn't disable device.\n"); +pr_err (DRV_PFX "Couldn't disable device.\n" );return -ENXIO ; }
@@ -2808,8 +2803,8 @@ static int sony_pic_add(struct acpi_device *device)struct sony_pic_ioport *io, *tmp_io;struct sony_pic_irq *irq, *tmp_irq; - printk(KERN_INFO DRV_PFX "%s v%s.\n", - SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); +pr_info (DRV_PFX "%s v%s.\n" ,SONY_PIC_DRIVER_NAME , +SONY_LAPTOP_DRIVER_VERSION ); spic_dev.acpi_dev = device;strcpy (acpi_device_class (device),"sony/hotkey" );
@@ -2819,16 +2814,14 @@ static int sony_pic_add(struct acpi_device *device)/* read _PRS resources */ result =sony_pic_possible_resources (device);if (result) { - printk(KERN_ERR DRV_PFX - "Unable to read possible resources.\n"); +pr_err (DRV_PFX "Unable to read possible resources.\n" ); goto err_free_resources; }/* setup input devices and helper fifo */ result =sony_laptop_setup_input (device);if (result) { - printk(KERN_ERR DRV_PFX - "Unable to create input devices.\n"); +pr_err (DRV_PFX "Unable to create input devices.\n" ); goto err_free_resources; }
@@ -2869,7 +2862,7 @@ static int sony_pic_add(struct acpi_device *device) } }if (!spic_dev.cur_ioport) { - printk(KERN_ERR DRV_PFX "Failed to request_region.\n"); +pr_err (DRV_PFX "Failed to request_region.\n" ); result = -ENODEV ; goto err_remove_compat; }
@@ -2889,7 +2882,7 @@ static int sony_pic_add(struct acpi_device *device) } }if (!spic_dev.cur_irq) { - printk(KERN_ERR DRV_PFX "Failed to request_irq.\n"); +pr_err (DRV_PFX "Failed to request_irq.\n" ); result = -ENODEV ; goto err_release_region; }
@@ -2897,7 +2890,7 @@ static int sony_pic_add(struct acpi_device *device)/* set resource status _SRS */ result =sony_pic_enable (device, spic_dev.cur_ioport, spic_dev.cur_irq);if (result) { - printk(KERN_ERR DRV_PFX "Couldn't enable device.\n"); +pr_err (DRV_PFX "Couldn't enable device.\n" ); goto err_free_irq; }
@@ -3006,8 +2999,7 @@ static int __init sony_laptop_init(void)if (!no_spic &&dmi_check_system (sonypi_dmi_table)) { result =acpi_bus_register_driver (&sony_pic_driver);if (result) { - printk(KERN_ERR DRV_PFX - "Unable to register SPIC driver."); +pr_err (DRV_PFX "Unable to register SPIC driver." ); goto out; } spic_drv_registered =1 ;
@@ -3015,7 +3007,7 @@ static int __init sony_laptop_init(void) result =acpi_bus_register_driver (&sony_nc_driver);if (result) { - printk(KERN_ERR DRV_PFX "Unable to register SNC driver."); +pr_err (DRV_PFX "Unable to register SNC driver." ); goto out_unregister_pic; }
Signature · 1 line
1.7.2.3
Mattia Dongili
maintainerPATCH 5/8 sony-laptop: remove unused Type4 define
In reply to Mattia Dongili--- drivers/platform/x86/sony-laptop.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/platform/x86/sony-laptop.c +0 -1
@@ -1442,7 +1442,6 @@ static struct acpi_driver sony_nc_driver = {#define SONYPI_DEVICE_TYPE1 0x00000001#define SONYPI_DEVICE_TYPE2 0x00000002#define SONYPI_DEVICE_TYPE3 0x00000004 -#define SONYPI_DEVICE_TYPE4 0x00000008#define SONYPI_TYPE1_OFFSET 0x04#define SONYPI_TYPE2_OFFSET 0x12
Signature · 1 line
1.7.2.3
Mattia Dongili
maintainerPATCH 6/8 sony-laptop: cache handles and report them via sysfs
In reply to Mattia DongiliAvoid calling into acpi each time we need to lookup a method handle and report the available handles to ease collection of information when debugging issues. Also move initialization of the platform driver earlier to allow adding files from other setup functions.
--- drivers/platform/x86/sony-laptop.c | 97 ++++++++++++++++++++++++++++++------ 1 files changed, 81 insertions(+), 16 deletions(-)
drivers/platform/x86/sony-laptop.c +81 -16
@@ -727,20 +727,79 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,return -1 ; } -static int sony_find_snc_handle (int handle) +struct sony_nc_handles { +u16 cap[0x10 ]; +struct device_attribute devattr; +}; + +struct sony_nc_handles *handles; + +static ssize_t sony_nc_handles_show (struct device *dev, +struct device_attribute *attr,char *buffer) +{ +ssize_t len =0 ; +int i; + +for (i =0 ; i <ARRAY_SIZE (handles->cap); i++) { + len +=snprintf (buffer + len,PAGE_SIZE - len,"0x%.4x " , + handles->cap[i]); + } + len +=snprintf (buffer + len,PAGE_SIZE - len,"\n" ); + +return len; +} + +static int sony_nc_handles_setup (struct platform_device *pd) {int i;int result; -for (i =0x20 ; i <0x30 ; i++) { -acpi_callsetfunc (sony_nc_acpi_handle,"SN00" , i, &result); -if (result == handle) { -dprintk ("found handle 0x%.4x (offset: 0x%.2x)\n" , - handle, i -0x20 ); -return i-0x20 ; + handles =kzalloc (sizeof (*handles),GFP_KERNEL ); + +sysfs_attr_init (handles->devattr); + handles->devattr.attr.name ="handles" ; + handles->devattr.attr.mode =S_IRUGO ; + handles->devattr.show = sony_nc_handles_show; + +for (i =0 ; i <ARRAY_SIZE (handles->cap); i++) { +if (!acpi_callsetfunc (sony_nc_acpi_handle, +"SN00" , i +0x20 , &result)) { +dprintk ("caching handle 0x%.4x (offset: 0x%.2x)\n" , + result, i); + handles->cap[i] = result; } } +/* allow reading capabilities via sysfs */ +if (device_create_file (&pd->dev, &handles->devattr)) { +kfree (handles); + handles =NULL ; +return -1 ; + } + +return 0 ; +} + +static int sony_nc_handles_cleanup (struct platform_device *pd) +{ +if (handles) { +device_remove_file (&pd->dev, &handles->devattr); +kfree (handles); + handles =NULL ; + } +return 0 ; +} + +static int sony_find_snc_handle (int handle) +{ +int i; +for (i =0 ; i <0x10 ; i++) { +if (handles->cap[i] == handle) { +dprintk ("found handle 0x%.4x (offset: 0x%.2x)\n" , + handle, i); +return i; + } + }dprintk ("handle 0x%.4x not found\n" , handle);return -1 ; }
@@ -1274,6 +1333,10 @@ static int sony_nc_add(struct acpi_device *device) goto outwalk; } + result =sony_pf_add (); +if (result) + goto outpresent; +if (debug) { status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 1, sony_walk_callback,
@@ -1281,7 +1344,7 @@ static int sony_nc_add(struct acpi_device *device)if (ACPI_FAILURE (status)) {pr_warn (DRV_PFX "unable to walk acpi resources\n" ); result = -ENODEV ; - goto outwalk; + goto outpresent; } }
@@ -1294,6 +1357,8 @@ static int sony_nc_add(struct acpi_device *device)if (ACPI_SUCCESS (acpi_get_handle (sony_nc_acpi_handle,"SN00" , &handle))) {dprintk ("Doing SNC setup\n" ); +if (sony_nc_handles_setup (sony_pf_device)) + goto outpresent;sony_nc_function_setup (device);sony_nc_rfkill_setup (device); }
@@ -1302,7 +1367,7 @@ static int sony_nc_add(struct acpi_device *device) result =sony_laptop_setup_input (device);if (result) {pr_err (DRV_PFX "Unable to create input devices.\n" ); - goto outwalk; + goto outsnc; }if (acpi_video_backlight_support ()) {
@@ -1329,10 +1394,6 @@ static int sony_nc_add(struct acpi_device *device) } - result =sony_pf_add (); -if (result) - goto outbacklight; -/* create sony_pf sysfs attributes related to the SNC device */ for (item = sony_nc_values; item->name; ++item) {
@@ -1378,14 +1439,17 @@ static int sony_nc_add(struct acpi_device *device)for (item = sony_nc_values; item->name; ++item) {device_remove_file (&sony_pf_device->dev, &item->devattr); } -sony_pf_remove (); - - outbacklight:if (sony_backlight_device)backlight_device_unregister (sony_backlight_device);sony_laptop_remove_input (); + outsnc: +sony_nc_handles_cleanup (sony_pf_device); + + outpresent: +sony_pf_remove (); + outwalk:sony_nc_rfkill_cleanup ();return result;
@@ -1404,6 +1468,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)device_remove_file (&sony_pf_device->dev, &item->devattr); } +sony_nc_handles_cleanup (sony_pf_device);sony_pf_remove ();sony_laptop_remove_input ();sony_nc_rfkill_cleanup ();
Signature · 1 line
1.7.2.3
Mattia Dongili
maintainerPATCH 7/8 sony-laptop: implement keyboard backlight support
In reply to Mattia DongiliRecent Vaios have the opportunity to control the keyboard backlight via ACPI calls to the SNC device.
Introduce two module parameters to control how keyboard backlight should be set at module loading (default to on and with 10 seconds timeout).
--- drivers/platform/x86/sony-laptop.c | 176 +++++++++++++++++++++++++++++++++++- 1 files changed, 175 insertions(+), 1 deletions(-)
drivers/platform/x86/sony-laptop.c +175 -1
@@ -125,6 +125,19 @@ MODULE_PARM_DESC(minor, "default is -1 (automatic)");#endif +static int kbd_backlight;/* = 1 */ +module_param (kbd_backlight, int,0444 ); +MODULE_PARM_DESC (kbd_backlight, +"set this to 0 to disable keyboard backlight, " +"1 to enable it (default: 0)" ); + +static int kbd_backlight_timeout;/* = 0 */ +module_param (kbd_backlight_timeout, int,0444 ); +MODULE_PARM_DESC (kbd_backlight_timeout, +"set this to 0 to set the default 10 seconds timeout, " +"1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout " +"(default: 0)" ); +enum sony_nc_rfkill {SONY_WIFI ,SONY_BLUETOOTH ,
@@ -1309,6 +1322,161 @@ out_no_enum:return ; } +/* Keyboard backlight feature */ +#define KBDBL_HANDLER 0x137 +#define KBDBL_PRESENT 0xB00 +#define SET_MODE 0xC00 +#define SET_TIMEOUT 0xE00 + +struct kbd_backlight { +int mode; +int timeout; +struct device_attribute mode_attr; +struct device_attribute timeout_attr; +}; + +struct kbd_backlight *kbdbl_handle; + +static ssize_t __sony_nc_kbd_backlight_mode_set (u8 value) +{ +int result; + +if (value >1 ) +return -EINVAL ; + +if (sony_call_snc_handle (KBDBL_HANDLER , + (value <<0x10 ) |SET_MODE , &result)) +return -EIO ; + + kbdbl_handle->mode = value; + +return 0 ; +} + +static ssize_t sony_nc_kbd_backlight_mode_store (struct device *dev, +struct device_attribute *attr, +const char *buffer,size_t count) +{ +int ret =0 ; +unsigned long value; + +if (count >31 ) +return -EINVAL ; + +if (strict_strtoul (buffer,10 , &value)) +return -EINVAL ; + + ret =__sony_nc_kbd_backlight_mode_set (value); +if (ret <0 ) +return ret; + +return count; +} + +static ssize_t sony_nc_kbd_backlight_mode_show (struct device *dev, +struct device_attribute *attr,char *buffer) +{ +ssize_t count =0 ; + count =snprintf (buffer,PAGE_SIZE ,"%d\n" , kbdbl_handle->mode); +return count; +} + +static int __sony_nc_kbd_backlight_timeout_set (u8 value) +{ +int result; + +if (value >3 ) +return -EINVAL ; + +if (sony_call_snc_handle (KBDBL_HANDLER , + (value <<0x10 ) |SET_TIMEOUT , &result)) +return -EIO ; + + kbdbl_handle->timeout = value; + +return 0 ; +} + +static ssize_t sony_nc_kbd_backlight_timeout_store (struct device *dev, +struct device_attribute *attr, +const char *buffer,size_t count) +{ +int ret =0 ; +unsigned long value; + +if (count >31 ) +return -EINVAL ; + +if (strict_strtoul (buffer,10 , &value)) +return -EINVAL ; + + ret =__sony_nc_kbd_backlight_timeout_set (value); +if (ret <0 ) +return ret; + +return count; +} + +static ssize_t sony_nc_kbd_backlight_timeout_show (struct device *dev, +struct device_attribute *attr,char *buffer) +{ +ssize_t count =0 ; + count =snprintf (buffer,PAGE_SIZE ,"%d\n" , kbdbl_handle->timeout); +return count; +} + +static int sony_nc_kbd_backlight_setup (struct platform_device *pd) +{ +int result; + +if (sony_call_snc_handle (0x137 ,KBDBL_PRESENT , &result)) +return 0 ; +if (!(result &0x02 )) +return 0 ; + + kbdbl_handle =kzalloc (sizeof (*kbdbl_handle),GFP_KERNEL ); + +sysfs_attr_init (kbdbl_handle->mode_attr); + kbdbl_handle->mode_attr.attr.name ="kbd_backlight" ; + kbdbl_handle->mode_attr.attr.mode =S_IRUGO |S_IWUSR ; + kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show; + kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store; + +sysfs_attr_init (kbdbl_handle->timeout_attr); + kbdbl_handle->timeout_attr.attr.name ="kbd_backlight_timeout" ; + kbdbl_handle->timeout_attr.attr.mode =S_IRUGO |S_IWUSR ; + kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; + kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; + +if (device_create_file (&pd->dev, &kbdbl_handle->mode_attr)) + goto outkzalloc; + +if (device_create_file (&pd->dev, &kbdbl_handle->timeout_attr)) + goto outmode; + +__sony_nc_kbd_backlight_mode_set (kbd_backlight); +__sony_nc_kbd_backlight_timeout_set (kbd_backlight_timeout); + +return 0 ; + +outmode: +device_remove_file (&pd->dev, &kbdbl_handle->mode_attr); +outkzalloc: +kfree (kbdbl_handle); + kbdbl_handle =NULL ; +return -1 ; +} + +static int sony_nc_kbd_backlight_cleanup (struct platform_device *pd) +{ +if (kbdbl_handle) { +device_remove_file (&pd->dev, &kbdbl_handle->mode_attr); +device_remove_file (&pd->dev, &kbdbl_handle->timeout_attr); +kfree (kbdbl_handle); + } +return 0 ; +} +static int sony_nc_add (struct acpi_device *device) {acpi_status status;
@@ -1359,6 +1527,8 @@ static int sony_nc_add(struct acpi_device *device)dprintk ("Doing SNC setup\n" );if (sony_nc_handles_setup (sony_pf_device)) goto outpresent; +if (sony_nc_kbd_backlight_setup (sony_pf_device)) + goto outsnc;sony_nc_function_setup (device);sony_nc_rfkill_setup (device); }
@@ -1367,7 +1537,7 @@ static int sony_nc_add(struct acpi_device *device) result =sony_laptop_setup_input (device);if (result) {pr_err (DRV_PFX "Unable to create input devices.\n" ); - goto outsnc; + goto outkbdbacklight; }if (acpi_video_backlight_support ()) {
@@ -1444,6 +1614,9 @@ static int sony_nc_add(struct acpi_device *device)sony_laptop_remove_input (); + outkbdbacklight: +sony_nc_kbd_backlight_cleanup (sony_pf_device); + outsnc:sony_nc_handles_cleanup (sony_pf_device);
@@ -1468,6 +1641,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)device_remove_file (&sony_pf_device->dev, &item->devattr); } +sony_nc_kbd_backlight_cleanup (sony_pf_device);sony_nc_handles_cleanup (sony_pf_device);sony_pf_remove ();sony_laptop_remove_input ();
Signature · 1 line
1.7.2.3
Mattia Dongili
maintainerPATCH 8/8 sony-laptop: implement new backlight control method
In reply to Mattia DongiliReasonably recent Vaios have a 0x12f or 0x137 handler that exposes a fine lid backlight regulation with values ranging from 0 to 255. The patch is based on findings and code from Javier Achirica <[email protected]> and Marco Chiappero <[email protected]>
--- drivers/platform/x86/sony-laptop.c | 108 ++++++++++++++++++++++++++---------- 1 files changed, 78 insertions(+), 30 deletions(-)
drivers/platform/x86/sony-laptop.c +78 -30
@@ -938,11 +938,39 @@ static int sony_backlight_get_brightness(struct backlight_device *bd)return value -1 ; } -static struct backlight_device *sony_backlight_device; +static int sony_nc_get_brightness_ng (struct backlight_device *bd) +{ +int result; +int *handle = (int *)bl_get_data (bd); + +sony_call_snc_handle (*handle,0x0200 , &result); + +return result &0xff ; +} + +static int sony_nc_update_status_ng (struct backlight_device *bd) +{ +int value, result; +int *handle = (int *)bl_get_data (bd); + + value = bd->props.brightness; +sony_call_snc_handle (*handle,0x0100 | (value <<16 ), &result); + +return sony_nc_get_brightness_ng (bd); +} +static const struct backlight_ops sony_backlight_ops = { + .options =BL_CORE_SUSPENDRESUME , .update_status = sony_backlight_update_status, .get_brightness = sony_backlight_get_brightness, }; +static const struct backlight_ops sony_backlight_ng_ops = { + .options =BL_CORE_SUSPENDRESUME , + .update_status = sony_nc_update_status_ng, + .get_brightness = sony_nc_get_brightness_ng, +}; +static int backlight_ng_handle; +static struct backlight_device *sony_backlight_device;/* * New SNC-only Vaios event mapping to driver known keys
@@ -1135,11 +1163,6 @@ static int sony_nc_resume(struct acpi_device *device)sony_nc_function_setup (device); } -/* set the last requested brightness level */ -if (sony_backlight_device && -sony_backlight_update_status (sony_backlight_device) <0 ) -pr_warn (DRV_PFX "unable to restore brightness level\n" ); -/* re-read rfkill state */ sony_nc_rfkill_update ();
@@ -1477,6 +1500,51 @@ static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)return 0 ; } +static void sony_nc_backlight_setup (void ) +{ +acpi_handle unused; +int max_brightness =0 ; +const struct backlight_ops *ops =NULL ; +struct backlight_properties props; + +if (sony_find_snc_handle (0x12f ) !=-1 ) { + backlight_ng_handle =0x12f ; + ops = &sony_backlight_ng_ops; + max_brightness =0xff ; + + }else if (sony_find_snc_handle (0x137 ) !=-1 ) { + backlight_ng_handle =0x137 ; + ops = &sony_backlight_ng_ops; + max_brightness =0xff ; + + }else if (ACPI_SUCCESS (acpi_get_handle (sony_nc_acpi_handle,"GBRT" , + &unused))) { + ops = &sony_backlight_ops; + max_brightness =SONY_MAX_BRIGHTNESS -1 ; + + }else +return ; + +memset (&props,0 ,sizeof (struct backlight_properties )); + props.max_brightness = max_brightness; + sony_backlight_device =backlight_device_register ("sony" ,NULL , + &backlight_ng_handle, + ops, &props); + +if (IS_ERR (sony_backlight_device)) { +pr_warning (DRV_PFX "unable to register backlight device\n" ); + sony_backlight_device =NULL ; + }else + sony_backlight_device->props.brightness = + ops->get_brightness (sony_backlight_device); +} + +static void sony_nc_backlight_cleanup (void ) +{ +if (sony_backlight_device) +backlight_device_unregister (sony_backlight_device); +} +static int sony_nc_add (struct acpi_device *device) {acpi_status status;
@@ -1543,26 +1611,8 @@ static int sony_nc_add(struct acpi_device *device)if (acpi_video_backlight_support ()) {pr_info (DRV_PFX "brightness ignored, must be " "controlled by ACPI video driver\n" ); - }else if (ACPI_SUCCESS (acpi_get_handle (sony_nc_acpi_handle,"GBRT" , - &handle))) { -struct backlight_properties props; -memset (&props,0 ,sizeof (struct backlight_properties )); - props.max_brightness =SONY_MAX_BRIGHTNESS -1 ; - sony_backlight_device =backlight_device_register ("sony" ,NULL , -NULL , - &sony_backlight_ops, - &props); - -if (IS_ERR (sony_backlight_device)) { -pr_warning (DRV_PFX "unable to register backlight device\n" ); - sony_backlight_device =NULL ; - }else { - sony_backlight_device->props.brightness = -sony_backlight_get_brightness - (sony_backlight_device); - } - - } + }else +sony_nc_backlight_setup ();/* create sony_pf sysfs attributes related to the SNC device */ for (item = sony_nc_values; item->name; ++item) {
@@ -1609,8 +1659,7 @@ static int sony_nc_add(struct acpi_device *device)for (item = sony_nc_values; item->name; ++item) {device_remove_file (&sony_pf_device->dev, &item->devattr); } -if (sony_backlight_device) -backlight_device_unregister (sony_backlight_device); +sony_nc_backlight_cleanup ();sony_laptop_remove_input ();
@@ -1632,8 +1681,7 @@ static int sony_nc_remove(struct acpi_device *device, int type) {struct sony_nc_value *item; -if (sony_backlight_device) -backlight_device_unregister (sony_backlight_device); +sony_nc_backlight_cleanup (); sony_nc_acpi_device =NULL ;
Signature · 1 line
1.7.2.3
Matthew Garrett
AppliedApplied the series for -next. THanks!
Signature · 1 line
Matthew Garrett | [email protected]