From: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
To: "Sean Young" <sean@mess.org>,
linux-media@vger.kernel.org,
"Mauro Carvalho Chehab" <mchehab@kernel.org>,
"Thierry Reding" <thierry.reding@gmail.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org
Subject: Re: [PATCH v2 3/3] media: pwm-ir-tx: trigger edges from hrtimer interrupt context
Date: Sun, 15 Oct 2023 09:31:34 +0300 [thread overview]
Message-ID: <e47d4d33-4689-915d-3169-5c122075df05@gmail.com> (raw)
In-Reply-To: <1560b474f7d426bc77100665c14c3a29c3af3e75.1697193646.git.sean@mess.org>
On 13.10.23 г. 13:46 ч., Sean Young wrote:
> 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 c5f37c03af9c..3e801fa8ee2c 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 completion;
what about 'struct completion tx_done'?
> + struct pwm_state *state;
> + uint carrier;
> + uint duty_cycle;
With my c++ developer hat on, I think either 'u32' or 'unsigned int' is
more proper type for carrier and duty_cycle. Both s_tx_duty_cycle and
s_tx_carrier are declared with second parameter of type u32, maybe
that's what have to be used all over the place if you are to change from
'unsigned int'. But better leave as it is, pwm_set_relative_duty_cycle()
takes 'unsigned int' anyway.
> + uint *txbuf;
> + uint txbuf_len;
> + uint txbuf_index;
OTOH, it is (*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n),
so maybe you should use 'unsigned' or 'unsigned int' for those.
I know at the end all those will be compiled to same type, but still :)
> };
>
> 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->completion);
> +
> + 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_state_atomic(pwm_ir->pwm, pwm_ir->state);
> +
> + if (pwm_ir->txbuf_index >= pwm_ir->txbuf_len) {
> + complete(&pwm_ir->completion);
> +
> + 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->completion);
> + 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;
>
>
next prev parent reply other threads:[~2023-10-15 6:31 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1697193646.git.sean@mess.org>
2023-10-13 10:46 ` [PATCH v2 1/3] pwm: make it possible to apply pwm changes in atomic context Sean Young
2023-10-13 11:51 ` Thierry Reding
2023-10-13 14:58 ` Sean Young
2023-10-13 15:34 ` Thierry Reding
2023-10-13 18:04 ` Uwe Kleine-König
2023-10-14 8:31 ` Sean Young
2023-10-13 10:46 ` [PATCH v2 2/3] pwm: bcm2835: allow pwm driver to be used " Sean Young
2023-10-13 11:04 ` Stefan Wahren
2023-10-13 11:13 ` Alexander Stein
2023-10-13 11:44 ` Stefan Wahren
2023-10-13 17:51 ` Uwe Kleine-König
2023-10-14 6:51 ` Ivaylo Dimitrov
2023-10-14 8:47 ` Uwe Kleine-König
2023-10-13 10:46 ` [PATCH v2 3/3] media: pwm-ir-tx: trigger edges from hrtimer interrupt context Sean Young
2023-10-15 6:31 ` Ivaylo Dimitrov [this message]
2023-10-15 21:25 ` Sean Young
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=e47d4d33-4689-915d-3169-5c122075df05@gmail.com \
--to=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 \
--cc=sean@mess.org \
--cc=thierry.reding@gmail.com \
--cc=u.kleine-koenig@pengutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox