Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
7c27fd19
Commit
7c27fd19
authored
Apr 05, 2009
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'sony-laptop' into release
parents
336d63b8
16dd55f3
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
402 additions
and
138 deletions
+402
-138
drivers/platform/x86/Kconfig
drivers/platform/x86/Kconfig
+1
-0
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/sony-laptop.c
+393
-138
include/linux/sonypi.h
include/linux/sonypi.h
+8
-0
No files found.
drivers/platform/x86/Kconfig
View file @
7c27fd19
...
...
@@ -165,6 +165,7 @@ config SONY_LAPTOP
depends on ACPI
select BACKLIGHT_CLASS_DEVICE
depends on INPUT
depends on RFKILL
---help---
This mini-driver drives the SNC and SPIC devices present in the ACPI
BIOS of the Sony Vaio laptops.
...
...
drivers/platform/x86/sony-laptop.c
View file @
7c27fd19
...
...
@@ -2,7 +2,7 @@
* ACPI Sony Notebook Control Driver (SNC and SPIC)
*
* Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
* Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
* Copyright (C) 2007
-2009
Mattia Dongili <malattia@linux.it>
*
* Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
* which are copyrighted by their respective authors.
...
...
@@ -46,7 +46,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/types.h>
#include <linux/backlight.h>
#include <linux/platform_device.h>
...
...
@@ -64,6 +63,7 @@
#include <asm/uaccess.h>
#include <linux/sonypi.h>
#include <linux/sony-laptop.h>
#include <linux/rfkill.h>
#ifdef CONFIG_SONYPI_COMPAT
#include <linux/poll.h>
#include <linux/miscdevice.h>
...
...
@@ -123,6 +123,18 @@ MODULE_PARM_DESC(minor,
"default is -1 (automatic)"
);
#endif
enum
sony_nc_rfkill
{
SONY_WIFI
,
SONY_BLUETOOTH
,
SONY_WWAN
,
SONY_WIMAX
,
SONY_RFKILL_MAX
,
};
static
struct
rfkill
*
sony_rfkill_devices
[
SONY_RFKILL_MAX
];
static
int
sony_rfkill_address
[
SONY_RFKILL_MAX
]
=
{
0x300
,
0x500
,
0x700
,
0x900
};
static
void
sony_nc_rfkill_update
(
void
);
/*********** Input Devices ***********/
#define SONY_LAPTOP_BUF_SIZE 128
...
...
@@ -134,6 +146,7 @@ struct sony_laptop_input_s {
spinlock_t
fifo_lock
;
struct
workqueue_struct
*
wq
;
};
static
struct
sony_laptop_input_s
sony_laptop_input
=
{
.
users
=
ATOMIC_INIT
(
0
),
};
...
...
@@ -211,6 +224,14 @@ static int sony_laptop_input_index[] = {
48
,
/* 61 SONYPI_EVENT_WIRELESS_OFF */
49
,
/* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */
50
,
/* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */
51
,
/* 64 SONYPI_EVENT_CD_EJECT_PRESSED */
52
,
/* 65 SONYPI_EVENT_MODEKEY_PRESSED */
53
,
/* 66 SONYPI_EVENT_PKEY_P4 */
54
,
/* 67 SONYPI_EVENT_PKEY_P5 */
55
,
/* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */
56
,
/* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
57
,
/* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
-
1
,
/* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
};
static
int
sony_laptop_input_keycode_map
[]
=
{
...
...
@@ -264,7 +285,14 @@ static int sony_laptop_input_keycode_map[] = {
KEY_WLAN
,
/* 47 SONYPI_EVENT_WIRELESS_ON */
KEY_WLAN
,
/* 48 SONYPI_EVENT_WIRELESS_OFF */
KEY_ZOOMIN
,
/* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */
KEY_ZOOMOUT
/* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
KEY_ZOOMOUT
,
/* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
KEY_EJECTCD
,
/* 51 SONYPI_EVENT_CD_EJECT_PRESSED */
KEY_F13
,
/* 52 SONYPI_EVENT_MODEKEY_PRESSED */
KEY_PROG4
,
/* 53 SONYPI_EVENT_PKEY_P4 */
KEY_F14
,
/* 54 SONYPI_EVENT_PKEY_P5 */
KEY_F15
,
/* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
KEY_VOLUMEUP
,
/* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
KEY_VOLUMEDOWN
,
/* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
};
/* release buttons after a short delay if pressed */
...
...
@@ -369,7 +397,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
sony_laptop_input
.
wq
=
create_singlethread_workqueue
(
"sony-laptop"
);
if
(
!
sony_laptop_input
.
wq
)
{
printk
(
KERN_ERR
DRV_PFX
"Unabe to create workqueue.
\n
"
);
"Unab
l
e to create workqueue.
\n
"
);
error
=
-
ENXIO
;
goto
err_free_kfifo
;
}
...
...
@@ -689,6 +717,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
return
-
1
;
}
static
int
sony_find_snc_handle
(
int
handle
)
{
int
i
;
int
result
;
for
(
i
=
0x20
;
i
<
0x30
;
i
++
)
{
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN00"
,
i
,
&
result
);
if
(
result
==
handle
)
return
i
-
0x20
;
}
return
-
1
;
}
static
int
sony_call_snc_handle
(
int
handle
,
int
argument
,
int
*
result
)
{
int
offset
=
sony_find_snc_handle
(
handle
);
if
(
offset
<
0
)
return
-
1
;
return
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN07"
,
offset
|
argument
,
result
);
}
/*
* sony_nc_values input/output validate functions
*/
...
...
@@ -809,87 +862,53 @@ struct sony_nc_event {
u8
event
;
};
static
struct
sony_nc_event
*
sony_nc_events
;
/* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence
* for Fn keys
*/
static
int
sony_nc_C_enable
(
const
struct
dmi_system_id
*
id
)
{
int
result
=
0
;
printk
(
KERN_NOTICE
DRV_PFX
"detected %s
\n
"
,
id
->
ident
);
sony_nc_events
=
id
->
driver_data
;
if
(
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN02"
,
0x4
,
&
result
)
<
0
||
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN07"
,
0x2
,
&
result
)
<
0
||
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN02"
,
0x10
,
&
result
)
<
0
||
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN07"
,
0x0
,
&
result
)
<
0
||
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN03"
,
0x2
,
&
result
)
<
0
||
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN07"
,
0x101
,
&
result
)
<
0
)
{
printk
(
KERN_WARNING
DRV_PFX
"failed to initialize SNC, some "
"functionalities may be missing
\n
"
);
return
1
;
}
return
0
;
}
static
struct
sony_nc_event
sony_C_events
[]
=
{
static
struct
sony_nc_event
sony_100_events
[]
=
{
{
0x90
,
SONYPI_EVENT_PKEY_P1
},
{
0x10
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x91
,
SONYPI_EVENT_PKEY_P2
},
{
0x11
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x81
,
SONYPI_EVENT_FNKEY_F1
},
{
0x01
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x82
,
SONYPI_EVENT_FNKEY_F2
},
{
0x02
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x83
,
SONYPI_EVENT_FNKEY_F3
},
{
0x03
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x84
,
SONYPI_EVENT_FNKEY_F4
},
{
0x04
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x85
,
SONYPI_EVENT_FNKEY_F5
},
{
0x05
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x86
,
SONYPI_EVENT_FNKEY_F6
},
{
0x06
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x87
,
SONYPI_EVENT_FNKEY_F7
},
{
0x07
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x89
,
SONYPI_EVENT_FNKEY_F9
},
{
0x09
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x8A
,
SONYPI_EVENT_FNKEY_F10
},
{
0x0A
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x8C
,
SONYPI_EVENT_FNKEY_F12
},
{
0x0C
,
SONYPI_EVENT_FNKEY_RELEASED
},
{
0x9f
,
SONYPI_EVENT_CD_EJECT_PRESSED
},
{
0x1f
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0
,
0
},
};
/* SNC-only model map */
static
const
struct
dmi_system_id
sony_nc_ids
[]
=
{
{
.
ident
=
"Sony Vaio FE Series"
,
.
callback
=
sony_nc_C_enable
,
.
driver_data
=
sony_C_events
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Sony Corporation"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"VGN-FE"
),
},
},
{
.
ident
=
"Sony Vaio FZ Series"
,
.
callback
=
sony_nc_C_enable
,
.
driver_data
=
sony_C_events
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Sony Corporation"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"VGN-FZ"
),
},
},
{
.
ident
=
"Sony Vaio C Series"
,
.
callback
=
sony_nc_C_enable
,
.
driver_data
=
sony_C_events
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Sony Corporation"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"VGN-C"
),
},
},
{
.
ident
=
"Sony Vaio N Series"
,
.
callback
=
sony_nc_C_enable
,
.
driver_data
=
sony_C_events
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Sony Corporation"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"VGN-N"
),
},
},
{
}
static
struct
sony_nc_event
sony_127_events
[]
=
{
{
0x81
,
SONYPI_EVENT_MODEKEY_PRESSED
},
{
0x01
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x82
,
SONYPI_EVENT_PKEY_P1
},
{
0x02
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x83
,
SONYPI_EVENT_PKEY_P2
},
{
0x03
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x84
,
SONYPI_EVENT_PKEY_P3
},
{
0x04
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x85
,
SONYPI_EVENT_PKEY_P4
},
{
0x05
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x86
,
SONYPI_EVENT_PKEY_P5
},
{
0x06
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x06
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0x87
,
SONYPI_EVENT_SETTINGKEY_PRESSED
},
{
0x07
,
SONYPI_EVENT_ANYBUTTON_RELEASED
},
{
0
,
0
},
};
/*
...
...
@@ -897,38 +916,59 @@ static const struct dmi_system_id sony_nc_ids[] = {
*/
static
void
sony_acpi_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
{
struct
sony_nc_event
*
evmap
;
u32
ev
=
event
;
if
(
ev
>=
0x90
)
{
/* New-style event */
int
result
;
int
key_handle
=
0
;
ev
-=
0x90
;
if
(
sony_find_snc_handle
(
0x100
)
==
ev
)
key_handle
=
0x100
;
if
(
sony_find_snc_handle
(
0x127
)
==
ev
)
key_handle
=
0x127
;
if
(
key_handle
)
{
struct
sony_nc_event
*
key_event
;
if
(
sony_call_snc_handle
(
key_handle
,
0x200
,
&
result
))
{
dprintk
(
"sony_acpi_notify, unable to decode"
" event 0x%.2x 0x%.2x
\n
"
,
key_handle
,
ev
);
/* restore the original event */
ev
=
event
;
}
else
{
ev
=
result
&
0xFF
;
if
(
ev
==
0x92
)
{
/* read the key pressed from EC.GECR
* A call to SN07 with 0x0202 will do it as well respecting
* the current protocol on different OSes
*
* Note: the path for GECR may be
* \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends)
* \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR)
*
* TODO: we may want to do the same for the older GHKE -need
* dmi list- so this snippet may become one more callback.
*/
if
(
acpi_callsetfunc
(
handle
,
"SN07"
,
0x0202
,
&
result
)
<
0
)
dprintk
(
"sony_acpi_notify, unable to decode event 0x%.2x
\n
"
,
ev
);
if
(
key_handle
==
0x100
)
key_event
=
sony_100_events
;
else
ev
=
result
&
0xFF
;
}
key_event
=
sony_127_events
;
if
(
sony_nc_events
)
for
(
evmap
=
sony_nc_events
;
evmap
->
event
;
evmap
++
)
{
if
(
evmap
->
data
==
ev
)
{
ev
=
evmap
->
event
;
for
(;
key_event
->
data
;
key_event
++
)
{
if
(
key_event
->
data
==
ev
)
{
ev
=
key_event
->
event
;
break
;
}
}
dprintk
(
"sony_acpi_notify, event: 0x%.2x
\n
"
,
ev
);
if
(
!
key_event
->
data
)
printk
(
KERN_INFO
DRV_PFX
"Unknown event: 0x%x 0x%x
\n
"
,
key_handle
,
ev
);
else
sony_laptop_report_input_event
(
ev
);
}
}
else
if
(
sony_find_snc_handle
(
0x124
)
==
ev
)
{
sony_nc_rfkill_update
();
return
;
}
}
else
sony_laptop_report_input_event
(
ev
);
dprintk
(
"sony_acpi_notify, event: 0x%.2x
\n
"
,
ev
);
acpi_bus_generate_proc_event
(
sony_nc_acpi_device
,
1
,
ev
);
}
...
...
@@ -953,9 +993,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
/*
* ACPI device
*/
static
int
sony_nc_function_setup
(
struct
acpi_device
*
device
)
{
int
result
;
/* Enable all events */
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"SN02"
,
0xffff
,
&
result
);
/* Setup hotkeys */
sony_call_snc_handle
(
0x0100
,
0
,
&
result
);
sony_call_snc_handle
(
0x0101
,
0
,
&
result
);
sony_call_snc_handle
(
0x0102
,
0x100
,
&
result
);
return
0
;
}
static
int
sony_nc_resume
(
struct
acpi_device
*
device
)
{
struct
sony_nc_value
*
item
;
acpi_handle
handle
;
for
(
item
=
sony_nc_values
;
item
->
name
;
item
++
)
{
int
ret
;
...
...
@@ -970,13 +1026,188 @@ static int sony_nc_resume(struct acpi_device *device)
}
}
if
(
ACPI_SUCCESS
(
acpi_get_handle
(
sony_nc_acpi_handle
,
"ECON"
,
&
handle
)))
{
if
(
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"ECON"
,
1
,
NULL
))
dprintk
(
"ECON Method failed
\n
"
);
}
if
(
ACPI_SUCCESS
(
acpi_get_handle
(
sony_nc_acpi_handle
,
"SN00"
,
&
handle
)))
{
dprintk
(
"Doing SNC setup
\n
"
);
sony_nc_function_setup
(
device
);
}
/* set the last requested brightness level */
if
(
sony_backlight_device
&&
!
sony_backlight_update_status
(
sony_backlight_device
))
printk
(
KERN_WARNING
DRV_PFX
"unable to restore brightness level
\n
"
);
/* re-initialize models with specific requirements */
dmi_check_system
(
sony_nc_ids
);
return
0
;
}
static
void
sony_nc_rfkill_cleanup
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
SONY_RFKILL_MAX
;
i
++
)
{
if
(
sony_rfkill_devices
[
i
])
rfkill_unregister
(
sony_rfkill_devices
[
i
]);
}
}
static
int
sony_nc_rfkill_get
(
void
*
data
,
enum
rfkill_state
*
state
)
{
int
result
;
int
argument
=
sony_rfkill_address
[(
long
)
data
];
sony_call_snc_handle
(
0x124
,
0x200
,
&
result
);
if
(
result
&
0x1
)
{
sony_call_snc_handle
(
0x124
,
argument
,
&
result
);
if
(
result
&
0xf
)
*
state
=
RFKILL_STATE_UNBLOCKED
;
else
*
state
=
RFKILL_STATE_SOFT_BLOCKED
;
}
else
{
*
state
=
RFKILL_STATE_HARD_BLOCKED
;
}
return
0
;
}
static
int
sony_nc_rfkill_set
(
void
*
data
,
enum
rfkill_state
state
)
{
int
result
;
int
argument
=
sony_rfkill_address
[(
long
)
data
]
+
0x100
;
if
(
state
==
RFKILL_STATE_UNBLOCKED
)
argument
|=
0xff0000
;
return
sony_call_snc_handle
(
0x124
,
argument
,
&
result
);
}
static
int
sony_nc_setup_wifi_rfkill
(
struct
acpi_device
*
device
)
{
int
err
=
0
;
struct
rfkill
*
sony_wifi_rfkill
;
sony_wifi_rfkill
=
rfkill_allocate
(
&
device
->
dev
,
RFKILL_TYPE_WLAN
);
if
(
!
sony_wifi_rfkill
)
return
-
1
;
sony_wifi_rfkill
->
name
=
"sony-wifi"
;
sony_wifi_rfkill
->
toggle_radio
=
sony_nc_rfkill_set
;
sony_wifi_rfkill
->
get_state
=
sony_nc_rfkill_get
;
sony_wifi_rfkill
->
user_claim_unsupported
=
1
;
sony_wifi_rfkill
->
data
=
(
void
*
)
SONY_WIFI
;
err
=
rfkill_register
(
sony_wifi_rfkill
);
if
(
err
)
rfkill_free
(
sony_wifi_rfkill
);
else
sony_rfkill_devices
[
SONY_WIFI
]
=
sony_wifi_rfkill
;
return
err
;
}
static
int
sony_nc_setup_bluetooth_rfkill
(
struct
acpi_device
*
device
)
{
int
err
=
0
;
struct
rfkill
*
sony_bluetooth_rfkill
;
sony_bluetooth_rfkill
=
rfkill_allocate
(
&
device
->
dev
,
RFKILL_TYPE_BLUETOOTH
);
if
(
!
sony_bluetooth_rfkill
)
return
-
1
;
sony_bluetooth_rfkill
->
name
=
"sony-bluetooth"
;
sony_bluetooth_rfkill
->
toggle_radio
=
sony_nc_rfkill_set
;
sony_bluetooth_rfkill
->
get_state
=
sony_nc_rfkill_get
;
sony_bluetooth_rfkill
->
user_claim_unsupported
=
1
;
sony_bluetooth_rfkill
->
data
=
(
void
*
)
SONY_BLUETOOTH
;
err
=
rfkill_register
(
sony_bluetooth_rfkill
);
if
(
err
)
rfkill_free
(
sony_bluetooth_rfkill
);
else
sony_rfkill_devices
[
SONY_BLUETOOTH
]
=
sony_bluetooth_rfkill
;
return
err
;
}
static
int
sony_nc_setup_wwan_rfkill
(
struct
acpi_device
*
device
)
{
int
err
=
0
;
struct
rfkill
*
sony_wwan_rfkill
;
sony_wwan_rfkill
=
rfkill_allocate
(
&
device
->
dev
,
RFKILL_TYPE_WWAN
);
if
(
!
sony_wwan_rfkill
)
return
-
1
;
sony_wwan_rfkill
->
name
=
"sony-wwan"
;
sony_wwan_rfkill
->
toggle_radio
=
sony_nc_rfkill_set
;
sony_wwan_rfkill
->
get_state
=
sony_nc_rfkill_get
;
sony_wwan_rfkill
->
user_claim_unsupported
=
1
;
sony_wwan_rfkill
->
data
=
(
void
*
)
SONY_WWAN
;
err
=
rfkill_register
(
sony_wwan_rfkill
);
if
(
err
)
rfkill_free
(
sony_wwan_rfkill
);
else
sony_rfkill_devices
[
SONY_WWAN
]
=
sony_wwan_rfkill
;
return
err
;
}
static
int
sony_nc_setup_wimax_rfkill
(
struct
acpi_device
*
device
)
{
int
err
=
0
;
struct
rfkill
*
sony_wimax_rfkill
;
sony_wimax_rfkill
=
rfkill_allocate
(
&
device
->
dev
,
RFKILL_TYPE_WIMAX
);
if
(
!
sony_wimax_rfkill
)
return
-
1
;
sony_wimax_rfkill
->
name
=
"sony-wimax"
;
sony_wimax_rfkill
->
toggle_radio
=
sony_nc_rfkill_set
;
sony_wimax_rfkill
->
get_state
=
sony_nc_rfkill_get
;
sony_wimax_rfkill
->
user_claim_unsupported
=
1
;
sony_wimax_rfkill
->
data
=
(
void
*
)
SONY_WIMAX
;
err
=
rfkill_register
(
sony_wimax_rfkill
);
if
(
err
)
rfkill_free
(
sony_wimax_rfkill
);
else
sony_rfkill_devices
[
SONY_WIMAX
]
=
sony_wimax_rfkill
;
return
err
;
}
static
void
sony_nc_rfkill_update
()
{
int
i
;
enum
rfkill_state
state
;
for
(
i
=
0
;
i
<
SONY_RFKILL_MAX
;
i
++
)
{
if
(
sony_rfkill_devices
[
i
])
{
sony_rfkill_devices
[
i
]
->
get_state
(
sony_rfkill_devices
[
i
]
->
data
,
&
state
);
rfkill_force_state
(
sony_rfkill_devices
[
i
],
state
);
}
}
}
static
int
sony_nc_rfkill_setup
(
struct
acpi_device
*
device
)
{
int
result
,
ret
;
if
(
sony_find_snc_handle
(
0x124
)
==
-
1
)
return
-
1
;
ret
=
sony_call_snc_handle
(
0x124
,
0xb00
,
&
result
);
if
(
ret
)
{
printk
(
KERN_INFO
DRV_PFX
"Unable to enumerate rfkill devices: %x
\n
"
,
ret
);
return
ret
;
}
if
(
result
&
0x1
)
sony_nc_setup_wifi_rfkill
(
device
);
if
(
result
&
0x2
)
sony_nc_setup_bluetooth_rfkill
(
device
);
if
(
result
&
0x1c
)
sony_nc_setup_wwan_rfkill
(
device
);
if
(
result
&
0x20
)
sony_nc_setup_wimax_rfkill
(
device
);
return
0
;
}
...
...
@@ -1024,11 +1255,24 @@ static int sony_nc_add(struct acpi_device *device)
dprintk
(
"_INI Method failed
\n
"
);
}
if
(
ACPI_SUCCESS
(
acpi_get_handle
(
sony_nc_acpi_handle
,
"ECON"
,
&
handle
)))
{
if
(
acpi_callsetfunc
(
sony_nc_acpi_handle
,
"ECON"
,
1
,
NULL
))
dprintk
(
"ECON Method failed
\n
"
);
}
if
(
ACPI_SUCCESS
(
acpi_get_handle
(
sony_nc_acpi_handle
,
"SN00"
,
&
handle
)))
{
dprintk
(
"Doing SNC setup
\n
"
);
sony_nc_function_setup
(
device
);
sony_nc_rfkill_setup
(
device
);
}
/* setup input devices and helper fifo */
result
=
sony_laptop_setup_input
(
device
);
if
(
result
)
{
printk
(
KERN_ERR
DRV_PFX
"Unabe to create input devices.
\n
"
);
"Unab
l
e to create input devices.
\n
"
);
goto
outwalk
;
}
...
...
@@ -1063,9 +1307,6 @@ static int sony_nc_add(struct acpi_device *device)
}
/* initialize models with specific requirements */
dmi_check_system
(
sony_nc_ids
);
result
=
sony_pf_add
();
if
(
result
)
goto
outbacklight
;
...
...
@@ -1131,6 +1372,7 @@ static int sony_nc_add(struct acpi_device *device)
sony_laptop_remove_input
();
outwalk:
sony_nc_rfkill_cleanup
();
return
result
;
}
...
...
@@ -1156,6 +1398,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
sony_pf_remove
();
sony_laptop_remove_input
();
sony_nc_rfkill_cleanup
();
dprintk
(
SONY_NC_DRIVER_NAME
" removed.
\n
"
);
return
0
;
...
...
@@ -1195,7 +1438,6 @@ static struct acpi_driver sony_nc_driver = {
#define SONYPI_TYPE1_OFFSET 0x04
#define SONYPI_TYPE2_OFFSET 0x12
#define SONYPI_TYPE3_OFFSET 0x12
#define SONYPI_TYPE4_OFFSET 0x12
struct
sony_pic_ioport
{
struct
acpi_resource_io
io1
;
...
...
@@ -1328,6 +1570,7 @@ static struct sonypi_event sonypi_pkeyev[] = {
{
0x01
,
SONYPI_EVENT_PKEY_P1
},
{
0x02
,
SONYPI_EVENT_PKEY_P2
},
{
0x04
,
SONYPI_EVENT_PKEY_P3
},
{
0x20
,
SONYPI_EVENT_PKEY_P1
},
{
0
,
0
}
};
...
...
@@ -1371,6 +1614,7 @@ static struct sonypi_event sonypi_zoomev[] = {
{
0x39
,
SONYPI_EVENT_ZOOM_PRESSED
},
{
0x10
,
SONYPI_EVENT_ZOOM_IN_PRESSED
},
{
0x20
,
SONYPI_EVENT_ZOOM_OUT_PRESSED
},
{
0x04
,
SONYPI_EVENT_ZOOM_PRESSED
},
{
0
,
0
}
};
...
...
@@ -1401,6 +1645,19 @@ static struct sonypi_event sonypi_batteryev[] = {
{
0
,
0
}
};
/* The set of possible volume events */
static
struct
sonypi_event
sonypi_volumeev
[]
=
{
{
0x01
,
SONYPI_EVENT_VOLUME_INC_PRESSED
},
{
0x02
,
SONYPI_EVENT_VOLUME_DEC_PRESSED
},
{
0
,
0
}
};
/* The set of possible brightness events */
static
struct
sonypi_event
sonypi_brightnessev
[]
=
{
{
0x80
,
SONYPI_EVENT_BRIGHTNESS_PRESSED
},
{
0
,
0
}
};
static
struct
sonypi_eventtypes
type1_events
[]
=
{
{
0
,
0xffffffff
,
sonypi_releaseev
},
{
0x70
,
SONYPI_MEYE_MASK
,
sonypi_meyeev
},
...
...
@@ -1438,17 +1695,11 @@ static struct sonypi_eventtypes type3_events[] = {
{
0x31
,
SONYPI_MEMORYSTICK_MASK
,
sonypi_memorystickev
},
{
0x41
,
SONYPI_BATTERY_MASK
,
sonypi_batteryev
},
{
0x31
,
SONYPI_PKEY_MASK
,
sonypi_pkeyev
},
{
0
},
};
static
struct
sonypi_eventtypes
type4_events
[]
=
{
{
0
,
0xffffffff
,
sonypi_releaseev
},
{
0x21
,
SONYPI_FNKEY_MASK
,
sonypi_fnkeyev
},
{
0x31
,
SONYPI_WIRELESS_MASK
,
sonypi_wlessev
},
{
0x31
,
SONYPI_MEMORYSTICK_MASK
,
sonypi_memorystickev
},
{
0x41
,
SONYPI_BATTERY_MASK
,
sonypi_batteryev
},
{
0x05
,
SONYPI_PKEY_MASK
,
sonypi_pkeyev
},
{
0x05
,
SONYPI_ZOOM_MASK
,
sonypi_zoomev
},
{
0x05
,
SONYPI_CAPTURE_MASK
,
sonypi_captureev
},
{
0x05
,
SONYPI_PKEY_MASK
,
sonypi_volumeev
},
{
0x05
,
SONYPI_PKEY_MASK
,
sonypi_brightnessev
},
{
0
},
};
...
...
@@ -1511,11 +1762,11 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
/*
* minidrivers for SPIC models
*/
static
int
type
4
_handle_irq
(
const
u8
data_mask
,
const
u8
ev
)
static
int
type
3
_handle_irq
(
const
u8
data_mask
,
const
u8
ev
)
{
/*
* 0x31 could mean we have to take some extra action and wait for
* the next irq for some Type
4
models, it will generate a new
* the next irq for some Type
3
models, it will generate a new
* irq and we can read new data from the device:
* - 0x5c and 0x5f requires 0xA0
* - 0x61 requires 0xB3
...
...
@@ -1545,16 +1796,10 @@ static struct device_ctrl spic_types[] = {
},
{
.
model
=
SONYPI_DEVICE_TYPE3
,
.
handle_irq
=
NULL
,
.
handle_irq
=
type3_handle_irq
,
.
evport_offset
=
SONYPI_TYPE3_OFFSET
,
.
event_types
=
type3_events
,
},
{
.
model
=
SONYPI_DEVICE_TYPE4
,
.
handle_irq
=
type4_handle_irq
,
.
evport_offset
=
SONYPI_TYPE4_OFFSET
,
.
event_types
=
type4_events
,
},
};
static
void
sony_pic_detect_device_type
(
struct
sony_pic_dev
*
dev
)
...
...
@@ -1578,14 +1823,21 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
pcidev
=
pci_get_device
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH7_1
,
NULL
);
if
(
pcidev
)
{
dev
->
control
=
&
spic_types
[
3
];
dev
->
control
=
&
spic_types
[
2
];
goto
out
;
}
pcidev
=
pci_get_device
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH8_4
,
NULL
);
if
(
pcidev
)
{
dev
->
control
=
&
spic_types
[
3
];
dev
->
control
=
&
spic_types
[
2
];
goto
out
;
}
pcidev
=
pci_get_device
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH9_1
,
NULL
);
if
(
pcidev
)
{
dev
->
control
=
&
spic_types
[
2
];
goto
out
;
}
...
...
@@ -1598,8 +1850,7 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
printk
(
KERN_INFO
DRV_PFX
"detected Type%d model
\n
"
,
dev
->
control
->
model
==
SONYPI_DEVICE_TYPE1
?
1
:
dev
->
control
->
model
==
SONYPI_DEVICE_TYPE2
?
2
:
dev
->
control
->
model
==
SONYPI_DEVICE_TYPE3
?
3
:
4
);
dev
->
control
->
model
==
SONYPI_DEVICE_TYPE2
?
2
:
3
);
}
/* camera tests and poweron/poweroff */
...
...
@@ -1754,17 +2005,14 @@ int sony_pic_camera_command(int command, u8 value)
EXPORT_SYMBOL
(
sony_pic_camera_command
);
/* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */
static
void
sony_pic_set_wwanpower
(
u8
state
)
static
void
__
sony_pic_set_wwanpower
(
u8
state
)
{
state
=
!!
state
;
mutex_lock
(
&
spic_dev
.
lock
);
if
(
spic_dev
.
wwan_power
==
state
)
{
mutex_unlock
(
&
spic_dev
.
lock
);
if
(
spic_dev
.
wwan_power
==
state
)
return
;
}
sony_pic_call2
(
0xB0
,
state
);
sony_pic_call1
(
0x82
);
spic_dev
.
wwan_power
=
state
;
mutex_unlock
(
&
spic_dev
.
lock
);
}
static
ssize_t
sony_pic_wwanpower_store
(
struct
device
*
dev
,
...
...
@@ -1776,7 +2024,9 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev,
return
-
EINVAL
;
value
=
simple_strtoul
(
buffer
,
NULL
,
10
);
sony_pic_set_wwanpower
(
value
);
mutex_lock
(
&
spic_dev
.
lock
);
__sony_pic_set_wwanpower
(
value
);
mutex_unlock
(
&
spic_dev
.
lock
);
return
count
;
}
...
...
@@ -1934,10 +2184,15 @@ static int sonypi_misc_release(struct inode *inode, struct file *file)
static
int
sonypi_misc_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
/* Flush input queue on first open */
lock_kernel
();
unsigned
long
flags
;
spin_lock_irqsave
(
sonypi_compat
.
fifo
->
lock
,
flags
);
if
(
atomic_inc_return
(
&
sonypi_compat
.
open_count
)
==
1
)
kfifo_reset
(
sonypi_compat
.
fifo
);
unlock_kernel
();
__kfifo_reset
(
sonypi_compat
.
fifo
);
spin_unlock_irqrestore
(
sonypi_compat
.
fifo
->
lock
,
flags
);
return
0
;
}
...
...
@@ -1990,8 +2245,8 @@ static int ec_read16(u8 addr, u16 *value)
return
0
;
}
static
int
sonypi_misc_ioctl
(
struct
inode
*
ip
,
struct
file
*
fp
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
long
sonypi_misc_ioctl
(
struct
file
*
fp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
ret
=
0
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
...
...
@@ -2125,7 +2380,7 @@ static const struct file_operations sonypi_misc_fops = {
.
open
=
sonypi_misc_open
,
.
release
=
sonypi_misc_release
,
.
fasync
=
sonypi_misc_fasync
,
.
ioctl
=
sonypi_misc_ioctl
,
.
unlocked_ioctl
=
sonypi_misc_ioctl
,
};
static
struct
miscdevice
sonypi_misc_device
=
{
...
...
@@ -2566,7 +2821,7 @@ static int sony_pic_add(struct acpi_device *device)
result
=
sony_pic_possible_resources
(
device
);
if
(
result
)
{
printk
(
KERN_ERR
DRV_PFX
"Unabe to read possible resources.
\n
"
);
"Unab
l
e to read possible resources.
\n
"
);
goto
err_free_resources
;
}
...
...
@@ -2574,7 +2829,7 @@ static int sony_pic_add(struct acpi_device *device)
result
=
sony_laptop_setup_input
(
device
);
if
(
result
)
{
printk
(
KERN_ERR
DRV_PFX
"Unabe to create input devices.
\n
"
);
"Unab
l
e to create input devices.
\n
"
);
goto
err_free_resources
;
}
...
...
include/linux/sonypi.h
View file @
7c27fd19
...
...
@@ -103,6 +103,14 @@
#define SONYPI_EVENT_WIRELESS_OFF 61
#define SONYPI_EVENT_ZOOM_IN_PRESSED 62
#define SONYPI_EVENT_ZOOM_OUT_PRESSED 63
#define SONYPI_EVENT_CD_EJECT_PRESSED 64
#define SONYPI_EVENT_MODEKEY_PRESSED 65
#define SONYPI_EVENT_PKEY_P4 66
#define SONYPI_EVENT_PKEY_P5 67
#define SONYPI_EVENT_SETTINGKEY_PRESSED 68
#define SONYPI_EVENT_VOLUME_INC_PRESSED 69
#define SONYPI_EVENT_VOLUME_DEC_PRESSED 70
#define SONYPI_EVENT_BRIGHTNESS_PRESSED 71
/* get/set brightness */
#define SONYPI_IOCGBRT _IOR('v', 0, __u8)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment