Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
58ac7aa0
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
58ac7aa0
编写于
8月 10, 2010
作者:
D
David Woodhouse
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add Lenovo ideapad driver
Signed-off-by:
N
David Woodhouse
<
David.Woodhouse@intel.com
>
上级
f6cec0ae
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
290 addition
and
0 deletion
+290
-0
drivers/platform/x86/Kconfig
drivers/platform/x86/Kconfig
+7
-0
drivers/platform/x86/Makefile
drivers/platform/x86/Makefile
+1
-0
drivers/platform/x86/ideapad_acpi.c
drivers/platform/x86/ideapad_acpi.c
+282
-0
未找到文件。
drivers/platform/x86/Kconfig
浏览文件 @
58ac7aa0
...
...
@@ -219,6 +219,13 @@ config SONYPI_COMPAT
---help---
Build the sonypi driver compatibility code into the sony-laptop driver.
config IDEAPAD_ACPI
tristate "Lenovo IdeaPad ACPI Laptop Extras"
depends on ACPI
depends on RFKILL
help
This is a driver for the rfkill switches on Lenovo IdeaPad netbooks.
config THINKPAD_ACPI
tristate "ThinkPad ACPI Laptop Extras"
depends on ACPI
...
...
drivers/platform/x86/Makefile
浏览文件 @
58ac7aa0
...
...
@@ -15,6 +15,7 @@ obj-$(CONFIG_ACERHDF) += acerhdf.o
obj-$(CONFIG_HP_WMI)
+=
hp-wmi.o
obj-$(CONFIG_TC1100_WMI)
+=
tc1100-wmi.o
obj-$(CONFIG_SONY_LAPTOP)
+=
sony-laptop.o
obj-$(CONFIG_IDEAPAD_ACPI)
+=
ideapad_acpi.o
obj-$(CONFIG_THINKPAD_ACPI)
+=
thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP)
+=
fujitsu-laptop.o
obj-$(CONFIG_PANASONIC_LAPTOP)
+=
panasonic-laptop.o
...
...
drivers/platform/x86/ideapad_acpi.c
0 → 100644
浏览文件 @
58ac7aa0
/*
* ideapad_acpi.c - Lenovo IdeaPad ACPI Extras
*
* Copyright © 2010 Intel Corporation
* Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/rfkill.h>
#define IDEAPAD_DEV_CAMERA 0
#define IDEAPAD_DEV_WLAN 1
#define IDEAPAD_DEV_BLUETOOTH 2
#define IDEAPAD_DEV_3G 3
#define IDEAPAD_DEV_KILLSW 4
static
struct
rfkill
*
ideapad_rfkill
[
5
];
static
const
char
*
ideapad_rfk_names
[]
=
{
"ideapad_camera"
,
"ideapad_wlan"
,
"ideapad_bluetooth"
,
"ideapad_3g"
,
"ideapad_rfkill"
};
static
const
int
ideapad_rfk_types
[]
=
{
0
,
RFKILL_TYPE_WLAN
,
RFKILL_TYPE_BLUETOOTH
,
RFKILL_TYPE_WWAN
,
RFKILL_TYPE_WLAN
};
static
int
ideapad_dev_exists
(
int
device
)
{
acpi_status
status
;
union
acpi_object
in_param
;
struct
acpi_object_list
input
=
{
1
,
&
in_param
};
struct
acpi_buffer
output
;
union
acpi_object
out_obj
;
output
.
length
=
sizeof
(
out_obj
);
output
.
pointer
=
&
out_obj
;
in_param
.
type
=
ACPI_TYPE_INTEGER
;
in_param
.
integer
.
value
=
device
+
1
;
status
=
acpi_evaluate_object
(
NULL
,
"
\\
_SB_.DECN"
,
&
input
,
&
output
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_WARNING
"IdeaPAD
\\
_SB_.DECN method failed %d. Is this an IdeaPAD?
\n
"
,
status
);
return
-
ENODEV
;
}
if
(
out_obj
.
type
!=
ACPI_TYPE_INTEGER
)
{
printk
(
KERN_WARNING
"IdeaPAD
\\
_SB_.DECN method returned unexpected type
\n
"
);
return
-
ENODEV
;
}
return
out_obj
.
integer
.
value
;
}
static
int
ideapad_dev_get_state
(
int
device
)
{
acpi_status
status
;
union
acpi_object
in_param
;
struct
acpi_object_list
input
=
{
1
,
&
in_param
};
struct
acpi_buffer
output
;
union
acpi_object
out_obj
;
output
.
length
=
sizeof
(
out_obj
);
output
.
pointer
=
&
out_obj
;
in_param
.
type
=
ACPI_TYPE_INTEGER
;
in_param
.
integer
.
value
=
device
+
1
;
status
=
acpi_evaluate_object
(
NULL
,
"
\\
_SB_.GECN"
,
&
input
,
&
output
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_WARNING
"IdeaPAD
\\
_SB_.GECN method failed %d
\n
"
,
status
);
return
-
ENODEV
;
}
if
(
out_obj
.
type
!=
ACPI_TYPE_INTEGER
)
{
printk
(
KERN_WARNING
"IdeaPAD
\\
_SB_.GECN method returned unexpected type
\n
"
);
return
-
ENODEV
;
}
return
out_obj
.
integer
.
value
;
}
static
int
ideapad_dev_set_state
(
int
device
,
int
state
)
{
acpi_status
status
;
union
acpi_object
in_params
[
2
];
struct
acpi_object_list
input
=
{
2
,
in_params
};
in_params
[
0
].
type
=
ACPI_TYPE_INTEGER
;
in_params
[
0
].
integer
.
value
=
device
+
1
;
in_params
[
1
].
type
=
ACPI_TYPE_INTEGER
;
in_params
[
1
].
integer
.
value
=
state
;
status
=
acpi_evaluate_object
(
NULL
,
"
\\
_SB_.SECN"
,
&
input
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_WARNING
"IdeaPAD
\\
_SB_.SECN method failed %d
\n
"
,
status
);
return
-
ENODEV
;
}
return
0
;
}
static
ssize_t
show_ideapad_cam
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
int
state
=
ideapad_dev_get_state
(
IDEAPAD_DEV_CAMERA
);
if
(
state
<
0
)
return
state
;
return
sprintf
(
buf
,
"%d
\n
"
,
state
);
}
static
ssize_t
store_ideapad_cam
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
int
ret
,
state
;
if
(
!
count
)
return
0
;
if
(
sscanf
(
buf
,
"%i"
,
&
state
)
!=
1
)
return
-
EINVAL
;
ret
=
ideapad_dev_set_state
(
IDEAPAD_DEV_CAMERA
,
state
);
if
(
ret
<
0
)
return
ret
;
return
count
;
}
static
DEVICE_ATTR
(
camera_power
,
0644
,
show_ideapad_cam
,
store_ideapad_cam
);
static
int
ideapad_rfk_set
(
void
*
data
,
bool
blocked
)
{
int
device
=
(
unsigned
long
)
data
;
if
(
device
==
IDEAPAD_DEV_KILLSW
)
return
-
EINVAL
;
return
ideapad_dev_set_state
(
device
,
!
blocked
);
}
static
struct
rfkill_ops
ideapad_rfk_ops
=
{
.
set_block
=
ideapad_rfk_set
,
};
static
void
ideapad_sync_rfk_state
(
void
)
{
int
hw_blocked
=
!
ideapad_dev_get_state
(
IDEAPAD_DEV_KILLSW
);
int
i
;
rfkill_set_hw_state
(
ideapad_rfkill
[
IDEAPAD_DEV_KILLSW
],
hw_blocked
);
for
(
i
=
IDEAPAD_DEV_WLAN
;
i
<
IDEAPAD_DEV_KILLSW
;
i
++
)
if
(
ideapad_rfkill
[
i
])
rfkill_set_hw_state
(
ideapad_rfkill
[
i
],
hw_blocked
);
if
(
hw_blocked
)
return
;
for
(
i
=
IDEAPAD_DEV_WLAN
;
i
<
IDEAPAD_DEV_KILLSW
;
i
++
)
if
(
ideapad_rfkill
[
i
])
rfkill_set_sw_state
(
ideapad_rfkill
[
i
],
!
ideapad_dev_get_state
(
i
));
}
static
int
ideapad_register_rfkill
(
struct
acpi_device
*
device
,
int
dev
)
{
int
ret
;
ideapad_rfkill
[
dev
]
=
rfkill_alloc
(
ideapad_rfk_names
[
dev
],
&
device
->
dev
,
ideapad_rfk_types
[
dev
],
&
ideapad_rfk_ops
,
(
void
*
)(
long
)
dev
);
if
(
!
ideapad_rfkill
[
dev
])
return
-
ENOMEM
;
ret
=
rfkill_register
(
ideapad_rfkill
[
dev
]);
if
(
ret
)
{
rfkill_destroy
(
ideapad_rfkill
[
dev
]);
return
ret
;
}
return
0
;
}
static
void
ideapad_unregister_rfkill
(
int
dev
)
{
if
(
!
ideapad_rfkill
[
dev
])
return
;
rfkill_unregister
(
ideapad_rfkill
[
dev
]);
rfkill_destroy
(
ideapad_rfkill
[
dev
]);
}
static
const
struct
acpi_device_id
ideapad_device_ids
[]
=
{
{
"VPC2004"
,
0
},
{
""
,
0
},
};
MODULE_DEVICE_TABLE
(
acpi
,
ideapad_device_ids
);
static
int
ideapad_acpi_add
(
struct
acpi_device
*
device
)
{
int
i
;
int
devs_present
[
5
];
for
(
i
=
IDEAPAD_DEV_CAMERA
;
i
<
IDEAPAD_DEV_KILLSW
;
i
++
)
{
devs_present
[
i
]
=
ideapad_dev_exists
(
i
);
if
(
devs_present
[
i
]
<
0
)
return
devs_present
[
i
];
}
/* The hardware switch is always present */
devs_present
[
IDEAPAD_DEV_KILLSW
]
=
1
;
if
(
devs_present
[
IDEAPAD_DEV_CAMERA
])
{
int
ret
=
device_create_file
(
&
device
->
dev
,
&
dev_attr_camera_power
);
if
(
ret
)
return
ret
;
}
for
(
i
=
IDEAPAD_DEV_WLAN
;
i
<=
IDEAPAD_DEV_KILLSW
;
i
++
)
{
if
(
!
devs_present
[
i
])
continue
;
ideapad_register_rfkill
(
device
,
i
);
}
ideapad_sync_rfk_state
();
return
0
;
}
static
int
ideapad_acpi_remove
(
struct
acpi_device
*
device
,
int
type
)
{
int
i
;
device_remove_file
(
&
device
->
dev
,
&
dev_attr_camera_power
);
for
(
i
=
0
;
i
<
5
;
i
++
)
ideapad_unregister_rfkill
(
i
);
return
0
;
}
static
void
ideapad_acpi_notify
(
struct
acpi_device
*
device
,
u32
event
)
{
ideapad_sync_rfk_state
();
}
static
struct
acpi_driver
ideapad_acpi_driver
=
{
.
name
=
"ideapad_acpi"
,
.
class
=
"IdeaPad"
,
.
ids
=
ideapad_device_ids
,
.
ops
.
add
=
ideapad_acpi_add
,
.
ops
.
remove
=
ideapad_acpi_remove
,
.
ops
.
notify
=
ideapad_acpi_notify
,
.
owner
=
THIS_MODULE
,
};
static
int
__init
ideapad_acpi_module_init
(
void
)
{
acpi_bus_register_driver
(
&
ideapad_acpi_driver
);
return
0
;
}
static
void
__exit
ideapad_acpi_module_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
ideapad_acpi_driver
);
}
MODULE_AUTHOR
(
"David Woodhouse <dwmw2@infradead.org>"
);
MODULE_DESCRIPTION
(
"IdeaPad ACPI Extras"
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
ideapad_acpi_module_init
);
module_exit
(
ideapad_acpi_module_exit
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录