Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: gpio-ir-tx: fix transmit with long spaces on Orange Pi PC

Calling udelay for than 1000us does not always yield the correct
results.

Cc: stable@vger.kernel.org
Reported-by: Михаил <vrserver1@gmail.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
5ad05eca 10923471

+21 -7
+21 -7
drivers/media/rc/gpio-ir-tx.c
··· 48 48 return 0; 49 49 } 50 50 51 + static void delay_until(ktime_t until) 52 + { 53 + /* 54 + * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on 55 + * m68k ndelay(s64) does not compile; so use s32 rather than s64. 56 + */ 57 + s32 delta; 58 + 59 + while (true) { 60 + delta = ktime_us_delta(until, ktime_get()); 61 + if (delta <= 0) 62 + return; 63 + 64 + /* udelay more than 1ms may not work */ 65 + delta = min(delta, 1000); 66 + udelay(delta); 67 + } 68 + } 69 + 51 70 static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf, 52 71 uint count) 53 72 { 54 73 ktime_t edge; 55 - s32 delta; 56 74 int i; 57 75 58 76 local_irq_disable(); ··· 81 63 gpiod_set_value(gpio_ir->gpio, !(i % 2)); 82 64 83 65 edge = ktime_add_us(edge, txbuf[i]); 84 - delta = ktime_us_delta(edge, ktime_get()); 85 - if (delta > 0) 86 - udelay(delta); 66 + delay_until(edge); 87 67 } 88 68 89 69 gpiod_set_value(gpio_ir->gpio, 0); ··· 113 97 if (i % 2) { 114 98 // space 115 99 edge = ktime_add_us(edge, txbuf[i]); 116 - delta = ktime_us_delta(edge, ktime_get()); 117 - if (delta > 0) 118 - udelay(delta); 100 + delay_until(edge); 119 101 } else { 120 102 // pulse 121 103 ktime_t last = ktime_add_us(edge, txbuf[i]);