[PATCH] media: rc: nuvoton: remove rudimentary transmit functionality

2017-07-15 Thread Heiner Kallweit
Transmit support in this driver was never tested and based on the code
it can't work. Just one example:
The buffer provided to nvt_tx_ir holds unsigned int values in
micro seconds: First value is for a pulse, second for a pause, etc.
Bytes in this buffer are copied as-is to the chip FIFO what can't work
as the chip-internal format is totally different. See also conversion
done in nvt_process_rx_ir_data.

Even if we would try to fix this we have the issue that we can't test
it. There seems to be no device on the market using IR transmit with
one of the chips supported by this driver.

To facilitate maintenance of the driver I'd propose to remove the
rudimentary transmit support.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 114 ++---
 drivers/media/rc/nuvoton-cir.h |  24 -
 2 files changed, 3 insertions(+), 135 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index ec4b25bd..7651975b 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -727,70 +727,6 @@ static int nvt_ir_raw_set_wakeup_filter(struct rc_dev *dev,
return ret;
 }
 
-/*
- * nvt_tx_ir
- *
- * 1) clean TX fifo first (handled by AP)
- * 2) copy data from user space
- * 3) disable RX interrupts, enable TX interrupts: TTR & TFU
- * 4) send 9 packets to TX FIFO to open TTR
- * in interrupt_handler:
- * 5) send all data out
- * go back to write():
- * 6) disable TX interrupts, re-enable RX interupts
- *
- * The key problem of this function is user space data may larger than
- * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to
- * buf, and keep current copied data buf num in cur_buf_num. But driver's buf
- * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to
- * set TXFCONT as 0xff, until buf_count less than 0xff.
- */
-static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n)
-{
-   struct nvt_dev *nvt = dev->priv;
-   unsigned long flags;
-   unsigned int i;
-   u8 iren;
-   int ret;
-
-   spin_lock_irqsave(&nvt->lock, flags);
-
-   ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n);
-   nvt->tx.buf_count = (ret * sizeof(unsigned));
-
-   memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count);
-
-   nvt->tx.cur_buf_num = 0;
-
-   /* save currently enabled interrupts */
-   iren = nvt_cir_reg_read(nvt, CIR_IREN);
-
-   /* now disable all interrupts, save TFU & TTR */
-   nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN);
-
-   nvt->tx.tx_state = ST_TX_REPLY;
-
-   nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 |
- CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
-
-   /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */
-   for (i = 0; i < 9; i++)
-   nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
-
-   spin_unlock_irqrestore(&nvt->lock, flags);
-
-   wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
-
-   spin_lock_irqsave(&nvt->lock, flags);
-   nvt->tx.tx_state = ST_TX_NONE;
-   spin_unlock_irqrestore(&nvt->lock, flags);
-
-   /* restore enabled interrupts to prior state */
-   nvt_cir_reg_write(nvt, iren, CIR_IREN);
-
-   return ret;
-}
-
 /* dump contents of the last rx buffer we got from the hw rx fifo */
 static void nvt_dump_rx_buf(struct nvt_dev *nvt)
 {
@@ -895,11 +831,6 @@ static void nvt_cir_log_irqs(u8 status, u8 iren)
   CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : "");
 }
 
-static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
-{
-   return nvt->tx.tx_state == ST_TX_NONE;
-}
-
 /* interrupt service routine for incoming and outgoing CIR data */
 static irqreturn_t nvt_cir_isr(int irq, void *data)
 {
@@ -952,40 +883,8 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 
if (status & CIR_IRSTS_RFO)
nvt_handle_rx_fifo_overrun(nvt);
-
-   else if (status & (CIR_IRSTS_RTR | CIR_IRSTS_PE)) {
-   /* We only do rx if not tx'ing */
-   if (nvt_cir_tx_inactive(nvt))
-   nvt_get_rx_ir_data(nvt);
-   }
-
-   if (status & CIR_IRSTS_TE)
-   nvt_clear_tx_fifo(nvt);
-
-   if (status & CIR_IRSTS_TTR) {
-   unsigned int pos, count;
-   u8 tmp;
-
-   pos = nvt->tx.cur_buf_num;
-   count = nvt->tx.buf_count;
-
-   /* Write data into the hardware tx fifo while pos < count */
-   if (pos < count) {
-   nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO);
-   nvt->tx.cur_buf_num++;
-   /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */
-   } else {
-  

[PATCH v2 2/5] media: rc: meson-ir: make use of the bitfield macros

2017-04-12 Thread Heiner Kallweit
Make use of the bitfield macros thus partially hiding the complexity
of dealing with bitfields.

The patch also includes a minor fix to REG0_RATE_MASK, so far it was
set to bit 0..10, but according to the spec it's bit 0..11.

Signed-off-by: Heiner Kallweit 
Reviewed-by: Neil Armstrong 
---
v2:
- revert change in meson_ir_set_mask
- add R-b
---
 drivers/media/rc/meson-ir.c | 26 --
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index a4128d7c..3864ebe3 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -36,27 +37,24 @@
 /* only available on Meson 8b and newer */
 #define IR_DEC_REG20x20
 
-#define REG0_RATE_MASK (BIT(11) - 1)
+#define REG0_RATE_MASK GENMASK(11, 0)
 
 #define DECODE_MODE_NEC0x0
 #define DECODE_MODE_RAW0x2
 
 /* Meson 6b uses REG1 to configure the mode */
 #define REG1_MODE_MASK GENMASK(8, 7)
-#define REG1_MODE_SHIFT7
 
 /* Meson 8b / GXBB use REG2 to configure the mode */
 #define REG2_MODE_MASK GENMASK(3, 0)
-#define REG2_MODE_SHIFT0
 
-#define REG1_TIME_IV_SHIFT 16
-#define REG1_TIME_IV_MASK  ((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
+#define REG1_TIME_IV_MASK  GENMASK(28, 16)
 
-#define REG1_IRQSEL_MASK   (BIT(2) | BIT(3))
-#define REG1_IRQSEL_NEC_MODE   (0 << 2)
-#define REG1_IRQSEL_RISE_FALL  (1 << 2)
-#define REG1_IRQSEL_FALL   (2 << 2)
-#define REG1_IRQSEL_RISE   (3 << 2)
+#define REG1_IRQSEL_MASK   GENMASK(3, 2)
+#define REG1_IRQSEL_NEC_MODE   0
+#define REG1_IRQSEL_RISE_FALL  1
+#define REG1_IRQSEL_FALL   2
+#define REG1_IRQSEL_RISE   3
 
 #define REG1_RESET BIT(0)
 #define REG1_ENABLEBIT(15)
@@ -91,7 +89,7 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
spin_lock(&ir->lock);
 
duration = readl(ir->reg + IR_DEC_REG1);
-   duration = (duration & REG1_TIME_IV_MASK) >> REG1_TIME_IV_SHIFT;
+   duration = FIELD_GET(REG1_TIME_IV_MASK, duration);
rawir.duration = US_TO_NS(duration * MESON_TRATE);
 
rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN);
@@ -170,16 +168,16 @@ static int meson_ir_probe(struct platform_device *pdev)
/* Set general operation mode (= raw/software decoding) */
if (of_device_is_compatible(node, "amlogic,meson6-ir"))
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK,
- DECODE_MODE_RAW << REG1_MODE_SHIFT);
+ FIELD_PREP(REG1_MODE_MASK, DECODE_MODE_RAW));
else
meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK,
- DECODE_MODE_RAW << REG2_MODE_SHIFT);
+ FIELD_PREP(REG2_MODE_MASK, DECODE_MODE_RAW));
 
/* Set rate */
meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
/* IRQ on rising and falling edges */
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_IRQSEL_MASK,
- REG1_IRQSEL_RISE_FALL);
+ FIELD_PREP(REG1_IRQSEL_MASK, REG1_IRQSEL_RISE_FALL));
/* Enable the decoder */
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, REG1_ENABLE);
 
-- 
2.12.2




[PATCH v2 4/5] media: rc: meson-ir: use readl_relaxed in the interrupt handler

2017-04-12 Thread Heiner Kallweit
We don't need the memory barriers here and an interrupt handler should
be as fast as possible. Therefore switch to readl_relaxed.

Signed-off-by: Heiner Kallweit 
Reviewed-by: Neil Armstrong 
---
v2:
- added R-b
---
 drivers/media/rc/meson-ir.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index cf8943d2..1c72593d 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -83,16 +83,17 @@ static void meson_ir_set_mask(struct meson_ir *ir, unsigned 
int reg,
 static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
 {
struct meson_ir *ir = dev_id;
-   u32 duration;
+   u32 duration, status;
DEFINE_IR_RAW_EVENT(rawir);
 
spin_lock(&ir->lock);
 
-   duration = readl(ir->reg + IR_DEC_REG1);
+   duration = readl_relaxed(ir->reg + IR_DEC_REG1);
duration = FIELD_GET(REG1_TIME_IV_MASK, duration);
rawir.duration = US_TO_NS(duration * MESON_TRATE);
 
-   rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN);
+   status = readl_relaxed(ir->reg + IR_DEC_STATUS);
+   rawir.pulse = !!(status & STATUS_IR_DEC_IN);
 
ir_raw_event_store_with_filter(ir->rc, &rawir);
ir_raw_event_handle(ir->rc);
-- 
2.12.2




[PATCH v2 3/5] media: rc: meson-ir: switch to managed rc device allocation / registration

2017-04-12 Thread Heiner Kallweit
Switch to the managed versions of rc_allocate_device/rc_register_device,
thus simplifying the code.

Signed-off-by: Heiner Kallweit 
Reviewed-by: Neil Armstrong 
---
v2:
- added R-b
---
 drivers/media/rc/meson-ir.c | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 3864ebe3..cf8943d2 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -128,7 +128,7 @@ static int meson_ir_probe(struct platform_device *pdev)
return irq;
}
 
-   ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+   ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
if (!ir->rc) {
dev_err(dev, "failed to allocate rc device\n");
return -ENOMEM;
@@ -140,7 +140,6 @@ static int meson_ir_probe(struct platform_device *pdev)
ir->rc->input_id.bustype = BUS_HOST;
map_name = of_get_property(node, "linux,rc-map-name", NULL);
ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY;
-   ir->rc->dev.parent = dev;
ir->rc->allowed_protocols = RC_BIT_ALL_IR_DECODER;
ir->rc->rx_resolution = US_TO_NS(MESON_TRATE);
ir->rc->timeout = MS_TO_NS(200);
@@ -149,16 +148,16 @@ static int meson_ir_probe(struct platform_device *pdev)
spin_lock_init(&ir->lock);
platform_set_drvdata(pdev, ir);
 
-   ret = rc_register_device(ir->rc);
+   ret = devm_rc_register_device(dev, ir->rc);
if (ret) {
dev_err(dev, "failed to register rc device\n");
-   goto out_free;
+   return ret;
}
 
ret = devm_request_irq(dev, irq, meson_ir_irq, 0, "ir-meson", ir);
if (ret) {
dev_err(dev, "failed to request irq\n");
-   goto out_unreg;
+   return ret;
}
 
/* Reset the decoder */
@@ -184,13 +183,6 @@ static int meson_ir_probe(struct platform_device *pdev)
dev_info(dev, "receiver initialized\n");
 
return 0;
-out_unreg:
-   rc_unregister_device(ir->rc);
-   ir->rc = NULL;
-out_free:
-   rc_free_device(ir->rc);
-
-   return ret;
 }
 
 static int meson_ir_remove(struct platform_device *pdev)
@@ -203,8 +195,6 @@ static int meson_ir_remove(struct platform_device *pdev)
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0);
spin_unlock_irqrestore(&ir->lock, flags);
 
-   rc_unregister_device(ir->rc);
-
return 0;
 }
 
-- 
2.12.2




[PATCH v2 1/5] media: rc: meson-ir: remove irq from struct meson_ir

2017-04-12 Thread Heiner Kallweit
The irq number is used in the probe function only, therefore just use
a local variable.

Signed-off-by: Heiner Kallweit 
---
v2:
- no changes
---
 drivers/media/rc/meson-ir.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 5576dbd6..a4128d7c 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -68,7 +68,6 @@
 struct meson_ir {
void __iomem*reg;
struct rc_dev   *rc;
-   int irq;
spinlock_t  lock;
 };
 
@@ -112,7 +111,7 @@ static int meson_ir_probe(struct platform_device *pdev)
struct resource *res;
const char *map_name;
struct meson_ir *ir;
-   int ret;
+   int irq, ret;
 
ir = devm_kzalloc(dev, sizeof(struct meson_ir), GFP_KERNEL);
if (!ir)
@@ -125,10 +124,10 @@ static int meson_ir_probe(struct platform_device *pdev)
return PTR_ERR(ir->reg);
}
 
-   ir->irq = platform_get_irq(pdev, 0);
-   if (ir->irq < 0) {
+   irq = platform_get_irq(pdev, 0);
+   if (irq < 0) {
dev_err(dev, "no irq resource\n");
-   return ir->irq;
+   return irq;
}
 
ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
@@ -158,7 +157,7 @@ static int meson_ir_probe(struct platform_device *pdev)
goto out_free;
}
 
-   ret = devm_request_irq(dev, ir->irq, meson_ir_irq, 0, "ir-meson", ir);
+   ret = devm_request_irq(dev, irq, meson_ir_irq, 0, "ir-meson", ir);
if (ret) {
dev_err(dev, "failed to request irq\n");
goto out_unreg;
-- 
2.12.2




[PATCH v2 5/5] media: rc: meson-ir: change irq name to to of node name

2017-04-12 Thread Heiner Kallweit
Switch the interrupt description to the default which is the of node
name. This is more in line with the interrupt descriptions in
other meson drivers.

Signed-off-by: Heiner Kallweit 
---
v2:
- no changes
---
 drivers/media/rc/meson-ir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 1c72593d..1ece3c04 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -155,7 +155,7 @@ static int meson_ir_probe(struct platform_device *pdev)
return ret;
}
 
-   ret = devm_request_irq(dev, irq, meson_ir_irq, 0, "ir-meson", ir);
+   ret = devm_request_irq(dev, irq, meson_ir_irq, 0, NULL, ir);
if (ret) {
dev_err(dev, "failed to request irq\n");
return ret;
-- 
2.12.2




[PATCH v2 0/5] media: rc: meson-ir: series with smaller improvements

2017-04-12 Thread Heiner Kallweit
This series includes smaller improvements for the meson-ir driver.
Tested on a Odroid C2.

v2:
- minor change to patch 2
- added Reviewed-by to patch 2, 3, 4

Heiner Kallweit (5):
  media: rc: meson-ir: remove irq from struct meson_ir
  media: rc: meson-ir: make use of the bitfield macros
  media: rc: meson-ir: switch to managed rc device allocation / registration
  media: rc: meson-ir: use readl_relaxed in the interrupt handler
  media: rc: meson-ir: change irq name to to of node name

 drivers/media/rc/meson-ir.c | 64 ++---
 1 file changed, 26 insertions(+), 38 deletions(-)

-- 
2.12.2



[PATCH 5/5] media: rc: meson-ir: change irq name to to of node name

2017-04-10 Thread Heiner Kallweit
Switch the interrupt description to the default which is the of node
name. This is more in line with the interrupt descriptions in
other meson drivers.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/meson-ir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 246da2db..471251b3 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -155,7 +155,7 @@ static int meson_ir_probe(struct platform_device *pdev)
return ret;
}
 
-   ret = devm_request_irq(dev, irq, meson_ir_irq, 0, "ir-meson", ir);
+   ret = devm_request_irq(dev, irq, meson_ir_irq, 0, NULL, ir);
if (ret) {
dev_err(dev, "failed to request irq\n");
return ret;
-- 
2.12.2




[PATCH 3/5] media: rc: meson-ir: switch to managed rc device allocation / registration

2017-04-10 Thread Heiner Kallweit
Switch to the managed versions of rc_allocate_device/rc_register_device,
thus simplifying the code.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/meson-ir.c | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index a52036c5..d56ef27e 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -128,7 +128,7 @@ static int meson_ir_probe(struct platform_device *pdev)
return irq;
}
 
-   ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+   ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
if (!ir->rc) {
dev_err(dev, "failed to allocate rc device\n");
return -ENOMEM;
@@ -140,7 +140,6 @@ static int meson_ir_probe(struct platform_device *pdev)
ir->rc->input_id.bustype = BUS_HOST;
map_name = of_get_property(node, "linux,rc-map-name", NULL);
ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY;
-   ir->rc->dev.parent = dev;
ir->rc->allowed_protocols = RC_BIT_ALL_IR_DECODER;
ir->rc->rx_resolution = US_TO_NS(MESON_TRATE);
ir->rc->timeout = MS_TO_NS(200);
@@ -149,16 +148,16 @@ static int meson_ir_probe(struct platform_device *pdev)
spin_lock_init(&ir->lock);
platform_set_drvdata(pdev, ir);
 
-   ret = rc_register_device(ir->rc);
+   ret = devm_rc_register_device(dev, ir->rc);
if (ret) {
dev_err(dev, "failed to register rc device\n");
-   goto out_free;
+   return ret;
}
 
ret = devm_request_irq(dev, irq, meson_ir_irq, 0, "ir-meson", ir);
if (ret) {
dev_err(dev, "failed to request irq\n");
-   goto out_unreg;
+   return ret;
}
 
/* Reset the decoder */
@@ -184,13 +183,6 @@ static int meson_ir_probe(struct platform_device *pdev)
dev_info(dev, "receiver initialized\n");
 
return 0;
-out_unreg:
-   rc_unregister_device(ir->rc);
-   ir->rc = NULL;
-out_free:
-   rc_free_device(ir->rc);
-
-   return ret;
 }
 
 static int meson_ir_remove(struct platform_device *pdev)
@@ -203,8 +195,6 @@ static int meson_ir_remove(struct platform_device *pdev)
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0);
spin_unlock_irqrestore(&ir->lock, flags);
 
-   rc_unregister_device(ir->rc);
-
return 0;
 }
 
-- 
2.12.2




[PATCH 2/5] media: rc: meson-ir: make use of the bitfield macros

2017-04-10 Thread Heiner Kallweit
Make use of the bitfield macros thus partially hiding the complexity
of dealing with bitfields.

The patch also includes a minor fix to REG0_RATE_MASK, so far it was
set to bit 0..10, but according to the spec it's bit 0..11.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/meson-ir.c | 28 +---
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index a4128d7c..a52036c5 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -36,27 +37,24 @@
 /* only available on Meson 8b and newer */
 #define IR_DEC_REG20x20
 
-#define REG0_RATE_MASK (BIT(11) - 1)
+#define REG0_RATE_MASK GENMASK(11, 0)
 
 #define DECODE_MODE_NEC0x0
 #define DECODE_MODE_RAW0x2
 
 /* Meson 6b uses REG1 to configure the mode */
 #define REG1_MODE_MASK GENMASK(8, 7)
-#define REG1_MODE_SHIFT7
 
 /* Meson 8b / GXBB use REG2 to configure the mode */
 #define REG2_MODE_MASK GENMASK(3, 0)
-#define REG2_MODE_SHIFT0
 
-#define REG1_TIME_IV_SHIFT 16
-#define REG1_TIME_IV_MASK  ((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
+#define REG1_TIME_IV_MASK  GENMASK(28, 16)
 
-#define REG1_IRQSEL_MASK   (BIT(2) | BIT(3))
-#define REG1_IRQSEL_NEC_MODE   (0 << 2)
-#define REG1_IRQSEL_RISE_FALL  (1 << 2)
-#define REG1_IRQSEL_FALL   (2 << 2)
-#define REG1_IRQSEL_RISE   (3 << 2)
+#define REG1_IRQSEL_MASK   GENMASK(3, 2)
+#define REG1_IRQSEL_NEC_MODE   0
+#define REG1_IRQSEL_RISE_FALL  1
+#define REG1_IRQSEL_FALL   2
+#define REG1_IRQSEL_RISE   3
 
 #define REG1_RESET BIT(0)
 #define REG1_ENABLEBIT(15)
@@ -78,7 +76,7 @@ static void meson_ir_set_mask(struct meson_ir *ir, unsigned 
int reg,
 
data = readl(ir->reg + reg);
data &= ~mask;
-   data |= (value & mask);
+   data |= value;
writel(data, ir->reg + reg);
 }
 
@@ -91,7 +89,7 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
spin_lock(&ir->lock);
 
duration = readl(ir->reg + IR_DEC_REG1);
-   duration = (duration & REG1_TIME_IV_MASK) >> REG1_TIME_IV_SHIFT;
+   duration = FIELD_GET(REG1_TIME_IV_MASK, duration);
rawir.duration = US_TO_NS(duration * MESON_TRATE);
 
rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN);
@@ -170,16 +168,16 @@ static int meson_ir_probe(struct platform_device *pdev)
/* Set general operation mode (= raw/software decoding) */
if (of_device_is_compatible(node, "amlogic,meson6-ir"))
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK,
- DECODE_MODE_RAW << REG1_MODE_SHIFT);
+ FIELD_PREP(REG1_MODE_MASK, DECODE_MODE_RAW));
else
meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK,
- DECODE_MODE_RAW << REG2_MODE_SHIFT);
+ FIELD_PREP(REG2_MODE_MASK, DECODE_MODE_RAW));
 
/* Set rate */
meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
/* IRQ on rising and falling edges */
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_IRQSEL_MASK,
- REG1_IRQSEL_RISE_FALL);
+ FIELD_PREP(REG1_IRQSEL_MASK, REG1_IRQSEL_RISE_FALL));
/* Enable the decoder */
meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, REG1_ENABLE);
 
-- 
2.12.2




[PATCH 1/5] media: rc: meson-ir: remove irq from struct meson_ir

2017-04-10 Thread Heiner Kallweit
The irq number is used in the probe function only, therefore just use
a local variable.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/meson-ir.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 5576dbd6..a4128d7c 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -68,7 +68,6 @@
 struct meson_ir {
void __iomem*reg;
struct rc_dev   *rc;
-   int irq;
spinlock_t  lock;
 };
 
@@ -112,7 +111,7 @@ static int meson_ir_probe(struct platform_device *pdev)
struct resource *res;
const char *map_name;
struct meson_ir *ir;
-   int ret;
+   int irq, ret;
 
ir = devm_kzalloc(dev, sizeof(struct meson_ir), GFP_KERNEL);
if (!ir)
@@ -125,10 +124,10 @@ static int meson_ir_probe(struct platform_device *pdev)
return PTR_ERR(ir->reg);
}
 
-   ir->irq = platform_get_irq(pdev, 0);
-   if (ir->irq < 0) {
+   irq = platform_get_irq(pdev, 0);
+   if (irq < 0) {
dev_err(dev, "no irq resource\n");
-   return ir->irq;
+   return irq;
}
 
ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
@@ -158,7 +157,7 @@ static int meson_ir_probe(struct platform_device *pdev)
goto out_free;
}
 
