1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Support for rfkill on some Fujitsu-Siemens Amilo laptops.
4 * Copyright 2011 Ben Hutchings.
6 * Based in part on the fsam7440 driver, which is:
7 * Copyright 2005 Alejandro Vidal Mata & Javier Vidal Mata.
8 * and on the fsaa1655g driver, which is:
9 * Copyright 2006 Martin Večeřa.
12 #include <linux/module.h>
13 #include <linux/dmi.h>
14 #include <linux/i8042.h>
16 #include <linux/moduleparam.h>
17 #include <linux/platform_device.h>
18 #include <linux/rfkill.h>
21 * These values were obtained from disassembling and debugging the
22 * PM.exe program installed in the Fujitsu-Siemens AMILO A1655G
24 #define A1655_WIFI_COMMAND 0x10C5
25 #define A1655_WIFI_ON 0x25
26 #define A1655_WIFI_OFF 0x45
28 static int amilo_a1655_rfkill_set_block(void *data
, bool blocked
)
30 u8 param
= blocked
? A1655_WIFI_OFF
: A1655_WIFI_ON
;
34 rc
= i8042_command(¶m
, A1655_WIFI_COMMAND
);
39 static const struct rfkill_ops amilo_a1655_rfkill_ops
= {
40 .set_block
= amilo_a1655_rfkill_set_block
44 * These values were obtained from disassembling the PM.exe program
45 * installed in the Fujitsu-Siemens AMILO M 7440
47 #define M7440_PORT1 0x118f
48 #define M7440_PORT2 0x118e
49 #define M7440_RADIO_ON1 0x12
50 #define M7440_RADIO_ON2 0x80
51 #define M7440_RADIO_OFF1 0x10
52 #define M7440_RADIO_OFF2 0x00
54 static int amilo_m7440_rfkill_set_block(void *data
, bool blocked
)
56 u8 val1
= blocked
? M7440_RADIO_OFF1
: M7440_RADIO_ON1
;
57 u8 val2
= blocked
? M7440_RADIO_OFF2
: M7440_RADIO_ON2
;
59 outb(val1
, M7440_PORT1
);
60 outb(val2
, M7440_PORT2
);
62 /* Check whether the state has changed correctly */
63 if (inb(M7440_PORT1
) != val1
|| inb(M7440_PORT2
) != val2
)
69 static const struct rfkill_ops amilo_m7440_rfkill_ops
= {
70 .set_block
= amilo_m7440_rfkill_set_block
73 static const struct dmi_system_id amilo_rfkill_id_table
[] = {
76 DMI_MATCH(DMI_SYS_VENDOR
, "FUJITSU SIEMENS"),
77 DMI_MATCH(DMI_BOARD_NAME
, "AMILO A1655"),
79 .driver_data
= (void *)&amilo_a1655_rfkill_ops
83 DMI_MATCH(DMI_SYS_VENDOR
, "FUJITSU SIEMENS"),
84 DMI_MATCH(DMI_BOARD_NAME
, "AMILO L1310"),
86 .driver_data
= (void *)&amilo_a1655_rfkill_ops
90 DMI_MATCH(DMI_SYS_VENDOR
, "FUJITSU SIEMENS"),
91 DMI_MATCH(DMI_BOARD_NAME
, "AMILO M7440"),
93 .driver_data
= (void *)&amilo_m7440_rfkill_ops
98 static struct platform_device
*amilo_rfkill_pdev
;
99 static struct rfkill
*amilo_rfkill_dev
;
101 static int amilo_rfkill_probe(struct platform_device
*device
)
104 const struct dmi_system_id
*system_id
=
105 dmi_first_match(amilo_rfkill_id_table
);
110 amilo_rfkill_dev
= rfkill_alloc(KBUILD_MODNAME
, &device
->dev
,
112 system_id
->driver_data
, NULL
);
113 if (!amilo_rfkill_dev
)
116 rc
= rfkill_register(amilo_rfkill_dev
);
123 rfkill_destroy(amilo_rfkill_dev
);
127 static int amilo_rfkill_remove(struct platform_device
*device
)
129 rfkill_unregister(amilo_rfkill_dev
);
130 rfkill_destroy(amilo_rfkill_dev
);
134 static struct platform_driver amilo_rfkill_driver
= {
136 .name
= KBUILD_MODNAME
,
138 .probe
= amilo_rfkill_probe
,
139 .remove
= amilo_rfkill_remove
,
142 static int __init
amilo_rfkill_init(void)
146 if (dmi_first_match(amilo_rfkill_id_table
) == NULL
)
149 rc
= platform_driver_register(&amilo_rfkill_driver
);
153 amilo_rfkill_pdev
= platform_device_register_simple(KBUILD_MODNAME
, -1,
155 if (IS_ERR(amilo_rfkill_pdev
)) {
156 rc
= PTR_ERR(amilo_rfkill_pdev
);
163 platform_driver_unregister(&amilo_rfkill_driver
);
167 static void __exit
amilo_rfkill_exit(void)
169 platform_device_unregister(amilo_rfkill_pdev
);
170 platform_driver_unregister(&amilo_rfkill_driver
);
173 MODULE_AUTHOR("Ben Hutchings <ben@decadent.org.uk>");
174 MODULE_LICENSE("GPL");
175 MODULE_DEVICE_TABLE(dmi
, amilo_rfkill_id_table
);
177 module_init(amilo_rfkill_init
);
178 module_exit(amilo_rfkill_exit
);