summaryrefslogtreecommitdiff
path: root/drivers/hwmon/aquacomputer_d5next.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/aquacomputer_d5next.c')
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c233
1 files changed, 181 insertions, 52 deletions
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index c51a2678f0eb..9cc10080160b 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -59,7 +59,7 @@ static u8 secondary_ctrl_report[] = {
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6
};
-/* Register offsets for all Aquacomputer devices */
+/* Sensor sizes and offsets for all Aquacomputer devices */
#define AQC_TEMP_SENSOR_SIZE 0x02
#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF
#define AQC_FAN_PERCENT_OFFSET 0x00
@@ -68,62 +68,81 @@ static u8 secondary_ctrl_report[] = {
#define AQC_FAN_POWER_OFFSET 0x06
#define AQC_FAN_SPEED_OFFSET 0x08
-/* Register offsets for the D5 Next pump */
-#define D5NEXT_POWER_CYCLES 0x18
-#define D5NEXT_COOLANT_TEMP 0x57
+/* Specs of the D5 Next pump */
#define D5NEXT_NUM_FANS 2
#define D5NEXT_NUM_SENSORS 1
#define D5NEXT_NUM_VIRTUAL_SENSORS 8
-#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
+#define D5NEXT_CTRL_REPORT_SIZE 0x329
+
+/* Sensor report offsets for the D5 Next pump */
+#define D5NEXT_POWER_CYCLES 0x18
+#define D5NEXT_COOLANT_TEMP 0x57
#define D5NEXT_PUMP_OFFSET 0x6c
#define D5NEXT_FAN_OFFSET 0x5f
#define D5NEXT_5V_VOLTAGE 0x39
#define D5NEXT_12V_VOLTAGE 0x37
-#define D5NEXT_CTRL_REPORT_SIZE 0x329
+#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
static u8 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET };
-/* Pump and fan speed registers in D5 Next control report (from 0-100%) */
-static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 };
+/* Control report offsets for the D5 Next pump */
+#define D5NEXT_TEMP_CTRL_OFFSET 0x2D /* Temperature sensor offsets location */
+static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 }; /* Pump and fan speed (from 0-100%) */
-/* Register offsets for the Farbwerk RGB controller */
+/* Spec and sensor report offset for the Farbwerk RGB controller */
#define FARBWERK_NUM_SENSORS 4
#define FARBWERK_SENSOR_START 0x2f
-/* Register offsets for the Farbwerk 360 RGB controller */
+/* Specs of the Farbwerk 360 RGB controller */
#define FARBWERK360_NUM_SENSORS 4
-#define FARBWERK360_SENSOR_START 0x32
#define FARBWERK360_NUM_VIRTUAL_SENSORS 16
+#define FARBWERK360_CTRL_REPORT_SIZE 0x682
+
+/* Sensor report offsets for the Farbwerk 360 */
+#define FARBWERK360_SENSOR_START 0x32
#define FARBWERK360_VIRTUAL_SENSORS_START 0x3a
-/* Register offsets for the Octo fan controller */
-#define OCTO_POWER_CYCLES 0x18
+/* Control report offsets for the Farbwerk 360 */
+#define FARBWERK360_TEMP_CTRL_OFFSET 0x8
+
+/* Specs of the Octo fan controller */
#define OCTO_NUM_FANS 8
#define OCTO_NUM_SENSORS 4
-#define OCTO_SENSOR_START 0x3D
#define OCTO_NUM_VIRTUAL_SENSORS 16
-#define OCTO_VIRTUAL_SENSORS_START 0x45
#define OCTO_CTRL_REPORT_SIZE 0x65F
+
+/* Sensor report offsets for the Octo */
+#define OCTO_POWER_CYCLES 0x18
+#define OCTO_SENSOR_START 0x3D
+#define OCTO_VIRTUAL_SENSORS_START 0x45
static u8 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
-/* Fan speed registers in Octo control report (from 0-100%) */
+/* Control report offsets for the Octo */
+#define OCTO_TEMP_CTRL_OFFSET 0xA
+/* Fan speed offsets (0-100%) */
static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE };
-/* Register offsets for the Quadro fan controller */
-#define QUADRO_POWER_CYCLES 0x18
+/* Specs of Quadro fan controller */
#define QUADRO_NUM_FANS 4
#define QUADRO_NUM_SENSORS 4
-#define QUADRO_SENSOR_START 0x34
#define QUADRO_NUM_VIRTUAL_SENSORS 16
-#define QUADRO_VIRTUAL_SENSORS_START 0x3c
#define QUADRO_CTRL_REPORT_SIZE 0x3c1
+
+/* Sensor report offsets for the Quadro */
+#define QUADRO_POWER_CYCLES 0x18
+#define QUADRO_SENSOR_START 0x34
+#define QUADRO_VIRTUAL_SENSORS_START 0x3c
#define QUADRO_FLOW_SENSOR_OFFSET 0x6e
static u8 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 };
-/* Fan speed registers in Quadro control report (from 0-100%) */
-static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 };
+/* Control report offsets for the Quadro */
+#define QUADRO_TEMP_CTRL_OFFSET 0xA
+#define QUADRO_FLOW_PULSES_CTRL_OFFSET 0x6
+static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed offsets (0-100%) */
-/* Register offsets for the High Flow Next */
+/* Specs of High Flow Next flow sensor */
#define HIGHFLOWNEXT_NUM_SENSORS 2
+
+/* Sensor report offsets for the High Flow Next */
#define HIGHFLOWNEXT_SENSOR_START 85
#define HIGHFLOWNEXT_FLOW 81
#define HIGHFLOWNEXT_WATER_QUALITY 89
@@ -282,8 +301,10 @@ struct aqc_data {
int temp_sensor_start_offset;
int num_virtual_temp_sensors;
int virtual_temp_sensor_start_offset;
+ u16 temp_ctrl_offset;
u16 power_cycle_count_offset;
u8 flow_sensor_offset;
+ u8 flow_pulses_ctrl_offset;
/* General info, same across all devices */
u32 serial_number[2];
@@ -365,8 +386,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
return ret;
}
-/* Refreshes the control buffer and returns value at offset */
-static int aqc_get_ctrl_val(struct aqc_data *priv, int offset)
+/* Refreshes the control buffer and stores value at offset in val */
+static int aqc_get_ctrl_val(struct aqc_data *priv, int offset, long *val)
{
int ret;
@@ -376,7 +397,7 @@ static int aqc_get_ctrl_val(struct aqc_data *priv, int offset)
if (ret < 0)
goto unlock_and_return;
- ret = get_unaligned_be16(priv->buffer + offset);
+ *val = (s16)get_unaligned_be16(priv->buffer + offset);
unlock_and_return:
mutex_unlock(&priv->mutex);
@@ -393,7 +414,7 @@ static int aqc_set_ctrl_val(struct aqc_data *priv, int offset, long val)
if (ret < 0)
goto unlock_and_return;
- put_unaligned_be16((u16)val, priv->buffer + offset);
+ put_unaligned_be16((s16)val, priv->buffer + offset);
ret = aqc_send_ctrl_data(priv);
@@ -408,8 +429,28 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
switch (type) {
case hwmon_temp:
+ if (channel < priv->num_temp_sensors) {
+ switch (attr) {
+ case hwmon_temp_label:
+ case hwmon_temp_input:
+ return 0444;
+ case hwmon_temp_offset:
+ if (priv->temp_ctrl_offset != 0)
+ return 0644;
+ break;
+ default:
+ break;
+ }
+ }
+
if (channel < priv->num_temp_sensors + priv->num_virtual_temp_sensors)
- return 0444;
+ switch (attr) {
+ case hwmon_temp_label:
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ break;
+ }
break;
case hwmon_pwm:
if (priv->fan_ctrl_offsets && channel < priv->num_fans) {
@@ -422,20 +463,34 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
}
break;
case hwmon_fan:
- switch (priv->kind) {
- case highflownext:
- /* Special case to support flow sensor, water quality and conductivity */
- if (channel < 3)
- return 0444;
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_label:
+ switch (priv->kind) {
+ case highflownext:
+ /* Special case to support flow sensor, water quality
+ * and conductivity
+ */
+ if (channel < 3)
+ return 0444;
+ break;
+ case quadro:
+ /* Special case to support flow sensor */
+ if (channel < priv->num_fans + 1)
+ return 0444;
+ break;
+ default:
+ if (channel < priv->num_fans)
+ return 0444;
+ break;
+ }
break;
- case quadro:
- /* Special case to support flow sensor */
- if (channel < priv->num_fans + 1)
- return 0444;
+ case hwmon_fan_pulses:
+ /* Special case for Quadro flow sensor */
+ if (priv->kind == quadro && channel == priv->num_fans)
+ return 0644;
break;
default:
- if (channel < priv->num_fans)
- return 0444;
break;
}
break;
@@ -492,20 +547,46 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
switch (type) {
case hwmon_temp:
- if (priv->temp_input[channel] == -ENODATA)
- return -ENODATA;
+ switch (attr) {
+ case hwmon_temp_input:
+ if (priv->temp_input[channel] == -ENODATA)
+ return -ENODATA;
- *val = priv->temp_input[channel];
+ *val = priv->temp_input[channel];
+ break;
+ case hwmon_temp_offset:
+ ret =
+ aqc_get_ctrl_val(priv, priv->temp_ctrl_offset +
+ channel * AQC_TEMP_SENSOR_SIZE, val);
+ if (ret < 0)
+ return ret;
+
+ *val *= 10;
+ break;
+ default:
+ break;
+ }
break;
case hwmon_fan:
- *val = priv->speed_input[channel];
+ switch (attr) {
+ case hwmon_fan_input:
+ *val = priv->speed_input[channel];
+ break;
+ case hwmon_fan_pulses:
+ ret = aqc_get_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ break;
+ }
break;
case hwmon_power:
*val = priv->power_input[channel];
break;
case hwmon_pwm:
if (priv->fan_ctrl_offsets) {
- ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel]);
+ ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel], val);
if (ret < 0)
return ret;
@@ -563,6 +644,33 @@ static int aqc_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
struct aqc_data *priv = dev_get_drvdata(dev);
switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_offset:
+ /* Limit temp offset to +/- 15K as in the official software */
+ val = clamp_val(val, -15000, 15000) / 10;
+ ret =
+ aqc_set_ctrl_val(priv, priv->temp_ctrl_offset +
+ channel * AQC_TEMP_SENSOR_SIZE, val);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_pulses:
+ val = clamp_val(val, 10, 1000);
+ ret = aqc_set_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ break;
+ }
+ break;
case hwmon_pwm:
switch (attr) {
case hwmon_pwm_input:
@@ -597,10 +705,10 @@ static const struct hwmon_ops aqc_hwmon_ops = {
static const struct hwmon_channel_info *aqc_info[] = {
HWMON_CHANNEL_INFO(temp,
- HWMON_T_INPUT | HWMON_T_LABEL,
- HWMON_T_INPUT | HWMON_T_LABEL,
- HWMON_T_INPUT | HWMON_T_LABEL,
- HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL,
@@ -622,7 +730,7 @@ static const struct hwmon_channel_info *aqc_info[] = {
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL),
@@ -847,13 +955,17 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->num_fans = D5NEXT_NUM_FANS;
priv->fan_sensor_offsets = d5next_sensor_fan_offsets;
priv->fan_ctrl_offsets = d5next_ctrl_fan_offsets;
+
priv->num_temp_sensors = D5NEXT_NUM_SENSORS;
priv->temp_sensor_start_offset = D5NEXT_COOLANT_TEMP;
priv->num_virtual_temp_sensors = D5NEXT_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = D5NEXT_VIRTUAL_SENSORS_START;
- priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
+ priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
+
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
+ priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
+
priv->temp_label = label_d5next_temp;
priv->virtual_temp_label = label_virtual_temp_sensors;
priv->speed_label = label_d5next_speeds;
@@ -865,18 +977,24 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->kind = farbwerk;
priv->num_fans = 0;
+
priv->num_temp_sensors = FARBWERK_NUM_SENSORS;
priv->temp_sensor_start_offset = FARBWERK_SENSOR_START;
+
priv->temp_label = label_temp_sensors;
break;
case USB_PRODUCT_ID_FARBWERK360:
priv->kind = farbwerk360;
priv->num_fans = 0;
+
priv->num_temp_sensors = FARBWERK360_NUM_SENSORS;
priv->temp_sensor_start_offset = FARBWERK360_SENSOR_START;
priv->num_virtual_temp_sensors = FARBWERK360_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = FARBWERK360_VIRTUAL_SENSORS_START;
+ priv->temp_ctrl_offset = FARBWERK360_TEMP_CTRL_OFFSET;
+
+ priv->buffer_size = FARBWERK360_CTRL_REPORT_SIZE;
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -887,13 +1005,17 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->num_fans = OCTO_NUM_FANS;
priv->fan_sensor_offsets = octo_sensor_fan_offsets;
priv->fan_ctrl_offsets = octo_ctrl_fan_offsets;
+
priv->num_temp_sensors = OCTO_NUM_SENSORS;
priv->temp_sensor_start_offset = OCTO_SENSOR_START;
priv->num_virtual_temp_sensors = OCTO_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = OCTO_VIRTUAL_SENSORS_START;
- priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
+ priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
+
priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
+ priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
+
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
priv->speed_label = label_fan_speed;
@@ -907,13 +1029,18 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->num_fans = QUADRO_NUM_FANS;
priv->fan_sensor_offsets = quadro_sensor_fan_offsets;
priv->fan_ctrl_offsets = quadro_ctrl_fan_offsets;
+
priv->num_temp_sensors = QUADRO_NUM_SENSORS;
priv->temp_sensor_start_offset = QUADRO_SENSOR_START;
priv->num_virtual_temp_sensors = QUADRO_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = QUADRO_VIRTUAL_SENSORS_START;
- priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
+ priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
+
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
+
priv->flow_sensor_offset = QUADRO_FLOW_SENSOR_OFFSET;
+ priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
+ priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -926,8 +1053,10 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->kind = highflownext;
priv->num_fans = 0;
+
priv->num_temp_sensors = HIGHFLOWNEXT_NUM_SENSORS;
priv->temp_sensor_start_offset = HIGHFLOWNEXT_SENSOR_START;
+
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
priv->temp_label = label_highflownext_temp_sensors;