-   ret = devm_request_irq(dev, ir->irq, meson_ir_irq, 0, "ir-meson", ir);
+   ret = devm_request_irq(dev, irq, meson_ir_irq, 0, "ir-meson", ir);
if (ret) {
dev_err(dev, "failed to request irq\n");
goto out_unreg;
-- 
2.12.2




[PATCH 4/5] media: rc: meson-ir: use readl_relaxed in the interrupt handler

2017-04-10 Thread Heiner Kallweit
We don't need the memory barriers here and an interrupt handler should
be as fast as possible. Therefore switch to readl_relaxed.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/meson-ir.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index d56ef27e..246da2db 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -83,16 +83,17 @@ static void meson_ir_set_mask(struct meson_ir *ir, unsigned 
int reg,
 static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
 {
struct meson_ir *ir = dev_id;
-   u32 duration;
+   u32 duration, status;
DEFINE_IR_RAW_EVENT(rawir);
 
spin_lock(&ir->lock);
 
-   duration = readl(ir->reg + IR_DEC_REG1);
+   duration = readl_relaxed(ir->reg + IR_DEC_REG1);
duration = FIELD_GET(REG1_TIME_IV_MASK, duration);
rawir.duration = US_TO_NS(duration * MESON_TRATE);
 
-   rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN);
+   status = readl_relaxed(ir->reg + IR_DEC_STATUS);
+   rawir.pulse = !!(status & STATUS_IR_DEC_IN);
 
ir_raw_event_store_with_filter(ir->rc, &rawir);
ir_raw_event_handle(ir->rc);
-- 
2.12.2




[PATCH 0/5] media: rc: meson-ir: series with smaller improvements

2017-04-10 Thread Heiner Kallweit
This series includes smaller improvements for the meson-ir driver.
Tested on a Odroid C2.

Heiner Kallweit (5):
  media: rc: meson-ir: remove irq from struct meson_ir
  media: rc: meson-ir: make use of the bitfield macros
  media: rc: meson-ir: switch to managed rc device allocation / registration
  media: rc: meson-ir: use readl_relaxed in the interrupt handler
  media: rc: meson-ir: change irq name to to of node name

 drivers/media/rc/meson-ir.c | 64 ++---
 1 file changed, 26 insertions(+), 38 deletions(-)

-- 
2.12.2



[PATCH] media: rc: nuvoton: fix deadlock in nvt_write_wakeup_codes

2017-02-12 Thread Heiner Kallweit
nvt_write_wakeup_codes acquires the same lock as the ISR but doesn't
disable interrupts on the local CPU. This caused the following
deadlock. Fix this by using spin_lock_irqsave.

[  432.362008] 
[  432.362074] WARNING: inconsistent lock state
[  432.362144] 4.10.0-rc7-next-20170210 #1 Not tainted
[  432.362219] 
[  432.362286] inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage.
[  432.362379] swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes:
[  432.362457]  (&(&nvt->lock)->rlock){?.+...}, at: [] 
nvt_cir_isr+0x2d/0x520 [nuvoton_cir]
[  432.362611] {HARDIRQ-ON-W} state was registered at:
[  432.362686]
[  432.362698] [] __lock_acquire+0x5dc/0x1260
[  432.362812]
[  432.362817] [] lock_acquire+0xe9/0x1d0
[  432.362927]
[  432.362934] [] _raw_spin_lock+0x33/0x50
[  432.363045]
[  432.363051] [] nvt_write_wakeup_codes.isra.12+0x22/0xe0 
[nuvoton_cir]
[  432.363193]
[  432.363199] [] wakeup_data_store+0xdf/0xf0 [nuvoton_cir]
[  432.363327]
[  432.36] [] dev_attr_store+0x13/0x20
[  432.363441]
[  432.363449] [] sysfs_kf_write+0x40/0x50
[  432.363558]
[  432.363564] [] kernfs_fop_write+0x150/0x1e0
[  432.363676]
[  432.363685] [] __vfs_write+0x23/0x120
[  432.363791]
[  432.363798] [] vfs_write+0xc3/0x1e0
[  432.363902]
[  432.363909] [] SyS_write+0x44/0xa0
[  432.364012]
[  432.364021] [] do_syscall_64+0x57/0x140
[  432.364129]
[  432.364135] [] return_from_SYSCALL_64+0x0/0x7a
[  432.364252] irq event stamp: 415118
[  432.364313] hardirqs last  enabled at (415115): [] 
cpuidle_enter_state+0x11b/0x370
[  432.364445] hardirqs last disabled at (415116): [] 
common_interrupt+0x8b/0x90
[  432.364573] softirqs last  enabled at (415118): [] 
_local_bh_enable+0x1c/0x50
[  432.364699] softirqs last disabled at (415117): [] 
irq_enter+0x43/0x60
[  432.364814]
   other info that might help us debug this:
[  432.364909]  Possible unsafe locking scenario:

[  432.367821]CPU0
[  432.370645]
[  432.373432]   lock(&(&nvt->lock)->rlock);
[  432.376228]   
[  432.378982] lock(&(&nvt->lock)->rlock);
[  432.381757]
*** DEADLOCK ***

[  432.389888] no locks held by swapper/0/0.
[  432.392574]
   stack backtrace:
[  432.397774] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 
4.10.0-rc7-next-20170210 #1
[  432.400375] Hardware name: ZOTAC ZBOX-CI321NANO/ZBOX-CI321NANO, BIOS 
B246P105 06/01/2015
[  432.403023] Call Trace:
[  432.405636]  
[  432.408208]  dump_stack+0x68/0x93
[  432.410775]  print_usage_bug+0x1dd/0x1f0
[  432.413334]  mark_lock+0x559/0x5c0
[  432.415871]  ? print_shortest_lock_dependencies+0x1a0/0x1a0
[  432.418431]  __lock_acquire+0x6b1/0x1260
[  432.420941]  lock_acquire+0xe9/0x1d0
[  432.423396]  ? nvt_cir_isr+0x2d/0x520 [nuvoton_cir]
[  432.425844]  _raw_spin_lock+0x33/0x50
[  432.428252]  ? nvt_cir_isr+0x2d/0x520 [nuvoton_cir]
[  432.430670]  nvt_cir_isr+0x2d/0x520 [nuvoton_cir]
[  432.433085]  __handle_irq_event_percpu+0x43/0x330
[  432.435493]  handle_irq_event_percpu+0x1e/0x50
[  432.437884]  handle_irq_event+0x34/0x60
[  432.440236]  handle_edge_irq+0x6a/0x150
[  432.442561]  handle_irq+0x15/0x20
[  432.444854]  do_IRQ+0x57/0x110
[  432.447115]  common_interrupt+0x90/0x90
[  432.449380] RIP: 0010:cpuidle_enter_state+0x120/0x370
[  432.451653] RSP: 0018:81c03dd8 EFLAGS: 0206 ORIG_RAX: 
ffcc
[  432.453994] RAX: 81c14500 RBX: 0008 RCX: 0064aac6f2d2
[  432.456349] RDX:  RSI: 0001 RDI: 81c14500
[  432.458704] RBP: 81c03e18 R08: cccd R09: 0018
[  432.461072] R10:  R11:  R12: 880100a21260
[  432.463450] R13: 81c7e6f8 R14: 0008 R15: 81c7e6e0
[  432.465819]  
[  432.468104]  ? cpuidle_enter_state+0x11b/0x370
[  432.470413]  cpuidle_enter+0x12/0x20
[  432.472698]  call_cpuidle+0x1e/0x40
[  432.474967]  do_idle+0xe3/0x1c0
[  432.477172]  cpu_startup_entry+0x18/0x20
[  432.479376]  rest_init+0x130/0x140
[  432.481565]  start_kernel+0x3cc/0x3d9
[  432.483750]  x86_64_start_reservations+0x2a/0x2c
[  432.485980]  x86_64_start_kernel+0x178/0x18b
[  432.488222]  start_cpu+0x14/0x14
[  432.490453]  ? start_cpu+0x14/0x14

Fixes: 97c129747af5 "[media] rc: nuvoton-cir: Add support wakeup via sysfs 
filter callback"
Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index b109f824..ec4b25bd 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -176,12 +176,13 @@ static void nvt_write_wakeup_codes(struct rc_dev *dev,
 {
u8 tolerance, config;
struct nvt_dev *nvt = dev->priv;
+   unsigned long flags;
int i;
 
/* hardcode the tolerance to 10% */
tole

Re: [PATCH] media: rc: refactor raw handler kthread

2016-12-26 Thread Heiner Kallweit
Am 02.08.2016 um 07:44 schrieb Heiner Kallweit:
> I think we can get rid of the spinlock protecting the kthread from being
> interrupted by a wakeup in certain parts.
> Even with the current implementation of the kthread the only lost wakeup
> scenario could happen if the wakeup occurs between the kfifo_len check
> and setting the state to TASK_INTERRUPTIBLE.
> 
> In the changed version we could lose a wakeup if it occurs between
> processing the fifo content and setting the state to TASK_INTERRUPTIBLE.
> This scenario is covered by an additional check for available events in
> the fifo and setting the state to TASK_RUNNING in this case.
> 
> In addition the changed version flushes the kfifo before ending
> when the kthread is stopped.
> 
> With this patch we gain:
> - Get rid of the spinlock
> - Simplify code
> - Don't grep / release the mutex for each individual event but just once
>   for the complete fifo content. This reduces overhead if a driver e.g.
>   triggers processing after writing the content of a hw fifo to the kfifo.
> 
> Signed-off-by: Heiner Kallweit 

Sean added a review comment and his "Tested-by" a month ago.
Anything else missing before it can be applied?

> ---
>  drivers/media/rc/rc-core-priv.h |  2 --
>  drivers/media/rc/rc-ir-raw.c| 46 
> +++--
>  2 files changed, 17 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
> index 585d5e5..577128a 100644
> --- a/drivers/media/rc/rc-core-priv.h
> +++ b/drivers/media/rc/rc-core-priv.h
> @@ -20,7 +20,6 @@
>  #define  MAX_IR_EVENT_SIZE   512
>  
>  #include 
> -#include 
>  #include 
>  
>  struct ir_raw_handler {
> @@ -37,7 +36,6 @@ struct ir_raw_handler {
>  struct ir_raw_event_ctrl {
>   struct list_headlist;   /* to keep track of raw 
> clients */
>   struct task_struct  *thread;
> - spinlock_t  lock;
>   /* fifo for the pulse/space durations */
>   DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE);
>   ktime_t last_event; /* when last event 
> occurred */
> diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
> index 205ecc6..71a3e17 100644
> --- a/drivers/media/rc/rc-ir-raw.c
> +++ b/drivers/media/rc/rc-ir-raw.c
> @@ -17,7 +17,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include "rc-core-priv.h"
>  
>  /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
> @@ -35,32 +34,26 @@ static int ir_raw_event_thread(void *data)
>   struct ir_raw_handler *handler;
>   struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
>  
> - while (!kthread_should_stop()) {
> -
> - spin_lock_irq(&raw->lock);
> -
> - if (!kfifo_len(&raw->kfifo)) {
> - set_current_state(TASK_INTERRUPTIBLE);
> -
> - if (kthread_should_stop())
> - set_current_state(TASK_RUNNING);
> -
> - spin_unlock_irq(&raw->lock);
> - schedule();
> - continue;
> + while (1) {
> + mutex_lock(&ir_raw_handler_lock);
> + while (kfifo_out(&raw->kfifo, &ev, 1)) {
> + list_for_each_entry(handler, &ir_raw_handler_list, list)
> + if (raw->dev->enabled_protocols &
> + handler->protocols || !handler->protocols)
> + handler->decode(raw->dev, ev);
> + raw->prev_ev = ev;
>   }
> + mutex_unlock(&ir_raw_handler_lock);
>  
> - if(!kfifo_out(&raw->kfifo, &ev, 1))
> - dev_err(&raw->dev->dev, "IR event FIFO is empty!\n");
> - spin_unlock_irq(&raw->lock);
> + set_current_state(TASK_INTERRUPTIBLE);
>  
> - mutex_lock(&ir_raw_handler_lock);
> - list_for_each_entry(handler, &ir_raw_handler_list, list)
> - if (raw->dev->enabled_protocols & handler->protocols ||
> - !handler->protocols)
> - handler->decode(raw->dev, ev);
> - raw->prev_ev = ev;
> - mutex_unlock(&ir_raw_handler_lock);
> + if (kthread_should_stop()) {
> + __set_current_state(TASK_RUNNING);
> + br

Re: [PATCH v3 0/6] Add support for IR transmitters

2016-11-02 Thread Heiner Kallweit
Am 02.11.2016 um 11:40 schrieb Andi Shyti:
> Hi,
> 
> The main goal is to add support in the rc framework for IR
> transmitters, which currently is only supported by lirc but that
> is not the preferred way.
> 
> The last patch adds support for an IR transmitter driven by
> the MOSI line of an SPI controller, it's the case of the Samsung
> TM2(e) board which support is currently ongoing.
> 
> The last patch adds support for an IR transmitter driven by
> the MOSI line of an SPI controller, it's the case of the Samsung
> TM2(e) board which support is currently ongoing.
> 
> Thanks Sean for your prompt reviews.
> 
> Andi
> 
> Changelog from version 1:
> 
> The RFC is now PATCH. The main difference is that this version
> doesn't try to add the any bit streaming protocol and doesn't
> modify any LIRC interface specification.
> 
> patch 1: updates all the drivers using rc_allocate_device
> patch 2: fixed errors and warning reported from the kbuild test
>  robot
> patch 5: this patch has been dropped and replaced with a new one
>  which avoids waiting for transmitters.
> patch 6: added new properties to the dts specification
> patch 7: the driver uses the pulse/space input and converts it to
>  a bit stream.
> 
> 
> Changelog from version 2:
> 
> The original patch number 5 has been abandoned because it was not
> bringing much benenfit.
> 
> patch 1: rebased on the new kernel.
> patch 3: removed the sysfs attribute protocol for transmitters
> patch 5: the binding has been moved to the leds section instead
>  of the media. Fixed all the comments from Rob
> patch 6: fixed all the comments from Sean added also Sean's
>  review.
> 
> Andi Shyti (6):
>   [media] rc-main: assign driver type during allocation
>   [media] rc-main: split setup and unregister functions
>   [media] rc-core: add support for IR raw transmitters
>   [media] rc-ir-raw: do not generate any receiving thread for raw
> transmitters
>   Documentation: bindings: add documentation for ir-spi device driver
>   [media] rc: add support for IR LEDs driven through SPI
> 
Hi Andi,

at least patches 1 and 2 conflict with recent extensions. See commits
ddbf7d5a698c "rc: core: add managed versions of rc_allocate_device and
rc_register_device" and b6f3ece38733 "[media] rc: nuvoton: use managed
versions of rc_allocate_device and rc_register_device".

It would be good if you could rebase your patch set on top of the
latest master branch of media tree. Most likely you will have to make
changes to the recently introduced managed versions of
rc_allocate_device and rc_register_device.

Rgds, Heiner

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] media: rc: nuvoton: replace usage of spin_lock_irqsave in ISR

2016-10-25 Thread Heiner Kallweit
Kernel takes care that interrupts from one source are serialized.
So there's no need to use spinlock_irq_save.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 6332cf3..f21a2bc 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -840,11 +840,10 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 {
struct nvt_dev *nvt = data;
u8 status, iren;
-   unsigned long flags;
 
nvt_dbg_verbose("%s firing", __func__);
 
-   spin_lock_irqsave(&nvt->lock, flags);
+   spin_lock(&nvt->lock);
 
/*
 * Get IR Status register contents. Write 1 to ack/clear
@@ -866,7 +865,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 * logical device is being disabled.
 */
if (status == 0xff && iren == 0xff) {
-   spin_unlock_irqrestore(&nvt->lock, flags);
+   spin_unlock(&nvt->lock);
nvt_dbg_verbose("Spurious interrupt detected");
return IRQ_HANDLED;
}
@@ -875,7 +874,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 * status bit whether the related interrupt source is enabled
 */
if (!(status & iren)) {
-   spin_unlock_irqrestore(&nvt->lock, flags);
+   spin_unlock(&nvt->lock);
nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
return IRQ_NONE;
}
@@ -923,7 +922,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
}
}
 
-   spin_unlock_irqrestore(&nvt->lock, flags);
+   spin_unlock(&nvt->lock);
 
nvt_dbg_verbose("%s done", __func__);
return IRQ_HANDLED;
-- 
2.10.1


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] media: rc: nuvoton: eliminate member pdev from struct nvt_dev

2016-10-25 Thread Heiner Kallweit
Member pdev of struct nvt_dev is needed only to access &pdev->dev.
We can get rid of this it by using rdev->dev.parent instead
(both point to the same struct device).

Setting rdev->dev.parent can be removed from the probe function
as this is done by devm_rc_allocate_device now.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 27 ++-
 drivers/media/rc/nuvoton-cir.h |  1 -
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 37fce7b..a583066 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -48,6 +48,11 @@ static const struct nvt_chip nvt_chips[] = {
{ "NCT6779D", NVT_6779D },
 };
 
+static inline struct device *nvt_get_dev(const struct nvt_dev *nvt)
+{
+   return nvt->rdev->dev.parent;
+}
+
 static inline bool is_w83667hg(struct nvt_dev *nvt)
 {
return nvt->chip_ver == NVT_W83667HG;
@@ -385,6 +390,7 @@ static inline const char *nvt_find_chip(struct nvt_dev 
*nvt, int id)
 /* detect hardware features */
 static int nvt_hw_detect(struct nvt_dev *nvt)
 {
+   struct device *dev = nvt_get_dev(nvt);
const char *chip_name;
int chip_id;
 
@@ -405,8 +411,7 @@ static int nvt_hw_detect(struct nvt_dev *nvt)
 
chip_id = nvt->chip_major << 8 | nvt->chip_minor;
if (chip_id == NVT_INVALID) {
-   dev_err(&nvt->pdev->dev,
-   "No device found on either EFM port\n");
+   dev_err(dev, "No device found on either EFM port\n");
return -ENODEV;
}
 
@@ -414,12 +419,11 @@ static int nvt_hw_detect(struct nvt_dev *nvt)
 
/* warn, but still let the driver load, if we don't know this chip */
if (!chip_name)
-   dev_warn(&nvt->pdev->dev,
+   dev_warn(dev,
 "unknown chip, id: 0x%02x 0x%02x, it may not work...",
 nvt->chip_major, nvt->chip_minor);
else
-   dev_info(&nvt->pdev->dev,
-"found %s or compatible: chip id: 0x%02x 0x%02x",
+   dev_info(dev, "found %s or compatible: chip id: 0x%02x 0x%02x",
 chip_name, nvt->chip_major, nvt->chip_minor);
 
return 0;
@@ -616,7 +620,7 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
duration *= SAMPLE_PERIOD;
 
if (!count || !duration) {
-   dev_notice(&nvt->pdev->dev,
+   dev_notice(nvt_get_dev(nvt),
   "Unable to determine carrier! (c:%u, d:%u)",
   count, duration);
return 0;
@@ -781,7 +785,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 
 static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
 {
-   dev_warn(&nvt->pdev->dev, "RX FIFO overrun detected, flushing data!");
+   dev_warn(nvt_get_dev(nvt), "RX FIFO overrun detected, flushing data!");
 
nvt->pkts = 0;
nvt_clear_cir_fifo(nvt);
@@ -976,9 +980,10 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
return -ENOMEM;
 
/* input device for IR remote (and tx) */
-   rdev = devm_rc_allocate_device(&pdev->dev);
-   if (!rdev)
+   nvt->rdev = devm_rc_allocate_device(&pdev->dev);
+   if (!nvt->rdev)
return -ENOMEM;
+   rdev = nvt->rdev;
 
/* activate pnp device */
ret = pnp_activate_dev(pdev);
@@ -1017,7 +1022,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
spin_lock_init(&nvt->tx.lock);
 
pnp_set_drvdata(pdev, nvt);
-   nvt->pdev = pdev;
 
init_waitqueue_head(&nvt->tx.queue);
 
@@ -1050,7 +1054,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2;
rdev->input_id.product = nvt->chip_major;
rdev->input_id.version = nvt->chip_minor;
-   rdev->dev.parent = &pdev->dev;
rdev->driver_name = NVT_DRIVER_NAME;
rdev->map_name = RC_MAP_RC6_MCE;
rdev->timeout = MS_TO_NS(100);
@@ -1062,8 +1065,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
/* tx bits */
rdev->tx_resolution = XYZ;
 #endif
-   nvt->rdev = rdev;
-
ret = devm_rc_register_device(&pdev->dev, rdev);
if (ret)
return ret;
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index acf735f..77102a9 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -78,7 +78,6 @@ struct nvt_chip {
 }

[PATCH 4/5] media: rc: nuvoton: rename spinlock nvt_lock

2016-10-25 Thread Heiner Kallweit
Spinlock nvt_lock is a member of struct nvt_dev and there's no need
to prefix it with nvt_. So remove this prefix.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 40 
 drivers/media/rc/nuvoton-cir.h |  2 +-
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c677628..6332cf3 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -187,7 +187,7 @@ static ssize_t wakeup_data_show(struct device *dev,
ssize_t buf_len = 0;
int i;
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
+   spin_lock_irqsave(&nvt->lock, flags);
 
fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
fifo_len = min(fifo_len, WAKEUP_MAX_SIZE);
@@ -204,7 +204,7 @@ static ssize_t wakeup_data_show(struct device *dev,
}
buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, "\n");
 
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   spin_unlock_irqrestore(&nvt->lock, flags);
 
return buf_len;
 }
@@ -248,7 +248,7 @@ static ssize_t wakeup_data_store(struct device *dev,
/* hardcode the tolerance to 10% */
tolerance = DIV_ROUND_UP(count, 10);
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
+   spin_lock_irqsave(&nvt->lock, flags);
 
nvt_clear_cir_wake_fifo(nvt);
nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP);
@@ -265,7 +265,7 @@ static ssize_t wakeup_data_store(struct device *dev,
 
nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON);
 
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   spin_unlock_irqrestore(&nvt->lock, flags);
 
ret = len;
 out:
@@ -590,7 +590,7 @@ static void nvt_enable_wake(struct nvt_dev *nvt)
 
nvt_efm_disable(nvt);
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
+   spin_lock_irqsave(&nvt->lock, flags);
 
nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
   CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
@@ -599,11 +599,11 @@ static void nvt_enable_wake(struct nvt_dev *nvt)
nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
 
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   spin_unlock_irqrestore(&nvt->lock, flags);
 }
 
 #if 0 /* Currently unused */
-/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
+/* rx carrier detect only works in learning mode, must be called w/lock */
 static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
 {
u32 count, carrier, duration = 0;
@@ -688,7 +688,7 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, 
unsigned n)
u8 iren;
int ret;
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
+   spin_lock_irqsave(&nvt->lock, flags);
 
ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n);
nvt->tx.buf_count = (ret * sizeof(unsigned));
@@ -712,13 +712,13 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, 
unsigned n)
for (i = 0; i < 9; i++)
nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
 
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   spin_unlock_irqrestore(&nvt->lock, flags);
 
wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
+   spin_lock_irqsave(&nvt->lock, flags);
nvt->tx.tx_state = ST_TX_NONE;
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   spin_unlock_irqrestore(&nvt->lock, flags);
 
/* restore enabled interrupts to prior state */
nvt_cir_reg_write(nvt, iren, CIR_IREN);
@@ -844,7 +844,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 
nvt_dbg_verbose("%s firing", __func__);
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
+   spin_lock_irqsave(&nvt->lock, flags);
 
/*
 * Get IR Status register contents. Write 1 to ack/clear
@@ -866,7 +866,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 * logical device is being disabled.
 */
if (status == 0xff && iren == 0xff) {
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   spin_unlock_irqrestore(&nvt->lock, flags);
nvt_dbg_verbose("Spurious interrupt detected");
return IRQ_HANDLED;
}
@@ -875,7 +875,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 * status bit whether the related interrupt source is enabled
 */
if (!(status & iren)) {
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+  

[PATCH 3/5] media: rc: nuvoton: eliminate nvt->tx.lock

2016-10-25 Thread Heiner Kallweit
Using a separate spinlock to protect access to substruct tx of struct
nvt_dev doesn't provide any actual benefit. We can use spinlock
nvt_lock to protect all access to struct nvt_dev and get rid of
nvt->tx.lock.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 35 +--
 drivers/media/rc/nuvoton-cir.h |  1 -
 2 files changed, 9 insertions(+), 27 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index a583066..c677628 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -688,7 +688,7 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, 
unsigned n)
u8 iren;
int ret;
 
-   spin_lock_irqsave(&nvt->tx.lock, flags);
+   spin_lock_irqsave(&nvt->nvt_lock, flags);
 
ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n);
nvt->tx.buf_count = (ret * sizeof(unsigned));
@@ -712,13 +712,13 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, 
unsigned n)
for (i = 0; i < 9; i++)
nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
 
-   spin_unlock_irqrestore(&nvt->tx.lock, flags);
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 
wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
 
-   spin_lock_irqsave(&nvt->tx.lock, flags);
+   spin_lock_irqsave(&nvt->nvt_lock, flags);
nvt->tx.tx_state = ST_TX_NONE;
-   spin_unlock_irqrestore(&nvt->tx.lock, flags);
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 
/* restore enabled interrupts to prior state */
nvt_cir_reg_write(nvt, iren, CIR_IREN);
@@ -832,14 +832,7 @@ static void nvt_cir_log_irqs(u8 status, u8 iren)
 
 static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
 {
-   unsigned long flags;
-   u8 tx_state;
-
-   spin_lock_irqsave(&nvt->tx.lock, flags);
-   tx_state = nvt->tx.tx_state;
-   spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-   return tx_state == ST_TX_NONE;
+   return nvt->tx.tx_state == ST_TX_NONE;
 }
 
 /* interrupt service routine for incoming and outgoing CIR data */
@@ -902,8 +895,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
nvt_get_rx_ir_data(nvt);
}
 
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
if (status & CIR_IRSTS_TE)
nvt_clear_tx_fifo(nvt);
 
@@ -911,8 +902,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
unsigned int pos, count;
u8 tmp;
 
-   spin_lock_irqsave(&nvt->tx.lock, flags);
-
pos = nvt->tx.cur_buf_num;
count = nvt->tx.buf_count;
 
@@ -925,20 +914,17 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
tmp = nvt_cir_reg_read(nvt, CIR_IREN);
nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
}
-
-   spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
}
 
if (status & CIR_IRSTS_TFU) {
-   spin_lock_irqsave(&nvt->tx.lock, flags);
if (nvt->tx.tx_state == ST_TX_REPLY) {
nvt->tx.tx_state = ST_TX_REQUEST;
wake_up(&nvt->tx.queue);
}
-   spin_unlock_irqrestore(&nvt->tx.lock, flags);
}
 
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
nvt_dbg_verbose("%s done", __func__);
return IRQ_HANDLED;
 }
@@ -1019,7 +1005,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
nvt->cr_efdr = CR_EFDR;
 
spin_lock_init(&nvt->nvt_lock);
-   spin_lock_init(&nvt->tx.lock);
 
pnp_set_drvdata(pdev, nvt);
 
@@ -1117,12 +1102,10 @@ static int nvt_suspend(struct pnp_dev *pdev, 
pm_message_t state)
 
nvt_dbg("%s called", __func__);
 
-   spin_lock_irqsave(&nvt->tx.lock, flags);
-   nvt->tx.tx_state = ST_TX_NONE;
-   spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
spin_lock_irqsave(&nvt->nvt_lock, flags);
 
+   nvt->tx.tx_state = ST_TX_NONE;
+
/* disable all CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
 
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 77102a9..a8569b6 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -87,7 +87,6 @@ struct nvt_dev {
unsigned int pkts;
 
struct {
-   spinlock_t lock;
u8 buf[TX_BUF_LEN];
unsigned int buf_count;
unsigned int cur_buf_num;
-- 
2.10.1


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] media: rc: nuvoton: remove nvt_open and nvt_close

2016-10-25 Thread Heiner Kallweit
What is done in nvt_probe was done in nvt_probe already
(in nvt_cir_ldev_init and nvt_cir_regs_init, both called from
nvt_probe). It's the same with nvt_close, it's covered by nvt_remove.
Therefore I don't see any benefit in implementing the open and close
hooks at all and both functions can be removed.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 35 ---
 1 file changed, 35 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 3df3bd9..37fce7b 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -964,39 +964,6 @@ static void nvt_disable_cir(struct nvt_dev *nvt)
nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
 }
 
-static int nvt_open(struct rc_dev *dev)
-{
-   struct nvt_dev *nvt = dev->priv;
-   unsigned long flags;
-
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
-
-   /* set function enable flags */
-   nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
- CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
- CIR_IRCON);
-
-   /* clear all pending interrupts */
-   nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
-   /* enable interrupts */
-   nvt_set_cir_iren(nvt);
-
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-   /* enable the CIR logical device */
-   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
-
-   return 0;
-}
-
-static void nvt_close(struct rc_dev *dev)
-{
-   struct nvt_dev *nvt = dev->priv;
-
-   nvt_disable_cir(nvt);
-}
-
 /* Allocate memory, probe hardware, and initialize everything */
 static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 {
@@ -1075,8 +1042,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
rdev->priv = nvt;
rdev->driver_type = RC_DRIVER_IR_RAW;
rdev->allowed_protocols = RC_BIT_ALL;
-   rdev->open = nvt_open;
-   rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
rdev->s_tx_carrier = nvt_set_tx_carrier;
rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver";
-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] rc: core: add managed versions of rc_allocate_device and rc_register_device

2016-09-30 Thread Heiner Kallweit
Introduce managed versions of both functions.
They allows to simplify the error path in the probe function of
rc drivers, and usually also to simplify the remove function.

New element managed_alloc in struct rc_dev is needed to correctly
handle mixed use, e.g. managed version of rc_register_device and
normal version of rc_allocate_device.

In addition devm_rc_allocate_device sets rc->dev.parent as having a
reference to the parent device might be useful for future extensions.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-main.c | 58 +-
 include/media/rc-core.h| 18 ++
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index d9c1f2f..c8c6aa5 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1403,6 +1403,34 @@ void rc_free_device(struct rc_dev *dev)
 }
 EXPORT_SYMBOL_GPL(rc_free_device);
 
