From 67dd4d137557909279a21c1b5de87a24c84903f9 Mon Sep 17 00:00:00 2001
From: Giedrius <giedrius@blokas.io>
Date: Tue, 7 Jan 2020 11:04:21 +0200
Subject: [PATCH] Pisound: MIDI communication fixes for scaled down
 CPU.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Increased maximum SPI communication speed to avoid running too slow
  when the CPU is scaled down and losing MIDI data.

* Keep track of buffer usage in millibytes for higher precision.

Signed-off-by: Giedrius Trainavičius <giedrius@blokas.io>
---
 sound/soc/bcm/pisound.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

--- a/sound/soc/bcm/pisound.c
+++ b/sound/soc/bcm/pisound.c
@@ -1,6 +1,6 @@
 /*
  * Pisound Linux kernel module.
- * Copyright (C) 2016-2019  Vilniaus Blokas UAB, https://blokas.io/pisound
+ * Copyright (C) 2016-2020  Vilniaus Blokas UAB, https://blokas.io/pisound
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -326,7 +326,7 @@ static void spi_transfer(const uint8_t *
 	transfer.tx_buf = txbuf;
 	transfer.rx_buf = rxbuf;
 	transfer.len = len;
-	transfer.speed_hz = 100000;
+	transfer.speed_hz = 150000;
 	transfer.delay_usecs = 10;
 	spi_message_add_tail(&transfer, &msg);
 
@@ -403,9 +403,9 @@ static struct spi_device *pisnd_spi_find
 static void pisnd_work_handler(struct work_struct *work)
 {
 	enum { TRANSFER_SIZE = 4 };
-	enum { PISOUND_OUTPUT_BUFFER_SIZE = 128 };
-	enum { MIDI_BYTES_PER_SECOND = 3125 };
-	int out_buffer_used = 0;
+	enum { PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES = 127 * 1000 };
+	enum { MIDI_MILLIBYTES_PER_JIFFIE = (3125 * 1000) / HZ };
+	int out_buffer_used_millibytes = 0;
 	unsigned long now;
 	uint8_t val;
 	uint8_t txbuf[TRANSFER_SIZE];
@@ -445,7 +445,9 @@ static void pisnd_work_handler(struct wo
 			had_data = false;
 			memset(txbuf, 0, sizeof(txbuf));
 			for (i = 0; i < sizeof(txbuf) &&
-				out_buffer_used < PISOUND_OUTPUT_BUFFER_SIZE;
+				((out_buffer_used_millibytes+1000 <
+				PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES) ||
+				g_ledFlashDurationChanged);
 				i += 2) {
 
 				val = 0;
@@ -458,7 +460,7 @@ static void pisnd_work_handler(struct wo
 				} else if (kfifo_get(&spi_fifo_out, &val)) {
 					txbuf[i+0] = 0x0f;
 					txbuf[i+1] = val;
-					++out_buffer_used;
+					out_buffer_used_millibytes += 1000;
 				}
 			}
 
@@ -469,12 +471,14 @@ static void pisnd_work_handler(struct wo
 			 * rate.
 			 */
 			now = jiffies;
-			out_buffer_used -=
-				(MIDI_BYTES_PER_SECOND / HZ) /
-				(now - last_transfer_at);
-			if (out_buffer_used < 0)
-				out_buffer_used = 0;
-			last_transfer_at = now;
+			if (now != last_transfer_at) {
+				out_buffer_used_millibytes -=
+					(now - last_transfer_at) *
+					MIDI_MILLIBYTES_PER_JIFFIE;
+				if (out_buffer_used_millibytes < 0)
+					out_buffer_used_millibytes = 0;
+				last_transfer_at = now;
+			}
 
 			for (i = 0; i < sizeof(rxbuf); i += 2) {
 				if (rxbuf[i]) {
@@ -489,6 +493,7 @@ static void pisnd_work_handler(struct wo
 			|| !kfifo_is_empty(&spi_fifo_out)
 			|| pisnd_spi_has_more()
 			|| g_ledFlashDurationChanged
+			|| out_buffer_used_millibytes != 0
 			);
 
 		if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
