All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Young <sean@mess.org>
To: linux-media@vger.kernel.org, linux-pwm@vger.kernel.org,
	Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>,
	Sean Young <sean@mess.org>,
	Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH v3 3/3] media: pwm-ir-tx: trigger edges from hrtimer interrupt context
Date: Tue, 17 Oct 2023 10:17:39 +0100	[thread overview]
Message-ID: <ebf90ef3c851dad20ca4cfacca8c1a2205833196.1697534024.git.sean@mess.org> (raw)
In-Reply-To: <cover.1697534024.git.sean@mess.org>

This makes the driver much more precise.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/pwm-ir-tx.c | 79 ++++++++++++++++++++++++++++++++++--
 1 file changed, 76 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c
index ccb86890adcea..4f9844e6d3fa2 100644
--- a/drivers/media/rc/pwm-ir-tx.c
+++ b/drivers/media/rc/pwm-ir-tx.c
@@ -10,6 +10,8 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/hrtimer.h>
+#include <linux/completion.h>
 #include <media/rc-core.h>
 
 #define DRIVER_NAME	"pwm-ir-tx"
@@ -17,8 +19,14 @@
 
 struct pwm_ir {
 	struct pwm_device *pwm;
-	unsigned int carrier;
-	unsigned int duty_cycle;
+	struct hrtimer timer;
+	struct completion tx_done;
+	struct pwm_state *state;
+	u32 carrier;
+	u32 duty_cycle;
+	uint *txbuf;
+	uint txbuf_len;
+	uint txbuf_index;
 };
 
 static const struct of_device_id pwm_ir_of_match[] = {
@@ -82,6 +90,62 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
 	return count;
 }
 
