+static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
+ {
+ .ident = "MSI N034",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"),
+ DMI_MATCH(DMI_CHASSIS_VENDOR,
+ "MICRO-STAR INTERNATIONAL CO., LTD")
+ },
+ .callback = dmi_check_cb
+ },
+ { }
+};
+
+static int rfkill_bluetooth_set(void *data, bool blocked)
+{
+ /* Do something with blocked...*/
+ /*
+ * blocked == false is on
+ * blocked == true is off
+ */
+ if (blocked)
+ set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
+ else
+ set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
+
+ return 0;
+}
+
+static int rfkill_wlan_set(void *data, bool blocked)
+{
+ if (blocked)
+ set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK);
+ else
+ set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK);
+
+ return 0;
+}
+
+static int rfkill_threeg_set(void *data, bool blocked)
+{
+ if (blocked)
+ set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK);
+ else
+ set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK);
+
+ return 0;
+}
+
+static struct rfkill_ops rfkill_bluetooth_ops = {
+ .set_block = rfkill_bluetooth_set
+};
+
+static struct rfkill_ops rfkill_wlan_ops = {
+ .set_block = rfkill_wlan_set
+};
+
+static struct rfkill_ops rfkill_threeg_ops = {
+ .set_block = rfkill_threeg_set
+};
+
+static void rfkill_cleanup(void)
+{
+ if (rfk_bluetooth) {
+ rfkill_unregister(rfk_bluetooth);
+ rfkill_destroy(rfk_bluetooth);
+ }
+
+ if (rfk_threeg) {
+ rfkill_unregister(rfk_threeg);
+ rfkill_destroy(rfk_threeg);
+ }
+
+ if (rfk_wlan) {
+ rfkill_unregister(rfk_wlan);
+ rfkill_destroy(rfk_wlan);
+ }
+}
+
+static int rfkill_init(struct platform_device *sdev)
+{
+ /* add rfkill */
+ int retval;
+
+ rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev,
+ RFKILL_TYPE_BLUETOOTH,
+ &rfkill_bluetooth_ops, NULL);
+ if (!rfk_bluetooth) {
+ retval = -ENOMEM;
+ goto err_bluetooth;
+ }
+ retval = rfkill_register(rfk_bluetooth);
+ if (retval)
+ goto err_bluetooth;
+
+ rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN,
+ &rfkill_wlan_ops, NULL);
+ if (!rfk_wlan) {
+ retval = -ENOMEM;
+ goto err_wlan;
+ }
+ retval = rfkill_register(rfk_wlan);
+ if (retval)
+ goto err_wlan;
+
+ rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, RFKILL_TYPE_WWAN,
+ &rfkill_threeg_ops, NULL);
+ if (!rfk_threeg) {
+ retval = -ENOMEM;
+ goto err_threeg;
+ }
+ retval = rfkill_register(rfk_threeg);
+ if (retval)
+ goto err_threeg;
+
+ return 0;
+
+err_threeg:
+ rfkill_destroy(rfk_threeg);
+ if (rfk_wlan)
+ rfkill_unregister(rfk_wlan);
+err_wlan:
+ rfkill_destroy(rfk_wlan);
+ if (rfk_bluetooth)
+ rfkill_unregister(rfk_bluetooth);
+err_bluetooth:
+ rfkill_destroy(rfk_bluetooth);
+
+ return retval;
+}
+
+static int load_scm_model_init(struct platform_device *sdev)
+{
+ u8 data;
+ int result;
+
+ /* allow userland write sysfs file */
+ dev_attr_bluetooth.store = store_bluetooth;
+ dev_attr_wlan.store = store_wlan;
+ dev_attr_threeg.store = store_threeg;
+ dev_attr_bluetooth.attr.mode |= S_IWUSR;
+ dev_attr_wlan.attr.mode |= S_IWUSR;
+ dev_attr_threeg.attr.mode |= S_IWUSR;
+
+ /* disable hardware control by fn key */
+ result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
+ if (result < 0)
+ return result;
+
+ result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
+ data | MSI_STANDARD_EC_SCM_LOAD_MASK);
+ if (result < 0)
+ return result;
+
+ /* initial rfkill */
+ result = rfkill_init(sdev);
+ if (result < 0)
+ return result;
+
+ return 0;
+}
+