hwmon: (nzxt-kraken3) Add support for NZXT Kraken 2023 (standard and Elite) models

Add support for NZXT Kraken 2023 (standard) and NZXT Kraken 2023 Elite
all-in-one CPU coolers. These models communicate identically to the NZXT
Kraken Z-series (Z53 code paths) in all cases except when writing the
fan curve, where setting additional bits in the report is needed.

Reviewed-by: Jonas Malaco <jonas@protocubo.io>
Signed-off-by: Aleksa Savic <savicaleksa83@gmail.com>
Link: https://lore.kernel.org/r/20240428104812.14037-3-savicaleksa83@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Aleksa Savic 2024-04-28 12:48:11 +02:00 committed by Guenter Roeck
parent cbeb479ff4
commit 8ec8d6c509
2 changed files with 41 additions and 16 deletions

View File

@ -11,17 +11,20 @@ Supported devices:
* NZXT Kraken Z53
* NZXT Kraken Z63
* NZXT Kraken Z73
* NZXT Kraken 2023
* NZXT Kraken 2023 Elite
Author: Jonas Malaco, Aleksa Savic
Description
-----------
This driver enables hardware monitoring support for NZXT Kraken X53/X63/X73 and
Z53/Z63/Z73 all-in-one CPU liquid coolers. All models expose liquid temperature
and pump speed (in RPM), as well as PWM control (either as a fixed value
or through a temp-PWM curve). The Z-series models additionally expose the speed
and duty of an optionally connected fan, with the same PWM control capabilities.
This driver enables hardware monitoring support for NZXT Kraken X53/X63/X73,
Z53/Z63/Z73 and Kraken 2023 (standard and Elite) all-in-one CPU liquid coolers.
All models expose liquid temperature and pump speed (in RPM), as well as PWM
control (either as a fixed value or through a temp-PWM curve). The Z-series and
Kraken 2023 models additionally expose the speed and duty of an optionally connected
fan, with the same PWM control capabilities.
Pump and fan duty control mode can be set through pwm[1-2]_enable, where 1 is
for the manual control mode and 2 is for the liquid temp to PWM curve mode.
@ -39,9 +42,9 @@ The devices can report if they are faulty. The driver supports that situation
and will issue a warning. This can also happen when the USB cable is connected,
but SATA power is not.
The addressable RGB LEDs and LCD screen (only on Z-series models) are not
supported in this driver, but can be controlled through existing userspace tools,
such as `liquidctl`_.
The addressable RGB LEDs and LCD screen (only on Z-series and Kraken 2023 models)
are not supported in this driver, but can be controlled through existing userspace
tools, such as `liquidctl`_.
.. _liquidctl: https://github.com/liquidctl/liquidctl

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* hwmon driver for NZXT Kraken X53/X63/X73 and Z53/Z63/Z73 all in one coolers.
* X53 and Z53 in code refer to all models in their respective series (shortened
* for brevity).
* hwmon driver for NZXT Kraken X53/X63/X73, Z53/Z63/Z73 and 2023/2023 Elite all in one coolers.
* X53 and Z53 in code refer to all models in their respective series (shortened for brevity).
* 2023 models use the Z53 code paths.
*
* Copyright 2021 Jonas Malaco <jonas@protocubo.io>
* Copyright 2022 Aleksa Savic <savicaleksa83@gmail.com>
@ -23,8 +23,10 @@
#define USB_PRODUCT_ID_X53 0x2007
#define USB_PRODUCT_ID_X53_SECOND 0x2014
#define USB_PRODUCT_ID_Z53 0x3008
#define USB_PRODUCT_ID_KRAKEN2023 0x300E
#define USB_PRODUCT_ID_KRAKEN2023_ELITE 0x300C
enum kinds { X53, Z53 } __packed;
enum kinds { X53, Z53, KRAKEN2023 } __packed;
enum pwm_enable { off, manual, curve } __packed;
#define DRIVER_NAME "nzxt_kraken3"
@ -136,6 +138,7 @@ static umode_t kraken3_is_visible(const void *data, enum hwmon_sensor_types type
return 0444;
break;
case Z53:
case KRAKEN2023:
/* Pump and fan */
if (channel < 2)
return 0444;
@ -155,6 +158,7 @@ static umode_t kraken3_is_visible(const void *data, enum hwmon_sensor_types type
return 0644;
break;
case Z53:
case KRAKEN2023:
/* Pump and fan */
if (channel < 2)
return 0644;
@ -242,6 +246,7 @@ static int kraken3_read_x53(struct kraken3_data *priv)
return 0;
}
/* Covers Z53 and KRAKEN2023 device kinds */
static int kraken3_read_z53(struct kraken3_data *priv)
{
int ret = mutex_lock_interruptible(&priv->z53_status_request_lock);
@ -355,6 +360,13 @@ static int kraken3_write_curve(struct kraken3_data *priv, u8 *curve_array, int c
/* Set the correct ID for writing pump/fan duty (0x01 or 0x02, respectively) */
fixed_duty_cmd[SET_DUTY_ID_OFFSET] = channel + 1;
if (priv->kind == KRAKEN2023) {
/* These require 1s in the next one or two slots after SET_DUTY_ID_OFFSET */
fixed_duty_cmd[SET_DUTY_ID_OFFSET + 1] = 1;
if (channel == 1) /* Fan */
fixed_duty_cmd[SET_DUTY_ID_OFFSET + 2] = 1;
}
/* Copy curve to command */
memcpy(fixed_duty_cmd + SET_CURVE_DUTY_CMD_HEADER_LENGTH, curve_array, CUSTOM_CURVE_POINTS);
@ -502,8 +514,8 @@ static umode_t kraken3_curve_props_are_visible(struct kobject *kobj, struct attr
struct device *dev = kobj_to_dev(kobj);
struct kraken3_data *priv = dev_get_drvdata(dev);
/* Only Z53 has the fan curve */
if (index >= CUSTOM_CURVE_POINTS && priv->kind != Z53)
/* X53 does not have a fan */
if (index >= CUSTOM_CURVE_POINTS && priv->kind == X53)
return 0;
return attr->mode;
@ -769,8 +781,8 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report,
if (priv->kind == X53 && !completion_done(&priv->status_report_processed)) {
/* Mark first X-series device report as received */
complete_all(&priv->status_report_processed);
} else if (priv->kind == Z53) {
/* Additional readings for Z53 */
} else if (priv->kind == Z53 || priv->kind == KRAKEN2023) {
/* Additional readings for Z53 and KRAKEN2023 */
priv->fan_input[1] = get_unaligned_le16(data + Z53_FAN_SPEED_OFFSET);
priv->channel_info[1].reported_duty =
kraken3_percent_to_pwm(data[Z53_FAN_DUTY_OFFSET]);
@ -907,6 +919,14 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
priv->kind = Z53;
device_name = "z53";
break;
case USB_PRODUCT_ID_KRAKEN2023:
priv->kind = KRAKEN2023;
device_name = "kraken2023";
break;
case USB_PRODUCT_ID_KRAKEN2023_ELITE:
priv->kind = KRAKEN2023;
device_name = "kraken2023elite";
break;
default:
break;
}
@ -969,6 +989,8 @@ static const struct hid_device_id kraken3_table[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_X53) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_X53_SECOND) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_Z53) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_KRAKEN2023) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_KRAKEN2023_ELITE) },
{ }
};