+static void devm_rc_alloc_release(struct device *dev, void *res)
+{
+   rc_free_device(*(struct rc_dev **)res);
+}
+
+struct rc_dev *devm_rc_allocate_device(struct device *dev)
+{
+   struct rc_dev **dr, *rc;
+
+   dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL);
+   if (!dr)
+   return NULL;
+
+   rc = rc_allocate_device();
+   if (!rc) {
+   devres_free(dr);
+   return NULL;
+   }
+
+   rc->dev.parent = dev;
+   rc->managed_alloc = true;
+   *dr = rc;
+   devres_add(dev, dr);
+
+   return rc;
+}
+EXPORT_SYMBOL_GPL(devm_rc_allocate_device);
+
 int rc_register_device(struct rc_dev *dev)
 {
static bool raw_init = false; /* raw decoders loaded? */
@@ -1531,6 +1559,33 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(rc_register_device);
 
+static void devm_rc_release(struct device *dev, void *res)
+{
+   rc_unregister_device(*(struct rc_dev **)res);
+}
+
+int devm_rc_register_device(struct device *parent, struct rc_dev *dev)
+{
+   struct rc_dev **dr;
+   int ret;
+
+   dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL);
+   if (!dr)
+   return -ENOMEM;
+
+   ret = rc_register_device(dev);
+   if (ret) {
+   devres_free(dr);
+   return ret;
+   }
+
+   *dr = dev;
+   devres_add(parent, dr);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(devm_rc_register_device);
+
 void rc_unregister_device(struct rc_dev *dev)
 {
if (!dev)
@@ -1552,7 +1607,8 @@ void rc_unregister_device(struct rc_dev *dev)
 
ida_simple_remove(&rc_ida, dev->minor);
 
-   rc_free_device(dev);
+   if (!dev->managed_alloc)
+   rc_free_device(dev);
 }
 
 EXPORT_SYMBOL_GPL(rc_unregister_device);
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 40188d3..55281b9 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -68,6 +68,7 @@ enum rc_filter_type {
  * struct rc_dev - represents a remote control device
  * @dev: driver model's view of this device
  * @initialized: 1 if the device init has completed, 0 otherwise
+ * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
  * @sysfs_groups: sysfs attribute groups
  * @input_name: name of the input child device
  * @input_phys: physical path to the input child device
@@ -131,6 +132,7 @@ enum rc_filter_type {
 struct rc_dev {
struct device   dev;
atomic_tinitialized;
+   boolmanaged_alloc;
const struct attribute_group*sysfs_groups[5];
const char  *input_name;
const char  *input_phys;
@@ -203,6 +205,14 @@ struct rc_dev {
 struct rc_dev *rc_allocate_device(void);
 
 /**
+ * devm_rc_allocate_device - Managed RC device allocation
+ *
+ * @dev: pointer to struct device
+ * returns a pointer to struct rc_dev.
+ */
+struct rc_dev *devm_rc_allocate_device(struct device *dev);
+
+/**
  * rc_free_device - Frees a RC device
  *
  * @dev: pointer to struct rc_dev.
@@ -217,6 +227,14 @@ void rc_free_device(struct rc_dev *dev);
 int rc_register_device(struct rc_dev *dev);
 
 /**
+ * devm_rc_register_device - Manageded registering of a RC device
+ *
+ * @parent: pointer to struct device.
+ * @dev: pointer to struct rc_dev.
+ */
+int devm_rc_register_device(struct device *parent, struct rc_dev *dev);
+
+/**
  * rc_unregister_device - Unregisters a RC device
  *
  * @dev: pointer to struct rc_dev.
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] rc: nuvoton: use managed versions of rc_allocate_device and rc_register_device

2016-09-30 Thread Heiner Kallweit
Simplify the remove function and the error path in the probe function by
using the managed versions of rc_allocate_device and rc_register_device.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 50 +-
 1 file changed, 20 insertions(+), 30 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 04fedaa..3df3bd9 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1002,40 +1002,40 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
 {
struct nvt_dev *nvt;
struct rc_dev *rdev;
-   int ret = -ENOMEM;
+   int ret;
 
nvt = devm_kzalloc(&pdev->dev, sizeof(struct nvt_dev), GFP_KERNEL);
if (!nvt)
-   return ret;
+   return -ENOMEM;
 
/* input device for IR remote (and tx) */
-   rdev = rc_allocate_device();
+   rdev = devm_rc_allocate_device(&pdev->dev);
if (!rdev)
-   goto exit_free_dev_rdev;
+   return -ENOMEM;
 
-   ret = -ENODEV;
/* activate pnp device */
-   if (pnp_activate_dev(pdev) < 0) {
+   ret = pnp_activate_dev(pdev);
+   if (ret) {
dev_err(&pdev->dev, "Could not activate PNP device!\n");
-   goto exit_free_dev_rdev;
+   return ret;
}
 
/* validate pnp resources */
if (!pnp_port_valid(pdev, 0) ||
pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
dev_err(&pdev->dev, "IR PNP Port not valid!\n");
-   goto exit_free_dev_rdev;
+   return -EINVAL;
}
 
if (!pnp_irq_valid(pdev, 0)) {
dev_err(&pdev->dev, "PNP IRQ not valid!\n");
-   goto exit_free_dev_rdev;
+   return -EINVAL;
}
 
if (!pnp_port_valid(pdev, 1) ||
pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
-   goto exit_free_dev_rdev;
+   return -EINVAL;
}
 
nvt->cir_addr = pnp_port_start(pdev, 0);
@@ -1056,7 +1056,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
 
ret = nvt_hw_detect(nvt);
if (ret)
-   goto exit_free_dev_rdev;
+   return ret;
 
/* Initialize CIR & CIR Wake Logical Devices */
nvt_efm_enable(nvt);
@@ -1099,27 +1099,27 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
 #endif
nvt->rdev = rdev;
 
-   ret = rc_register_device(rdev);
+   ret = devm_rc_register_device(&pdev->dev, rdev);
if (ret)
-   goto exit_free_dev_rdev;
+   return ret;
 
-   ret = -EBUSY;
/* now claim resources */
if (!devm_request_region(&pdev->dev, nvt->cir_addr,
CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
-   goto exit_unregister_device;
+   return -EBUSY;
 
-   if (devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr,
-IRQF_SHARED, NVT_DRIVER_NAME, (void *)nvt))
-   goto exit_unregister_device;
+   ret = devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr,
+  IRQF_SHARED, NVT_DRIVER_NAME, nvt);
+   if (ret)
+   return ret;
 
if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr,
CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake"))
-   goto exit_unregister_device;
+   return -EBUSY;
 
ret = device_create_file(&rdev->dev, &dev_attr_wakeup_data);
if (ret)
-   goto exit_unregister_device;
+   return ret;
 
device_init_wakeup(&pdev->dev, true);
 
@@ -1130,14 +1130,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
}
 
return 0;
-
-exit_unregister_device:
-   rc_unregister_device(rdev);
-   rdev = NULL;
-exit_free_dev_rdev:
-   rc_free_device(rdev);
-
-   return ret;
 }
 
 static void nvt_remove(struct pnp_dev *pdev)
@@ -1150,8 +1142,6 @@ static void nvt_remove(struct pnp_dev *pdev)
 
/* enable CIR Wake (for IR power-on) */
nvt_enable_wake(nvt);
-
-   rc_unregister_device(nvt->rdev);
 }
 
 static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
-- 
2.10.0


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] rc: ir-raw: change type of available_protocols to atomic64_t

2016-09-27 Thread Heiner Kallweit
Changing available_protocols to atomic64_t allows to get rid of the
mutex protecting access to the variable. This helps to simplify
the code.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-ir-raw.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 205ecc6..1c42a9f 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -26,8 +26,7 @@ static LIST_HEAD(ir_raw_client_list);
 /* Used to handle IR raw handler extensions */
 static DEFINE_MUTEX(ir_raw_handler_lock);
 static LIST_HEAD(ir_raw_handler_list);
-static DEFINE_MUTEX(available_protocols_lock);
-static u64 available_protocols;
+static atomic64_t available_protocols = ATOMIC64_INIT(0);
 
 static int ir_raw_event_thread(void *data)
 {
@@ -234,11 +233,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 u64
 ir_raw_get_allowed_protocols(void)
 {
-   u64 protocols;
-   mutex_lock(&available_protocols_lock);
-   protocols = available_protocols;
-   mutex_unlock(&available_protocols_lock);
-   return protocols;
+   return atomic64_read(&available_protocols);
 }
 
 static int change_protocol(struct rc_dev *dev, u64 *rc_type)
@@ -331,9 +326,7 @@ int ir_raw_handler_register(struct ir_raw_handler 
*ir_raw_handler)
if (ir_raw_handler->raw_register)
list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_register(raw->dev);
-   mutex_lock(&available_protocols_lock);
-   available_protocols |= ir_raw_handler->protocols;
-   mutex_unlock(&available_protocols_lock);
+   atomic64_or(ir_raw_handler->protocols, &available_protocols);
mutex_unlock(&ir_raw_handler_lock);
 
return 0;
@@ -352,9 +345,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler)
if (ir_raw_handler->raw_unregister)
ir_raw_handler->raw_unregister(raw->dev);
}
-   mutex_lock(&available_protocols_lock);
-   available_protocols &= ~protocols;
-   mutex_unlock(&available_protocols_lock);
+   atomic64_andnot(protocols, &available_protocols);
mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] media: rc: nuvoton: remove usage of b_idx in nvt_get_rx_ir_data

2016-08-01 Thread Heiner Kallweit
The call to nvt_get_rx_ir_data and nvt_process_rx_ir_data from
the ISR is protected with spinlock nvt->lock. Therefore it's
guaranteed that nvt->pkts is 0 when entering nvt_get_rx_ir_data
(as nvt->pkts is set to 0 at the end of nvt_process_rx_ir_data).
Having said that we can remove b_idx.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 0c69536..e4158a9 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -802,7 +802,6 @@ static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
 static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 {
u8 fifocount, val;
-   unsigned int b_idx;
int i;
 
/* Get count of how many bytes to read from RX FIFO */
@@ -810,21 +809,13 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 
nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
 
-   b_idx = nvt->pkts;
-
-   /* This should never happen, but lets check anyway... */
-   if (b_idx + fifocount > RX_BUF_LEN) {
-   nvt_process_rx_ir_data(nvt);
-   b_idx = 0;
-   }
-
/* Read fifocount bytes from CIR Sample RX FIFO register */
for (i = 0; i < fifocount; i++) {
val = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
-   nvt->buf[b_idx + i] = val;
+   nvt->buf[i] = val;
}
 
-   nvt->pkts += fifocount;
+   nvt->pkts = fifocount;
nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
 
nvt_process_rx_ir_data(nvt);
-- 
2.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] media: rc: nuvoton: remove unneeded call to ir_raw_event_handle

2016-08-01 Thread Heiner Kallweit
ir_raw_event_handle is called anyway after the hw fifo content stored
in nvt->buf[] has been written to the kfifo. There is not really a
benefit in the potential additional call to ir_raw_event_handle
whilst nvt->buf[] is being processed.
Getting rid of this additional call allows to simplify the code.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index e4158a9..fc462f6 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -769,21 +769,11 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
rawir.pulse ? "pulse" : "space", rawir.duration);
 
ir_raw_event_store_with_filter(nvt->rdev, &rawir);
-
-   /*
-* BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE
-* indicates end of IR signal, but new data incoming. In both
-* cases, it means we're ready to call ir_raw_event_handle
-*/
-   if ((sample == BUF_PULSE_BIT) && (i + 1 < nvt->pkts)) {
-   nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
-   ir_raw_event_handle(nvt->rdev);
-   }
}
 
nvt->pkts = 0;
 
-   nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
+   nvt_dbg("Calling ir_raw_event_handle\n");
ir_raw_event_handle(nvt->rdev);
 
nvt_dbg_verbose("%s done", __func__);
-- 
2.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: refactor raw handler kthread

2016-08-01 Thread Heiner Kallweit
I think we can get rid of the spinlock protecting the kthread from being
interrupted by a wakeup in certain parts.
Even with the current implementation of the kthread the only lost wakeup
scenario could happen if the wakeup occurs between the kfifo_len check
and setting the state to TASK_INTERRUPTIBLE.

In the changed version we could lose a wakeup if it occurs between
processing the fifo content and setting the state to TASK_INTERRUPTIBLE.
This scenario is covered by an additional check for available events in
the fifo and setting the state to TASK_RUNNING in this case.

In addition the changed version flushes the kfifo before ending
when the kthread is stopped.

With this patch we gain:
- Get rid of the spinlock
- Simplify code
- Don't grep / release the mutex for each individual event but just once
  for the complete fifo content. This reduces overhead if a driver e.g.
  triggers processing after writing the content of a hw fifo to the kfifo.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-core-priv.h |  2 --
 drivers/media/rc/rc-ir-raw.c| 46 +++--
 2 files changed, 17 insertions(+), 31 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 585d5e5..577128a 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -20,7 +20,6 @@
 #defineMAX_IR_EVENT_SIZE   512
 
 #include 
