+/*************************************************************************
+ * DYTC subdriver, for the Lenovo lapmode feature
+ */
+
+#define DYTC_CMD_GET 2 /* To get current IC function and mode */
+#define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */
+
+static bool dytc_lapmode;
+
+static void dytc_lapmode_notify_change(void)
+{
+ sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "dytc_lapmode");
+}
+
+static int dytc_command(int command, int *output)
+{
+ acpi_handle dytc_handle;
+
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) {
+ /* Platform doesn't support DYTC */
+ return -ENODEV;
+ }
+ if (!acpi_evalf(dytc_handle, output, NULL, "dd", command))
+ return -EIO;
+ return 0;
+}
+
+static int dytc_lapmode_get(bool *state)
+{
+ int output, err;
+
+ err = dytc_command(DYTC_CMD_GET, &output);
+ if (err)
+ return err;
+ *state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;
+ return 0;
+}
+
+static void dytc_lapmode_refresh(void)
+{
+ bool new_state;
+ int err;
+
+ err = dytc_lapmode_get(&new_state);
+ if (err || (new_state == dytc_lapmode))
+ return;
+
+ dytc_lapmode = new_state;
+ dytc_lapmode_notify_change();
+}
+
+/* sysfs lapmode entry */
+static ssize_t dytc_lapmode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", dytc_lapmode);
+}
+
+static DEVICE_ATTR_RO(dytc_lapmode);
+
+static struct attribute *dytc_attributes[] = {
+ &dev_attr_dytc_lapmode.attr,
+ NULL,
+};
+
+static const struct attribute_group dytc_attr_group = {
+ .attrs = dytc_attributes,
+};
+
+static int tpacpi_dytc_init(struct ibm_init_struct *iibm)
+{
+ int err;
+
+ err = dytc_lapmode_get(&dytc_lapmode);
+ /* If support isn't available (ENODEV) then don't return an error
+ * but just don't create the sysfs group
+ */
+ if (err == -ENODEV)
+ return 0;
+ /* For all other errors we can flag the failure */
+ if (err)
+ return err;
+
+ /* Platform supports this feature - create the group */
+ err = sysfs_create_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
+ return err;
+}
+
+static void dytc_exit(void)
+{
+ sysfs_remove_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
+}
+
+static struct ibm_struct dytc_driver_data = {
+ .name = "dytc",
+ .exit = dytc_exit,
+};
+