+static int pwm_ir_tx_atomic(struct rc_dev *dev, unsigned int *txbuf,
+			    unsigned int count)
+{
+	struct pwm_ir *pwm_ir = dev->priv;
+	struct pwm_device *pwm = pwm_ir->pwm;
+	struct pwm_state state;
+
+	pwm_init_state(pwm, &state);
+
+	state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier);
+	pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100);
+
+	pwm_ir->txbuf = txbuf;
+	pwm_ir->txbuf_len = count;
+	pwm_ir->txbuf_index = 0;
+	pwm_ir->state = &state;
+
+	hrtimer_start(&pwm_ir->timer, 0, HRTIMER_MODE_REL);
+
+	wait_for_completion(&pwm_ir->tx_done);
+
+	return count;
+}
+
+static enum hrtimer_restart pwm_ir_timer(struct hrtimer *timer)
+{
+	struct pwm_ir *pwm_ir = container_of(timer, struct pwm_ir, timer);
+	ktime_t now;
+
+	/*
+	 * If we happen to hit an odd latency spike, loop through the
+	 * pulses until we catch up.
+	 */
+	do {
+		u64 ns;
+
+		pwm_ir->state->enabled = !(pwm_ir->txbuf_index % 2);
+		pwm_apply(pwm_ir->pwm, pwm_ir->state);
+
+		if (pwm_ir->txbuf_index >= pwm_ir->txbuf_len) {
+			complete(&pwm_ir->tx_done);
+
+			return HRTIMER_NORESTART;
+		}
+
+		ns = US_TO_NS(pwm_ir->txbuf[pwm_ir->txbuf_index]);
+		hrtimer_add_expires_ns(timer, ns);
+
+		pwm_ir->txbuf_index++;
+
+		now = timer->base->get_time();
+	} while (hrtimer_get_expires_tv64(timer) < now);
+
+	return HRTIMER_RESTART;
+}
+
 static int pwm_ir_probe(struct platform_device *pdev)
 {
 	struct pwm_ir *pwm_ir;
@@ -103,10 +167,19 @@ static int pwm_ir_probe(struct platform_device *pdev)
 	if (!rcdev)
 		return -ENOMEM;
 
+	if (pwm_is_atomic(pwm_ir->pwm)) {
+		init_completion(&pwm_ir->tx_done);
+		hrtimer_init(&pwm_ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		pwm_ir->timer.function = pwm_ir_timer;
+		rcdev->tx_ir = pwm_ir_tx_atomic;
+	} else {
+		dev_info(&pdev->dev, "tx will not be accurate as pwm device does not support atomic mode");
+		rcdev->tx_ir = pwm_ir_tx;
+	}
+
 	rcdev->priv = pwm_ir;
 	rcdev->driver_name = DRIVER_NAME;
 	rcdev->device_name = DEVICE_NAME;
-	rcdev->tx_ir = pwm_ir_tx;
 	rcdev->s_tx_duty_cycle = pwm_ir_set_duty_cycle;
 	rcdev->s_tx_carrier = pwm_ir_set_carrier;
 
-- 
2.42.0


      parent reply	other threads:[~2023-10-17  9:30 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-17  9:17 [PATCH v3 0/3] Improve pwm-ir-tx precision Sean Young
2023-10-17  9:17 ` [PATCH v3 1/3] pwm: make it possible to apply pwm changes in atomic context Sean Young
2023-10-17  9:17   ` [Intel-gfx] " Sean Young
2023-10-17  9:17   ` Sean Young
2023-10-17  9:17   ` Sean Young
2023-10-18 13:57   ` Hans de Goede
2023-10-18 13:57     ` Hans de Goede
2023-10-18 13:57     ` [Intel-gfx] " Hans de Goede
2023-10-18 13:57     ` Hans de Goede
2023-10-19 10:51     ` Uwe Kleine-König
2023-10-19 10:51       ` Uwe Kleine-König
2023-10-19 10:51       ` [Intel-gfx] " Uwe Kleine-König
2023-10-19 10:51       ` Uwe Kleine-König
2023-10-21  9:08       ` Hans de Goede
2023-10-21  9:08         ` [Intel-gfx] " Hans de Goede
2023-10-21  9:08         ` Hans de Goede
2023-10-21  9:08         ` Hans de Goede
2023-10-22 10:46         ` Sean Young
2023-10-22 10:46           ` [Intel-gfx] " Sean Young
2023-10-22 10:46           ` Sean Young
2023-10-22 10:46           ` Sean Young
2023-10-23 13:17           ` Hans de Goede
2023-10-23 13:17             ` [Intel-gfx] " Hans de Goede
2023-10-23 13:17             ` Hans de Goede
2023-10-23 13:17             ` Hans de Goede
2023-10-23 13:34           ` Daniel Thompson
2023-10-23 13:34             ` Daniel Thompson
2023-10-23 13:34             ` [Intel-gfx] " Daniel Thompson
2023-10-23 13:34             ` Daniel Thompson
2023-10-25  9:53             ` Sean Young
2023-10-25  9:53               ` [Intel-gfx] " Sean Young
2023-10-25  9:53               ` Sean Young
2023-10-25  9:53               ` Sean Young
2023-10-25 10:47               ` Uwe Kleine-König
2023-10-25 10:47                 ` [Intel-gfx] " Uwe Kleine-König
2023-10-25 10:47                 ` Uwe Kleine-König
2023-10-25 10:47                 ` Uwe Kleine-König
2023-10-21 23:55   ` kernel test robot
2023-10-23 10:47   ` Jani Nikula
2023-10-23 10:47     ` Jani Nikula
2023-10-23 10:47     ` [Intel-gfx] " Jani Nikula
2023-10-23 10:47     ` Jani Nikula
2023-10-17  9:17 ` [PATCH v3 2/3] pwm: bcm2835: allow pwm driver to be used " Sean Young
2023-10-17  9:17   ` Sean Young
2023-10-18 15:00   ` Stefan Wahren
2023-10-18 15:00     ` Stefan Wahren
2023-10-19 11:19     ` Sean Young
2023-10-19 11:19       ` Sean Young
2023-10-17  9:17 ` Sean Young [this message]

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=ebf90ef3c851dad20ca4cfacca8c1a2205833196.1697534024.git.sean@mess.org \
    --to=sean@mess.org \
    --cc=ivo.g.dimitrov.75@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=mchehab@kernel.org \
    /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.