-#include 
 #include 
 
 struct ir_raw_handler {
@@ -37,7 +36,6 @@ struct ir_raw_handler {
 struct ir_raw_event_ctrl {
struct list_headlist;   /* to keep track of raw 
clients */
struct task_struct  *thread;
-   spinlock_t  lock;
/* fifo for the pulse/space durations */
DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE);
ktime_t last_event; /* when last event 
occurred */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 205ecc6..71a3e17 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -17,7 +17,6 @@
 #include 
 #include 
 #include 
-#include 
 #include "rc-core-priv.h"
 
 /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
@@ -35,32 +34,26 @@ static int ir_raw_event_thread(void *data)
struct ir_raw_handler *handler;
struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
 
-   while (!kthread_should_stop()) {
-
-   spin_lock_irq(&raw->lock);
-
-   if (!kfifo_len(&raw->kfifo)) {
-   set_current_state(TASK_INTERRUPTIBLE);
-
-   if (kthread_should_stop())
-   set_current_state(TASK_RUNNING);
-
-   spin_unlock_irq(&raw->lock);
-   schedule();
-   continue;
+   while (1) {
+   mutex_lock(&ir_raw_handler_lock);
+   while (kfifo_out(&raw->kfifo, &ev, 1)) {
+   list_for_each_entry(handler, &ir_raw_handler_list, list)
+   if (raw->dev->enabled_protocols &
+   handler->protocols || !handler->protocols)
+   handler->decode(raw->dev, ev);
+   raw->prev_ev = ev;
}
+   mutex_unlock(&ir_raw_handler_lock);
 
-   if(!kfifo_out(&raw->kfifo, &ev, 1))
-   dev_err(&raw->dev->dev, "IR event FIFO is empty!\n");
-   spin_unlock_irq(&raw->lock);
+   set_current_state(TASK_INTERRUPTIBLE);
 
-   mutex_lock(&ir_raw_handler_lock);
-   list_for_each_entry(handler, &ir_raw_handler_list, list)
-   if (raw->dev->enabled_protocols & handler->protocols ||
-   !handler->protocols)
-   handler->decode(raw->dev, ev);
-   raw->prev_ev = ev;
-   mutex_unlock(&ir_raw_handler_lock);
+   if (kthread_should_stop()) {
+   __set_current_state(TASK_RUNNING);
+   break;
+   } else if (!kfifo_is_empty(&raw->kfifo))
+   set_current_state(TASK_RUNNING);
+
+   schedule();
}
 
return 0;
@@ -219,14 +212,10 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
  */
 void ir_raw_event_handle(struct rc_dev *dev)
 {
-   unsigned long flags;
-
if (!dev->raw)
return;
 
-   spin_lock_irqsave(&dev->raw->lock, flags);
wake_up_process(dev->raw->thread);
-   spin_unlock_irqrestore(&dev->raw->lock, flags);
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 
@@ -274,7 +263,

[PATCH 3/3] media: rc: nuvoton: simplify nvt_get_rx_ir_data a little

2016-08-01 Thread Heiner Kallweit
Simplify the code a little.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index fc462f6..04fedaa 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -791,7 +791,7 @@ static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
 /* copy data from hardware rx fifo into driver buffer */
 static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 {
-   u8 fifocount, val;
+   u8 fifocount;
int i;
 
/* Get count of how many bytes to read from RX FIFO */
@@ -800,10 +800,8 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
 
/* Read fifocount bytes from CIR Sample RX FIFO register */
-   for (i = 0; i < fifocount; i++) {
-   val = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
-   nvt->buf[i] = val;
-   }
+   for (i = 0; i < fifocount; i++)
+   nvt->buf[i] = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
 
nvt->pkts = fifocount;
nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
-- 
2.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: nuvoton: ignore spurious interrupt when logical device is being disabled

2016-07-31 Thread Heiner Kallweit
When removing module nuvoton-cir I get a fifo overrun warning.
It turned out to be caused by a spurious interrupt when the logical CIR
device is being disabled (although no interrupt source bit being set).
Reading the interrupt status register returns 0xff, therefore the fifo
overrun bit is mistakenly interpreted as being set.

Fix this by ignoring interrupts when interrupt source and status register
reads return 0xff.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 00215f3..0c69536 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -886,6 +886,15 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
status = nvt_cir_reg_read(nvt, CIR_IRSTS);
iren = nvt_cir_reg_read(nvt, CIR_IREN);
 
+   /* At least NCT6779D creates a spurious interrupt when the
+* logical device is being disabled.
+*/
+   if (status == 0xff && iren == 0xff) {
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+   nvt_dbg_verbose("Spurious interrupt detected");
+   return IRQ_HANDLED;
+   }
+
/* IRQ may be shared with CIR WAKE, therefore check for each
 * status bit whether the related interrupt source is enabled
 */
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: fix deadlock when module ir_lirc_codec is removed

2016-07-31 Thread Heiner Kallweit
When removing module ir_lirc_codec I got this deadlock warning.
Fix this by introducing a separate mutex to protect access
to available_protocols instead of using ir_raw_handler_lock
for this purpose.

==
[ INFO: possible circular locking dependency detected ]
4.7.0-next-20160729 #1 Not tainted
---
rmmod/2542 is trying to acquire lock:
 (&dev->lock){+.+.+.}, at: []
ir_raw_handler_unregister+0x77/0xd0 [rc_core]

but task is already holding lock:
 (ir_raw_handler_lock){+.+.+.}, at: []
ir_raw_handler_unregister+0x22/0xd0 [rc_core]

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (ir_raw_handler_lock){+.+.+.}:
   [] lock_acquire+0xb2/0x1e0
   [] mutex_lock_nested+0x5f/0x360
   [] ir_raw_get_allowed_protocols+0x13/0x30 [rc_core]
   [] store_protocols+0x2fa/0x480 [rc_core]
   [] dev_attr_store+0x13/0x20
   [] sysfs_kf_write+0x40/0x50
   [] kernfs_fop_write+0x150/0x1e0
   [] __vfs_write+0x23/0x120
   [] vfs_write+0xb0/0x190
   [] SyS_write+0x44/0xa0
   [] entry_SYSCALL_64_fastpath+0x18/0xa8

-> #0 (&dev->lock){+.+.+.}:
   [] __lock_acquire+0x10fc/0x1270
   [] lock_acquire+0xb2/0x1e0
   [] mutex_lock_nested+0x5f/0x360
   [] ir_raw_handler_unregister+0x77/0xd0 [rc_core]
   [] ir_lirc_codec_exit+0x10/0x12 [ir_lirc_codec]
   [] SyS_delete_module+0x168/0x220
   [] entry_SYSCALL_64_fastpath+0x18/0xa8

other info that might help us debug this:

 Possible unsafe locking scenario:

   CPU0CPU1
   
  lock(ir_raw_handler_lock);
   lock(&dev->lock);
   lock(ir_raw_handler_lock);
  lock(&dev->lock);

 *** DEADLOCK ***

1 lock held by rmmod/2542:
 #0:  (ir_raw_handler_lock){+.+.+.}, at: []
ir_raw_handler_unregister+0x22/0xd0 [rc_core]

stack backtrace:
CPU: 0 PID: 2542 Comm: rmmod Not tainted 4.7.0-next-20160729 #1
Hardware name: ZOTAC ZBOX-CI321NANO/ZBOX-CI321NANO, BIOS B246P105 06/01/2015
  88006e607cc0 812715f5 8232b230
 8232b230 88006e607d00 810a846e 790107f0
 880079010818 8800790107f0 1efeb9f4f0dd2e6f 88007901
Call Trace:
 [] dump_stack+0x68/0x93
 [] print_circular_bug+0x1be/0x210
 [] __lock_acquire+0x10fc/0x1270
 [] ? debug_lockdep_rcu_enabled+0x1d/0x20
 [] lock_acquire+0xb2/0x1e0
 [] ? ir_raw_handler_unregister+0x77/0xd0 [rc_core]
 [] mutex_lock_nested+0x5f/0x360
 [] ? ir_raw_handler_unregister+0x77/0xd0 [rc_core]
 [] ? trace_hardirqs_on_caller+0xee/0x1b0
 [] ir_raw_handler_unregister+0x77/0xd0 [rc_core]
 [] ir_lirc_codec_exit+0x10/0x12 [ir_lirc_codec]
 [] SyS_delete_module+0x168/0x220
 [] entry_SYSCALL_64_fastpath+0x18/0xa8

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-ir-raw.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 144304c..205ecc6 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -26,6 +26,7 @@ static LIST_HEAD(ir_raw_client_list);
 /* Used to handle IR raw handler extensions */
 static DEFINE_MUTEX(ir_raw_handler_lock);
 static LIST_HEAD(ir_raw_handler_list);
+static DEFINE_MUTEX(available_protocols_lock);
 static u64 available_protocols;
 
 static int ir_raw_event_thread(void *data)
@@ -234,9 +235,9 @@ u64
 ir_raw_get_allowed_protocols(void)
 {
u64 protocols;
-   mutex_lock(&ir_raw_handler_lock);
+   mutex_lock(&available_protocols_lock);
protocols = available_protocols;
-   mutex_unlock(&ir_raw_handler_lock);
+   mutex_unlock(&available_protocols_lock);
return protocols;
 }
 
@@ -330,7 +331,9 @@ int ir_raw_handler_register(struct ir_raw_handler 
*ir_raw_handler)
if (ir_raw_handler->raw_register)
list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_register(raw->dev);
+   mutex_lock(&available_protocols_lock);
available_protocols |= ir_raw_handler->protocols;
+   mutex_unlock(&available_protocols_lock);
mutex_unlock(&ir_raw_handler_lock);
 
return 0;
@@ -349,7 +352,9 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler)
if (ir_raw_handler->raw_unregister)
ir_raw_handler->raw_unregister(raw->dev);
}
+   mutex_lock(&available_protocols_lock);
available_protocols &= ~protocols;
+   mutex_unlock(&available_protocols_lock);
mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
-- 
2.9.0

--
To unsubscribe from this list: send the l

[PATCH] rc: nuvoton: fix hang if chip is configured for alternative EFM IO address

2016-07-06 Thread Heiner Kallweit
If a system configures the Nuvoton chip to use the alternative
EFM IO address (CR_EFIR2) then after probing the primary EFM IO
address (CR_EFIR) this region is not released.

If a driver for another function of the Nuvoton Super I/O
chip uses the same probing mechanism then it will hang if
loaded after the nuvoton-cir driver.
This was reported for the nct6775 hwmon driver.

Fix this by properly releasing the region after probing CR_EFIR.
This regression was introduced with kernel 4.6 so cc it to stable.

Reported-by: Antti Seppälä 
Signed-off-by: Heiner Kallweit 
Tested-by: Antti Seppälä 
Cc:  # 4.6.x-
---
 drivers/media/rc/nuvoton-cir.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 99b303b..e8ceb0e 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -401,6 +401,7 @@ static int nvt_hw_detect(struct nvt_dev *nvt)
/* Check if we're wired for the alternate EFER setup */
nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
if (nvt->chip_major == 0xff) {
+   nvt_efm_disable(nvt);
nvt->cr_efir = CR_EFIR2;
nvt->cr_efdr = CR_EFDR2;
nvt_efm_enable(nvt);
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Recent nuvoton-cir changes introduce a hang with nct6775

2016-07-06 Thread Heiner Kallweit
Am 06.07.2016 um 08:51 schrieb Antti Seppälä:
> Hello.
> 
> I recently updated my kernel to a newer version but couldn't boot it
> because it hangs.
> 
> It turns out that your patch[1] to nuvoton-cir has really bad
> side-effects when it interacts with nct6775 module. It could be that
> one of the devices never frees the request_muxed_region which causes
> the other module to wait indefinitely.
> 
> Reverting the patch or preventing nct6775 module from loading makes
> the issue go away.
> 
> Other people have run into this issue too[2].
> 
> This is a regression and should be fixed.
> Could you look into it and maybe submit a follow-up patch to fix this
> or shall I perhaps ask for a revert of the troublesome commit?
> 
> 
> [1]: 
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/media/rc/nuvoton-cir.c?id=3def9ad6d3066e597d0ce86801a81eedb130b04a
> 
> [2]: https://bbs.archlinux.org/viewtopic.php?id=213647
> 
> 
> Regards,
> 
Thanks for reporting. Indeed there may be an issue with systems using
the alternative EFM IO address of the Nuvoton chip.
Therefore it doesn't occur on all systems with this chip and then
only if the nct6775 driver is loaded after the nuvoton-cir driver.
Could you please check whether the following patch fixes the issue for you?

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 99b303b..e8ceb0e 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -401,6 +401,7 @@ static int nvt_hw_detect(struct nvt_dev *nvt)
/* Check if we're wired for the alternate EFER setup */
nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
if (nvt->chip_major == 0xff) {
+   nvt_efm_disable(nvt);
nvt->cr_efir = CR_EFIR2;
nvt->cr_efdr = CR_EFDR2;
nvt_efm_enable(nvt);
--
2.9.0

Regards, Heiner

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: rc: nuvoton: decrease size of raw event fifo

2016-07-05 Thread Heiner Kallweit
Am 05.07.2016 um 11:17 schrieb Sean Young:
> On Tue, Jul 05, 2016 at 08:05:16AM +0200, Heiner Kallweit wrote:
>> Am 04.07.2016 um 23:06 schrieb Sean Young:
>>> On Mon, Jul 04, 2016 at 10:51:50PM +0200, Heiner Kallweit wrote:
>>>> Am 04.07.2016 um 22:13 schrieb Sean Young:
>>>>> On Wed, May 18, 2016 at 10:29:41PM +0200, Heiner Kallweit wrote:
>>>>>> This chip has a 32 byte HW FIFO only. Therefore the default fifo size
>>>>>> of 512 raw events is not needed and can be significantly decreased.
>>>>>>
>>>>>> Signed-off-by: Heiner Kallweit 
>>>>>
>>>>> The 32 byte hardware queue is read from an interrupt handler and added
>>>>> to the kfifo. The kfifo is read by the decoders in a seperate kthread
>>>>> (in ir_raw_event_thread). If we have a long IR (e.g. nec which has 
>>>>> 66 edges) and the kthread is not scheduled in time (e.g. high load), will
>>>>> we not end up with an overflow in the kfifo and unable to decode it?
>>>>>
>>>> The interrupt handler is triggered latest when 24 bytes have been read.
>>>> (at least that's how the chip gets configured at the moment)
>>>> This gives the decoder thread at least 8 bytes time to process the
>>>> kfifo. This should be sufficient even under high load.
>>>
>>> No, it gives the interrupt handler at least 8 bytes time to read the
>>> hardware fifo (and add it to the kfifo). There are no guarantees about
>>> when the decoder kthread runs (which reads the kfifo).
>>>
>>> To put it another way, in the nuvoton interrupt handler, you call 
>>> ir_raw_event_handle() which does a wake_up_process(). That puts the
>>> decoder process (it has a pid) in a runnable state and it will run at
>>> some future time.
>>>
>> You're right, that's the more precise description.
>> These 8 bytes time give the decoder process few msec's to start.
>> (Not sure wheter there's any protocol resulting in much shorter time.)
>> At least during my tests this was always sufficient.
> 
> So worst case scenario with NEC IR (I have not checked all ir protocols).
> 1. 32 bytes of IR read from hardware fifo.
> 2. IR in the middle of series of 1s (two edges, 1.125ms each)
> 3. After 13.5ms interrupt is triggered again as 12 new bits generated 24 edges
> 4. Decoder thread has not run and emptied the fifo.
> 5. kfifo overflow and IR cannot be decoded; key lost
> 
At least in the nuvoton driver the decoder thread is started whenever
something was read from the hw fifo and written to kfifo.
-> call to ir_raw_event_handle() at the end of nvt_process_rx_ir_data
It doesn't wait for the end of an IR packet.
Means in your example the decoder thread would be started after step 1
and whenever the hw fifo reaches the threshold to generate an irq.

>> However if you think 32 bytes might be too small as kfifo size I'd
>> also be fine with increasing it. The result should still be better
>> than the default size of 512.
> 
> So this depends on how many edges an remote could possible generate and
> how often the kthread will be scheduled to read it. For example I have
> a remote which repeats the entire nec code after 20ms if you hold a
> button down. That's about 800 edges per second, so with a kfifo of 512
> the kthread would have to be scheduled twice a second.
> 
> I think we should stick to the default of 512.
> 
> 
> Sean
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: rc: nuvoton: decrease size of raw event fifo

2016-07-04 Thread Heiner Kallweit
Am 04.07.2016 um 23:06 schrieb Sean Young:
> On Mon, Jul 04, 2016 at 10:51:50PM +0200, Heiner Kallweit wrote:
>> Am 04.07.2016 um 22:13 schrieb Sean Young:
>>> On Wed, May 18, 2016 at 10:29:41PM +0200, Heiner Kallweit wrote:
>>>> This chip has a 32 byte HW FIFO only. Therefore the default fifo size
>>>> of 512 raw events is not needed and can be significantly decreased.
>>>>
>>>> Signed-off-by: Heiner Kallweit 
>>>
>>> The 32 byte hardware queue is read from an interrupt handler and added
>>> to the kfifo. The kfifo is read by the decoders in a seperate kthread
>>> (in ir_raw_event_thread). If we have a long IR (e.g. nec which has 
>>> 66 edges) and the kthread is not scheduled in time (e.g. high load), will
>>> we not end up with an overflow in the kfifo and unable to decode it?
>>>
>> The interrupt handler is triggered latest when 24 bytes have been read.
>> (at least that's how the chip gets configured at the moment)
>> This gives the decoder thread at least 8 bytes time to process the
>> kfifo. This should be sufficient even under high load.
> 
> No, it gives the interrupt handler at least 8 bytes time to read the
> hardware fifo (and add it to the kfifo). There are no guarantees about
> when the decoder kthread runs (which reads the kfifo).
> 
> To put it another way, in the nuvoton interrupt handler, you call 
> ir_raw_event_handle() which does a wake_up_process(). That puts the
> decoder process (it has a pid) in a runnable state and it will run at
> some future time.
> 
You're right, that's the more precise description.
These 8 bytes time give the decoder process few msec's to start.
(Not sure wheter there's any protocol resulting in much shorter time.)
At least during my tests this was always sufficient.

However if you think 32 bytes might be too small as kfifo size I'd
also be fine with increasing it. The result should still be better
than the default size of 512.

Heiner

> 
> Sean
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: IR remote stopped working in kernels 4.5 and 4.6

2016-07-04 Thread Heiner Kallweit
Am 04.07.2016 um 23:18 schrieb James Bottomley:
> On Mon, 2016-07-04 at 23:08 +0200, Heiner Kallweit wrote:
>> Am 04.07.2016 um 22:36 schrieb James Bottomley:
>>> This looks to be a problem with the rc subsystem.  The IR 
>>> controller in question is part of a cx8800 atsc card. In the 4.4 
>>> kernel, where it works, this is what ir-keytable says:
>>>
>>> Found /sys/class/rc/rc0/ (/dev/input/event12) with:
>>> Driver cx88xx, table rc-hauppauge
>>> Supported protocols: other lirc rc-5 jvc sony nec sanyo mce-kbd
>>> rc-6 sharp xmp 
>>> Enabled protocols: lirc nec 
>>> Name: cx88 IR (pcHDTV HD3000 HDTV)
>>> bus: 1, vendor/product: 7063:3000, version: 0x0001
>>> Repeat delay = 500 ms, repeat period = 125 ms
>>>
>>> And in 4.6, where it doesn't work:
>>>
>>> Found /sys/class/rc/rc0/ (/dev/input/event12) with:
>>> Driver cx88xx, table rc-hauppauge
>>> Supported protocols: lirc 
After having had a look at the cx88 driver the issue seems to be there.
For the HD3000 allowed_protocols is initialized to RC_BIT_OTHER only.
This prevents autoloading of the NEC module.

If the device is not restricted to a particular protocol (some devices
supported by cx88 seem to be restricted to the NEC protocol) then
allowed_protocols should be set to RC_BIT_ALL.

Can you test with this change?

If HD3000 is restricted to NEC then the initialization should be
similar to e.g. PROLINK PLAYTVPVR

>>> Enabled protocols: lirc 
>>> Name: cx88 IR (pcHDTV HD3000 HDTV)
>>> bus: 1, vendor/product: 7063:3000, version: 0x0001
>>> Repeat delay = 500 ms, repeat period = 125 ms
>>>
>>> The particular remote in question seems to require the nec protocol 
>>> to work and the failure in 4.5 and 4.6 is having any supported
>>> protocols at all.  I can get the remote to start working again by 
>>> adding the nec protocol:
>>>
>>> echo nec > /sys/class/rc/rc0/protocols
>>>
>>> But it would be nice to have this happen by default rather than 
>>> having to add yet another work around init script.
>>>
>> Meanwhile decoder modules are loaded on demand only. This can be done
>> automatically w/o the need for additional init scripts.
>>
>> If /etc/rc_maps.cfg includes a keymap with type NEC then the nec 
>> decoder module is loaded automatically.
>>
>> My rc_maps.cfg looks like this (and causes the SONY decoder module to 
>> be loaded automatically):
>>
>> #driver tablefile
>> *   *sony-rm-sx800
>>
>> And the keymap:
>>
>> # table sony-rm-sx800, type SONY
>> 0x110030KEY_PREVIOUS
>> 0x110031KEY_NEXT
>> 0x110033KEY_BACK
>> ..
>> ..
> 
> 
> Well, to work in the 4.4 kernel, the rc_maps.cfg names a table with the
> nec controller, so it seems that whatever is supposed to trigger
> autoloading isn't.
> 
> Is ir-keytable supposed to do this?  The current debian testing one is
> 
> Package: ir-keytable
> Source: v4l-utils
> Version: 1.10.1-1
> 
> Which seems to be the most current one.
> 
> James
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: IR remote stopped working in kernels 4.5 and 4.6

2016-07-04 Thread Heiner Kallweit
Am 04.07.2016 um 22:36 schrieb James Bottomley:
> This looks to be a problem with the rc subsystem.  The IR controller in
> question is part of a cx8800 atsc card. In the 4.4 kernel, where it
> works, this is what ir-keytable says:
> 
> Found /sys/class/rc/rc0/ (/dev/input/event12) with:
>   Driver cx88xx, table rc-hauppauge
>   Supported protocols: other lirc rc-5 jvc sony nec sanyo mce-kbd rc-6 
> sharp xmp 
>   Enabled protocols: lirc nec 
>   Name: cx88 IR (pcHDTV HD3000 HDTV)
>   bus: 1, vendor/product: 7063:3000, version: 0x0001
>   Repeat delay = 500 ms, repeat period = 125 ms
> 
> And in 4.6, where it doesn't work:
> 
> Found /sys/class/rc/rc0/ (/dev/input/event12) with:
>   Driver cx88xx, table rc-hauppauge
>   Supported protocols: lirc 
>   Enabled protocols: lirc 
>   Name: cx88 IR (pcHDTV HD3000 HDTV)
>   bus: 1, vendor/product: 7063:3000, version: 0x0001
>   Repeat delay = 500 ms, repeat period = 125 ms
> 
> The particular remote in question seems to require the nec protocol to
> work and the failure in 4.5 and 4.6 is having any supported protocols
> at all.  I can get the remote to start working again by adding the nec
> protocol:
> 
> echo nec > /sys/class/rc/rc0/protocols
> 
> But it would be nice to have this happen by default rather than having
> to add yet another work around init script.
> 
Meanwhile decoder modules are loaded on demand only. This can be done
automatically w/o the need for additional init scripts.

If /etc/rc_maps.cfg includes a keymap with type NEC then the nec decoder
module is loaded automatically.

My rc_maps.cfg looks like this (and causes the SONY decoder module to be
loaded automatically):

#driver tablefile
*   *sony-rm-sx800

And the keymap:

# table sony-rm-sx800, type SONY
0x110030KEY_PREVIOUS
0x110031KEY_NEXT
0x110033KEY_BACK
..
..

Heiner

> James
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: rc: nuvoton: decrease size of raw event fifo

2016-07-04 Thread Heiner Kallweit
Am 04.07.2016 um 22:13 schrieb Sean Young:
> On Wed, May 18, 2016 at 10:29:41PM +0200, Heiner Kallweit wrote:
>> This chip has a 32 byte HW FIFO only. Therefore the default fifo size
>> of 512 raw events is not needed and can be significantly decreased.
>>
>> Signed-off-by: Heiner Kallweit 
> 
> The 32 byte hardware queue is read from an interrupt handler and added
> to the kfifo. The kfifo is read by the decoders in a seperate kthread
> (in ir_raw_event_thread). If we have a long IR (e.g. nec which has 
> 66 edges) and the kthread is not scheduled in time (e.g. high load), will
> we not end up with an overflow in the kfifo and unable to decode it?
> 
The interrupt handler is triggered latest when 24 bytes have been read.
(at least that's how the chip gets configured at the moment)
This gives the decoder thread at least 8 bytes time to process the
kfifo. This should be sufficient even under high load.

If somebody configures the driver the generate an interrupt after 32 bytes
only then there are possible issues under high load or with longer code
pieces with interrupts disabled anyway:
Then the next byte might arrive (and make the chip fifo overrun) before
the interrupt handler can read the chip fifo.

Heiner

> 
> Sean
> 
>> ---
>>  drivers/media/rc/nuvoton-cir.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
>> index 99b303b..e98c955 100644
>> --- a/drivers/media/rc/nuvoton-cir.c
>> +++ b/drivers/media/rc/nuvoton-cir.c
>> @@ -1186,6 +1186,7 @@ static int nvt_probe(struct pnp_dev *pdev, const 
>> struct pnp_device_id *dev_id)
>>  rdev->priv = nvt;
>>  rdev->driver_type = RC_DRIVER_IR_RAW;
>>  rdev->allowed_protocols = RC_BIT_ALL;
>> +rdev->raw_fifo_size = RX_BUF_LEN;
>>  rdev->open = nvt_open;
>>  rdev->close = nvt_close;
>>  rdev->tx_ir = nvt_tx_ir;
>> -- 
>> 2.8.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/9] media: rc: nuvoton: remove study states

2016-06-23 Thread Heiner Kallweit
Study states have never been used and are not needed. Remove them.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 11 +--
 drivers/media/rc/nuvoton-cir.h | 13 -
 2 files changed, 1 insertion(+), 23 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 9d9717d..5ce0238 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -865,7 +865,7 @@ static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
 static irqreturn_t nvt_cir_isr(int irq, void *data)
 {
struct nvt_dev *nvt = data;
-   u8 status, iren, cur_state;
+   u8 status, iren;
unsigned long flags;
 
nvt_dbg_verbose("%s firing", __func__);
@@ -907,7 +907,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
nvt_handle_rx_fifo_overrun(nvt);
 
if (status & CIR_IRSTS_RTR) {
-   /* FIXME: add code for study/learn mode */
/* We only do rx if not tx'ing */
if (nvt_cir_tx_inactive(nvt))
nvt_get_rx_ir_data(nvt);
@@ -916,11 +915,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
if (status & CIR_IRSTS_PE) {
if (nvt_cir_tx_inactive(nvt))
nvt_get_rx_ir_data(nvt);
-
-   cur_state = nvt->study_state;
-
-   if (cur_state == ST_STUDY_NONE)
-   nvt_clear_cir_fifo(nvt);
}
 
spin_unlock_irqrestore(&nvt->nvt_lock, flags);
@@ -1193,9 +1187,6 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t 
state)
 
spin_lock_irqsave(&nvt->nvt_lock, flags);
 
-   /* zero out misc state tracking */
-   nvt->study_state = ST_STUDY_NONE;
-
/* disable all CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
 
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 8bd35bd..65324ef 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -117,23 +117,10 @@ struct nvt_dev {
/* rx settings */
bool learning_enabled;
 
-   /* for study */
-   u8 study_state;
/* carrier period = 1 / frequency */
u32 carrier;
 };
 
-/* study states */
-#define ST_STUDY_NONE  0x0
-#define ST_STUDY_START 0x1
-#define ST_STUDY_CARRIER   0x2
-#define ST_STUDY_ALL_RECV  0x4
-
-/* receive states */
-#define ST_RX_WAIT_7F  0x1
-#define ST_RX_WAIT_HEAD0x2
-#define ST_RX_WAIT_SILENT_END  0x4
-
 /* send states */
 #define ST_TX_NONE 0x0
 #define ST_TX_REQUEST  0x2
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/9] media: rc: nuvoton: simplify interrupt handling code

2016-06-23 Thread Heiner Kallweit
Simplify interupt handling code.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 5ce0238..180f589 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -906,17 +906,12 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
if (status & CIR_IRSTS_RFO)
nvt_handle_rx_fifo_overrun(nvt);
 
-   if (status & CIR_IRSTS_RTR) {
+   else if (status & (CIR_IRSTS_RTR | CIR_IRSTS_PE)) {
/* We only do rx if not tx'ing */
if (nvt_cir_tx_inactive(nvt))
nvt_get_rx_ir_data(nvt);
}
 
-   if (status & CIR_IRSTS_PE) {
-   if (nvt_cir_tx_inactive(nvt))
-   nvt_get_rx_ir_data(nvt);
-   }
-
spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 
if (status & CIR_IRSTS_TE)
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/9] media: rc: nuvoton: remove wake states

2016-06-23 Thread Heiner Kallweit
Wake states have never been in use and now that we can set the
wakeup sequence via sysfs there's in general no need for them.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 1 -
 drivers/media/rc/nuvoton-cir.h | 7 ---
 2 files changed, 8 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c8999cc..c405c83 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1207,7 +1207,6 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t 
state)
 
/* zero out misc state tracking */
nvt->study_state = ST_STUDY_NONE;
-   nvt->wake_state = ST_WAKE_NONE;
 
/* disable all CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 68431f0..8bd35bd 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -117,8 +117,6 @@ struct nvt_dev {
/* rx settings */
bool learning_enabled;
 
-   /* track cir wake state */
-   u8 wake_state;
/* for study */
u8 study_state;
/* carrier period = 1 / frequency */
@@ -131,11 +129,6 @@ struct nvt_dev {
 #define ST_STUDY_CARRIER   0x2
 #define ST_STUDY_ALL_RECV  0x4
 
-/* wake states */
-#define ST_WAKE_NONE   0x0
-#define ST_WAKE_START  0x1
-#define ST_WAKE_FINISH 0x2
-
 /* receive states */
 #define ST_RX_WAIT_7F  0x1
 #define ST_RX_WAIT_HEAD0x2
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/9] media: rc: nuvoton: clean up initialization of wakeup registers

2016-06-23 Thread Heiner Kallweit
The registers defining wakeup sequence handling are set when the
wakeup sequence is set via sysfs. There's no need to initialize them
otherwise.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 25 +++--
 1 file changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index b32f3bf..c8999cc 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -564,34 +564,15 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt)
 
 static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
 {
-   /* set number of bytes needed for wake from s3 (default 65) */
-   nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_CMP_BYTES,
-  CIR_WAKE_FIFO_CMP_DEEP);
-
-   /* set tolerance/variance allowed per byte during wake compare */
-   nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE,
-  CIR_WAKE_FIFO_CMP_TOL);
-
-   /* set sample limit count (PE interrupt raised when reached) */
-   nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH);
-   nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL);
-
-   /* set cir wake fifo rx trigger level (currently 67) */
-   nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV,
-  CIR_WAKE_FIFOCON);
-
/*
-* Enable TX and RX, specific carrier on = low, off = high, and set
-* sample period (currently 50us)
+* Disable RX, set specific carrier on = low, off = high,
+* and sample period (currently 50us)
 */
-   nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
+   nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 |
   CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
   CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
   CIR_WAKE_IRCON);
 
-   /* clear cir wake rx fifo */
-   nvt_clear_cir_wake_fifo(nvt);
-
/* clear any and all stray interrupts */
nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
 
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 9/9] media: rc: nuvoton: remove two unused elements in struct nvt_dev

2016-06-23 Thread Heiner Kallweit
These two fields are not used and can be removed.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.h | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 65324ef..acf735f 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -111,12 +111,8 @@ struct nvt_dev {
u8 chip_minor;
 
/* hardware features */
-   bool hw_learning_capable;
bool hw_tx_capable;
 
-   /* rx settings */
-   bool learning_enabled;
-
/* carrier period = 1 / frequency */
u32 carrier;
 };
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/9] media: rc: nuvoton: remove interrupt handling for wakeup

2016-06-23 Thread Heiner Kallweit
There is a rudimentary ISR for handling interrupts generated by the
wakeup part of the chip. Interrupts however have never been enabled
in the wakeup part.
Also, now that we can set the wakeup sequence via sysfs, there's in
general no need to enable interrupts in the wakeup part.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 58 ++
 drivers/media/rc/nuvoton-cir.h |  1 -
 2 files changed, 2 insertions(+), 57 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 4a8f79c..b32f3bf 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -480,10 +480,8 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
 
nvt_set_ioaddr(nvt, &nvt->cir_wake_addr);
 
-   nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC);
-
-   nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d",
-   nvt->cir_wake_addr, nvt->cir_wake_irq);
+   nvt_dbg("CIR Wake initialized, base io port address: 0x%lx",
+   nvt->cir_wake_addr);
 }
 
 /* clear out the hardware's cir rx fifo */
@@ -997,51 +995,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
return IRQ_HANDLED;
 }
 
-/* Interrupt service routine for CIR Wake */
-static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
-{
-   u8 status, iren, val;
-   struct nvt_dev *nvt = data;
-   unsigned long flags;
-
-   nvt_dbg_wake("%s firing", __func__);
-
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
-
-   status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
-   iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
-
-   /* IRQ may be shared with CIR, therefore check for each
-* status bit whether the related interrupt source is enabled
-*/
-   if (!(status & iren)) {
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-   return IRQ_NONE;
-   }
-
-   if (status & CIR_WAKE_IRSTS_IR_PENDING)
-   nvt_clear_cir_wake_fifo(nvt);
-
-   nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS);
-   nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS);
-
-   if ((status & CIR_WAKE_IRSTS_PE) &&
-   (nvt->wake_state == ST_WAKE_START)) {
-   while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) {
-   val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
-   nvt_dbg("setting wake up key: 0x%x", val);
-   }
-
-   nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
-   nvt->wake_state = ST_WAKE_FINISH;
-   }
-
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-   nvt_dbg_wake("%s done", __func__);
-   return IRQ_HANDLED;
-}
-
 static void nvt_disable_cir(struct nvt_dev *nvt)
 {
unsigned long flags;
@@ -1145,8 +1098,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
nvt->cir_irq  = pnp_irq(pdev, 0);
 
nvt->cir_wake_addr = pnp_port_start(pdev, 1);
-   /* irq is always shared between cir and cir wake */
-   nvt->cir_wake_irq  = nvt->cir_irq;
 
nvt->cr_efir = CR_EFIR;
nvt->cr_efdr = CR_EFDR;
@@ -1223,11 +1174,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake"))
goto exit_unregister_device;
 
-   if (devm_request_irq(&pdev->dev, nvt->cir_wake_irq,
-nvt_cir_wake_isr, IRQF_SHARED,
-NVT_DRIVER_NAME "-wake", (void *)nvt))
-   goto exit_unregister_device;
-
ret = device_create_file(&rdev->dev, &dev_attr_wakeup_data);
if (ret)
goto exit_unregister_device;
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index c9c98eb..68431f0 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -104,7 +104,6 @@ struct nvt_dev {
unsigned long cir_addr;
unsigned long cir_wake_addr;
int cir_irq;
-   int cir_wake_irq;
 
enum nvt_chip_ver chip_ver;
/* hardware id */
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/9] media: rc: nuvoton: several clean-ups / removal of dead code

2016-06-23 Thread Heiner Kallweit
This patch set for the nuvoton-cir driver includes several
clean-ups and removes dead code.

Heiner Kallweit (9):
  media: rc: nuvoton: remove interrupt handling for wakeup
  media: rc: nuvoton: clean up initialization of wakeup registers
  media: rc: nuvoton: remove wake states
  media: rc: nuvoton: simplify a few functions
  media: rc: nuvoton: remove unneeded code in nvt_process_rx_ir_data
  media: rc: nuvoton: remove study states
  media: rc: nuvoton: simplify interrupt handling code
  media: rc: nuvoton: remove unneeded check in nvt_get_rx_ir_data
  media: rc: nuvoton: remove two unused elements in struct nvt_dev

 drivers/media/rc/nuvoton-cir.c | 123 -
 drivers/media/rc/nuvoton-cir.h |  25 -
 2 files changed, 10 insertions(+), 138 deletions(-)

-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/9] media: rc: nuvoton: remove unneeded check in nvt_get_rx_ir_data

2016-06-23 Thread Heiner Kallweit
If the logical device is disabled then it can not generate interrupts.
Therefore this check is not needed.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 180f589..7a6f6c4 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -806,9 +806,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 
/* Get count of how many bytes to read from RX FIFO */
fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT);
-   /* if we get 0xff, probably means the logical dev is disabled */
-   if (fifocount == 0xff)
-   return;
 
nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
 
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/9] media: rc: nuvoton: remove unneeded code in nvt_process_rx_ir_data

2016-06-23 Thread Heiner Kallweit
The definition of rawir includes the initialization already.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 1d99f10..9d9717d 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -757,8 +757,6 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 
nvt_dbg_verbose("Processing buffer of len %d", nvt->pkts);
 
-   init_ir_raw_event(&rawir);
-
for (i = 0; i < nvt->pkts; i++) {
sample = nvt->buf[i];
 
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/9] media: rc: nuvoton: simplify a few functions

2016-06-23 Thread Heiner Kallweit
Simplify a few functions.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c405c83..1d99f10 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -139,11 +139,7 @@ static inline void nvt_cir_reg_write(struct nvt_dev *nvt, 
u8 val, u8 offset)
 /* read val from cir config register */
 static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset)
 {
-   u8 val;
-
-   val = inb(nvt->cir_addr + offset);
-
-   return val;
+   return inb(nvt->cir_addr + offset);
 }
 
 /* write val to cir wake register */
@@ -156,11 +152,7 @@ static inline void nvt_cir_wake_reg_write(struct nvt_dev 
*nvt,
 /* read val from cir wake config register */
 static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
 {
-   u8 val;
-
-   val = inb(nvt->cir_wake_addr + offset);
-
-   return val;
+   return inb(nvt->cir_wake_addr + offset);
 }
 
 /* don't override io address if one is set already */
@@ -487,9 +479,7 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
 /* clear out the hardware's cir rx fifo */
 static void nvt_clear_cir_fifo(struct nvt_dev *nvt)
 {
-   u8 val;
-
-   val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
+   u8 val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
 }
 
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: nuvoton: fix rx fifo overrun handling

2016-05-22 Thread Heiner Kallweit
To detect a rx fifo overrun it's checked whether the number of elements
in the chip fifo exceeds the fifo size. This check can never return true
and is wrong.
Instead we should generate an interrupt if the fifo overruns.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 028574b..74a8de2 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -525,7 +525,7 @@ static void nvt_set_cir_iren(struct nvt_dev *nvt)
 {
u8 iren;
 
-   iren = CIR_IREN_RTR | CIR_IREN_PE;
+   iren = CIR_IREN_RTR | CIR_IREN_PE | CIR_IREN_RFO;
nvt_cir_reg_write(nvt, iren, CIR_IREN);
 }
 
@@ -833,7 +833,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 {
u8 fifocount, val;
unsigned int b_idx;
-   bool overrun = false;
int i;
 
/* Get count of how many bytes to read from RX FIFO */
@@ -841,11 +840,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
/* if we get 0xff, probably means the logical dev is disabled */
if (fifocount == 0xff)
return;
-   /* watch out for a fifo overrun condition */
-   else if (fifocount > RX_BUF_LEN) {
-   overrun = true;
-   fifocount = RX_BUF_LEN;
-   }
 
nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
 
@@ -867,9 +861,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
 
nvt_process_rx_ir_data(nvt);
-
-   if (overrun)
-   nvt_handle_rx_fifo_overrun(nvt);
 }
 
 static void nvt_cir_log_irqs(u8 status, u8 iren)
@@ -943,6 +934,9 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 
nvt_cir_log_irqs(status, iren);
 
+   if (status & CIR_IRSTS_RFO)
+   nvt_handle_rx_fifo_overrun(nvt);
+
if (status & CIR_IRSTS_RTR) {
/* FIXME: add code for study/learn mode */
/* We only do rx if not tx'ing */
-- 
2.8.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] media: rc: nuvoton: decrease size of raw event fifo

2016-05-19 Thread Heiner Kallweit
This chip has a 32 byte HW FIFO only. Therefore the default fifo size
of 512 raw events is not needed and can be significantly decreased.

Signed-off-by: Heiner Kallweit 
---
v2:
- make patch part of a series
---
 drivers/media/rc/nuvoton-cir.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 99b303b..e98c955 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1186,6 +1186,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
rdev->priv = nvt;
rdev->driver_type = RC_DRIVER_IR_RAW;
rdev->allowed_protocols = RC_BIT_ALL;
+   rdev->raw_fifo_size = RX_BUF_LEN;
rdev->open = nvt_open;
rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
-- 
2.8.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/2] media: rc: make fifo size for raw events configurable via rc_dev

2016-05-19 Thread Heiner Kallweit
Currently the fifo size is 512 elements. After a recent patch the size
of struct ir_raw_event is down to 8 bytes, so the fifo still consumes
4KB. In most cases a much smaller fifo is sufficient, e.g. nuvoton-cir
triggers event processing after 24 events latest.

This patch introduces an element raw_fifo_size to struct rc_dev to
allow configuring the fifo size. If not set the current default
MAX_IR_EVENT_SIZE is used.

