+static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE, 0x2);
+static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point3_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE, 0x3);
+static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point4_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE, 0x4);
+static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point5_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE, 0x5);
+static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point6_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE, 0x6);
+
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_temp,
msi_wmi_platform_temp_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE, 0x0);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_temp,
msi_wmi_platform_temp_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE, 0x3);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point3_temp,
msi_wmi_platform_temp_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE, 0x4);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point4_temp,
msi_wmi_platform_temp_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE, 0x5);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point5_temp,
msi_wmi_platform_temp_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE, 0x6);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point6_temp,
msi_wmi_platform_temp_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE, 0x7);
+
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE, 0x1);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE, 0x2);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point3_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE, 0x3);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point4_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE, 0x4);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point5_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE, 0x5);
+static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point6_pwm,
msi_wmi_platform_fan_table,
+ MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE, 0x6);
+
+static struct attribute *msi_wmi_platform_hwmon_attrs[] = {
+ &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
+
+ &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point5_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point6_temp.dev_attr.attr,
+
+ &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point5_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point6_pwm.dev_attr.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(msi_wmi_platform_hwmon);
+
static umode_t msi_wmi_platform_is_visible(const void *drvdata,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
+ if (type == hwmon_pwm && attr == hwmon_pwm_enable)
+ return 0644;
+
return 0444;
}
@@ -233,24 +444,102 @@ static int msi_wmi_platform_read(struct
device *dev, enum hwmon_sensor_types typ
struct msi_wmi_platform_data *data = dev_get_drvdata(dev);
u8 buffer[32] = { 0 };
u16 value;
+ u8 flags;
int ret;
- ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_FAN, buf,
sizeof(buf));
- if (ret < 0)
- return ret;
+ switch (type) {
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_input:
+ buffer[0] = MSI_PLATFORM_FAN_SUBFEATURE_FAN_SPEED;
+ ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_FAN,
buffer,
+ sizeof(buffer));
+ if (ret < 0)
+ return ret;
+
+ value = get_unaligned_be16(&buffer[channel * 2 + 1]);
+ if (!value)
+ *val = 0;
+ else
+ *val = 480000 / value;
+
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_enable:
+ buffer[0] = MSI_PLATFORM_AP_SUBFEATURE_FAN_MODE;
+ ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_AP,
buffer,
+ sizeof(buffer));
+ if (ret < 0)
+ return ret;
+
+ flags = buffer[MSI_PLATFORM_AP_FAN_FLAGS_OFFSET];
+ if (flags & MSI_PLATFORM_AP_ENABLE_FAN_TABLES)
+ *val = 1;
+ else
+ *val = 2;
+
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
- value = get_unaligned_be16(&buffer[channel * 2 + 1]);
- if (!value)
- *val = 0;
- else
- *val = 480000 / value;
+static int msi_wmi_platform_write(struct device *dev, enum
hwmon_sensor_types type, u32 attr,
+ int channel, long val)
+{
+ struct msi_wmi_platform_data *data = dev_get_drvdata(dev);
+ u8 buffer[32] = { };
+ int ret;
- return 0;
+ switch (type) {
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_enable:
+ guard(mutex)(&data->wmi_lock);
+
+ buffer[0] = MSI_PLATFORM_AP_SUBFEATURE_FAN_MODE;
+ ret = msi_wmi_platform_query_unlocked(
+ data, MSI_PLATFORM_GET_AP, buffer,
+ sizeof(buffer));
+ if (ret < 0)
+ return ret;
+
+ buffer[0] = MSI_PLATFORM_AP_SUBFEATURE_FAN_MODE;
+ switch (val) {
+ case 1:
+ buffer[MSI_PLATFORM_AP_FAN_FLAGS_OFFSET] |=
+ MSI_PLATFORM_AP_ENABLE_FAN_TABLES;
+ break;
+ case 2:
+ buffer[MSI_PLATFORM_AP_FAN_FLAGS_OFFSET] &=
+ ~MSI_PLATFORM_AP_ENABLE_FAN_TABLES;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return msi_wmi_platform_query_unlocked(
+ data, MSI_PLATFORM_SET_AP, buffer,
+ sizeof(buffer));
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
}
static const struct hwmon_ops msi_wmi_platform_ops = {
.is_visible = msi_wmi_platform_is_visible,
.read = msi_wmi_platform_read,
+ .write = msi_wmi_platform_write,
};
static const struct hwmon_channel_info * const
msi_wmi_platform_info[] = {
@@ -260,6 +549,10 @@ static const struct hwmon_channel_info * const
msi_wmi_platform_info[] = {
HWMON_F_INPUT,
HWMON_F_INPUT
),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_ENABLE,
+ HWMON_PWM_ENABLE
+ ),
NULL
};
@@ -268,8 +561,8 @@ static const struct hwmon_chip_info
msi_wmi_platform_chip_info = {
.info = msi_wmi_platform_info,
};
-static ssize_t msi_wmi_platform_write(struct file *fp, const char
__user *input, size_t length,
- loff_t *offset)
+static ssize_t msi_wmi_platform_debugfs_write(struct file *fp, const
char __user *input,
+ size_t length, loff_t *offset)
{
struct seq_file *seq = fp->private_data;
struct msi_wmi_platform_debugfs_data *data = seq->private;
@@ -303,7 +596,7 @@ static ssize_t msi_wmi_platform_write(struct file
*fp, const char __user *input,
return length;
}
-static int msi_wmi_platform_show(struct seq_file *seq, void *p)
+static int msi_wmi_platform_debugfs_show(struct seq_file *seq, void *p)
{
struct msi_wmi_platform_debugfs_data *data = seq->private;
int ret;
@@ -315,19 +608,19 @@ static int msi_wmi_platform_show(struct
seq_file *seq, void *p)
return ret;
}
-static int msi_wmi_platform_open(struct inode *inode, struct file
*fp)
+static int msi_wmi_platform_debugfs_open(struct inode *inode, struct
file *fp)
{
struct msi_wmi_platform_debugfs_data *data = inode->i_private;
/* The seq_file uses the last byte of the buffer for
detecting buffer overflows */
- return single_open_size(fp, msi_wmi_platform_show, data,
data->length + 1);
+ return single_open_size(fp, msi_wmi_platform_debugfs_show, data,
data->length + 1);
}
static const struct file_operations msi_wmi_platform_debugfs_fops
= {
.owner = THIS_MODULE,
- .open = msi_wmi_platform_open,
+ .open = msi_wmi_platform_debugfs_open,
.read = seq_read,
- .write = msi_wmi_platform_write,
+ .write = msi_wmi_platform_debugfs_write,
.llseek = seq_lseek,
.release = single_release,
};
@@ -389,7 +682,8 @@ static int msi_wmi_platform_hwmon_init(struct
msi_wmi_platform_data *data)
struct device *hdev;
hdev = devm_hwmon_device_register_with_info(&data->wdev->dev,
"msi_wmi_platform", data,
- &msi_wmi_platform_chip_info, NULL);
+ &msi_wmi_platform_chip_info,
+ msi_wmi_platform_hwmon_groups);
return PTR_ERR_OR_ZERO(hdev);
}