On Fri Jun 13 14:21:51 2025 +0300, Cosmin Tanislav wrote:
> Replace the static transmit buffer with a dynamically allocated one,
> removing the limit imposed on the number of pulses to transmit.
> 
> Calculate the number of pulses for each duration in the received buffer
> ahead of time, while also adding up the total pulses, to be able to
> allocate a buffer that perfectly fits the total number of pulses, then
> populate it.
> 
> Signed-off-by: Cosmin Tanislav <demonsin...@gmail.com>
> Signed-off-by: Sean Young <s...@mess.org>
> Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/rc/ir-spi.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

---

diff --git a/drivers/media/rc/ir-spi.c b/drivers/media/rc/ir-spi.c
index 8fc8e496e6aa..50e30e2fae22 100644
--- a/drivers/media/rc/ir-spi.c
+++ b/drivers/media/rc/ir-spi.c
@@ -21,13 +21,11 @@
 #define IR_SPI_DRIVER_NAME             "ir-spi"
 
 #define IR_SPI_DEFAULT_FREQUENCY       38000
-#define IR_SPI_MAX_BUFSIZE              4096
 
 struct ir_spi_data {
        u32 freq;
        bool negated;
 
-       u16 tx_buf[IR_SPI_MAX_BUFSIZE];
        u16 pulse;
        u16 space;
 
@@ -43,17 +41,22 @@ static int ir_spi_tx(struct rc_dev *dev, unsigned int 
*buffer, unsigned int coun
        unsigned int len = 0;
        struct ir_spi_data *idata = dev->priv;
        struct spi_transfer xfer;
+       u16 *tx_buf;
 
        /* convert the pulse/space signal to raw binary signal */
        for (i = 0; i < count; i++) {
-               unsigned int periods;
-               int j;
-               u16 val;
+               buffer[i] = DIV_ROUND_CLOSEST(buffer[i] * idata->freq, 1000000);
+               len += buffer[i];
+       }
 
-               periods = DIV_ROUND_CLOSEST(buffer[i] * idata->freq, 1000000);
+       tx_buf = kmalloc_array(len, sizeof(*tx_buf), GFP_KERNEL);
+       if (!tx_buf)
+               return -ENOMEM;
 
-               if (len + periods >= IR_SPI_MAX_BUFSIZE)
-                       return -EINVAL;
+       len = 0;
+       for (i = 0; i < count; i++) {
+               int j;
+               u16 val;
 
                /*
                 * The first value in buffer is a pulse, so that 0, 2, 4, ...
@@ -61,19 +64,19 @@ static int ir_spi_tx(struct rc_dev *dev, unsigned int 
*buffer, unsigned int coun
                 * contain a space duration.
                 */
                val = (i % 2) ? idata->space : idata->pulse;
-               for (j = 0; j < periods; j++)
-                       idata->tx_buf[len++] = val;
+               for (j = 0; j < buffer[i]; j++)
+                       tx_buf[len++] = val;
        }
 
        memset(&xfer, 0, sizeof(xfer));
 
        xfer.speed_hz = idata->freq * 16;
-       xfer.len = len * sizeof(*idata->tx_buf);
-       xfer.tx_buf = idata->tx_buf;
+       xfer.len = len * sizeof(*tx_buf);
+       xfer.tx_buf = tx_buf;
 
        ret = regulator_enable(idata->regulator);
        if (ret)
-               return ret;
+               goto err_free_tx_buf;
 
        ret = spi_sync_transfer(idata->spi, &xfer, 1);
        if (ret)
@@ -81,6 +84,10 @@ static int ir_spi_tx(struct rc_dev *dev, unsigned int 
*buffer, unsigned int coun
 
        regulator_disable(idata->regulator);
 
+err_free_tx_buf:
+
+       kfree(tx_buf);
+
        return ret ? ret : count;
 }
 

Reply via email to