Signed-off-by: Heiner Kallweit 
---
v2:
- access dev->raw_fifo_size only after check for !dev
---
 drivers/media/rc/rc-core-priv.h |  2 +-
 drivers/media/rc/rc-ir-raw.c| 14 --
 include/media/rc-core.h |  2 ++
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 585d5e5..ae6f81e 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -39,7 +39,7 @@ struct ir_raw_event_ctrl {
struct task_struct  *thread;
spinlock_t  lock;
/* fifo for the pulse/space durations */
-   DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE);
+   DECLARE_KFIFO_PTR(kfifo, struct ir_raw_event);
ktime_t last_event; /* when last event 
occurred */
enum raw_event_type last_type;  /* last event type */
struct rc_dev   *dev;   /* pointer to the 
parent rc_dev */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 144304c..f9b7734 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -261,17 +261,24 @@ int ir_raw_event_register(struct rc_dev *dev)
 {
int rc;
struct ir_raw_handler *handler;
+   unsigned fifo_size = MAX_IR_EVENT_SIZE;
 
if (!dev)
return -EINVAL;
 
+   if (dev->raw_fifo_size)
+   fifo_size = dev->raw_fifo_size;
+
dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
if (!dev->raw)
return -ENOMEM;
 
dev->raw->dev = dev;
dev->change_protocol = change_protocol;
-   INIT_KFIFO(dev->raw->kfifo);
+
+   rc = kfifo_alloc(&dev->raw->kfifo, fifo_size, GFP_KERNEL);
+   if (rc)
+   goto out;
 
spin_lock_init(&dev->raw->lock);
dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
@@ -279,7 +286,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
if (IS_ERR(dev->raw->thread)) {
rc = PTR_ERR(dev->raw->thread);
-   goto out;
+   goto out_kfifo;
}
 
mutex_lock(&ir_raw_handler_lock);
@@ -291,6 +298,8 @@ int ir_raw_event_register(struct rc_dev *dev)
 
return 0;
 
+out_kfifo:
+   kfifo_free(&dev->raw->kfifo);
 out:
kfree(dev->raw);
dev->raw = NULL;
@@ -313,6 +322,7 @@ void ir_raw_event_unregister(struct rc_dev *dev)
handler->raw_unregister(dev);
mutex_unlock(&ir_raw_handler_lock);
 
+   kfifo_free(&dev->raw->kfifo);
kfree(dev->raw);
dev->raw = NULL;
 }
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index f6f55b7..07e096b 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -72,6 +72,7 @@ enum rc_filter_type {
  * anyone can call show_protocols or store_protocols
  * @minor: unique minor remote control device number
  * @raw: additional data for raw pulse/space devices
+ * @raw_fifo_size: size of fifo for raw events
  * @input_dev: the input child device used to communicate events to userspace
  * @driver_type: specifies if protocol decoding is done in hardware or software
  * @idle: used to keep track of RX state
@@ -133,6 +134,7 @@ struct rc_dev {
struct mutexlock;
unsigned intminor;
struct ir_raw_event_ctrl*raw;
+   unsignedraw_fifo_size;
struct input_dev*input_dev;
enum rc_driver_type driver_type;
boolidle;
-- 
2.8.2


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: nuvoton: decrease size of raw event fifo

2016-05-18 Thread Heiner Kallweit
This chip has a 32 byte HW FIFO only. Therefore the default fifo size
of 512 raw events is not needed and can be significantly decreased.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 99b303b..e98c955 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1186,6 +1186,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
rdev->priv = nvt;
rdev->driver_type = RC_DRIVER_IR_RAW;
rdev->allowed_protocols = RC_BIT_ALL;
+   rdev->raw_fifo_size = RX_BUF_LEN;
rdev->open = nvt_open;
rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
-- 
2.8.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: make fifo size for raw events configurable via rc_dev

2016-05-18 Thread Heiner Kallweit
Currently the fifo size is 512 elements. After a recent patch the size
of struct ir_raw_event is down to 8 bytes, so the fifo still consumes
4KB. In most cases a much smaller fifo is sufficient, e.g. nuvoton-cir
triggers event processing after 24 events latest.

This patch introduces an element raw_fifo_size to struct rc_dev to
allow configuring the fifo size. If not set the current default
MAX_IR_EVENT_SIZE is used.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-core-priv.h |  2 +-
 drivers/media/rc/rc-ir-raw.c| 11 +--
 include/media/rc-core.h |  2 ++
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 585d5e5..ae6f81e 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -39,7 +39,7 @@ struct ir_raw_event_ctrl {
struct task_struct  *thread;
spinlock_t  lock;
/* fifo for the pulse/space durations */
-   DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE);
+   DECLARE_KFIFO_PTR(kfifo, struct ir_raw_event);
ktime_t last_event; /* when last event 
occurred */
enum raw_event_type last_type;  /* last event type */
struct rc_dev   *dev;   /* pointer to the 
parent rc_dev */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 144304c..96270f1 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -261,6 +261,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 {
int rc;
struct ir_raw_handler *handler;
+   unsigned fifo_size = dev->raw_fifo_size ?: MAX_IR_EVENT_SIZE;
 
if (!dev)
return -EINVAL;
@@ -271,7 +272,10 @@ int ir_raw_event_register(struct rc_dev *dev)
 
dev->raw->dev = dev;
dev->change_protocol = change_protocol;
-   INIT_KFIFO(dev->raw->kfifo);
+
+   rc = kfifo_alloc(&dev->raw->kfifo, fifo_size, GFP_KERNEL);
+   if (rc)
+   goto out;
 
spin_lock_init(&dev->raw->lock);
dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
@@ -279,7 +283,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
if (IS_ERR(dev->raw->thread)) {
rc = PTR_ERR(dev->raw->thread);
-   goto out;
+   goto out_kfifo;
}
 
mutex_lock(&ir_raw_handler_lock);
@@ -291,6 +295,8 @@ int ir_raw_event_register(struct rc_dev *dev)
 
return 0;
 
+out_kfifo:
+   kfifo_free(&dev->raw->kfifo);
 out:
kfree(dev->raw);
dev->raw = NULL;
@@ -313,6 +319,7 @@ void ir_raw_event_unregister(struct rc_dev *dev)
handler->raw_unregister(dev);
mutex_unlock(&ir_raw_handler_lock);
 
+   kfifo_free(&dev->raw->kfifo);
kfree(dev->raw);
dev->raw = NULL;
 }
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index f6f55b7..07e096b 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -72,6 +72,7 @@ enum rc_filter_type {
  * anyone can call show_protocols or store_protocols
  * @minor: unique minor remote control device number
  * @raw: additional data for raw pulse/space devices
+ * @raw_fifo_size: size of fifo for raw events
  * @input_dev: the input child device used to communicate events to userspace
  * @driver_type: specifies if protocol decoding is done in hardware or software
  * @idle: used to keep track of RX state
@@ -133,6 +134,7 @@ struct rc_dev {
struct mutexlock;
unsigned intminor;
struct ir_raw_event_ctrl*raw;
+   unsignedraw_fifo_size;
struct input_dev*input_dev;
enum rc_driver_type driver_type;
boolidle;
-- 
2.8.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: rc: remove unneeded mutex in rc_register_device

2016-03-20 Thread Heiner Kallweit
Am 16.03.2016 um 20:33 schrieb Vladimir Zapolskiy:
> On 16.03.2016 20:53, Heiner Kallweit wrote:
>> Access to dev->initialized is atomic, therefore we don't have to
>> protect it with a mutex.
> 
> Mutexes are used to split the code to mutually exclusive execution blocks,
> so not arguing about the apparently correct change itself I want to
> emphasize that the given explanation of the change in the commit message is
> wrong. Atomic access does not cancel a specific care about execution
> ordering.
> 
> Indirectly it applies to ("rc-core: allow calling rc_open with device not
> initialized"), where "initialized" bool property was changed to atomic_t
> type --- this (sub-)change is just useless.
> 
> Please grasp the topic and reword the commit message.
> 
Thanks for the hint, you're right.
Will change the commit message and send a v2.

Regards, Heiner

>> Signed-off-by: Heiner Kallweit 
>> ---
>>  drivers/media/rc/rc-main.c | 2 --
>>  1 file changed, 2 deletions(-)
>>
>> diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
>> index 4e9bbe7..68541b1 100644
>> --- a/drivers/media/rc/rc-main.c
>> +++ b/drivers/media/rc/rc-main.c
>> @@ -1492,9 +1492,7 @@ int rc_register_device(struct rc_dev *dev)
>>  }
>>  
>>  /* Allow the RC sysfs nodes to be accessible */
>> -mutex_lock(&dev->lock);
>>  atomic_set(&dev->initialized, 1);
>> -mutex_unlock(&dev->lock);
>>  
>>  IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
>> dev->minor,
>>
> 
> --
> With best wishes,
> Vladimir
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: reduce size of struct ir_raw_event

2016-03-19 Thread Heiner Kallweit
struct ir_raw_event currently has a size of 12 bytes on most (all?)
architectures. This can be reduced to 8 bytes whilst maintaining
full backwards compatibility.
This saves 2KB in size of struct ir_raw_event_ctrl (as element
kfifo is reduced by 512 * 4 bytes) and it allows to copy the
full struct ir_raw_event with a single 64 bit operation.

Successfully tested with the Nuvoton driver and successfully
compile-tested with the ene_ir driver (as it uses the carrier /
duty_cycle elements).

Signed-off-by: Heiner Kallweit 
---
 include/media/rc-core.h | 26 --
 1 file changed, 8 insertions(+), 18 deletions(-)

diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 0f77b3d..b8f27c9 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -214,27 +214,17 @@ enum raw_event_type {
 
 struct ir_raw_event {
union {
-   u32 duration;
-
-   struct {
-   u32 carrier;
-   u8  duty_cycle;
-   };
+   u32 duration;
+   u32 carrier;
};
-
-   unsignedpulse:1;
-   unsignedreset:1;
-   unsignedtimeout:1;
-   unsignedcarrier_report:1;
+   u8  duty_cycle;
+   u8  pulse:1;
+   u8  reset:1;
+   u8  timeout:1;
+   u8  carrier_report:1;
 };
 
-#define DEFINE_IR_RAW_EVENT(event) \
-   struct ir_raw_event event = { \
-   { .duration = 0 } , \
-   .pulse = 0, \
-   .reset = 0, \
-   .timeout = 0, \
-   .carrier_report = 0 }
+#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {}
 
 static inline void init_ir_raw_event(struct ir_raw_event *ev)
 {
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: remove unneeded mutex in rc_register_device

2016-03-19 Thread Heiner Kallweit
Access to dev->initialized is atomic, therefore we don't have to
protect it with a mutex.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 4e9bbe7..68541b1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1492,9 +1492,7 @@ int rc_register_device(struct rc_dev *dev)
}
 
/* Allow the RC sysfs nodes to be accessible */
-   mutex_lock(&dev->lock);
atomic_set(&dev->initialized, 1);
-   mutex_unlock(&dev->lock);
 
IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
   dev->minor,
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: rc: reduce size of struct ir_raw_event

2016-03-19 Thread Heiner Kallweit
Am 17.03.2016 um 11:53 schrieb Sean Young:
> On Thu, Mar 17, 2016 at 07:40:59AM +0100, Heiner Kallweit wrote:
>> Am 16.03.2016 um 23:28 schrieb Sean Young:
>>> On Wed, Mar 16, 2016 at 10:18:38PM +0100, Heiner Kallweit wrote:
>>>> +  u8  pulse:1;
>>>> +  u8  reset:1;
>>>> +  u8  timeout:1;
>>>> +  u8  carrier_report:1;
>>>
>>> Why are you changing the type of the bitfields? 
>>>
>> I did this to make sure that the compiler uses one byte for
>> the bit field. When testing gcc also used just one byte when
>> keeping the original "unsigned" type for the bit field members.
>> Therefore it wouldn't be strictly neeeded.
>>
>> But I'm not sure whether it's guaranteed that the compiler packs a
>> bit field to the smallest possible data type and we can rely on it.
>> AFAIK C99 is a little more specific about this implementation detail of
>> bit fields but C89/C90 is used for kernel compilation.
> 
> It might be worth reading about structure packing rules rather than
> guessing.
> 
Whenever it became interesting when reading the statement was:
unspecified / implementation-dependent.
But at least C90 clearly states that only signed / unsigned int are
acceptable for bit fields. Therefore leave the bit field as it is.
I will provide a v2.

Heiner
> 
> Sean
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] media: rc: remove unneeded mutex in rc_register_device

2016-03-19 Thread Heiner Kallweit
Access to dev->initialized is atomic and dev->initialized isn't
accessed in any other code protected by this mutex.
Therefore we don't need to get the mutex here.

Signed-off-by: Heiner Kallweit 
---
v2:
- corrected commit message
---
 drivers/media/rc/rc-main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 4e9bbe7..68541b1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1492,9 +1492,7 @@ int rc_register_device(struct rc_dev *dev)
}
 
/* Allow the RC sysfs nodes to be accessible */
-   mutex_lock(&dev->lock);
atomic_set(&dev->initialized, 1);
-   mutex_unlock(&dev->lock);
 
IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
   dev->minor,
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] media: rc: reduce size of struct ir_raw_event

2016-03-18 Thread Heiner Kallweit
struct ir_raw_event currently has a size of 12 bytes on most (all?)
architectures. This can be reduced to 8 bytes whilst maintaining
full backwards compatibility.
This saves 2KB in size of struct ir_raw_event_ctrl (as element
kfifo is reduced by 512 * 4 bytes) and it allows to copy the
full struct ir_raw_event with a single 64 bit operation.

Successfully tested with the Nuvoton driver and successfully
compile-tested with the ene_ir driver (as it uses the carrier /
duty_cycle elements).

Signed-off-by: Heiner Kallweit 
---
v2:
- don't change type of bit field members
---
 include/media/rc-core.h | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 0f77b3d..f6f55b7 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -215,12 +215,9 @@ enum raw_event_type {
 struct ir_raw_event {
union {
u32 duration;
-
-   struct {
-   u32 carrier;
-   u8  duty_cycle;
-   };
+   u32 carrier;
};
+   u8  duty_cycle;
 
unsignedpulse:1;
unsignedreset:1;
@@ -228,13 +225,7 @@ struct ir_raw_event {
unsignedcarrier_report:1;
 };
 
-#define DEFINE_IR_RAW_EVENT(event) \
-   struct ir_raw_event event = { \
-   { .duration = 0 } , \
-   .pulse = 0, \
-   .reset = 0, \
-   .timeout = 0, \
-   .carrier_report = 0 }
+#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {}
 
 static inline void init_ir_raw_event(struct ir_raw_event *ev)
 {
@@ -256,8 +247,7 @@ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
 
 static inline void ir_raw_event_reset(struct rc_dev *dev)
 {
-   DEFINE_IR_RAW_EVENT(ev);
-   ev.reset = true;
+   struct ir_raw_event ev = { .reset = true };
 
ir_raw_event_store(dev, &ev);
ir_raw_event_handle(dev);
-- 
2.7.3


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: rc: reduce size of struct ir_raw_event

2016-03-18 Thread Heiner Kallweit
Am 16.03.2016 um 23:28 schrieb Sean Young:
> On Wed, Mar 16, 2016 at 10:18:38PM +0100, Heiner Kallweit wrote:
>> struct ir_raw_event currently has a size of 12 bytes on most (all?)
>> architectures. This can be reduced to 8 bytes whilst maintaining
>> full backwards compatibility.
>> This saves 2KB in size of struct ir_raw_event_ctrl (as element
>> kfifo is reduced by 512 * 4 bytes) and it allows to copy the
>> full struct ir_raw_event with a single 64 bit operation.
>>
>> Successfully tested with the Nuvoton driver and successfully
>> compile-tested with the ene_ir driver (as it uses the carrier /
>> duty_cycle elements).
>>
>> Signed-off-by: Heiner Kallweit 
>> ---
>>  include/media/rc-core.h | 26 --
>>  1 file changed, 8 insertions(+), 18 deletions(-)
>>
>> diff --git a/include/media/rc-core.h b/include/media/rc-core.h
>> index 0f77b3d..b8f27c9 100644
>> --- a/include/media/rc-core.h
>> +++ b/include/media/rc-core.h
>> @@ -214,27 +214,17 @@ enum raw_event_type {
>>  
>>  struct ir_raw_event {
>>  union {
>> -u32 duration;
>> -
>> -struct {
>> -u32 carrier;
>> -u8  duty_cycle;
>> -};
>> +u32 duration;
>> +u32 carrier;
>>  };
>> -
>> -unsignedpulse:1;
>> -unsignedreset:1;
>> -unsignedtimeout:1;
>> -unsignedcarrier_report:1;
>> +u8  duty_cycle;
> 
> Moving duty_cycle does indeed reduce the structure size from 12 to 8.
> 
>> +u8  pulse:1;
>> +u8  reset:1;
>> +u8  timeout:1;
>> +u8  carrier_report:1;
> 
> Why are you changing the type of the bitfields? 
> 
I did this to make sure that the compiler uses one byte for
the bit field. When testing gcc also used just one byte when
keeping the original "unsigned" type for the bit field members.
Therefore it wouldn't be strictly neeeded.

But I'm not sure whether it's guaranteed that the compiler packs a
bit field to the smallest possible data type and we can rely on it.
AFAIK C99 is a little more specific about this implementation detail of
bit fields but C89/C90 is used for kernel compilation.

Heiner

>>  };
>>  
>> -#define DEFINE_IR_RAW_EVENT(event) \
>> -struct ir_raw_event event = { \
>> -{ .duration = 0 } , \
>> -.pulse = 0, \
>> -.reset = 0, \
>> -.timeout = 0, \
>> -.carrier_report = 0 }
>> +#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {}
> 
> Seems fine. I've always kinda wondered why this macro is needed.
> 
> 
> Sean
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


media: rc: make raw event fifo size a module parameter

2016-03-18 Thread Heiner Kallweit
Currently the fifo size is 512 elements. After a recent patch the size
of struct ir_raw_event is down to 8 bytes, so the fifo still consumes
4KB. In most cases a much smaller fifo is sufficient, e.g. nuvoton-cir
triggers event processing after 24 events latest. However the needed
fifo size may also depend on system performance.

Therefore make the fifo size a module parameter with the current value
of 512 being the default.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-core-priv.h |  2 +-
 drivers/media/rc/rc-ir-raw.c| 20 +---
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 585d5e5..ae6f81e 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -39,7 +39,7 @@ struct ir_raw_event_ctrl {
struct task_struct  *thread;
spinlock_t  lock;
/* fifo for the pulse/space durations */
-   DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE);
+   DECLARE_KFIFO_PTR(kfifo, struct ir_raw_event);
ktime_t last_event; /* when last event 
occurred */
enum raw_event_type last_type;  /* last event type */
struct rc_dev   *dev;   /* pointer to the 
parent rc_dev */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 144304c..620b036 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "rc-core-priv.h"
 
 /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
@@ -28,6 +29,9 @@ static DEFINE_MUTEX(ir_raw_handler_lock);
 static LIST_HEAD(ir_raw_handler_list);
 static u64 available_protocols;
 
+/* module param */
+static unsigned int ir_raw_event_fifo_size = MAX_IR_EVENT_SIZE;
+
 static int ir_raw_event_thread(void *data)
 {
struct ir_raw_event ev;
@@ -262,7 +266,7 @@ int ir_raw_event_register(struct rc_dev *dev)
int rc;
struct ir_raw_handler *handler;
 
-   if (!dev)
+   if (!dev || !ir_raw_event_fifo_size)
return -EINVAL;
 
dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
@@ -271,7 +275,10 @@ int ir_raw_event_register(struct rc_dev *dev)
 
dev->raw->dev = dev;
dev->change_protocol = change_protocol;
-   INIT_KFIFO(dev->raw->kfifo);
+
+   rc = kfifo_alloc(&dev->raw->kfifo, ir_raw_event_fifo_size, GFP_KERNEL);
+   if (rc)
+   goto out;
 
spin_lock_init(&dev->raw->lock);
dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
@@ -279,7 +286,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
if (IS_ERR(dev->raw->thread)) {
rc = PTR_ERR(dev->raw->thread);
-   goto out;
+   goto out_kfifo;
}
 
mutex_lock(&ir_raw_handler_lock);
@@ -291,6 +298,8 @@ int ir_raw_event_register(struct rc_dev *dev)
 
return 0;
 
+out_kfifo:
+   kfifo_free(&dev->raw->kfifo);
 out:
kfree(dev->raw);
dev->raw = NULL;
@@ -313,6 +322,7 @@ void ir_raw_event_unregister(struct rc_dev *dev)
handler->raw_unregister(dev);
mutex_unlock(&ir_raw_handler_lock);
 
+   kfifo_free(&dev->raw->kfifo);
kfree(dev->raw);
dev->raw = NULL;
 }
@@ -353,3 +363,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler)
mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
+
+module_param_named(fifo_size, ir_raw_event_fifo_size, uint, S_IRUGO);
+MODULE_PARM_DESC(fifo_size,
+   "raw event fifo size, will be rounded up to next power of 2");
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: nuvoton: switch attribute wakeup_data to text

2016-03-04 Thread Heiner Kallweit
Switch attribute wakeup_data from binary to a text attribute.
This makes it easier to handle in userspace and allows to
use the output of tools like mode2 almost as is to set a
wakeup sequence.
Changing to a text format and values in microseconds also
makes the userspace interface independent of the setting of
SAMPLE_PERIOD in the driver.

In addition document the new sysfs attribute in
Documentation/ABI/testing/sysfs-class-rc-nuvoton.

Signed-off-by: Heiner Kallweit 
---
 Documentation/ABI/testing/sysfs-class-rc-nuvoton | 15 +
 drivers/media/rc/nuvoton-cir.c   | 85 +++-
 2 files changed, 68 insertions(+), 32 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rc-nuvoton

diff --git a/Documentation/ABI/testing/sysfs-class-rc-nuvoton 
b/Documentation/ABI/testing/sysfs-class-rc-nuvoton
new file mode 100644
index 000..905bcde
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rc-nuvoton
@@ -0,0 +1,15 @@
+What:  /sys/class/rc/rcN/wakeup_data
+Date:  Mar 2016
+KernelVersion: 4.6
+Contact:   Mauro Carvalho Chehab 
+Description:
+   Reading this file returns the stored CIR wakeup sequence.
+   It starts with a pulse, followed by a space, pulse etc.
+   All values are in microseconds.
+   The same format can be used to store a wakeup sequence
+   in the Nuvoton chip by writing to this file.
+
+   Note: Some systems reset the stored wakeup sequence to a
+   factory default on each boot. On such systems store the
+   wakeup sequence in a file and set it on boot using e.g.
+   a udev rule.
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c2ee5bd..99b303b 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -179,55 +179,74 @@ static void nvt_set_ioaddr(struct nvt_dev *nvt, unsigned 
long *ioaddr)
}
 }
 
-static ssize_t wakeup_data_read(struct file *fp, struct kobject *kobj,
-   struct bin_attribute *bin_attr,
-   char *buf, loff_t off, size_t count)
+static ssize_t wakeup_data_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
 {
-   struct device *dev = kobj_to_dev(kobj);
struct rc_dev *rc_dev = to_rc_dev(dev);
struct nvt_dev *nvt = rc_dev->priv;
-   int fifo_len, len;
+   int fifo_len, duration;
unsigned long flags;
+   ssize_t buf_len = 0;
int i;
 
spin_lock_irqsave(&nvt->nvt_lock, flags);
 
fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
-   len = min(fifo_len, WAKEUP_MAX_SIZE);
-
-   if (off >= len) {
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-   return 0;
-   }
-
-   if (len > count)
-   len = count;
+   fifo_len = min(fifo_len, WAKEUP_MAX_SIZE);
 
/* go to first element to be read */
-   while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX) != off)
+   while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX))
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
 
-   for (i = 0; i < len; i++)
-   buf[i] = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
+   for (i = 0; i < fifo_len; i++) {
+   duration = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
+   duration = (duration & BUF_LEN_MASK) * SAMPLE_PERIOD;
+   buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len,
+   "%d ", duration);
+   }
+   buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, "\n");
 
spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 
-   return len;
+   return buf_len;
 }
 
-static ssize_t wakeup_data_write(struct file *fp, struct kobject *kobj,
-   struct bin_attribute *bin_attr,
-   char *buf, loff_t off, size_t count)
+static ssize_t wakeup_data_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t len)
 {
-   struct device *dev = kobj_to_dev(kobj);
struct rc_dev *rc_dev = to_rc_dev(dev);
struct nvt_dev *nvt = rc_dev->priv;
unsigned long flags;
-   u8 tolerance, config;
-   int i;
+   u8 tolerance, config, wake_buf[WAKEUP_MAX_SIZE];
+   char **argv;
+   int i, count;
+   unsigned int val;
+   ssize_t ret;
+
+   argv = argv_split(GFP_KERNEL, buf, &count);
+   if (!argv)
+   return -ENOMEM;
+   if (!count || count > WAKEUP_MAX_SIZE) {
+   ret = -EINVAL;
+   goto out;
+   }
 
-   if (off > 0)
-   

Re: [git:media_tree/master] [media] media: rc: nuvoton: support reading / writing wakeup sequence via sysfs

2016-03-03 Thread Heiner Kallweit
Am 03.03.2016 um 21:56 schrieb Mauro Carvalho Chehab:
> Em Thu, 03 Mar 2016 20:22:35 +0100
> Heiner Kallweit  escreveu:
> 
>> Am 03.03.2016 um 19:52 schrieb Mauro Carvalho Chehab:
>>> Em Thu, 03 Mar 2016 19:18:17 +0100
>>> Heiner Kallweit  escreveu:
>>>   
>>>> Am 03.03.2016 um 12:28 schrieb Mauro Carvalho Chehab:  
>>>>> This is an automatic generated email to let you know that the following 
>>>>> patch were queued at the 
>>>>> http://git.linuxtv.org/cgit.cgi/media_tree.git tree:
>>>>>
>>>>> Subject: [media] media: rc: nuvoton: support reading / writing wakeup 
>>>>> sequence via sysfs
>>>>> Author:  Heiner Kallweit 
>>>>> Date:Mon Feb 8 17:25:59 2016 -0200
>>>>>
>>>>> This patch adds a binary attribute /sys/class/rc/rc?/wakeup_data which
>>>>> allows to read / write the wakeup sequence.
>>>>> 
>>>> When working on another module I was reminded not to forget updating 
>>>> Documentation/ABI.
>>>> I think the same applies here. This patch introduces a new sysfs attribute 
>>>> that should
>>>> be documented. I'll submit a patch for adding 
>>>> Documentation/ABI/testing/sysfs-class-rc-nuvoton  
>>>
>>> Good point.
>>>
>>> Another thing: wouldn't be better to use a text format? This would make
>>> esier to import from LIRC's irrecord format:
>>>
>>>   begin raw_codes
>>>
>>>   name power
>>>   850 90017501800 850 900
>>>   850 9001750 900 8501800
>>>   850 900 850 900 850 900
>>>  17501800 800
>>>
>>>   end raw_codes
>>>
>>> Regards,
>>> Mauro
>>>   
>> Most likely this is possible, but it would mean that we need a parser / 
>> generator
>> for this text format in the driver / kernel code. And I have my doubts that 
>> parsing
>> an application-specific file format (that could change anytime) in kernel 
>> code is
>> a good thing. Converting this format to raw binary data is better off in 
>> userspace
>> I think. What's your opinion?
> 
> I'm not telling that it should parse irrecord format, but, instead, to
> accept an ascii sequence of timings. The problem with raw binary data
> is that the format varies on big endian and long endian architectures,
> with doesn't seem to be nice to an API, as a data sequence recorded
> on one machine may not work on some other one.
> 
The Nuvoton wakeup sequence is a number of bytes (bit 7 = pulse/space indicator,
bit 6..0 = length / 50us). It doesn't include any multi-byte numbers.
Therefore endianness doesn't affect us.
However I also like the idea of having a text format with pulses / spaces in us.
(as that's what utilities like mode2 display) It's easier for the user to deal 
with.
I'll prepare an alternative patch using such a text format.

>>
>>>>
>>>> Rgds, Heiner
>>>>  
>>>>> In combination with the core extension for exposing the most recent raw
>>>>> packet this allows to easily define and set a wakeup sequence.
>>>>>
>>>>> At least on my Zotac CI321 the BIOS resets the wakeup sequence at each 
>>>>> boot
>>>>> to a factory default. Therefore I use a udev rule
>>>>> SUBSYSTEM=="rc", DRIVERS=="nuvoton-cir", ACTION=="add", RUN+="

Re: [git:media_tree/master] [media] media: rc: nuvoton: support reading / writing wakeup sequence via sysfs

2016-03-03 Thread Heiner Kallweit
Am 03.03.2016 um 19:52 schrieb Mauro Carvalho Chehab:
> Em Thu, 03 Mar 2016 19:18:17 +0100
> Heiner Kallweit  escreveu:
> 
>> Am 03.03.2016 um 12:28 schrieb Mauro Carvalho Chehab:
>>> This is an automatic generated email to let you know that the following 
>>> patch were queued at the 
>>> http://git.linuxtv.org/cgit.cgi/media_tree.git tree:
>>>
>>> Subject: [media] media: rc: nuvoton: support reading / writing wakeup 
>>> sequence via sysfs
>>> Author:  Heiner Kallweit 
>>> Date:Mon Feb 8 17:25:59 2016 -0200
>>>
>>> This patch adds a binary attribute /sys/class/rc/rc?/wakeup_data which
>>> allows to read / write the wakeup sequence.
>>>   
>> When working on another module I was reminded not to forget updating 
>> Documentation/ABI.
>> I think the same applies here. This patch introduces a new sysfs attribute 
>> that should
>> be documented. I'll submit a patch for adding 
>> Documentation/ABI/testing/sysfs-class-rc-nuvoton
> 
> Good point.
> 
> Another thing: wouldn't be better to use a text format? This would make
> esier to import from LIRC's irrecord format:
> 
>   begin raw_codes
> 
>   name power
>   850 90017501800 850 900
>   850 9001750 900 8501800
>   850 900 850 900 850 900
>  17501800 800
> 
>   end raw_codes
> 
> Regards,
> Mauro
> 
Most likely this is possible, but it would mean that we need a parser / 
generator
for this text format in the driver / kernel code. And I have my doubts that 
parsing
an application-specific file format (that could change anytime) in kernel code 
is
a good thing. Converting this format to raw binary data is better off in 
userspace
I think. What's your opinion?

>>
>> Rgds, Heiner
>>
>>> In combination with the core extension for exposing the most recent raw
>>> packet this allows to easily define and set a wakeup sequence.
>>>
>>> At least on my Zotac CI321 the BIOS resets the wakeup sequence at each boot
>>> to a factory default. Therefore I use a udev rule
>>> SUBSYSTEM=="rc", DRIVERS=="nuvoton-cir", ACTION=="add", RUN+="

Re: [git:media_tree/master] [media] media: rc: nuvoton: support reading / writing wakeup sequence via sysfs

2016-03-03 Thread Heiner Kallweit
Am 03.03.2016 um 12:28 schrieb Mauro Carvalho Chehab:
> This is an automatic generated email to let you know that the following patch 
> were queued at the 
> http://git.linuxtv.org/cgit.cgi/media_tree.git tree:
> 
> Subject: [media] media: rc: nuvoton: support reading / writing wakeup 
> sequence via sysfs
> Author:  Heiner Kallweit 
> Date:Mon Feb 8 17:25:59 2016 -0200
> 
> This patch adds a binary attribute /sys/class/rc/rc?/wakeup_data which
> allows to read / write the wakeup sequence.
> 
When working on another module I was reminded not to forget updating 
Documentation/ABI.
I think the same applies here. This patch introduces a new sysfs attribute that 
should
be documented. I'll submit a patch for adding 
Documentation/ABI/testing/sysfs-class-rc-nuvoton

Rgds, Heiner

> In combination with the core extension for exposing the most recent raw
> packet this allows to easily define and set a wakeup sequence.
> 
> At least on my Zotac CI321 the BIOS resets the wakeup sequence at each boot
> to a factory default. Therefore I use a udev rule
> SUBSYSTEM=="rc", DRIVERS=="nuvoton-cir", ACTION=="add", RUN+="

[PATCH 07/16] media: rc: nuvoton-cir: fix setting ioport base address

2015-12-30 Thread Heiner Kallweit
At least on Zotac CI321 ACPI provides an ioport range for the wake up part
but accessing these ioports has no effect.
Instead the ioport base address is set to another value already
(0xa20 in my case) and accessing this ioport range works.

Therefore set a new ioport base address only if the current ioport base
address is 0 (register reset default).

The need to use the existing base address instead of trying to set
an own one doesn't seem to be limited to this specific device as other
drivers like hwmon/nct6775 do it the same way.

This change was successfully tested on the mentioned device.
And the change should be generic enough to not break the driver for
other chips (however due to lack of appropriate hardware I wasn't
able to test this).

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index f624851..342e21d 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -161,6 +161,22 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 
offset)
return val;
 }
 
