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
6d3bf681
Commit
6d3bf681
authored
Dec 24, 2009
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'classmate' into release
parents
da3df858
529aa8cb
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
628 additions
and
0 deletions
+628
-0
MAINTAINERS
MAINTAINERS
+6
-0
drivers/platform/x86/Kconfig
drivers/platform/x86/Kconfig
+12
-0
drivers/platform/x86/Makefile
drivers/platform/x86/Makefile
+1
-0
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/classmate-laptop.c
+609
-0
No files found.
MAINTAINERS
View file @
6d3bf681
...
...
@@ -1472,6 +1472,12 @@ L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/fnic/
CMPC ACPI DRIVER
M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
M: Daniel Oliveira Nascimento <don@syst.com.br>
S: Supported
F: drivers/platform/x86/classmate-laptop.c
CODA FILE SYSTEM
M: Jan Harkes <jaharkes@cs.cmu.edu>
M: coda@cs.cmu.edu
...
...
drivers/platform/x86/Kconfig
View file @
6d3bf681
...
...
@@ -464,4 +464,16 @@ config TOSHIBA_BT_RFKILL
If you have a modern Toshiba laptop with a Bluetooth and an
RFKill switch (such as the Portege R500), say Y.
config ACPI_CMPC
tristate "CMPC Laptop Extras"
depends on X86 && ACPI
select INPUT
select BACKLIGHT_CLASS_DEVICE
default n
help
Support for Intel Classmate PC ACPI devices, including some
keys as input device, backlight device, tablet and accelerometer
devices.
endif # X86_PLATFORM_DEVICES
drivers/platform/x86/Makefile
View file @
6d3bf681
...
...
@@ -5,6 +5,7 @@
obj-$(CONFIG_ASUS_LAPTOP)
+=
asus-laptop.o
obj-$(CONFIG_EEEPC_LAPTOP)
+=
eeepc-laptop.o
obj-$(CONFIG_MSI_LAPTOP)
+=
msi-laptop.o
obj-$(CONFIG_ACPI_CMPC)
+=
classmate-laptop.o
obj-$(CONFIG_COMPAL_LAPTOP)
+=
compal-laptop.o
obj-$(CONFIG_DELL_LAPTOP)
+=
dell-laptop.o
obj-$(CONFIG_DELL_WMI)
+=
dell-wmi.o
...
...
drivers/platform/x86/classmate-laptop.c
0 → 100644
View file @
6d3bf681
/*
* Copyright (C) 2009 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <acpi/acpi_drivers.h>
#include <linux/backlight.h>
#include <linux/input.h>
MODULE_LICENSE
(
"GPL"
);
struct
cmpc_accel
{
int
sensitivity
;
};
#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5
/*
* Generic input device code.
*/
typedef
void
(
*
input_device_init
)(
struct
input_dev
*
dev
);
static
int
cmpc_add_acpi_notify_device
(
struct
acpi_device
*
acpi
,
char
*
name
,
input_device_init
idev_init
)
{
struct
input_dev
*
inputdev
;
int
error
;
inputdev
=
input_allocate_device
();
if
(
!
inputdev
)
return
-
ENOMEM
;
inputdev
->
name
=
name
;
inputdev
->
dev
.
parent
=
&
acpi
->
dev
;
idev_init
(
inputdev
);
error
=
input_register_device
(
inputdev
);
if
(
error
)
{
input_free_device
(
inputdev
);
return
error
;
}
dev_set_drvdata
(
&
acpi
->
dev
,
inputdev
);
return
0
;
}
static
int
cmpc_remove_acpi_notify_device
(
struct
acpi_device
*
acpi
)
{
struct
input_dev
*
inputdev
=
dev_get_drvdata
(
&
acpi
->
dev
);
input_unregister_device
(
inputdev
);
return
0
;
}
/*
* Accelerometer code.
*/
static
acpi_status
cmpc_start_accel
(
acpi_handle
handle
)
{
union
acpi_object
param
[
2
];
struct
acpi_object_list
input
;
acpi_status
status
;
param
[
0
].
type
=
ACPI_TYPE_INTEGER
;
param
[
0
].
integer
.
value
=
0x3
;
param
[
1
].
type
=
ACPI_TYPE_INTEGER
;
input
.
count
=
2
;
input
.
pointer
=
param
;
status
=
acpi_evaluate_object
(
handle
,
"ACMD"
,
&
input
,
NULL
);
return
status
;
}
static
acpi_status
cmpc_stop_accel
(
acpi_handle
handle
)
{
union
acpi_object
param
[
2
];
struct
acpi_object_list
input
;
acpi_status
status
;
param
[
0
].
type
=
ACPI_TYPE_INTEGER
;
param
[
0
].
integer
.
value
=
0x4
;
param
[
1
].
type
=
ACPI_TYPE_INTEGER
;
input
.
count
=
2
;
input
.
pointer
=
param
;
status
=
acpi_evaluate_object
(
handle
,
"ACMD"
,
&
input
,
NULL
);
return
status
;
}
static
acpi_status
cmpc_accel_set_sensitivity
(
acpi_handle
handle
,
int
val
)
{
union
acpi_object
param
[
2
];
struct
acpi_object_list
input
;
param
[
0
].
type
=
ACPI_TYPE_INTEGER
;
param
[
0
].
integer
.
value
=
0x02
;
param
[
1
].
type
=
ACPI_TYPE_INTEGER
;
param
[
1
].
integer
.
value
=
val
;
input
.
count
=
2
;
input
.
pointer
=
param
;
return
acpi_evaluate_object
(
handle
,
"ACMD"
,
&
input
,
NULL
);
}
static
acpi_status
cmpc_get_accel
(
acpi_handle
handle
,
unsigned
char
*
x
,
unsigned
char
*
y
,
unsigned
char
*
z
)
{
union
acpi_object
param
[
2
];
struct
acpi_object_list
input
;
struct
acpi_buffer
output
=
{
ACPI_ALLOCATE_BUFFER
,
0
};
unsigned
char
*
locs
;
acpi_status
status
;
param
[
0
].
type
=
ACPI_TYPE_INTEGER
;
param
[
0
].
integer
.
value
=
0x01
;
param
[
1
].
type
=
ACPI_TYPE_INTEGER
;
input
.
count
=
2
;
input
.
pointer
=
param
;
status
=
acpi_evaluate_object
(
handle
,
"ACMD"
,
&
input
,
&
output
);
if
(
ACPI_SUCCESS
(
status
))
{
union
acpi_object
*
obj
;
obj
=
output
.
pointer
;
locs
=
obj
->
buffer
.
pointer
;
*
x
=
locs
[
0
];
*
y
=
locs
[
1
];
*
z
=
locs
[
2
];
kfree
(
output
.
pointer
);
}
return
status
;
}
static
void
cmpc_accel_handler
(
struct
acpi_device
*
dev
,
u32
event
)
{
if
(
event
==
0x81
)
{
unsigned
char
x
,
y
,
z
;
acpi_status
status
;
status
=
cmpc_get_accel
(
dev
->
handle
,
&
x
,
&
y
,
&
z
);
if
(
ACPI_SUCCESS
(
status
))
{
struct
input_dev
*
inputdev
=
dev_get_drvdata
(
&
dev
->
dev
);
input_report_abs
(
inputdev
,
ABS_X
,
x
);
input_report_abs
(
inputdev
,
ABS_Y
,
y
);
input_report_abs
(
inputdev
,
ABS_Z
,
z
);
input_sync
(
inputdev
);
}
}
}
static
ssize_t
cmpc_accel_sensitivity_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
acpi_device
*
acpi
;
struct
input_dev
*
inputdev
;
struct
cmpc_accel
*
accel
;
acpi
=
to_acpi_device
(
dev
);
inputdev
=
dev_get_drvdata
(
&
acpi
->
dev
);
accel
=
dev_get_drvdata
(
&
inputdev
->
dev
);
return
sprintf
(
buf
,
"%d
\n
"
,
accel
->
sensitivity
);
}
static
ssize_t
cmpc_accel_sensitivity_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
acpi_device
*
acpi
;
struct
input_dev
*
inputdev
;
struct
cmpc_accel
*
accel
;
unsigned
long
sensitivity
;
int
r
;
acpi
=
to_acpi_device
(
dev
);
inputdev
=
dev_get_drvdata
(
&
acpi
->
dev
);
accel
=
dev_get_drvdata
(
&
inputdev
->
dev
);
r
=
strict_strtoul
(
buf
,
0
,
&
sensitivity
);
if
(
r
)
return
r
;
accel
->
sensitivity
=
sensitivity
;
cmpc_accel_set_sensitivity
(
acpi
->
handle
,
sensitivity
);
return
strnlen
(
buf
,
count
);
}
struct
device_attribute
cmpc_accel_sensitivity_attr
=
{
.
attr
=
{
.
name
=
"sensitivity"
,
.
mode
=
0660
},
.
show
=
cmpc_accel_sensitivity_show
,
.
store
=
cmpc_accel_sensitivity_store
};
static
int
cmpc_accel_open
(
struct
input_dev
*
input
)
{
struct
acpi_device
*
acpi
;
acpi
=
to_acpi_device
(
input
->
dev
.
parent
);
if
(
ACPI_SUCCESS
(
cmpc_start_accel
(
acpi
->
handle
)))
return
0
;
return
-
EIO
;
}
static
void
cmpc_accel_close
(
struct
input_dev
*
input
)
{
struct
acpi_device
*
acpi
;
acpi
=
to_acpi_device
(
input
->
dev
.
parent
);
cmpc_stop_accel
(
acpi
->
handle
);
}
static
void
cmpc_accel_idev_init
(
struct
input_dev
*
inputdev
)
{
set_bit
(
EV_ABS
,
inputdev
->
evbit
);
input_set_abs_params
(
inputdev
,
ABS_X
,
0
,
255
,
8
,
0
);
input_set_abs_params
(
inputdev
,
ABS_Y
,
0
,
255
,
8
,
0
);
input_set_abs_params
(
inputdev
,
ABS_Z
,
0
,
255
,
8
,
0
);
inputdev
->
open
=
cmpc_accel_open
;
inputdev
->
close
=
cmpc_accel_close
;
}
static
int
cmpc_accel_add
(
struct
acpi_device
*
acpi
)
{
int
error
;
struct
input_dev
*
inputdev
;
struct
cmpc_accel
*
accel
;
accel
=
kmalloc
(
sizeof
(
*
accel
),
GFP_KERNEL
);
if
(
!
accel
)
return
-
ENOMEM
;
accel
->
sensitivity
=
CMPC_ACCEL_SENSITIVITY_DEFAULT
;
cmpc_accel_set_sensitivity
(
acpi
->
handle
,
accel
->
sensitivity
);
error
=
device_create_file
(
&
acpi
->
dev
,
&
cmpc_accel_sensitivity_attr
);
if
(
error
)
goto
failed_file
;
error
=
cmpc_add_acpi_notify_device
(
acpi
,
"cmpc_accel"
,
cmpc_accel_idev_init
);
if
(
error
)
goto
failed_input
;
inputdev
=
dev_get_drvdata
(
&
acpi
->
dev
);
dev_set_drvdata
(
&
inputdev
->
dev
,
accel
);
return
0
;
failed_input:
device_remove_file
(
&
acpi
->
dev
,
&
cmpc_accel_sensitivity_attr
);
failed_file:
kfree
(
accel
);
return
error
;
}
static
int
cmpc_accel_remove
(
struct
acpi_device
*
acpi
,
int
type
)
{
struct
input_dev
*
inputdev
;
struct
cmpc_accel
*
accel
;
inputdev
=
dev_get_drvdata
(
&
acpi
->
dev
);
accel
=
dev_get_drvdata
(
&
inputdev
->
dev
);
device_remove_file
(
&
acpi
->
dev
,
&
cmpc_accel_sensitivity_attr
);
return
cmpc_remove_acpi_notify_device
(
acpi
);
}
static
const
struct
acpi_device_id
cmpc_accel_device_ids
[]
=
{
{
"ACCE0000"
,
0
},
{
""
,
0
}
};
MODULE_DEVICE_TABLE
(
acpi
,
cmpc_accel_device_ids
);
static
struct
acpi_driver
cmpc_accel_acpi_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"cmpc_accel"
,
.
class
=
"cmpc_accel"
,
.
ids
=
cmpc_accel_device_ids
,
.
ops
=
{
.
add
=
cmpc_accel_add
,
.
remove
=
cmpc_accel_remove
,
.
notify
=
cmpc_accel_handler
,
}
};
/*
* Tablet mode code.
*/
static
acpi_status
cmpc_get_tablet
(
acpi_handle
handle
,
unsigned
long
long
*
value
)
{
union
acpi_object
param
;
struct
acpi_object_list
input
;
unsigned
long
long
output
;
acpi_status
status
;
param
.
type
=
ACPI_TYPE_INTEGER
;
param
.
integer
.
value
=
0x01
;
input
.
count
=
1
;
input
.
pointer
=
&
param
;
status
=
acpi_evaluate_integer
(
handle
,
"TCMD"
,
&
input
,
&
output
);
if
(
ACPI_SUCCESS
(
status
))
*
value
=
output
;
return
status
;
}
static
void
cmpc_tablet_handler
(
struct
acpi_device
*
dev
,
u32
event
)
{
unsigned
long
long
val
=
0
;
struct
input_dev
*
inputdev
=
dev_get_drvdata
(
&
dev
->
dev
);
if
(
event
==
0x81
)
{
if
(
ACPI_SUCCESS
(
cmpc_get_tablet
(
dev
->
handle
,
&
val
)))
input_report_switch
(
inputdev
,
SW_TABLET_MODE
,
!
val
);
}
}
static
void
cmpc_tablet_idev_init
(
struct
input_dev
*
inputdev
)
{
unsigned
long
long
val
=
0
;
struct
acpi_device
*
acpi
;
set_bit
(
EV_SW
,
inputdev
->
evbit
);
set_bit
(
SW_TABLET_MODE
,
inputdev
->
swbit
);
acpi
=
to_acpi_device
(
inputdev
->
dev
.
parent
);
if
(
ACPI_SUCCESS
(
cmpc_get_tablet
(
acpi
->
handle
,
&
val
)))
input_report_switch
(
inputdev
,
SW_TABLET_MODE
,
!
val
);
}
static
int
cmpc_tablet_add
(
struct
acpi_device
*
acpi
)
{
return
cmpc_add_acpi_notify_device
(
acpi
,
"cmpc_tablet"
,
cmpc_tablet_idev_init
);
}
static
int
cmpc_tablet_remove
(
struct
acpi_device
*
acpi
,
int
type
)
{
return
cmpc_remove_acpi_notify_device
(
acpi
);
}
static
int
cmpc_tablet_resume
(
struct
acpi_device
*
acpi
)
{
struct
input_dev
*
inputdev
=
dev_get_drvdata
(
&
acpi
->
dev
);
unsigned
long
long
val
=
0
;
if
(
ACPI_SUCCESS
(
cmpc_get_tablet
(
acpi
->
handle
,
&
val
)))
input_report_switch
(
inputdev
,
SW_TABLET_MODE
,
!
val
);
return
0
;
}
static
const
struct
acpi_device_id
cmpc_tablet_device_ids
[]
=
{
{
"TBLT0000"
,
0
},
{
""
,
0
}
};
MODULE_DEVICE_TABLE
(
acpi
,
cmpc_tablet_device_ids
);
static
struct
acpi_driver
cmpc_tablet_acpi_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"cmpc_tablet"
,
.
class
=
"cmpc_tablet"
,
.
ids
=
cmpc_tablet_device_ids
,
.
ops
=
{
.
add
=
cmpc_tablet_add
,
.
remove
=
cmpc_tablet_remove
,
.
resume
=
cmpc_tablet_resume
,
.
notify
=
cmpc_tablet_handler
,
}
};
/*
* Backlight code.
*/
static
acpi_status
cmpc_get_brightness
(
acpi_handle
handle
,
unsigned
long
long
*
value
)
{
union
acpi_object
param
;
struct
acpi_object_list
input
;
unsigned
long
long
output
;
acpi_status
status
;
param
.
type
=
ACPI_TYPE_INTEGER
;
param
.
integer
.
value
=
0xC0
;
input
.
count
=
1
;
input
.
pointer
=
&
param
;
status
=
acpi_evaluate_integer
(
handle
,
"GRDI"
,
&
input
,
&
output
);
if
(
ACPI_SUCCESS
(
status
))
*
value
=
output
;
return
status
;
}
static
acpi_status
cmpc_set_brightness
(
acpi_handle
handle
,
unsigned
long
long
value
)
{
union
acpi_object
param
[
2
];
struct
acpi_object_list
input
;
acpi_status
status
;
unsigned
long
long
output
;
param
[
0
].
type
=
ACPI_TYPE_INTEGER
;
param
[
0
].
integer
.
value
=
0xC0
;
param
[
1
].
type
=
ACPI_TYPE_INTEGER
;
param
[
1
].
integer
.
value
=
value
;
input
.
count
=
2
;
input
.
pointer
=
param
;
status
=
acpi_evaluate_integer
(
handle
,
"GWRI"
,
&
input
,
&
output
);
return
status
;
}
static
int
cmpc_bl_get_brightness
(
struct
backlight_device
*
bd
)
{
acpi_status
status
;
acpi_handle
handle
;
unsigned
long
long
brightness
;
handle
=
bl_get_data
(
bd
);
status
=
cmpc_get_brightness
(
handle
,
&
brightness
);
if
(
ACPI_SUCCESS
(
status
))
return
brightness
;
else
return
-
1
;
}
static
int
cmpc_bl_update_status
(
struct
backlight_device
*
bd
)
{
acpi_status
status
;
acpi_handle
handle
;
handle
=
bl_get_data
(
bd
);
status
=
cmpc_set_brightness
(
handle
,
bd
->
props
.
brightness
);
if
(
ACPI_SUCCESS
(
status
))
return
0
;
else
return
-
1
;
}
static
struct
backlight_ops
cmpc_bl_ops
=
{
.
get_brightness
=
cmpc_bl_get_brightness
,
.
update_status
=
cmpc_bl_update_status
};
static
int
cmpc_bl_add
(
struct
acpi_device
*
acpi
)
{
struct
backlight_device
*
bd
;
bd
=
backlight_device_register
(
"cmpc_bl"
,
&
acpi
->
dev
,
acpi
->
handle
,
&
cmpc_bl_ops
);
bd
->
props
.
max_brightness
=
7
;
dev_set_drvdata
(
&
acpi
->
dev
,
bd
);
return
0
;
}
static
int
cmpc_bl_remove
(
struct
acpi_device
*
acpi
,
int
type
)
{
struct
backlight_device
*
bd
;
bd
=
dev_get_drvdata
(
&
acpi
->
dev
);
backlight_device_unregister
(
bd
);
return
0
;
}
static
const
struct
acpi_device_id
cmpc_device_ids
[]
=
{
{
"IPML200"
,
0
},
{
""
,
0
}
};
MODULE_DEVICE_TABLE
(
acpi
,
cmpc_device_ids
);
static
struct
acpi_driver
cmpc_bl_acpi_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"cmpc"
,
.
class
=
"cmpc"
,
.
ids
=
cmpc_device_ids
,
.
ops
=
{
.
add
=
cmpc_bl_add
,
.
remove
=
cmpc_bl_remove
}
};
/*
* Extra keys code.
*/
static
int
cmpc_keys_codes
[]
=
{
KEY_UNKNOWN
,
KEY_WLAN
,
KEY_SWITCHVIDEOMODE
,
KEY_BRIGHTNESSDOWN
,
KEY_BRIGHTNESSUP
,
KEY_VENDOR
,
KEY_MAX
};
static
void
cmpc_keys_handler
(
struct
acpi_device
*
dev
,
u32
event
)
{
struct
input_dev
*
inputdev
;
int
code
=
KEY_MAX
;
if
((
event
&
0x0F
)
<
ARRAY_SIZE
(
cmpc_keys_codes
))
code
=
cmpc_keys_codes
[
event
&
0x0F
];
inputdev
=
dev_get_drvdata
(
&
dev
->
dev
);;
input_report_key
(
inputdev
,
code
,
!
(
event
&
0x10
));
}
static
void
cmpc_keys_idev_init
(
struct
input_dev
*
inputdev
)
{
int
i
;
set_bit
(
EV_KEY
,
inputdev
->
evbit
);
for
(
i
=
0
;
cmpc_keys_codes
[
i
]
!=
KEY_MAX
;
i
++
)
set_bit
(
cmpc_keys_codes
[
i
],
inputdev
->
keybit
);
}
static
int
cmpc_keys_add
(
struct
acpi_device
*
acpi
)
{
return
cmpc_add_acpi_notify_device
(
acpi
,
"cmpc_keys"
,
cmpc_keys_idev_init
);
}
static
int
cmpc_keys_remove
(
struct
acpi_device
*
acpi
,
int
type
)
{
return
cmpc_remove_acpi_notify_device
(
acpi
);
}
static
const
struct
acpi_device_id
cmpc_keys_device_ids
[]
=
{
{
"FnBT0000"
,
0
},
{
""
,
0
}
};
MODULE_DEVICE_TABLE
(
acpi
,
cmpc_keys_device_ids
);
static
struct
acpi_driver
cmpc_keys_acpi_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"cmpc_keys"
,
.
class
=
"cmpc_keys"
,
.
ids
=
cmpc_keys_device_ids
,
.
ops
=
{
.
add
=
cmpc_keys_add
,
.
remove
=
cmpc_keys_remove
,
.
notify
=
cmpc_keys_handler
,
}
};
/*
* General init/exit code.
*/
static
int
cmpc_init
(
void
)
{
int
r
;
r
=
acpi_bus_register_driver
(
&
cmpc_keys_acpi_driver
);
if
(
r
)
goto
failed_keys
;
r
=
acpi_bus_register_driver
(
&
cmpc_bl_acpi_driver
);
if
(
r
)
goto
failed_bl
;
r
=
acpi_bus_register_driver
(
&
cmpc_tablet_acpi_driver
);
if
(
r
)
goto
failed_tablet
;
r
=
acpi_bus_register_driver
(
&
cmpc_accel_acpi_driver
);
if
(
r
)
goto
failed_accel
;
return
r
;
failed_accel:
acpi_bus_unregister_driver
(
&
cmpc_tablet_acpi_driver
);
failed_tablet:
acpi_bus_unregister_driver
(
&
cmpc_bl_acpi_driver
);
failed_bl:
acpi_bus_unregister_driver
(
&
cmpc_keys_acpi_driver
);
failed_keys:
return
r
;
}
static
void
cmpc_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
cmpc_accel_acpi_driver
);
acpi_bus_unregister_driver
(
&
cmpc_tablet_acpi_driver
);
acpi_bus_unregister_driver
(
&
cmpc_bl_acpi_driver
);
acpi_bus_unregister_driver
(
&
cmpc_keys_acpi_driver
);
}
module_init
(
cmpc_init
);
module_exit
(
cmpc_exit
);
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