@ -21,7 +21,6 @@
# include <linux/err.h>
# include <linux/dmi.h>
# include <linux/io.h>
# include <linux/rfkill.h>
# include <linux/power_supply.h>
# include <linux/acpi.h>
# include <linux/mm.h>
@ -90,11 +89,8 @@ static struct platform_driver platform_driver = {
static struct platform_device * platform_device ;
static struct backlight_device * dell_backlight_device ;
static struct rfkill * wifi_rfkill ;
static struct rfkill * bluetooth_rfkill ;
static struct rfkill * wwan_rfkill ;
static const struct dmi_system_id __initdata dell_device_table [ ] = {
static const struct dmi_system_id dell_device_table [ ] __initconst = {
{
. ident = " Dell laptop " ,
. matches = {
@ -119,96 +115,94 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
} ;
MODULE_DEVICE_TABLE ( dmi , dell_device_table ) ;
static struct dmi_system_id __devinitdata dell_blacklist [ ] = {
/* Supported by compal-laptop */
{
. ident = " Dell Mini 9 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 910 " ) ,
} ,
} ,
static struct dmi_system_id __devinitdata dell_quirks [ ] = {
{
. ident = " Dell Mini 10 " ,
. callback = dmi_matched ,
. ident = " Dell Vostro V130 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 101 0" ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro V130 " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. ident = " Dell Mini 10v " ,
. callback = dmi_matched ,
. ident = " Dell Vostro V131 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 101 1" ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro V13 1" ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. ident = " Dell Mini 1012 " ,
. callback = dmi_matched ,
. ident = " Dell Vostro 3350 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 1012 " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 3350 " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. ident = " Dell Inspiron 11z " ,
. callback = dmi_matched ,
. ident = " Dell Vostro 3555 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 1110 " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 3555 " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. ident = " Dell Mini 12 " ,
. callback = dmi_matched ,
. ident = " Dell Inspiron N311z " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 1210 " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron N311z " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{ }
} ;
static struct dmi_system_id __devinitdata dell_quirks [ ] = {
{
. callback = dmi_matched ,
. ident = " Dell Vostro V13 0 " ,
. ident = " Dell Inspiron M5110 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro V13 0" ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron M511 0" ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. callback = dmi_matched ,
. ident = " Dell Vostro V131 " ,
. ident = " Dell Vostro 3360 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro V131 " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 3360 " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. callback = dmi_matched ,
. ident = " Dell Vostro 3555 " ,
. ident = " Dell Vostro 3460 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 3555 " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 3460 " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. callback = dmi_matched ,
. ident = " Dell Inspiron N311z " ,
. ident = " Dell Vostro 3560 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron N311z " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 3560 " ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
{
. callback = dmi_matched ,
. ident = " Dell Inspiron M511 0 " ,
. ident = " Dell Vostro 345 0 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron M511 0" ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Dell System Vostro 345 0" ) ,
} ,
. driver_data = & quirk_dell_vostro_v130 ,
} ,
@ -305,94 +299,6 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
return buffer ;
}
/* Derived from information in DellWirelessCtl.cpp:
Class 17 , select 11 is radio control . It returns an array of 32 - bit values .
Input byte 0 = 0 : Wireless information
result [ 0 ] : return code
result [ 1 ] :
Bit 0 : Hardware switch supported
Bit 1 : Wifi locator supported
Bit 2 : Wifi is supported
Bit 3 : Bluetooth is supported
Bit 4 : WWAN is supported
Bit 5 : Wireless keyboard supported
Bits 6 - 7 : Reserved
Bit 8 : Wifi is installed
Bit 9 : Bluetooth is installed
Bit 10 : WWAN is installed
Bits 11 - 15 : Reserved
Bit 16 : Hardware switch is on
Bit 17 : Wifi is blocked
Bit 18 : Bluetooth is blocked
Bit 19 : WWAN is blocked
Bits 20 - 31 : Reserved
result [ 2 ] : NVRAM size in bytes
result [ 3 ] : NVRAM format version number
Input byte 0 = 2 : Wireless switch configuration
result [ 0 ] : return code
result [ 1 ] :
Bit 0 : Wifi controlled by switch
Bit 1 : Bluetooth controlled by switch
Bit 2 : WWAN controlled by switch
Bits 3 - 6 : Reserved
Bit 7 : Wireless switch config locked
Bit 8 : Wifi locator enabled
Bits 9 - 14 : Reserved
Bit 15 : Wifi locator setting locked
Bits 16 - 31 : Reserved
*/
static int dell_rfkill_set ( void * data , bool blocked )
{
int disable = blocked ? 1 : 0 ;
unsigned long radio = ( unsigned long ) data ;
int hwswitch_bit = ( unsigned long ) data - 1 ;
int ret = 0 ;
get_buffer ( ) ;
dell_send_request ( buffer , 17 , 11 ) ;
/* If the hardware switch controls this radio, and the hardware
switch is disabled , don ' t allow changing the software state */
if ( ( hwswitch_state & BIT ( hwswitch_bit ) ) & &
! ( buffer - > output [ 1 ] & BIT ( 16 ) ) ) {
ret = - EINVAL ;
goto out ;
}
buffer - > input [ 0 ] = ( 1 | ( radio < < 8 ) | ( disable < < 16 ) ) ;
dell_send_request ( buffer , 17 , 11 ) ;
out :
release_buffer ( ) ;
return ret ;
}
static void dell_rfkill_query ( struct rfkill * rfkill , void * data )
{
int status ;
int bit = ( unsigned long ) data + 16 ;
int hwswitch_bit = ( unsigned long ) data - 1 ;
get_buffer ( ) ;
dell_send_request ( buffer , 17 , 11 ) ;
status = buffer - > output [ 1 ] ;
release_buffer ( ) ;
rfkill_set_sw_state ( rfkill , ! ! ( status & BIT ( bit ) ) ) ;
if ( hwswitch_state & ( BIT ( hwswitch_bit ) ) )
rfkill_set_hw_state ( rfkill , ! ( status & BIT ( 16 ) ) ) ;
}
static const struct rfkill_ops dell_rfkill_ops = {
. set_block = dell_rfkill_set ,
. query = dell_rfkill_query ,
} ;
static struct dentry * dell_laptop_dir ;
static int dell_debugfs_show ( struct seq_file * s , void * data )
@ -462,108 +368,6 @@ static const struct file_operations dell_debugfs_fops = {
. release = single_release ,
} ;
static void dell_update_rfkill ( struct work_struct * ignored )
{
if ( wifi_rfkill )
dell_rfkill_query ( wifi_rfkill , ( void * ) 1 ) ;
if ( bluetooth_rfkill )
dell_rfkill_query ( bluetooth_rfkill , ( void * ) 2 ) ;
if ( wwan_rfkill )
dell_rfkill_query ( wwan_rfkill , ( void * ) 3 ) ;
}
static DECLARE_DELAYED_WORK ( dell_rfkill_work , dell_update_rfkill ) ;
static int __init dell_setup_rfkill ( void )
{
int status ;
int ret ;
if ( dmi_check_system ( dell_blacklist ) ) {
pr_info ( " Blacklisted hardware detected - not enabling rfkill \n " ) ;
return 0 ;
}
get_buffer ( ) ;
dell_send_request ( buffer , 17 , 11 ) ;
status = buffer - > output [ 1 ] ;
buffer - > input [ 0 ] = 0x2 ;
dell_send_request ( buffer , 17 , 11 ) ;
hwswitch_state = buffer - > output [ 1 ] ;
release_buffer ( ) ;
if ( ( status & ( 1 < < 2 | 1 < < 8 ) ) = = ( 1 < < 2 | 1 < < 8 ) ) {
wifi_rfkill = rfkill_alloc ( " dell-wifi " , & platform_device - > dev ,
RFKILL_TYPE_WLAN ,
& dell_rfkill_ops , ( void * ) 1 ) ;
if ( ! wifi_rfkill ) {
ret = - ENOMEM ;
goto err_wifi ;
}
ret = rfkill_register ( wifi_rfkill ) ;
if ( ret )
goto err_wifi ;
}
if ( ( status & ( 1 < < 3 | 1 < < 9 ) ) = = ( 1 < < 3 | 1 < < 9 ) ) {
bluetooth_rfkill = rfkill_alloc ( " dell-bluetooth " ,
& platform_device - > dev ,
RFKILL_TYPE_BLUETOOTH ,
& dell_rfkill_ops , ( void * ) 2 ) ;
if ( ! bluetooth_rfkill ) {
ret = - ENOMEM ;
goto err_bluetooth ;
}
ret = rfkill_register ( bluetooth_rfkill ) ;
if ( ret )
goto err_bluetooth ;
}
if ( ( status & ( 1 < < 4 | 1 < < 10 ) ) = = ( 1 < < 4 | 1 < < 10 ) ) {
wwan_rfkill = rfkill_alloc ( " dell-wwan " ,
& platform_device - > dev ,
RFKILL_TYPE_WWAN ,
& dell_rfkill_ops , ( void * ) 3 ) ;
if ( ! wwan_rfkill ) {
ret = - ENOMEM ;
goto err_wwan ;
}
ret = rfkill_register ( wwan_rfkill ) ;
if ( ret )
goto err_wwan ;
}
return 0 ;
err_wwan :
rfkill_destroy ( wwan_rfkill ) ;
if ( bluetooth_rfkill )
rfkill_unregister ( bluetooth_rfkill ) ;
err_bluetooth :
rfkill_destroy ( bluetooth_rfkill ) ;
if ( wifi_rfkill )
rfkill_unregister ( wifi_rfkill ) ;
err_wifi :
rfkill_destroy ( wifi_rfkill ) ;
return ret ;
}
static void dell_cleanup_rfkill ( void )
{
if ( wifi_rfkill ) {
rfkill_unregister ( wifi_rfkill ) ;
rfkill_destroy ( wifi_rfkill ) ;
}
if ( bluetooth_rfkill ) {
rfkill_unregister ( bluetooth_rfkill ) ;
rfkill_destroy ( bluetooth_rfkill ) ;
}
if ( wwan_rfkill ) {
rfkill_unregister ( wwan_rfkill ) ;
rfkill_destroy ( wwan_rfkill ) ;
}
}
static int dell_send_intensity ( struct backlight_device * bd )
{
int ret = 0 ;
@ -655,30 +459,6 @@ static void touchpad_led_exit(void)
led_classdev_unregister ( & touchpad_led ) ;
}
static bool dell_laptop_i8042_filter ( unsigned char data , unsigned char str ,
struct serio * port )
{
static bool extended ;
if ( str & 0x20 )
return false ;
if ( unlikely ( data = = 0xe0 ) ) {
extended = true ;
return false ;
} else if ( unlikely ( extended ) ) {
switch ( data ) {
case 0x8 :
schedule_delayed_work ( & dell_rfkill_work ,
round_jiffies_relative ( HZ ) ) ;
break ;
}
extended = false ;
}
return false ;
}
static int __init dell_init ( void )
{
int max_intensity = 0 ;
@ -720,26 +500,10 @@ static int __init dell_init(void)
goto fail_buffer ;
buffer = page_address ( bufferpage ) ;
ret = dell_setup_rfkill ( ) ;
if ( ret ) {
pr_warn ( " Unable to setup rfkill \n " ) ;
goto fail_rfkill ;
}
ret = i8042_install_filter ( dell_laptop_i8042_filter ) ;
if ( ret ) {
pr_warn ( " Unable to install key filter \n " ) ;
goto fail_filter ;
}
if ( quirks & & quirks - > touchpad_led )
touchpad_led_init ( & platform_device - > dev ) ;
dell_laptop_dir = debugfs_create_dir ( " dell_laptop " , NULL ) ;
if ( dell_laptop_dir ! = NULL )
debugfs_create_file ( " rfkill " , 0444 , dell_laptop_dir , NULL ,
& dell_debugfs_fops ) ;
# ifdef CONFIG_ACPI
/* In the event of an ACPI backlight being available, don't
@ -782,11 +546,6 @@ static int __init dell_init(void)
return 0 ;
fail_backlight :
i8042_remove_filter ( dell_laptop_i8042_filter ) ;
cancel_delayed_work_sync ( & dell_rfkill_work ) ;
fail_filter :
dell_cleanup_rfkill ( ) ;
fail_rfkill :
free_page ( ( unsigned long ) bufferpage ) ;
fail_buffer :
platform_device_del ( platform_device ) ;
@ -804,10 +563,7 @@ static void __exit dell_exit(void)
debugfs_remove_recursive ( dell_laptop_dir ) ;
if ( quirks & & quirks - > touchpad_led )
touchpad_led_exit ( ) ;
i8042_remove_filter ( dell_laptop_i8042_filter ) ;
cancel_delayed_work_sync ( & dell_rfkill_work ) ;
backlight_device_unregister ( dell_backlight_device ) ;
dell_cleanup_rfkill ( ) ;
if ( platform_device ) {
platform_device_unregister ( platform_device ) ;
platform_driver_unregister ( & platform_driver ) ;