+/* don't override io address if one is set already */
+static void nvt_set_ioaddr(struct nvt_dev *nvt, unsigned long *ioaddr)
+{
+   unsigned long old_addr;
+
+   old_addr = nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8;
+   old_addr |= nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO);
+
+   if (old_addr)
+   *ioaddr = old_addr;
+   else {
+   nvt_cr_write(nvt, *ioaddr >> 8, CR_CIR_BASE_ADDR_HI);
+   nvt_cr_write(nvt, *ioaddr & 0xff, CR_CIR_BASE_ADDR_LO);
+   }
+}
+
 /* dump current cir register contents */
 static void cir_dump_regs(struct nvt_dev *nvt)
 {
@@ -333,8 +349,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt)
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
 
-   nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI);
-   nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO);
+   nvt_set_ioaddr(nvt, &nvt->cir_addr);
 
nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC);
 
@@ -358,8 +373,7 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
 
-   nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI);
-   nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO);
+   nvt_set_ioaddr(nvt, &nvt->cir_wake_addr);
 
nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC);
 
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/16] media: rc: nuvoton-cir: fix wakeup interrupt bits

2015-12-30 Thread Heiner Kallweit
Most likely a copy & paste error.
The wakeup interrupt supports less triggering events.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.h | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 48c09c7..4a5650d 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -293,10 +293,7 @@ struct nvt_dev {
 #define CIR_WAKE_IREN_RTR  0x40
 #define CIR_WAKE_IREN_PE   0x20
 #define CIR_WAKE_IREN_RFO  0x10
-#define CIR_WAKE_IREN_TE   0x08
-#define CIR_WAKE_IREN_TTR  0x04
-#define CIR_WAKE_IREN_TFU  0x02
-#define CIR_WAKE_IREN_GH   0x01
+#define CIR_WAKE_IREN_GH   0x08
 
 /* CIR WAKE FIFOCON settings */
 #define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/16] media: rc: nuvoton-cir: add locking to calls of nvt_enable_wake

2015-12-30 Thread Heiner Kallweit
Add locking to nvt_enable_wake calls.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 252804d..c3294fb 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1173,16 +1173,16 @@ static int nvt_suspend(struct pnp_dev *pdev, 
pm_message_t state)
 
nvt_dbg("%s called", __func__);
 
-   /* zero out misc state tracking */
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
-   nvt->study_state = ST_STUDY_NONE;
-   nvt->wake_state = ST_WAKE_NONE;
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
spin_lock_irqsave(&nvt->tx.lock, flags);
nvt->tx.tx_state = ST_TX_NONE;
spin_unlock_irqrestore(&nvt->tx.lock, flags);
 
+   spin_lock_irqsave(&nvt->nvt_lock, flags);
+
+   /* zero out misc state tracking */
+   nvt->study_state = ST_STUDY_NONE;
+   nvt->wake_state = ST_WAKE_NONE;
+
/* disable all CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
 
@@ -1192,6 +1192,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t 
state)
/* make sure wake is enabled */
nvt_enable_wake(nvt);
 
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
return 0;
 }
 
@@ -1210,7 +1212,11 @@ static int nvt_resume(struct pnp_dev *pdev)
 static void nvt_shutdown(struct pnp_dev *pdev)
 {
struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+   unsigned long flags;
+
+   spin_lock_irqsave(&nvt->nvt_lock, flags);
nvt_enable_wake(nvt);
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 }
 
 static const struct pnp_device_id nvt_ids[] = {
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 16/16] media: rc: nuvoton-cir: improve locking in both interrupt handlers

2015-12-30 Thread Heiner Kallweit
Extend the locking to protect more critical actions like register accesses
in the interrupt handlers.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c0bee1e..b6acc84 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -727,7 +727,6 @@ static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
 /* copy data from hardware rx fifo into driver buffer */
 static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 {
-   unsigned long flags;
u8 fifocount, val;
unsigned int b_idx;
bool overrun = false;
@@ -746,8 +745,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 
nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
-
b_idx = nvt->pkts;
 
/* This should never happen, but lets check anyway... */
@@ -769,8 +766,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
 
if (overrun)
nvt_handle_rx_fifo_overrun(nvt);
-
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 }
 
 static void nvt_cir_log_irqs(u8 status, u8 iren)
@@ -811,6 +806,8 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 
nvt_dbg_verbose("%s firing", __func__);
 
+   spin_lock_irqsave(&nvt->nvt_lock, flags);
+
/*
 * Get IR Status register contents. Write 1 to ack/clear
 *
@@ -831,6 +828,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 * status bit whether the related interrupt source is enabled
 */
if (!(status & iren)) {
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
return IRQ_NONE;
}
@@ -852,16 +850,14 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
if (nvt_cir_tx_inactive(nvt))
nvt_get_rx_ir_data(nvt);
 
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
-
cur_state = nvt->study_state;
 
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
if (cur_state == ST_STUDY_NONE)
nvt_clear_cir_fifo(nvt);
}
 
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
if (status & CIR_IRSTS_TE)
nvt_clear_tx_fifo(nvt);
 
@@ -910,14 +906,18 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
 
nvt_dbg_wake("%s firing", __func__);
 
+   spin_lock_irqsave(&nvt->nvt_lock, flags);
+
status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
 
/* IRQ may be shared with CIR, therefore check for each
 * status bit whether the related interrupt source is enabled
 */
-   if (!(status & iren))
+   if (!(status & iren)) {
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
return IRQ_NONE;
+   }
 
if (status & CIR_WAKE_IRSTS_IR_PENDING)
nvt_clear_cir_wake_fifo(nvt);
@@ -933,11 +933,11 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
}
 
nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
-   spin_lock_irqsave(&nvt->nvt_lock, flags);
nvt->wake_state = ST_WAKE_FINISH;
-   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
}
 
+   spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
nvt_dbg_wake("%s done", __func__);
return IRQ_HANDLED;
 }
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/16] media: rc: nuvoton-cir: fix interrupt handling

2015-12-30 Thread Heiner Kallweit
Only handle an interrupt if at least one combination of event bit
and related interrupt bit is set.
Previously it was just checked that at least one event bit and
at least one interrupt bit are set.

This fixes issues like the following which was caused by
interrupt sharing:
An interrupt intended for nvt_cir_isr was handled by nvt_cir_wake_isr
first and because status bit CIR_WAKE_IRSTS_IR_PENDING was set
the wake fifo was accidently cleared.

This patch also fixes the bug that nvt_cir_wake_isr returned IRQ_HANDLED
even if it detected that the (shared) interrupt was meant for another
handler.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 29 -
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c3294fb..c0bee1e 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -825,9 +825,13 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 *   0: CIR_IRSTS_GH  - Min Length Detected
 */
status = nvt_cir_reg_read(nvt, CIR_IRSTS);
-   if (!status) {
+   iren = nvt_cir_reg_read(nvt, CIR_IREN);
+
+   /* IRQ may be shared with CIR WAKE, therefore check for each
+* status bit whether the related interrupt source is enabled
+*/
+   if (!(status & iren)) {
nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
-   nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
return IRQ_NONE;
}
 
@@ -835,13 +839,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
nvt_cir_reg_write(nvt, status, CIR_IRSTS);
nvt_cir_reg_write(nvt, 0, CIR_IRSTS);
 
-   /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */
-   iren = nvt_cir_reg_read(nvt, CIR_IREN);
-   if (!iren) {
-   nvt_dbg_verbose("%s exiting, CIR not enabled", __func__);
-   return IRQ_NONE;
-   }
-
nvt_cir_log_irqs(status, iren);
 
if (status & CIR_IRSTS_RTR) {
@@ -914,7 +911,12 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
nvt_dbg_wake("%s firing", __func__);
 
status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
-   if (!status)
+   iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
+
+   /* IRQ may be shared with CIR, therefore check for each
+* status bit whether the related interrupt source is enabled
+*/
+   if (!(status & iren))
return IRQ_NONE;
 
if (status & CIR_WAKE_IRSTS_IR_PENDING)
@@ -923,13 +925,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS);
nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS);
 
-   /* Interrupt may be shared with CIR, bail if Wake not enabled */
-   iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
-   if (!iren) {
-   nvt_dbg_wake("%s exiting, wake not enabled", __func__);
-   return IRQ_HANDLED;
-   }
-
if ((status & CIR_WAKE_IRSTS_PE) &&
(nvt->wake_state == ST_WAKE_START)) {
while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) {
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/16] media: rc: nuvoton-cir: remove unneeded EFM operation in nvt_cir_isr

2015-12-30 Thread Heiner Kallweit
Selecting the logical device in the interrupt handler is not needed
as no configuration register is accessed.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 342e21d..91f8fda 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -800,10 +800,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
 
nvt_dbg_verbose("%s firing", __func__);
 
-   nvt_efm_enable(nvt);
-   nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-   nvt_efm_disable(nvt);
-
/*
 * Get IR Status register contents. Write 1 to ack/clear
 *
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/16] media: rc: nuvoton-cir: remove unneeded call to nvt_set_cir_iren

2015-12-30 Thread Heiner Kallweit
Calling nvt_set_cir_iren separately is not needed as this is done
by nvt_cir_regs_init.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index e01fdc8..252804d 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1201,9 +1201,6 @@ static int nvt_resume(struct pnp_dev *pdev)
 
nvt_dbg("%s called", __func__);
 
-   /* open interrupt */
-   nvt_set_cir_iren(nvt);
-
nvt_cir_regs_init(nvt);
nvt_cir_wake_regs_init(nvt);
 
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/16] media: rc: nuvoton-cir: improve logical device handling

2015-12-30 Thread Heiner Kallweit
Only enable the logical devices after the registers have been initialized.

The call to nvt_enable_logical_dev in nvt_resume is not needed as this is
done implicitely by nvt_cir_regs_init now.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 21 -
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index cf6ccb3..e01fdc8 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -352,9 +352,8 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt)
val |= psval;
nvt_cr_write(nvt, val, psreg);
 
-   /* Select CIR logical device and enable */
+   /* Select CIR logical device */
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-   nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
 
nvt_set_ioaddr(nvt, &nvt->cir_addr);
 
@@ -366,7 +365,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt)
 
 static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
 {
-   /* Select ACPI logical device, enable it and CIR Wake */
+   /* Select ACPI logical device and anable it */
nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
 
@@ -376,9 +375,8 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
/* enable pme interrupt of cir wakeup event */
nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
 
-   /* Select CIR Wake logical device and enable */
+   /* Select CIR Wake logical device */
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
-   nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
 
nvt_set_ioaddr(nvt, &nvt->cir_wake_addr);
 
@@ -461,6 +459,9 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt)
 
/* and finally, enable interrupts */
nvt_set_cir_iren(nvt);
+
+   /* enable the CIR logical device */
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
 }
 
 static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
@@ -495,6 +496,9 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
 
/* clear any and all stray interrupts */
nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
+
+   /* enable the CIR WAKE logical device */
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
 }
 
 static void nvt_enable_wake(struct nvt_dev *nvt)
@@ -1070,7 +1074,9 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
nvt_cir_wake_ldev_init(nvt);
nvt_efm_disable(nvt);
 
-   /* Initialize CIR & CIR Wake Config Registers */
+   /* Initialize CIR & CIR Wake Config Registers
+* and enable logical devices
+*/
nvt_cir_regs_init(nvt);
nvt_cir_wake_regs_init(nvt);
 
@@ -1198,9 +1204,6 @@ static int nvt_resume(struct pnp_dev *pdev)
/* open interrupt */
nvt_set_cir_iren(nvt);
 
-   /* Enable CIR logical device */
-   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
-
nvt_cir_regs_init(nvt);
nvt_cir_wake_regs_init(nvt);
 
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/16] media: rc: nuvoton-cir: improve nvt_hw_detect

2015-12-30 Thread Heiner Kallweit
Check for the case that no Nuvoton chip is found on either EFM port.
Also move the position of nvt_efm_disable to reduce the time the
EFM ports are locked.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 17 +
 drivers/media/rc/nuvoton-cir.h |  3 ++-
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 91f8fda..cf6ccb3 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -291,7 +291,7 @@ static inline const char *nvt_find_chip(struct nvt_dev 
*nvt, int id)
 
 
 /* detect hardware features */
-static void nvt_hw_detect(struct nvt_dev *nvt)
+static int nvt_hw_detect(struct nvt_dev *nvt)
 {
const char *chip_name;
int chip_id;
@@ -306,10 +306,17 @@ static void nvt_hw_detect(struct nvt_dev *nvt)
nvt_efm_enable(nvt);
nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
}
-
nvt->chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO);
 
+   nvt_efm_disable(nvt);
+
chip_id = nvt->chip_major << 8 | nvt->chip_minor;
+   if (chip_id == NVT_INVALID) {
+   dev_err(&nvt->pdev->dev,
+   "No device found on either EFM port\n");
+   return -ENODEV;
+   }
+
chip_name = nvt_find_chip(nvt, chip_id);
 
/* warn, but still let the driver load, if we don't know this chip */
@@ -322,7 +329,7 @@ static void nvt_hw_detect(struct nvt_dev *nvt)
 "found %s or compatible: chip id: 0x%02x 0x%02x",
 chip_name, nvt->chip_major, nvt->chip_minor);
 
-   nvt_efm_disable(nvt);
+   return 0;
 }
 
 static void nvt_cir_ldev_init(struct nvt_dev *nvt)
@@ -1053,7 +1060,9 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
 
init_waitqueue_head(&nvt->tx.queue);
 
-   nvt_hw_detect(nvt);
+   ret = nvt_hw_detect(nvt);
+   if (ret)
+   goto exit_free_dev_rdev;
 
/* Initialize CIR & CIR Wake Logical Devices */
nvt_efm_enable(nvt);
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 6a3de08..48c09c7 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -68,7 +68,8 @@ enum nvt_chip_ver {
NVT_W83667HG= 0xa510,
NVT_6775F   = 0xb470,
NVT_6776F   = 0xc330,
-   NVT_6779D   = 0xc560
+   NVT_6779D   = 0xc560,
+   NVT_INVALID = 0x,
 };
 
 struct nvt_chip {
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/16] media: rc: nuvoton-cir: factor out logical device disabling

2015-12-30 Thread Heiner Kallweit
Factor out disabling of a logical device.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index f661eff..ceb6b95 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev 
*nvt, u8 ldev)
nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL);
 }
 
+/* select and disable logical device with setting EFM mode*/
+static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev)
+{
+   nvt_efm_enable(nvt);
+   nvt_select_logical_dev(nvt, ldev);
+   nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
+   nvt_efm_disable(nvt);
+}
+
 /* write val to cir config register */
 static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset)
 {
@@ -937,13 +946,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt)
nvt_clear_cir_fifo(nvt);
nvt_clear_tx_fifo(nvt);
 
-   nvt_efm_enable(nvt);
-
/* disable the CIR logical device */
-   nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-   nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
-
-   nvt_efm_disable(nvt);
+   nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
 }
 
 static int nvt_open(struct rc_dev *dev)
@@ -1145,13 +1149,8 @@ static int nvt_suspend(struct pnp_dev *pdev, 
pm_message_t state)
/* disable all CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
 
-   nvt_efm_enable(nvt);
-
/* disable cir logical dev */
-   nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-   nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
-
-   nvt_efm_disable(nvt);
+   nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
 
/* make sure wake is enabled */
nvt_enable_wake(nvt);
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/16] media: rc: nuvoton-cir: simplify nvt_select_logical_ dev

2015-12-30 Thread Heiner Kallweit
Use nvt_cr_write to simplify nvt_select_logical_ dev.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 62c82c5..2539d4f 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -107,8 +107,7 @@ static inline void nvt_efm_disable(struct nvt_dev *nvt)
  */
 static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev)
 {
-   outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir);
-   outb(ldev, nvt->cr_efdr);
+   nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL);
 }
 
 /* write val to cir config register */
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/16] media: rc: nuvoton-cir: fix clearing wake fifo

2015-12-30 Thread Heiner Kallweit
At least on NVT6779D clearing the wake fifo works in learning mode only
(although this condition is not mentioned in the chip spec).
Setting the clear fifo bit has no effect in wake up mode.
Even if clearing the wake fifo should work in wake up mode on other
chips this workaround doesn't hurt.
If needed the caller of nvt_clear_cir_wake_fifo has to take care
of locking.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 8ed8011..f624851 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -379,11 +379,19 @@ static void nvt_clear_cir_fifo(struct nvt_dev *nvt)
 /* clear out the hardware's cir wake rx fifo */
 static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt)
 {
-   u8 val;
+   u8 val, config;
+
+   config = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON);
+
+   /* clearing wake fifo works in learning mode only */
+   nvt_cir_wake_reg_write(nvt, config & ~CIR_WAKE_IRCON_MODE0,
+  CIR_WAKE_IRCON);
 
val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON);
nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR,
   CIR_WAKE_FIFOCON);
+
+   nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON);
 }
 
 /* clear out the hardware's cir tx fifo */
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/16] media: rc: nuvoton-cir: simplify nvt_cir_tx_inactive

2015-12-30 Thread Heiner Kallweit
Simplify nvt_cir_tx_inactive.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 2539d4f..f661eff 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -742,16 +742,13 @@ static void nvt_cir_log_irqs(u8 status, u8 iren)
 static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
 {
unsigned long flags;
-   bool tx_inactive;
u8 tx_state;
 
spin_lock_irqsave(&nvt->tx.lock, flags);
tx_state = nvt->tx.tx_state;
spin_unlock_irqrestore(&nvt->tx.lock, flags);
 
-   tx_inactive = (tx_state == ST_TX_NONE);
-
-   return tx_inactive;
+   return tx_state == ST_TX_NONE;
 }
 
 /* interrupt service routine for incoming and outgoing CIR data */
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/16] media: rc: nuvoton-cir: factor out logical device enabling

2015-12-30 Thread Heiner Kallweit
Factor out enabling of a logical device.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index ceb6b95..8ed8011 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev 
*nvt, u8 ldev)
nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL);
 }
 
+/* select and enable logical device with setting EFM mode*/
+static inline void nvt_enable_logical_dev(struct nvt_dev *nvt, u8 ldev)
+{
+   nvt_efm_enable(nvt);
+   nvt_select_logical_dev(nvt, ldev);
+   nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+   nvt_efm_disable(nvt);
+}
+
 /* select and disable logical device with setting EFM mode*/
 static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev)
 {
@@ -916,13 +925,8 @@ static void nvt_enable_cir(struct nvt_dev *nvt)
  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
  CIR_IRCON);
 
-   nvt_efm_enable(nvt);
-
/* enable the CIR logical device */
-   nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-   nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-   nvt_efm_disable(nvt);
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
 
/* clear all pending interrupts */
nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
@@ -1168,11 +1172,7 @@ static int nvt_resume(struct pnp_dev *pdev)
nvt_set_cir_iren(nvt);
 
/* Enable CIR logical device */
-   nvt_efm_enable(nvt);
-   nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-   nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-   nvt_efm_disable(nvt);
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
 
nvt_cir_regs_init(nvt);
nvt_cir_wake_regs_init(nvt);
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/16] media: rc: nuvoton-cir: use IR_DEFAULT_TIMEOUT and consider SAMPLE_PERIOD

2015-12-30 Thread Heiner Kallweit
Switch to using the recently introduced IR default timeout value
(IR_DEFAULT_TIMEOUT) and consider the value of SAMPLE_PERIOD
when calculating the limit count register value.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 0ad15d3..6a3de08 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -157,8 +157,8 @@ struct nvt_dev {
 /* total length of CIR and CIR WAKE */
 #define CIR_IOREG_LENGTH   0x0f
 
-/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
-#define CIR_RX_LIMIT_COUNT 0x7d0
+/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL */
+#define CIR_RX_LIMIT_COUNT  (IR_DEFAULT_TIMEOUT / US_TO_NS(SAMPLE_PERIOD))
 
 /* CIR Regs */
 #define CIR_IRCON  0x00
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/16] media: rc: nuvoton-cir: series with improvements and fixes

2015-12-30 Thread Heiner Kallweit

Heiner Kallweit (16):
  media: rc: nuvoton-cir: use request_muxed_region for accessing EFM registers
  media: rc: nuvoton-cir: simplify nvt_select_logical_ dev
  media: rc: nuvoton-cir: simplify nvt_cir_tx_inactive
  media: rc: nuvoton-cir: factor out logical device disabling
  media: rc: nuvoton-cir: factor out logical device enabling
  media: rc: nuvoton-cir: fix clearing wake fifo
  media: rc: nuvoton-cir: fix setting ioport base address
  media: rc: nuvoton-cir: remove unneeded EFM operation in nvt_cir_isr
  media: rc: nuvoton-cir: use IR_DEFAULT_TIMEOUT and consider SAMPLE_PERIOD
  media: rc: nuvoton-cir: improve nvt_hw_detect
  media: rc: nuvoton-cir: improve logical device handling
  media: rc: nuvoton-cir: remove unneeded call to nvt_set_cir_iren
  media: rc: nuvoton-cir: add locking to calls of nvt_enable_wake
  media: rc: nuvoton-cir: fix wakeup interrupt bits
  media: rc: nuvoton-cir: fix interrupt handling
  media: rc: nuvoton-cir: improve locking in both interrupt handlers

 drivers/media/rc/nuvoton-cir.c | 204 +++--
 drivers/media/rc/nuvoton-cir.h |  12 +--
 2 files changed, 122 insertions(+), 94 deletions(-)

-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/16] media: rc: nuvoton-cir: use request_muxed_region for accessing EFM registers

2015-12-30 Thread Heiner Kallweit
The two EFM ioports are accessed by drivers for other parts of the Nuvoton
Super-IO chips too. Therefore access to these ioports needs to be
protected by using request_muxed_region (like it's implemented e.g. in
hwmon/nct6775 already).

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 081435c..62c82c5 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -80,17 +80,24 @@ static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, 
u8 val, u8 reg)
 }
 
 /* enter extended function mode */
