All of lore.kernel.org
 help / color / mirror / Atom feed
From: jaap aarts <jaap.aarts1@gmail.com>
To: Jean Delvare <jdelvare@suse.com>,
	Guenter Roeck <linux@roeck-us.net>,
	linux-hwmon@vger.kernel.org, linux-usb@vger.kernel.org
Cc: jaap aarts <jaap.aarts1@gmail.com>, Jaap Aarts <jaap.aarts1@example.com>
Subject: [PATCH 3/6] rpm support for asetek gen 6 driver
Date: Mon, 13 Jul 2020 21:32:24 +0200	[thread overview]
Message-ID: <20200713193227.189751-3-jaap.aarts1@gmail.com> (raw)
In-Reply-To: <20200713193227.189751-1-jaap.aarts1@gmail.com>

Signed-off-by: Jaap Aarts <jaap.aarts1@example.com>
---
 drivers/hwmon/asetek_gen6.c | 190 ++++++++++++++++++++++++++++++++++--
 1 file changed, 182 insertions(+), 8 deletions(-)

diff --git a/drivers/hwmon/asetek_gen6.c b/drivers/hwmon/asetek_gen6.c
index b82a678717ab..5c3bd456f881 100644
--- a/drivers/hwmon/asetek_gen6.c
+++ b/drivers/hwmon/asetek_gen6.c
@@ -108,6 +108,50 @@ static bool check_succes(char command, char ret[SUCCES_LENGTH])
 	return strncmp(ret, success, SUCCES_LENGTH) == 0;
 }
 
+int set_fan_rpm_curve(struct driver *cdev, struct fan_hwmon_data *fan_data,
+		      struct curve_point point[7])
+{
+	int retval;
+	int wrote;
+	int sndpipe = usb_sndbulkpipe(cdev->udev, cdev->bulk_out_endpointAddr);
+	int rcvpipe = usb_rcvbulkpipe(cdev->udev, cdev->bulk_in_endpointAddr);
+
+	char *send_buf = cdev->bulk_out_buffer;
+	char *recv_buf = cdev->bulk_in_buffer;
+	memcpy(fan_data->curve, point, sizeof(fan_data->curve));
+
+	send_buf[0] = 0x40;
+	send_buf[1] = fan_data->fan_channel;
+	send_buf[2] = point[0].temp;
+	send_buf[3] = point[1].temp;
+	send_buf[4] = point[2].temp;
+	send_buf[5] = point[3].temp;
+	send_buf[6] = point[4].temp;
+	send_buf[7] = point[5].temp;
+	send_buf[8] = point[6].temp;
+	send_buf[9] = point[0].pwm;
+	send_buf[10] = point[1].pwm;
+	send_buf[11] = point[2].pwm;
+	send_buf[12] = point[3].pwm;
+	send_buf[13] = point[4].pwm;
+	send_buf[14] = point[5].pwm;
+	send_buf[15] = point[6].pwm;
+
+	retval = usb_bulk_msg(cdev->udev, sndpipe, send_buf, 16, &wrote, 100);
+	if (retval != 0)
+		return retval;
+
+	retval = usb_bulk_msg(cdev->udev, rcvpipe, recv_buf, 4, &wrote, 100);
+	if (retval != 0)
+		return retval;
+
+	if (!check_succes(
+		    send_buf[0],
+		    recv_buf) /* || recv_buf[3] != fan_data->fan_channel */)
+		printk(KERN_INFO "[*] Failled setting fan curve %d,%d,%d/%d\n",
+		       recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]);
+	return 0;
+}
 int set_fan_target_rpm(struct driver *cdev, struct fan_hwmon_data *fan_data,
 		       long val)
 {
@@ -177,6 +221,40 @@ int get_fan_current_rpm(struct driver *cdev, struct fan_hwmon_data *fan_data,
 	return 0;
 }
 
+int set_fan_target_pwm(struct driver *cdev, struct fan_hwmon_data *fan_data,
+		       long val)
+{
+	int retval;
+	int wrote;
+	int sndpipe = usb_sndbulkpipe(cdev->udev, cdev->bulk_out_endpointAddr);
+	int rcvpipe = usb_rcvbulkpipe(cdev->udev, cdev->bulk_in_endpointAddr);
+
+	unsigned char *send_buf = cdev->bulk_out_buffer;
+	unsigned char *recv_buf = cdev->bulk_in_buffer;
+
+	fan_data->fan_pwm_target = val;
+	fan_data->fan_target = 0;
+
+	send_buf[0] = 0x42;
+	send_buf[1] = fan_data->fan_channel;
+	send_buf[3] = fan_data->fan_pwm_target;
+
+	retval = usb_bulk_msg(cdev->udev, sndpipe, send_buf, 4, &wrote, 100);
+	if (retval != 0)
+		return retval;
+
+	retval = usb_bulk_msg(cdev->udev, rcvpipe, recv_buf, 6, &wrote, 100000);
+	if (retval != 0)
+		return retval;
+
+	//no error
+	if (!check_succes(send_buf[0], recv_buf) ||
+	    recv_buf[3] != fan_data->fan_channel)
+		printk(KERN_INFO "[*] Failled setting fan pwm %d,%d,%d/%d\n",
+		       recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]);
+	return 0;
+}
+
 umode_t is_visible_func(const void *d, enum hwmon_sensor_types type, u32 attr,
 			int channel)
 {
@@ -196,6 +274,19 @@ umode_t is_visible_func(const void *d, enum hwmon_sensor_types type, u32 attr,
 			break;
 		}
 		break;
+	case hwmon_pwm:
+		switch (attr) {
+		case hwmon_pwm_input:
+			return 0200;
+			break;
+		case hwmon_pwm_mode:
+			return 0644;
+			break;
+		default:
+			break;
+		}
+		break;
+
 	default:
 		break;
 	}
