V4L/DVB: ir-core: Add callbacks for input/evdev open/close on IR core
authorMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 31 Mar 2010 17:40:35 +0000 (14:40 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 18 May 2010 03:53:03 +0000 (00:53 -0300)
Especially when IR needs to do polling, it generates lots of wakeups per
second. This makes no sense, if the input event device is closed.

Adds a callback handler to the IR hardware driver, to allow registering
an open/close ops.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/IR/ir-keytable.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
include/media/ir-common.h
include/media/ir-core.h

index fcb0f0cb1fe1e607826f9d19b641f40847186b36..99cad829a18a34a467b0ba3bd6785bf7ec249eac 100644 (file)
@@ -446,6 +446,19 @@ void ir_keydown(struct input_dev *dev, int scancode)
 }
 EXPORT_SYMBOL_GPL(ir_keydown);
 
+static int ir_open(struct input_dev *input_dev)
+{
+       struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+
+       return ir_dev->props->open(ir_dev->props->priv);
+}
+
+static void ir_close(struct input_dev *input_dev)
+{
+       struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+
+       ir_dev->props->close(ir_dev->props->priv);
+}
 
 /**
  * ir_input_register() - sets the IR keycode table and add the handlers
@@ -495,6 +508,10 @@ int ir_input_register(struct input_dev *input_dev,
 
        ir_copy_table(&ir_dev->rc_tab, rc_tab);
        ir_dev->props = props;
+       if (props && props->open)
+               input_dev->open = ir_open;
+       if (props && props->close)
+               input_dev->close = ir_close;
 
        /* set the bits for the keys */
        IR_dprintk(1, "key map size: %d\n", rc_tab->size);
index a7ad7810fddcc96454abcc1f806c7d289cd2cb79..68cda10e0783987c61837efd225c7cbff1b030ac 100644 (file)
@@ -1227,7 +1227,7 @@ static int saa7134_resume(struct pci_dev *pci_dev)
        if (card_has_mpeg(dev))
                saa7134_ts_init_hw(dev);
        if (dev->remote)
-               saa7134_ir_start(dev, dev->remote);
+               saa7134_ir_start(dev);
        saa7134_hw_enable1(dev);
 
        msleep(100);
index e278d7304b3a3cb93d3d16989af131c41f07d34f..ae17b853f95722d1ef298e4b95c2520b8c3f29b6 100644 (file)
@@ -400,7 +400,14 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
-       struct card_ir *ir = dev->remote;
+       struct card_ir *ir;
+
+       if (!dev || !dev->remote)
+               return;
+
+       ir = dev->remote;
+       if (!ir->running)
+               return;
 
        if (ir->nec_gpio) {
                saa7134_nec_irq(dev);
@@ -432,10 +439,20 @@ void ir_raw_decode_timer_end(unsigned long data)
        ir->active = 0;
 }
 
-void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
+static int __saa7134_ir_start(void *priv)
 {
+       struct saa7134_dev *dev = priv;
+       struct card_ir *ir;
+
+       if (!dev)
+               return -EINVAL;
+
+       ir  = dev->remote;
+       if (!ir)
+               return -EINVAL;
+
        if (ir->running)
-               return;
+               return 0;
 
        ir->running = 1;
        if (ir->polling) {
@@ -467,11 +484,21 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
                ir->timer_end.data = (unsigned long)dev;
                ir->active = 0;
        }
+
+       return 0;
 }
 
-void saa7134_ir_stop(struct saa7134_dev *dev)
+static void __saa7134_ir_stop(void *priv)
 {
-       struct card_ir *ir = dev->remote;
+       struct saa7134_dev *dev = priv;
+       struct card_ir *ir;
+
+       if (!dev)
+               return;
+
+       ir  = dev->remote;
+       if (!ir)
+               return;
 
        if (!ir->running)
                return;
@@ -487,8 +514,42 @@ void saa7134_ir_stop(struct saa7134_dev *dev)
        }
 
        ir->running = 0;