-static inline void nvt_efm_enable(struct nvt_dev *nvt)
+static inline int nvt_efm_enable(struct nvt_dev *nvt)
 {
+   if (!request_muxed_region(nvt->cr_efir, 2, NVT_DRIVER_NAME))
+   return -EBUSY;
+
/* Enabling Extended Function Mode explicitly requires writing 2x */
outb(EFER_EFM_ENABLE, nvt->cr_efir);
outb(EFER_EFM_ENABLE, nvt->cr_efir);
+
+   return 0;
 }
 
 /* exit extended function mode */
 static inline void nvt_efm_disable(struct nvt_dev *nvt)
 {
outb(EFER_EFM_DISABLE, nvt->cr_efir);
+
+   release_region(nvt->cr_efir, 2);
 }
 
 /*
-- 
2.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: core: simplify DEFINE_IR_RAW_EVENT

2015-12-30 Thread Heiner Kallweit
DEFINE_IR_RAW_EVENT can be simplified and doesn't provide much benefit
as all elements are initialized to 0. But keep it as it is used in a
lot of places.
duration is the first element of the embedded union and therefore
used for the initialization even if not explicitely mentioned.

Signed-off-by: Heiner Kallweit 
---
 include/media/rc-core.h | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index f649470..91c6633 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -226,13 +226,7 @@ struct ir_raw_event {
unsignedcarrier_report:1;
 };
 
-#define DEFINE_IR_RAW_EVENT(event) \
-   struct ir_raw_event event = { \
-   { .duration = 0 } , \
-   .pulse = 0, \
-   .reset = 0, \
-   .timeout = 0, \
-   .carrier_report = 0 }
+#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {}
 
 static inline void init_ir_raw_event(struct ir_raw_event *ev)
 {
@@ -254,8 +248,7 @@ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
 
 static inline void ir_raw_event_reset(struct rc_dev *dev)
 {
-   DEFINE_IR_RAW_EVENT(ev);
-   ev.reset = true;
+   struct ir_raw_event ev = { .reset = true };
 
ir_raw_event_store(dev, &ev);
ir_raw_event_handle(dev);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] media: rc: improve lirc module detection

2015-12-08 Thread Heiner Kallweit
Improve detection whether lirc codec is loaded and avoid dependency
on config symbols and having to check for a specific module.

This also fixes the bug that the current check checks for module
lirc_dev instead of ir_lirc_codec (which depends on lirc_dev).
If the ir_lirc_codec module is unloaded the check would still
return OK.

Signed-off-by: Heiner Kallweit 
---
v2: export an accessor instead of the variable
---
drivers/media/rc/ir-lirc-codec.c |  4 
 drivers/media/rc/rc-main.c   | 24 ++--
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index a32659f..1f72bef 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -22,6 +22,8 @@
 
 #define LIRCBUF_SIZE 256
 
+extern void ir_raw_set_lirc_available(bool avail);
+
 /**
  * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
  *   lircd userspace daemon for decoding.
@@ -398,6 +400,7 @@ static int ir_lirc_register(struct rc_dev *dev)
 
dev->raw->lirc.drv = drv;
dev->raw->lirc.dev = dev;
+   ir_raw_set_lirc_available(true);
return 0;
 
 lirc_register_failed:
@@ -413,6 +416,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 {
struct lirc_codec *lirc = &dev->raw->lirc;
 
+   ir_raw_set_lirc_available(false);
lirc_unregister_driver(lirc->drv->minor);
lirc_buffer_free(lirc->drv->rbuf);
kfree(lirc->drv);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 1042fa3..600e9e9 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -829,22 +829,18 @@ struct rc_filter_attribute {
.mask = (_mask),\
}
 
-static bool lirc_is_present(void)
+static atomic_t lirc_available = ATOMIC_INIT(0);
+
+static inline bool lirc_is_present(void)
 {
-#if defined(CONFIG_LIRC_MODULE)
-   struct module *lirc;
-
-   mutex_lock(&module_mutex);
-   lirc = find_module("lirc_dev");
-   mutex_unlock(&module_mutex);
-
-   return lirc ? true : false;
-#elif defined(CONFIG_LIRC)
-   return true;
-#else
-   return false;
-#endif
+   return atomic_read(&lirc_available) != 0;
+}
+
+void ir_raw_set_lirc_available(bool avail)
+{
+   atomic_set(&lirc_available, avail);
 }
+EXPORT_SYMBOL(ir_raw_set_lirc_available);
 
 /**
  * show_protocols() - shows the current/wakeup IR protocol(s)
-- 
2.6.3


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] media: rc: improve lirc module detection

2015-12-03 Thread Heiner Kallweit
Am 03.12.2015 um 18:08 schrieb Mauro Carvalho Chehab:
> Em Sat, 21 Nov 2015 16:30:56 +0100
> Heiner Kallweit  escreveu:
> 
>> Improve detection whether lirc codec is loaded and avoid dependency
>> on config symbols and having to check for a specific module.
>>
>> This also fixes the bug that the current check checks for module
>> lirc_dev instead of ir_lirc_codec (which depends on lirc_dev).
>> If the ir_lirc_codec module is unloaded the check would still
>> return OK.
>>
>> Signed-off-by: Heiner Kallweit 
>> ---
>>  drivers/media/rc/ir-lirc-codec.c |  4 
>>  drivers/media/rc/rc-main.c   | 19 +--
>>  2 files changed, 9 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/media/rc/ir-lirc-codec.c 
>> b/drivers/media/rc/ir-lirc-codec.c
>> index a32659f..7fc5b3f 100644
>> --- a/drivers/media/rc/ir-lirc-codec.c
>> +++ b/drivers/media/rc/ir-lirc-codec.c
>> @@ -22,6 +22,8 @@
>>  
>>  #define LIRCBUF_SIZE 256
>>  
>> +extern atomic_t ir_raw_lirc_available;
>> +
> 
> No, this is not good, due to several reasons:
> 
> - it lacks an EXPORT_SYMBOL_GPL(ir_raw_lirc_available);
> - if lirc module is not compiled, the RC core will have a missed
>   symbol.
> 
> The right thing to do is to have a var inside the RC core and a
> way for LIRC to tell the core that it was loaded.
> 
IMHO that's actually the case.
The var is defined in rc_main.c and also exported from there.
Your comment is at the position where the variable is declared as "extern"
in the (potential) lirc module.

> I would prefer to not export a var. So, perhaps this could be
> done by calling some function.
> 
Sure, we could define the var static and add a public setter.
Would you prefer this?

> Anyway, the way the patch is, it will break compilation, depending
> on the config options.
> 
> Regards,
> Mauro
> 
Rgds, Heiner
> 
>>  /**
>>   * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
>>   *lircd userspace daemon for decoding.
>> @@ -398,6 +400,7 @@ static int ir_lirc_register(struct rc_dev *dev)
>>  
>>  dev->raw->lirc.drv = drv;
>>  dev->raw->lirc.dev = dev;
>> +atomic_set(&ir_raw_lirc_available, 1);
>>  return 0;
>>  
>>  lirc_register_failed:
>> @@ -413,6 +416,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
>>  {
>>  struct lirc_codec *lirc = &dev->raw->lirc;
>>  
>> +atomic_set(&ir_raw_lirc_available, 0);
>>  lirc_unregister_driver(lirc->drv->minor);
>>  lirc_buffer_free(lirc->drv->rbuf);
>>  kfree(lirc->drv);
>> diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
>> index 1042fa3..0bd11b4 100644
>> --- a/drivers/media/rc/rc-main.c
>> +++ b/drivers/media/rc/rc-main.c
>> @@ -829,21 +829,12 @@ struct rc_filter_attribute {
>>  .mask = (_mask),\
>>  }
>>  
>> -static bool lirc_is_present(void)
>> +atomic_t ir_raw_lirc_available = ATOMIC_INIT(0);
>> +EXPORT_SYMBOL(ir_raw_lirc_available);
>> +
>> +static inline bool lirc_is_present(void)
>>  {
>> -#if defined(CONFIG_LIRC_MODULE)
>> -struct module *lirc;
>> -
>> -mutex_lock(&module_mutex);
>> -lirc = find_module("lirc_dev");
>> -mutex_unlock(&module_mutex);
>> -
>> -return lirc ? true : false;
>> -#elif defined(CONFIG_LIRC)
>> -return true;
>> -#else
>> -return false;
>> -#endif
>> +return atomic_read(&ir_raw_lirc_available) != 0;
>>  }
>>  
>>  /**
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Can't access CIR wakeup registers of Nuvoton 6779D

2015-11-27 Thread Heiner Kallweit
I have a Zotac CI321 mini-PC which uses a Nuvoton 6779D (or compatible) Super-IO
for infrared remote control. The normal CIR part works flawlessly however I 
can't
access the wakeup registers.
Resource allocation works normal, /proc/ioports reports:

0220-022e : nuvoton-cir-wake
02e0-02ee : nuvoton-cir

Also configuring the logical device works normal as can be seen in the debug 
output.
However all reads to this ioport region fail.
I tried manually changing the ioport region but this didn't help either.

Meanwhile I'm wondering whether there might be stripped down versions of this 
chip
w/o the wake functionality as I'm running out of other ideas.
Appreciate any hint.

[ 7608.622878] nuvoton_cir: nuvoton-cir: Dump CIR logical device registers:
[ 7608.622949] nuvoton_cir:  * CR CIR ACTIVE :   0x1
[ 7608.623005] nuvoton_cir:  * CR CIR BASE ADDR: 0x2e0
[ 7608.623059] nuvoton_cir:  * CR CIR IRQ NUM:   0x3
[ 7608.623109] nuvoton_cir: nuvoton-cir: Dump CIR registers:
[ 7608.623166] nuvoton_cir:  * IRCON: 0x36
[ 7608.623210] nuvoton_cir:  * IRSTS: 0x0
[ 7608.623255] nuvoton_cir:  * IREN:  0x60
[ 7608.623299] nuvoton_cir:  * RXFCONT:   0x0
[ 7608.623344] nuvoton_cir:  * CP:0x0
[ 7608.623388] nuvoton_cir:  * CC:0x0
[ 7608.623432] nuvoton_cir:  * SLCH:  0x7
[ 7608.623478] nuvoton_cir:  * SLCL:  0xd0
[ 7608.623524] nuvoton_cir:  * FIFOCON:   0x23
[ 7608.623569] nuvoton_cir:  * IRFIFOSTS: 0x96
[ 7608.623614] nuvoton_cir:  * SRXFIFO:   0x84
[ 7608.623659] nuvoton_cir:  * TXFCONT:   0x0
[ 7608.623706] nuvoton_cir:  * STXFIFO:   0x0
[ 7608.623762] nuvoton_cir:  * FCCH:  0x0
[ 7608.623808] nuvoton_cir:  * FCCL:  0x0
[ 7608.623853] nuvoton_cir:  * IRFSM: 0x14
[ 7608.623904] nuvoton_cir: nuvoton-cir: Dump CIR WAKE logical device registers:
[ 7608.623979] nuvoton_cir:  * CR CIR WAKE ACTIVE :   0x1
[ 7608.624039] nuvoton_cir:  * CR CIR WAKE BASE ADDR: 0x220
[ 7608.624097] nuvoton_cir:  * CR CIR WAKE IRQ NUM:   0x3
[ 7608.624151] nuvoton_cir: nuvoton-cir: Dump CIR WAKE registers
[ 7608.624210] nuvoton_cir:  * IRCON:  0xff
[ 7608.624258] nuvoton_cir:  * IRSTS:  0xff
[ 7608.624308] nuvoton_cir:  * IREN:   0xff
[ 7608.624356] nuvoton_cir:  * FIFO CMP DEEP:  0xff
[ 7608.624404] nuvoton_cir:  * FIFO CMP TOL:   0xff
[ 7608.624453] nuvoton_cir:  * FIFO COUNT: 0xff
[ 7608.624502] nuvoton_cir:  * SLCH:   0xff
[ 7608.624550] nuvoton_cir:  * SLCL:   0xff
[ 7608.625897] nuvoton_cir:  * FIFOCON:0xff
[ 7608.627204] nuvoton_cir:  * SRXFSTS:0xff
[ 7608.628481] nuvoton_cir:  * SAMPLE RX FIFO: 0xff
[ 7608.629393] nuvoton_cir:  * WR FIFO DATA:   0xff
[ 7608.630157] nuvoton_cir:  * RD FIFO ONLY:   0xff
[ 7608.630906] nuvoton_cir:  * RD FIFO ONLY IDX: 0xff
[ 7608.631648] nuvoton_cir:  * FIFO IGNORE:0xff
[ 7608.632380] nuvoton_cir:  * IRFSM:  0xff
[ 7608.633085] nuvoton_cir: nuvoton-cir: Dump CIR WAKE FIFO (len 255)
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: raw: improve FIFO handling

2015-11-27 Thread Heiner Kallweit
The FIFO is used for ir_raw_event records, however for some historic
reason the FIFO is used on a per byte basis. IMHO this adds unneeded
complexity. Therefore set up the FIFO for ir_raw_event records.

This also allows to define the FIFO statically as part of
ir_raw_event_ctrl instead of having to allocate the FIFO dynamically.
In addition:

- When writing into the FIFO and it's full return ENOSPC instead of
  ENOMEM thus making it easier to tell between "FIFO full" and
  "Dynamic memory allocation failed" when the error is propagated to
  a higher level.
  Also add an error message.

- When reading from the FIFO check whether it's empty.
  This is not strictly needed here but kfifo_out is annotated
  "must check" anyway.

Successfully tested it with the nuvoton-cir driver.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-core-priv.h |  6 +-
 drivers/media/rc/rc-ir-raw.c| 23 ---
 2 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 7359f3d..585d5e5 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -16,6 +16,9 @@
 #ifndef _RC_CORE_PRIV
 #define _RC_CORE_PRIV
 
+/* Define the max number of pulse/space transitions to buffer */
+#defineMAX_IR_EVENT_SIZE   512
+
 #include 
 #include 
 #include 
@@ -35,7 +38,8 @@ struct ir_raw_event_ctrl {
struct list_headlist;   /* to keep track of raw 
clients */
struct task_struct  *thread;
spinlock_t  lock;
-   struct kfifo_rec_ptr_1  kfifo;  /* fifo for the 
pulse/space durations */
+   /* fifo for the pulse/space durations */
+   DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE);
ktime_t last_event; /* when last event 
occurred */
enum raw_event_type last_type;  /* last event type */
struct rc_dev   *dev;   /* pointer to the 
parent rc_dev */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index c69807f..144304c 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -20,9 +20,6 @@
 #include 
 #include "rc-core-priv.h"
 
-/* Define the max number of pulse/space transitions to buffer */
-#define MAX_IR_EVENT_SIZE  512
-
 /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
 static LIST_HEAD(ir_raw_client_list);
 
@@ -36,14 +33,12 @@ static int ir_raw_event_thread(void *data)
struct ir_raw_event ev;
struct ir_raw_handler *handler;
struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
-   int retval;
 
while (!kthread_should_stop()) {
 
spin_lock_irq(&raw->lock);
-   retval = kfifo_len(&raw->kfifo);
 
-   if (retval < sizeof(ev)) {
+   if (!kfifo_len(&raw->kfifo)) {
set_current_state(TASK_INTERRUPTIBLE);
 
if (kthread_should_stop())
@@ -54,7 +49,8 @@ static int ir_raw_event_thread(void *data)
continue;
}
 
-   retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
+   if(!kfifo_out(&raw->kfifo, &ev, 1))
+   dev_err(&raw->dev->dev, "IR event FIFO is empty!\n");
spin_unlock_irq(&raw->lock);
 
mutex_lock(&ir_raw_handler_lock);
@@ -87,8 +83,10 @@ int ir_raw_event_store(struct rc_dev *dev, struct 
ir_raw_event *ev)
IR_dprintk(2, "sample: (%05dus %s)\n",
   TO_US(ev->duration), TO_STR(ev->pulse));
 
-   if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
-   return -ENOMEM;
+   if (!kfifo_put(&dev->raw->kfifo, *ev)) {
+   dev_err(&dev->dev, "IR event FIFO is full!\n");
+   return -ENOSPC;
+   }
 
return 0;
 }
@@ -273,11 +271,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 
dev->raw->dev = dev;
dev->change_protocol = change_protocol;
-   rc = kfifo_alloc(&dev->raw->kfifo,
-sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
-GFP_KERNEL);
-   if (rc < 0)
-   goto out;
+   INIT_KFIFO(dev->raw->kfifo);
 
spin_lock_init(&dev->raw->lock);
dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
@@ -319,7 +313,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
handler->raw_unregister(dev);
mutex_unlock(&ir_raw_handler_lock);
 
-   kfifo_free(&dev->raw->kfifo);
kfree(dev->raw);
dev->raw = NULL;
 }
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] media: rc: nuvoton: mark wakeup-related resources

2015-11-27 Thread Heiner Kallweit
When requesting resources use different names for the normal and
the wakeup part. This makes it easier to interpret the output
of e.g. /proc/interrupts and /proc/ioports.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/nuvoton-cir.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 18adf58..081435c 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1079,12 +1079,12 @@ static int nvt_probe(struct pnp_dev *pdev, const struct 
pnp_device_id *dev_id)
goto exit_unregister_device;
 
if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr,
-   CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+   CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake"))
goto exit_unregister_device;
 
if (devm_request_irq(&pdev->dev, nvt->cir_wake_irq,
 nvt_cir_wake_isr, IRQF_SHARED,
-NVT_DRIVER_NAME, (void *)nvt))
+NVT_DRIVER_NAME "-wake", (void *)nvt))
goto exit_unregister_device;
 
device_init_wakeup(&pdev->dev, true);
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] media: rc: improve lirc module detection

2015-11-21 Thread Heiner Kallweit
Improve detection whether lirc codec is loaded and avoid dependency
on config symbols and having to check for a specific module.

This also fixes the bug that the current check checks for module
lirc_dev instead of ir_lirc_codec (which depends on lirc_dev).
If the ir_lirc_codec module is unloaded the check would still
return OK.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/ir-lirc-codec.c |  4 
 drivers/media/rc/rc-main.c   | 19 +--
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index a32659f..7fc5b3f 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -22,6 +22,8 @@
 
 #define LIRCBUF_SIZE 256
 
+extern atomic_t ir_raw_lirc_available;
+
 /**
  * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
  *   lircd userspace daemon for decoding.
@@ -398,6 +400,7 @@ static int ir_lirc_register(struct rc_dev *dev)
 
dev->raw->lirc.drv = drv;
dev->raw->lirc.dev = dev;
+   atomic_set(&ir_raw_lirc_available, 1);
return 0;
 
 lirc_register_failed:
@@ -413,6 +416,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 {
struct lirc_codec *lirc = &dev->raw->lirc;
 
+   atomic_set(&ir_raw_lirc_available, 0);
lirc_unregister_driver(lirc->drv->minor);
lirc_buffer_free(lirc->drv->rbuf);
kfree(lirc->drv);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 1042fa3..0bd11b4 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -829,21 +829,12 @@ struct rc_filter_attribute {
.mask = (_mask),\
}
 
-static bool lirc_is_present(void)
+atomic_t ir_raw_lirc_available = ATOMIC_INIT(0);
+EXPORT_SYMBOL(ir_raw_lirc_available);
+
+static inline bool lirc_is_present(void)
 {
-#if defined(CONFIG_LIRC_MODULE)
-   struct module *lirc;
-
-   mutex_lock(&module_mutex);
-   lirc = find_module("lirc_dev");
-   mutex_unlock(&module_mutex);
-
-   return lirc ? true : false;
-#elif defined(CONFIG_LIRC)
-   return true;
-#else
-   return false;
-#endif
+   return atomic_read(&ir_raw_lirc_available) != 0;
 }
 
 /**
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] media: rc: remove unneeded code

2015-11-21 Thread Heiner Kallweit
Now that that the decoder modules are loaded on-demand we can move
loading the lirc module to rc_register_device directly and remove
unneeded functions and comments.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-core-priv.h |  7 ---
 drivers/media/rc/rc-ir-raw.c| 10 --
 drivers/media/rc/rc-main.c  |  4 +---
 3 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 071651a..7359f3d 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -167,11 +167,4 @@ void ir_raw_init(void);
  * loads the compiled decoders for their usage with IR raw events
  */
 
-/* from ir-lirc-codec.c */
-#ifdef CONFIG_IR_LIRC_CODEC_MODULE
-#define load_lirc_codec()  request_module_nowait("ir-lirc-codec")
-#else
-static inline void load_lirc_codec(void) { }
-#endif
-
 #endif /* _RC_CORE_PRIV */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index c6433e8..c69807f 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -360,13 +360,3 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler)
mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
-
-void ir_raw_init(void)
-{
-   /* Load the decoder modules */
-   load_lirc_codec();
-
-   /* If needed, we may later add some init code. In this case,
-  it is needed to change the CONFIG_MODULE test at rc-core.h
-*/
-}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 9d05d03..1042fa3 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1471,10 +1471,8 @@ int rc_register_device(struct rc_dev *dev)
kfree(path);
 
if (dev->driver_type == RC_DRIVER_IR_RAW) {
-   /* Load raw decoders, if they aren't already */
if (!raw_init) {
-   IR_dprintk(1, "Loading raw decoders\n");
-   ir_raw_init();
+   request_module_nowait("ir-lirc-codec");
raw_init = true;
}
/* calls ir_register_device so unlock mutex here*/
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 6/8] media: rc: treat lirc like any other protocol

2015-11-19 Thread Heiner Kallweit
Am 19.11.2015 um 14:49 schrieb Mauro Carvalho Chehab:
> Hi Heiner,
> 
> Em Mon, 16 Nov 2015 20:53:20 +0100
> Heiner Kallweit  escreveu:
> 
>> Introduce a protocol bit for lirc and treat it like any other protocol.
>> This allows to get rid of all the lirc-specific code.
> 
> LIRC were originally handled like a protocol, but, after some discussions,
> we decided to handle it in separate, as it is actually an API.
> 
> So, I'm not applying this patch.

I missed this discussion, sorry. Found it in the archive.
Exposing lirc as a protocol to the outside world (incl. the kernel outside rc 
core)
I also consider a bad idea, however I hoped that not listing it in the header 
file
would be sufficient to keep it internal. But it's totally fine with me as it is.

Thanks for the quick review of the patches.

Heiner

> Patches 1-5 and patch 7 looks OK, so I'm applying them.
> 
> Regards,
> Mauro
> 
>>
>> Signed-off-by: Heiner Kallweit 
>> ---
>>  drivers/media/rc/ir-lirc-codec.c |  2 +-
>>  drivers/media/rc/rc-core-priv.h  | 16 ++--
>>  drivers/media/rc/rc-ir-raw.c | 13 +
>>  drivers/media/rc/rc-main.c   | 37 -
>>  4 files changed, 8 insertions(+), 60 deletions(-)
>>
>> diff --git a/drivers/media/rc/ir-lirc-codec.c 
>> b/drivers/media/rc/ir-lirc-codec.c
>> index a32659f..40c66c8 100644
>> --- a/drivers/media/rc/ir-lirc-codec.c
>> +++ b/drivers/media/rc/ir-lirc-codec.c
>> @@ -421,7 +421,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
>>  }
>>  
>>  static struct ir_raw_handler lirc_handler = {
>> -.protocols  = 0,
>> +.protocols  = RC_BIT_LIRC,
>>  .decode = ir_lirc_decode,
>>  .raw_register   = ir_lirc_register,
>>  .raw_unregister = ir_lirc_unregister,
>> diff --git a/drivers/media/rc/rc-core-priv.h 
>> b/drivers/media/rc/rc-core-priv.h
>> index 071651a..74f2f15 100644
>> --- a/drivers/media/rc/rc-core-priv.h
>> +++ b/drivers/media/rc/rc-core-priv.h
>> @@ -20,6 +20,8 @@
>>  #include 
>>  #include 
>>  
>> +#define RC_BIT_LIRC (1ULL << 63)
>> +
>>  struct ir_raw_handler {
>>  struct list_head list;
>>  
>> @@ -160,18 +162,4 @@ int ir_raw_handler_register(struct ir_raw_handler 
>> *ir_raw_handler);
>>  void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
>>  void ir_raw_init(void);
>>  
>> -/*
>> - * Decoder initialization code
>> - *
>> - * Those load logic are called during ir-core init, and automatically
>> - * loads the compiled decoders for their usage with IR raw events
>> - */
>> -
>> -/* from ir-lirc-codec.c */
>> -#ifdef CONFIG_IR_LIRC_CODEC_MODULE
>> -#define load_lirc_codec()   request_module_nowait("ir-lirc-codec")
>> -#else
>> -static inline void load_lirc_codec(void) { }
>> -#endif
>> -
>>  #endif /* _RC_CORE_PRIV */
>> diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
>> index c6433e8..dbd8db5 100644
>> --- a/drivers/media/rc/rc-ir-raw.c
>> +++ b/drivers/media/rc/rc-ir-raw.c
>> @@ -59,8 +59,7 @@ static int ir_raw_event_thread(void *data)
>>  
>>  mutex_lock(&ir_raw_handler_lock);
>>  list_for_each_entry(handler, &ir_raw_handler_list, list)
>> -if (raw->dev->enabled_protocols & handler->protocols ||
>> -!handler->protocols)
>> +if (raw->dev->enabled_protocols & handler->protocols)
>>  handler->decode(raw->dev, ev);
>>  raw->prev_ev = ev;
>>  mutex_unlock(&ir_raw_handler_lock);
>> @@ -360,13 +359,3 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
>> *ir_raw_handler)
>>  mutex_unlock(&ir_raw_handler_lock);
>>  }
>>  EXPORT_SYMBOL(ir_raw_handler_unregister);
>> -
>> -void ir_raw_init(void)
>> -{
>> -/* Load the decoder modules */
>> -load_lirc_codec();
>> -
>> -/* If needed, we may later add some init code. In this case,
>> -   it is needed to change the CONFIG_MODULE test at rc-core.h
>> - */
>> -}
>> diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
>> index f2d5c50..d1611f1 100644
>> --- a/drivers/media/rc/rc-main.c
>> +++ b/drivers/media/rc/rc-main.c
>> @@ -802,6 +802,7 @@ static const struct {
>>  { RC_BIT_SHARP, "sharp","ir-sharp-decoder"

[PATCH] media: cx23885: fix type of allowed_protos

2015-11-16 Thread Heiner Kallweit
Protocol lists are represented as 64-bit bitmaps,
therefore use u64 instead of unsigned long.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/pci/cx23885/cx23885-input.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/pci/cx23885/cx23885-input.c 
b/drivers/media/pci/cx23885/cx23885-input.c
index 088799c..64328d0 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -268,7 +268,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
struct rc_dev *rc;
char *rc_map;
enum rc_driver_type driver_type;
-   unsigned long allowed_protos;
+   u64 allowed_protos;
 
int ret;
 
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 8/8] media: rc: define RC_BIT_ALL as ~0

2015-11-16 Thread Heiner Kallweit
Am 16.11.2015 um 21:47 schrieb kbuild test robot:
> Hi Heiner,
> 
> [auto build test WARNING on linuxtv-media/master]
> [also build test WARNING on v4.4-rc1 next-20151116]
> 
> url:
> https://github.com/0day-ci/linux/commits/Heiner-Kallweit/media-rc-fix-decoder-module-unloading/20151117-035809
> base:   git://linuxtv.org/media_tree.git master
> config: parisc-allmodconfig (attached as .config)
> reproduce:
> wget 
> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
>  -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=parisc 
> 
> All warnings (new ones prefixed by >>):
> 
>In file included from include/media/rc-core.h:23:0,
> from drivers/media/pci/cx23885/cx23885-input.c:34:
>drivers/media/pci/cx23885/cx23885-input.c: In function 
> 'cx23885_input_init':
>>> include/media/rc-map.h:57:21: warning: large integer implicitly truncated 
>>> to unsigned type [-Woverflow]
> #define RC_BIT_ALL  ~RC_BIT_NONE
> ^
>>> drivers/media/pci/cx23885/cx23885-input.c:289:20: note: in expansion of 
>>> macro 'RC_BIT_ALL'
>   allowed_protos = RC_BIT_ALL;
>^
>>> include/media/rc-map.h:57:21: warning: large integer implicitly truncated 
>>> to unsigned type [-Woverflow]
> #define RC_BIT_ALL  ~RC_BIT_NONE
> ^
>drivers/media/pci/cx23885/cx23885-input.c:303:20: note: in expansion of 
> macro 'RC_BIT_ALL'
>   allowed_protos = RC_BIT_ALL;
>^
>>> include/media/rc-map.h:57:21: warning: large integer implicitly truncated 
>>> to unsigned type [-Woverflow]
> #define RC_BIT_ALL  ~RC_BIT_NONE
> ^
>drivers/media/pci/cx23885/cx23885-input.c:310:20: note: in expansion of 
> macro 'RC_BIT_ALL'
>   allowed_protos = RC_BIT_ALL;
>^
>>> include/media/rc-map.h:57:21: warning: large integer implicitly truncated 
>>> to unsigned type [-Woverflow]
> #define RC_BIT_ALL  ~RC_BIT_NONE
> ^
>drivers/media/pci/cx23885/cx23885-input.c:318:20: note: in expansion of 
> macro 'RC_BIT_ALL'
>   allowed_protos = RC_BIT_ALL;
>^
>>> include/media/rc-map.h:57:21: warning: large integer implicitly truncated 
>>> to unsigned type [-Woverflow]
> #define RC_BIT_ALL  ~RC_BIT_NONE
> ^
>drivers/media/pci/cx23885/cx23885-input.c:330:20: note: in expansion of 
> macro 'RC_BIT_ALL'
>   allowed_protos = RC_BIT_ALL;
>^
>>> include/media/rc-map.h:57:21: warning: large integer implicitly truncated 
>>> to unsigned type [-Woverflow]
> #define RC_BIT_ALL  ~RC_BIT_NONE
> ^
>drivers/media/pci/cx23885/cx23885-input.c:336:20: note: in expansion of 
> macro 'RC_BIT_ALL'
>   allowed_protos = RC_BIT_ALL;
>^
> 
> vim +57 include/media/rc-map.h
> 
> 41#define RC_BIT_RC5_SZ   (1ULL << RC_TYPE_RC5_SZ)
> 42#define RC_BIT_JVC  (1ULL << RC_TYPE_JVC)
> 43#define RC_BIT_SONY12   (1ULL << RC_TYPE_SONY12)
> 44#define RC_BIT_SONY15   (1ULL << RC_TYPE_SONY15)
> 45#define RC_BIT_SONY20   (1ULL << RC_TYPE_SONY20)
> 46#define RC_BIT_NEC  (1ULL << RC_TYPE_NEC)
> 47#define RC_BIT_SANYO(1ULL << RC_TYPE_SANYO)
> 48#define RC_BIT_MCE_KBD  (1ULL << RC_TYPE_MCE_KBD)
> 49#define RC_BIT_RC6_0(1ULL << RC_TYPE_RC6_0)
> 50#define RC_BIT_RC6_6A_20(1ULL << RC_TYPE_RC6_6A_20)
> 51#define RC_BIT_RC6_6A_24(1ULL << RC_TYPE_RC6_6A_24)
> 52#define RC_BIT_RC6_6A_32(1ULL << RC_TYPE_RC6_6A_32)
> 53#define RC_BIT_RC6_MCE  (1ULL << RC_TYPE_RC6_MCE)
> 54#define RC_BIT_SHARP(1ULL << RC_TYPE_SHARP)
> 55#define RC_BIT_XMP  (1ULL << RC_TYPE_XMP)
> 56
>   > 57#define RC_BIT_ALL  ~RC_BIT_NONE
> 58
> 59#define RC_SCANCODE_UNKNOWN(x)  (x)
> 60#define RC_SCANCODE_OTHER(x)(x)
> 61#define RC_SCANCODE_NEC(addr, cmd)  (((addr) << 8) 
> | (cmd))
>