@@ -214,7 +305,11 @@ static int write_func(struct device *dev, enum hwmon_sensor_types type,
 	case hwmon_fan:;
 		switch (attr) {
 		case hwmon_fan_target:
+
 			fan_data = data->channel_data[channel];
+			if (fan_data->mode != 1) {
+				return -EINVAL;
+			}
 
 			retval = usb_autopm_get_interface(cdev->interface);
 			if (retval)
@@ -229,11 +324,70 @@ static int write_func(struct device *dev, enum hwmon_sensor_types type,
 			if (retval)
 				goto cleanup;
 
-			break;
+			goto exit;
 		default:
 			return -EINVAL;
 		}
-		break;
+		goto exit;
+	case hwmon_pwm:;
+
+		switch (attr) {
+		case hwmon_pwm_input:
+			fan_data = data->channel_data[channel];
+			if (fan_data->mode != 1) {
+				return -EINVAL;
+			}
+
+			retval = usb_autopm_get_interface(cdev->interface);
+			if (retval)
+				goto exit;
+
+			if (down_trylock(&cdev->limit_sem)) {
+				retval = -EAGAIN;
+				goto cleanup_interface;
+			}
+
+			retval = set_fan_target_pwm(cdev, fan_data, val);
+			if (retval)
+				return retval;
+
+			goto cleanup;
+		case hwmon_pwm_mode:
+			fan_data = data->channel_data[channel];
+
+			retval = usb_autopm_get_interface(cdev->interface);
+			if (retval)
+				goto exit;
+
+			if (down_trylock(&cdev->limit_sem)) {
+				retval = -EAGAIN;
+				goto cleanup_interface;
+			}
+			fan_data->mode = val;
+
+			if (val == 0) {
+				set_fan_rpm_curve(cdev, fan_data,
+						  default_curve);
+			} else if (val == 1) {
+				if (fan_data->fan_target != 0) {
+					retval = set_fan_target_rpm(
+						cdev, fan_data,
+						fan_data->fan_target);
+					if (retval)
+						goto cleanup;
+				} else if (fan_data->fan_pwm_target != 0) {
+					retval = set_fan_target_pwm(
+						cdev, fan_data,
+						fan_data->fan_pwm_target);
+					if (retval)
+						goto cleanup;
+				}
+			}
+			goto cleanup;
+		default:
+			return -EINVAL;
+		}
+		goto exit;
 	default:
 		return -EINVAL;
 	}
@@ -274,19 +428,36 @@ int read_func(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 			if (retval)
 				goto cleanup;
 
-			break;
+			goto cleanup;
 		case hwmon_fan_target:
 			fan_data = data->channel_data[channel];
+			if (fan_data->mode != 1) {
+				*val = 0;
+				goto exit;
+			}
 
 			get_fan_target_rpm(fan_data, val);
-			break;
+			goto exit;
 		case hwmon_fan_min:
 			*val = 200;
-			break;
+			goto exit;
+
 		default:
 			return -EINVAL;
 		}
-		break;
+		goto exit;
+
+	case hwmon_pwm:
+		switch (attr) {
+		case hwmon_pwm_mode:
+			fan_data = data->channel_data[channel];
+			*val = fan_data->mode;
+			goto exit;
+		default:
+			return -EINVAL;
+		}
+		goto exit;
+
 	default:
 		return -EINVAL;
 	}
@@ -299,8 +470,11 @@ int read_func(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 	return retval;
 }
 static const struct hwmon_channel_info *dual_fan[] = {
-	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_TARGET,
-			   HWMON_F_INPUT | HWMON_F_TARGET),
+	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_MIN,
+			   HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_MIN),
+	HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_MODE,
+			   HWMON_PWM_INPUT | HWMON_PWM_MODE),
+
 	NULL
 };
 
-- 
2.27.0


  parent reply	other threads:[~2020-07-13 19:32 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-13 19:32 [PATCH 1/6] skeleton for asetek gen 6 driver jaap aarts
2020-07-13 19:32 ` [PATCH 2/6] fan support " jaap aarts
2020-07-13 19:32 ` jaap aarts [this message]
2020-07-13 19:32 ` [PATCH 4/6] automatic fan count detection jaap aarts
2020-07-13 19:32 ` [PATCH 5/6] allow setting enable instead of mode, and support enable 2/3/4 jaap aarts
2020-07-13 19:32 ` [PATCH 6/6] added some comments and fixed some styling jaap aarts
2020-07-14  4:59 ` [PATCH 1/6] skeleton for asetek gen 6 driver Guenter Roeck
2020-07-14 10:03   ` jaap aarts
2020-07-14 17:30     ` Guenter Roeck
2020-07-14 17:43       ` jaap aarts
2020-07-14  5:19 ` Guenter Roeck
2020-07-14  5:54 ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200713193227.189751-3-jaap.aarts1@gmail.com \
    --to=jaap.aarts1@gmail.com \
    --cc=jaap.aarts1@example.com \
    --cc=jdelvare@suse.com \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux@roeck-us.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.