+
+       return;
+}
+
+int saa7134_ir_start(struct saa7134_dev *dev)
+{
+       if (dev->remote->users)
+               return __saa7134_ir_start(dev);
+
+       return 0;
+}
+
+void saa7134_ir_stop(struct saa7134_dev *dev)
+{
+       if (dev->remote->users)
+               __saa7134_ir_stop(dev);
+}
+
+static int saa7134_ir_open(void *priv)
+{
+       struct saa7134_dev *dev = priv;
+
+       dev->remote->users++;
+       return __saa7134_ir_start(dev);
+}
+
+static void saa7134_ir_close(void *priv)
+{
+       struct saa7134_dev *dev = priv;
+
+       dev->remote->users--;
+       if (!dev->remote->users)
+               __saa7134_ir_stop(dev);
 }
 
+
 int saa7134_ir_change_protocol(void *priv, u64 ir_type)
 {
        struct saa7134_dev *dev = priv;
@@ -513,7 +574,7 @@ int saa7134_ir_change_protocol(void *priv, u64 ir_type)
                saa7134_ir_stop(dev);
                ir->nec_gpio = nec_gpio;
                ir->rc5_gpio = rc5_gpio;
-               saa7134_ir_start(dev, ir);
+               saa7134_ir_start(dev);
        } else {
                ir->nec_gpio = nec_gpio;
                ir->rc5_gpio = rc5_gpio;
@@ -788,9 +849,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
                 pci_name(dev->pci));
 
+
+       ir->props.priv = dev;
+       ir->props.open = saa7134_ir_open;
+       ir->props.close = saa7134_ir_close;
+
        if (ir_codes->ir_type != IR_TYPE_OTHER && !raw_decode) {
                ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC;
-               ir->props.priv = dev;
                ir->props.change_protocol = saa7134_ir_change_protocol;
 
                /* Set IR protocol */
@@ -815,25 +880,21 @@ int saa7134_input_init1(struct saa7134_dev *dev)
 
        err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME);
        if (err)
-               goto err_out_stop;
+               goto err_out_free;
        if (ir_codes->ir_type != IR_TYPE_OTHER) {
                err = ir_raw_event_register(ir->dev);
                if (err)
-                       goto err_out_stop;
+                       goto err_out_free;
        }
 
-       saa7134_ir_start(dev, ir);
-
        /* the remote isn't as bouncy as a keyboard */
        ir->dev->rep[REP_DELAY] = repeat_delay;
        ir->dev->rep[REP_PERIOD] = repeat_period;
 
        return 0;
 
- err_out_stop:
-       saa7134_ir_stop(dev);
+err_out_free:
        dev->remote = NULL;
- err_out_free:
        kfree(ir);
        return err;
 }
index c3a1ae0adca02e4e76ca9023d366ae979a3b07ed..cad8aee98e5346684d02dc3624c1f73f349c3ed3 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,15)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0, 2, 16)
 
 #include <linux/pci.h>
 #include <linux/i2c.h>
@@ -810,7 +810,7 @@ int  saa7134_input_init1(struct saa7134_dev *dev);
 void saa7134_input_fini(struct saa7134_dev *dev);
 void saa7134_input_irq(struct saa7134_dev *dev);
 void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
-void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir);
+int saa7134_ir_start(struct saa7134_dev *dev);
 void saa7134_ir_stop(struct saa7134_dev *dev);
 
 
index 87f2ec78deb87602c54db2fb2524a3905eb30833..e403a9a5281a61ff56e7261c7d833e6e3f913189 100644 (file)
@@ -50,6 +50,7 @@ struct card_ir {
        struct ir_input_state   ir;
        char                    name[32];
        char                    phys[32];
+       int                     users;
 
        u32                     running:1;
        struct ir_dev_props     props;
index c704fa7cc11ee47fa1c132af396f71049b3c4d79..9a2f3084ffecae55c29f64d996b6817b762dbd3e 100644 (file)
@@ -56,6 +56,8 @@ struct ir_dev_props {
        unsigned long allowed_protos;
        void            *priv;
        int (*change_protocol)(void *priv, u64 ir_type);
+       int (*open)(void *priv);
+       void (*close)(void *priv);
 };
 
 struct ir_raw_event {