[PATCH 4/8] media: rc: load decoder modules on-demand

2015-11-16 Thread Heiner Kallweit
Remove code for unconditional decoder module loading (except lirc).

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-core-priv.h | 64 -
 drivers/media/rc/rc-ir-raw.c| 10 ---
 2 files changed, 74 deletions(-)

diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index b68d4f7..071651a 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -167,62 +167,6 @@ void ir_raw_init(void);
  * loads the compiled decoders for their usage with IR raw events
  */
 
-/* from ir-nec-decoder.c */
-#ifdef CONFIG_IR_NEC_DECODER_MODULE
-#define load_nec_decode()  request_module_nowait("ir-nec-decoder")
-#else
-static inline void load_nec_decode(void) { }
-#endif
-
-/* from ir-rc5-decoder.c */
-#ifdef CONFIG_IR_RC5_DECODER_MODULE
-#define load_rc5_decode()  request_module_nowait("ir-rc5-decoder")
-#else
-static inline void load_rc5_decode(void) { }
-#endif
-
-/* from ir-rc6-decoder.c */
-#ifdef CONFIG_IR_RC6_DECODER_MODULE
-#define load_rc6_decode()  request_module_nowait("ir-rc6-decoder")
-#else
-static inline void load_rc6_decode(void) { }
-#endif
-
-/* from ir-jvc-decoder.c */
-#ifdef CONFIG_IR_JVC_DECODER_MODULE
-#define load_jvc_decode()  request_module_nowait("ir-jvc-decoder")
-#else
-static inline void load_jvc_decode(void) { }
-#endif
-
-/* from ir-sony-decoder.c */
-#ifdef CONFIG_IR_SONY_DECODER_MODULE
-#define load_sony_decode() request_module_nowait("ir-sony-decoder")
-#else
-static inline void load_sony_decode(void) { }
-#endif
-
-/* from ir-sanyo-decoder.c */
-#ifdef CONFIG_IR_SANYO_DECODER_MODULE
-#define load_sanyo_decode()request_module_nowait("ir-sanyo-decoder")
-#else
-static inline void load_sanyo_decode(void) { }
-#endif
-
-/* from ir-sharp-decoder.c */
-#ifdef CONFIG_IR_SHARP_DECODER_MODULE
-#define load_sharp_decode()request_module_nowait("ir-sharp-decoder")
-#else
-static inline void load_sharp_decode(void) { }
-#endif
-
-/* from ir-mce_kbd-decoder.c */
-#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
-#define load_mce_kbd_decode()  request_module_nowait("ir-mce_kbd-decoder")
-#else
-static inline void load_mce_kbd_decode(void) { }
-#endif
-
 /* from ir-lirc-codec.c */
 #ifdef CONFIG_IR_LIRC_CODEC_MODULE
 #define load_lirc_codec()  request_module_nowait("ir-lirc-codec")
@@ -230,12 +174,4 @@ static inline void load_mce_kbd_decode(void) { }
 static inline void load_lirc_codec(void) { }
 #endif
 
-/* from ir-xmp-decoder.c */
-#ifdef CONFIG_IR_XMP_DECODER_MODULE
-#define load_xmp_decode()  request_module_nowait("ir-xmp-decoder")
-#else
-static inline void load_xmp_decode(void) { }
-#endif
-
-
 #endif /* _RC_CORE_PRIV */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 5cfb61f..763f8a8 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -362,17 +362,7 @@ EXPORT_SYMBOL(ir_raw_handler_unregister);
 void ir_raw_init(void)
 {
/* Load the decoder modules */
-
-   load_nec_decode();
-   load_rc5_decode();
-   load_rc6_decode();
-   load_jvc_decode();
-   load_sony_decode();
-   load_sanyo_decode();
-   load_sharp_decode();
-   load_mce_kbd_decode();
load_lirc_codec();
-   load_xmp_decode();
 
/* If needed, we may later add some init code. In this case,
   it is needed to change the CONFIG_MODULE test at rc-core.h
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] media: rc: treat lirc like any other protocol

2015-11-16 Thread Heiner Kallweit
Introduce a protocol bit for lirc and treat it like any other protocol.
This allows to get rid of all the lirc-specific code.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/ir-lirc-codec.c |  2 +-
 drivers/media/rc/rc-core-priv.h  | 16 ++--
 drivers/media/rc/rc-ir-raw.c | 13 +
 drivers/media/rc/rc-main.c   | 37 -
 4 files changed, 8 insertions(+), 60 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index a32659f..40c66c8 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -421,7 +421,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler lirc_handler = {
-   .protocols  = 0,
+   .protocols  = RC_BIT_LIRC,
.decode = ir_lirc_decode,
.raw_register   = ir_lirc_register,
.raw_unregister = ir_lirc_unregister,
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 071651a..74f2f15 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -20,6 +20,8 @@
 #include 
 #include 
 
+#define RC_BIT_LIRC(1ULL << 63)
+
 struct ir_raw_handler {
struct list_head list;
 
@@ -160,18 +162,4 @@ int ir_raw_handler_register(struct ir_raw_handler 
*ir_raw_handler);
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
 void ir_raw_init(void);
 
-/*
- * Decoder initialization code
- *
- * Those load logic are called during ir-core init, and automatically
- * loads the compiled decoders for their usage with IR raw events
- */
-
-/* from ir-lirc-codec.c */
-#ifdef CONFIG_IR_LIRC_CODEC_MODULE
-#define load_lirc_codec()  request_module_nowait("ir-lirc-codec")
-#else
-static inline void load_lirc_codec(void) { }
-#endif
-
 #endif /* _RC_CORE_PRIV */
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index c6433e8..dbd8db5 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -59,8 +59,7 @@ static int ir_raw_event_thread(void *data)
 
mutex_lock(&ir_raw_handler_lock);
list_for_each_entry(handler, &ir_raw_handler_list, list)
-   if (raw->dev->enabled_protocols & handler->protocols ||
-   !handler->protocols)
+   if (raw->dev->enabled_protocols & handler->protocols)
handler->decode(raw->dev, ev);
raw->prev_ev = ev;
mutex_unlock(&ir_raw_handler_lock);
@@ -360,13 +359,3 @@ void ir_raw_handler_unregister(struct ir_raw_handler 
*ir_raw_handler)
mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
-
-void ir_raw_init(void)
-{
-   /* Load the decoder modules */
-   load_lirc_codec();
-
-   /* If needed, we may later add some init code. In this case,
-  it is needed to change the CONFIG_MODULE test at rc-core.h
-*/
-}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index f2d5c50..d1611f1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -802,6 +802,7 @@ static const struct {
{ RC_BIT_SHARP, "sharp","ir-sharp-decoder"  },
{ RC_BIT_MCE_KBD,   "mce_kbd",  "ir-mce_kbd-decoder"},
{ RC_BIT_XMP,   "xmp",  "ir-xmp-decoder"},
+   { RC_BIT_LIRC,  "lirc", "ir-lirc-codec" },
 };
 
 /**
@@ -829,23 +830,6 @@ struct rc_filter_attribute {
.mask = (_mask),\
}
 
-static bool lirc_is_present(void)
-{
-#if defined(CONFIG_LIRC_MODULE)
-   struct module *lirc;
-
-   mutex_lock(&module_mutex);
-   lirc = find_module("lirc_dev");
-   mutex_unlock(&module_mutex);
-
-   return lirc ? true : false;
-#elif defined(CONFIG_LIRC)
-   return true;
-#else
-   return false;
-#endif
-}
-
 /**
  * show_protocols() - shows the current/wakeup IR protocol(s)
  * @device:the device descriptor
@@ -900,9 +884,6 @@ static ssize_t show_protocols(struct device *device,
allowed &= ~proto_names[i].type;
}
 
-   if (dev->driver_type == RC_DRIVER_IR_RAW && lirc_is_present())
-   tmp += sprintf(tmp, "[lirc] ");
-
if (tmp != buf)
tmp--;
*tmp = '\n';
@@ -954,12 +935,8 @@ static int parse_protocol_change(u64 *protocols, const 
char *buf)
}
 
if (i == ARRAY_SIZE(proto_names)) {
-   if (!strcasecmp(tmp, "lirc"))
-   mask = 0;
-   else {
- 

[PATCH 5/8] media: rc: move check whether a protocol is enabled to the core

2015-11-16 Thread Heiner Kallweit
Checking whether a protocol is enabled and calling the related decoder
functions should be done by the rc core, not the protocol handlers.

Properly handle lirc considering that no protocol bit is set for lirc.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/ir-jvc-decoder.c | 3 ---
 drivers/media/rc/ir-mce_kbd-decoder.c | 3 ---
 drivers/media/rc/ir-nec-decoder.c | 3 ---
 drivers/media/rc/ir-rc5-decoder.c | 3 ---
 drivers/media/rc/ir-rc6-decoder.c | 5 -
 drivers/media/rc/ir-sanyo-decoder.c   | 3 ---
 drivers/media/rc/ir-sharp-decoder.c   | 3 ---
 drivers/media/rc/ir-sony-decoder.c| 4 
 drivers/media/rc/ir-xmp-decoder.c | 3 ---
 drivers/media/rc/rc-ir-raw.c  | 4 +++-
 10 files changed, 3 insertions(+), 31 deletions(-)

diff --git a/drivers/media/rc/ir-jvc-decoder.c 
b/drivers/media/rc/ir-jvc-decoder.c
index 30bcf18..182402f 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -47,9 +47,6 @@ static int ir_jvc_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
 {
struct jvc_dec *data = &dev->raw->jvc;
 
-   if (!(dev->enabled_protocols & RC_BIT_JVC))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c 
b/drivers/media/rc/ir-mce_kbd-decoder.c
index 9f3c9b5..d809862 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -216,9 +216,6 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
u32 scancode;
unsigned long delay;
 
-   if (!(dev->enabled_protocols & RC_BIT_MCE_KBD))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
diff --git a/drivers/media/rc/ir-nec-decoder.c 
b/drivers/media/rc/ir-nec-decoder.c
index 7b81fec..bea0d1e 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -52,9 +52,6 @@ static int ir_nec_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
u8 address, not_address, command, not_command;
bool send_32bits = false;
 
-   if (!(dev->enabled_protocols & RC_BIT_NEC))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
diff --git a/drivers/media/rc/ir-rc5-decoder.c 
b/drivers/media/rc/ir-rc5-decoder.c
index 84fa6e9..6ffe776 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -53,9 +53,6 @@ static int ir_rc5_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
u32 scancode;
enum rc_type protocol;
 
-   if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X | 
RC_BIT_RC5_SZ)))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
diff --git a/drivers/media/rc/ir-rc6-decoder.c 
b/drivers/media/rc/ir-rc6-decoder.c
index d16bc67..e0e2ede 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -90,11 +90,6 @@ static int ir_rc6_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
u8 toggle;
enum rc_type protocol;
 
-   if (!(dev->enabled_protocols &
- (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
-  RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
diff --git a/drivers/media/rc/ir-sanyo-decoder.c 
b/drivers/media/rc/ir-sanyo-decoder.c
index ad1dc6a..7331e5e 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -58,9 +58,6 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
u32 scancode;
u8 address, command, not_command;
 
-   if (!(dev->enabled_protocols & RC_BIT_SANYO))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset) {
IR_dprintk(1, "SANYO event reset received. reset to 
state 0\n");
diff --git a/drivers/media/rc/ir-sharp-decoder.c 
b/drivers/media/rc/ir-sharp-decoder.c
index 1f33164..317677f 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -48,9 +48,6 @@ static int ir_sharp_decode(struct rc_dev *dev, struct 
ir_raw_event ev)
struct sharp_dec *data = &dev->raw->sharp;
u32 msg, echo, address, command, scancode;
 
-   if (!(dev->enabled_protocols & RC_BIT_SHARP))
-   return 0;
-
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
diff --git a/drivers/media/rc/ir-sony-decoder.c 

[PATCH 1/8] media: rc: fix decoder module unloading

2015-11-16 Thread Heiner Kallweit
Currently, if a decoder module is unloadad, the respective protocol
is still shown as enabled (if it was enabled before).
Fix this by resetting the respective protocol bits if a decoder
module is unloaded.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-ir-raw.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index ad26052..5cfb61f 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -246,6 +246,14 @@ static int change_protocol(struct rc_dev *dev, u64 
*rc_type)
return 0;
 }
 
+static void ir_raw_disable_protocols(struct rc_dev *dev, u64 protocols)
+{
+   mutex_lock(&dev->lock);
+   dev->enabled_protocols &= ~protocols;
+   dev->enabled_wakeup_protocols &= ~protocols;
+   mutex_unlock(&dev->lock);
+}
+
 /*
  * Used to (un)register raw event clients
  */
@@ -337,13 +345,16 @@ EXPORT_SYMBOL(ir_raw_handler_register);
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
 {
struct ir_raw_event_ctrl *raw;
+   u64 protocols = ir_raw_handler->protocols;
 
mutex_lock(&ir_raw_handler_lock);
list_del(&ir_raw_handler->list);
-   if (ir_raw_handler->raw_unregister)
-   list_for_each_entry(raw, &ir_raw_client_list, list)
+   list_for_each_entry(raw, &ir_raw_client_list, list) {
+   ir_raw_disable_protocols(raw->dev, protocols);
+   if (ir_raw_handler->raw_unregister)
ir_raw_handler->raw_unregister(raw->dev);
-   available_protocols &= ~ir_raw_handler->protocols;
+   }
+   available_protocols &= ~protocols;
mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] media: rc: define RC_BIT_ALL as ~0

2015-11-16 Thread Heiner Kallweit
RC_BIT_ALL explicitely lists each single currently defined protocol bit.
To simplify the code and make adding a protocol easier set each bit
no matter whether the respective protocol is defined yet.

RC_BIT_ALL is only used in checks whether a particular protocol is allowed
therefore it has no impact if bits for not (yet) defined protocols
are set.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-main.c |  1 -
 include/media/rc-map.h | 10 +-
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index d1611f1..d7055e1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1447,7 +1447,6 @@ int rc_register_device(struct rc_dev *dev)
kfree(path);
 
if (dev->driver_type == RC_DRIVER_IR_RAW) {
-   dev->allowed_protocols |= RC_BIT_LIRC;
/* calls ir_register_device so unlock mutex here*/
mutex_unlock(&dev->lock);
rc = ir_raw_event_register(dev);
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 7844e98..27aaf6b 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -54,15 +54,7 @@ enum rc_type {
 #define RC_BIT_SHARP   (1ULL << RC_TYPE_SHARP)
 #define RC_BIT_XMP (1ULL << RC_TYPE_XMP)
 
-#define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \
-RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
-RC_BIT_JVC | \
-RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20 | \
-RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \
-RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
-RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE | RC_BIT_SHARP | \
-RC_BIT_XMP)
-
+#define RC_BIT_ALL ~RC_BIT_NONE
 
 #define RC_SCANCODE_UNKNOWN(x) (x)
 #define RC_SCANCODE_OTHER(x)   (x)
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/8] media: rc: preparation for on-demand decoder module loading

2015-11-16 Thread Heiner Kallweit
Prepare on-demand decoder module loading by adding a module_name member
to struct proto_names and introducing the related load function.

After this patch of the series the decoder modules are still loaded
unconditionally.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-main.c | 72 +-
 1 file changed, 59 insertions(+), 13 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index c47ed33..cede8bc 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -780,27 +780,28 @@ static struct class rc_class = {
 static struct {
u64 type;
char*name;
+   const char  *module_name;
 } proto_names[] = {
-   { RC_BIT_NONE,  "none"  },
-   { RC_BIT_OTHER, "other" },
-   { RC_BIT_UNKNOWN,   "unknown"   },
+   { RC_BIT_NONE,  "none", NULL},
+   { RC_BIT_OTHER, "other",NULL},
+   { RC_BIT_UNKNOWN,   "unknown",  NULL},
{ RC_BIT_RC5 |
- RC_BIT_RC5X,  "rc-5"  },
-   { RC_BIT_NEC,   "nec"   },
+ RC_BIT_RC5X,  "rc-5", "ir-rc5-decoder"},
+   { RC_BIT_NEC,   "nec",  "ir-nec-decoder"},
{ RC_BIT_RC6_0 |
  RC_BIT_RC6_6A_20 |
  RC_BIT_RC6_6A_24 |
  RC_BIT_RC6_6A_32 |
- RC_BIT_RC6_MCE,   "rc-6"  },
-   { RC_BIT_JVC,   "jvc"   },
+ RC_BIT_RC6_MCE,   "rc-6", "ir-rc6-decoder"},
+   { RC_BIT_JVC,   "jvc",  "ir-jvc-decoder"},
{ RC_BIT_SONY12 |
  RC_BIT_SONY15 |
- RC_BIT_SONY20,"sony"  },
-   { RC_BIT_RC5_SZ,"rc-5-sz"   },
-   { RC_BIT_SANYO, "sanyo" },
-   { RC_BIT_SHARP, "sharp" },
-   { RC_BIT_MCE_KBD,   "mce_kbd"   },
-   { RC_BIT_XMP,   "xmp"   },
+ RC_BIT_SONY20,"sony", "ir-sony-decoder"   },
+   { RC_BIT_RC5_SZ,"rc-5-sz",  "ir-rc5-decoder"},
+   { RC_BIT_SANYO, "sanyo","ir-sanyo-decoder"  },
+   { RC_BIT_SHARP, "sharp","ir-sharp-decoder"  },
+   { RC_BIT_MCE_KBD,   "mce_kbd",  "ir-mce_kbd-decoder"},
+   { RC_BIT_XMP,   "xmp",  "ir-xmp-decoder"},
 };
 
 /**
@@ -979,6 +980,48 @@ static int parse_protocol_change(u64 *protocols, const 
char *buf)
return count;
 }
 
+static void ir_raw_load_modules(u64 *protocols)
+
+{
+   u64 available;
+   int i, ret;
+
+   for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+   if (proto_names[i].type == RC_BIT_NONE ||
+   proto_names[i].type & (RC_BIT_OTHER | RC_BIT_UNKNOWN))
+   continue;
+
+   available = ir_raw_get_allowed_protocols();
+   if (!(*protocols & proto_names[i].type & ~available))
+   continue;
+
+   if (!proto_names[i].module_name) {
+   pr_err("Can't enable IR protocol %s\n",
+  proto_names[i].name);
+   *protocols &= ~proto_names[i].type;
+   continue;
+   }
+
+   ret = request_module("%s", proto_names[i].module_name);
+   if (ret < 0) {
+   pr_err("Couldn't load IR protocol module %s\n",
+  proto_names[i].module_name);
+   *protocols &= ~proto_names[i].type;
+   continue;
+   }
+   msleep(20);
+   available = ir_raw_get_allowed_protocols();
+   if (!(*protocols & proto_names[i].type & ~available))
+   continue;
+
+   pr_err("Loaded IR protocol module %s, \
+  but protocol %s still not available\n",
+  proto_names[i].module_name,
+  proto_names[i].name);
+   *protocols &= ~proto_names[i].type;
+   }
+}
+
 /**
  * store_protocols() - changes the current/wakeup IR protocol(s)
  * @device:the device descriptor
@@ -1045,6 +1088,9 @@ static ssize_t store_protocols(struct device *device,
goto out;
}
 
+   if (dev->driver_type == RC_DRIVER_IR_RAW)
+   ir_raw_load_modules(&new_protocols);
+
if (new_protocols != old_protocols) {
*current_protocols = new_protocols;
IR_dprintk(1, "Protocols changed to 0x%llx\n",
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/8] media: rc: improve RC_BIT_ constant definition

2015-11-16 Thread Heiner Kallweit
The RC_BIT_ constants are used in 64-bit bitmaps.
In case of > 32 RC_BIT_ constants the current code will fail
on 32-bit systems.
Therefore define the RC_BIT_ constants as unsigned long long.

Signed-off-by: Heiner Kallweit 
---
 include/media/rc-map.h | 40 
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 7c4bbc4..7844e98 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -33,26 +33,26 @@ enum rc_type {
RC_TYPE_XMP = 18,   /* XMP protocol */
 };
 
-#define RC_BIT_NONE0
-#define RC_BIT_UNKNOWN (1 << RC_TYPE_UNKNOWN)
-#define RC_BIT_OTHER   (1 << RC_TYPE_OTHER)
-#define RC_BIT_RC5 (1 << RC_TYPE_RC5)
-#define RC_BIT_RC5X(1 << RC_TYPE_RC5X)
-#define RC_BIT_RC5_SZ  (1 << RC_TYPE_RC5_SZ)
-#define RC_BIT_JVC (1 << RC_TYPE_JVC)
-#define RC_BIT_SONY12  (1 << RC_TYPE_SONY12)
-#define RC_BIT_SONY15  (1 << RC_TYPE_SONY15)
-#define RC_BIT_SONY20  (1 << RC_TYPE_SONY20)
-#define RC_BIT_NEC (1 << RC_TYPE_NEC)
-#define RC_BIT_SANYO   (1 << RC_TYPE_SANYO)
-#define RC_BIT_MCE_KBD (1 << RC_TYPE_MCE_KBD)
-#define RC_BIT_RC6_0   (1 << RC_TYPE_RC6_0)
-#define RC_BIT_RC6_6A_20   (1 << RC_TYPE_RC6_6A_20)
-#define RC_BIT_RC6_6A_24   (1 << RC_TYPE_RC6_6A_24)
-#define RC_BIT_RC6_6A_32   (1 << RC_TYPE_RC6_6A_32)
-#define RC_BIT_RC6_MCE (1 << RC_TYPE_RC6_MCE)
-#define RC_BIT_SHARP   (1 << RC_TYPE_SHARP)
-#define RC_BIT_XMP (1 << RC_TYPE_XMP)
+#define RC_BIT_NONE0ULL
+#define RC_BIT_UNKNOWN (1ULL << RC_TYPE_UNKNOWN)
+#define RC_BIT_OTHER   (1ULL << RC_TYPE_OTHER)
+#define RC_BIT_RC5 (1ULL << RC_TYPE_RC5)
+#define RC_BIT_RC5X(1ULL << RC_TYPE_RC5X)
+#define RC_BIT_RC5_SZ  (1ULL << RC_TYPE_RC5_SZ)
+#define RC_BIT_JVC (1ULL << RC_TYPE_JVC)
+#define RC_BIT_SONY12  (1ULL << RC_TYPE_SONY12)
+#define RC_BIT_SONY15  (1ULL << RC_TYPE_SONY15)
+#define RC_BIT_SONY20  (1ULL << RC_TYPE_SONY20)
+#define RC_BIT_NEC (1ULL << RC_TYPE_NEC)
+#define RC_BIT_SANYO   (1ULL << RC_TYPE_SANYO)
+#define RC_BIT_MCE_KBD (1ULL << RC_TYPE_MCE_KBD)
+#define RC_BIT_RC6_0   (1ULL << RC_TYPE_RC6_0)
+#define RC_BIT_RC6_6A_20   (1ULL << RC_TYPE_RC6_6A_20)
+#define RC_BIT_RC6_6A_24   (1ULL << RC_TYPE_RC6_6A_24)
+#define RC_BIT_RC6_6A_32   (1ULL << RC_TYPE_RC6_6A_32)
+#define RC_BIT_RC6_MCE (1ULL << RC_TYPE_RC6_MCE)
+#define RC_BIT_SHARP   (1ULL << RC_TYPE_SHARP)
+#define RC_BIT_XMP (1ULL << RC_TYPE_XMP)
 
 #define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \
 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/8] media: rc: constify struct proto_names

2015-11-16 Thread Heiner Kallweit
Declare struct proto_names and its member name as const.

Signed-off-by: Heiner Kallweit 
---
 drivers/media/rc/rc-main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index cede8bc..f2d5c50 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -777,9 +777,9 @@ static struct class rc_class = {
  * used by the sysfs protocols file. Note that the order
  * of the entries is relevant.
  */
-static struct {
+static const struct {
u64 type;
-   char*name;
+   const char  *name;
const char  *module_name;
 } proto_names[] = {
{ RC_BIT_NONE,  "none", NULL},
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >