]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/dvb/ttpci/budget-ci.c
V4L/DVB (5335): Budget-ci: Use the repeat handling of the input subsystem
[linux-2.6-omap-h63xx.git] / drivers / media / dvb / ttpci / budget-ci.c
index d1b5402cd6fe8167385d9d563955fcf2c80f2c63..4ed4599ce816b78be6c5f3527ceb9f84028a2e8e 100644 (file)
@@ -29,8 +29,6 @@
  * the project's page is at http://www.linuxtv.org/dvb/
  */
 
-#include "budget.h"
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -39,6 +37,8 @@
 #include <linux/spinlock.h>
 #include <media/ir-common.h>
 
+#include "budget.h"
+
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
 #include "stv0297.h"
 #define SLOTSTATUS_READY       8
 #define SLOTSTATUS_OCCUPIED    (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
-/* Milliseconds during which key presses are regarded as key repeat and during
- * which the debounce logic is active
+/*
+ * Milliseconds during which a key is regarded as pressed.
+ * If an identical command arrives within this time, the timer will start over.
  */
-#define IR_REPEAT_TIMEOUT      350
+#define IR_KEYPRESS_TIMEOUT    250
 
-/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
- * this setting allows the superflous sequences to be ignored
- */
-static int debounce = 0;
-module_param(debounce, int, 0644);
-MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
+/* RC5 device wildcard */
+#define IR_DEVICE_ANY          255
+
+static int rc5_device = -1;
+module_param(rc5_device, int, 0644);
+MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
 
 struct budget_ci_ir {
        struct input_dev *dev;
        struct tasklet_struct msp430_irq_tasklet;
+       struct timer_list timer_keyup;
        char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
        char phys[32];
        struct ir_input_state state;
+       int rc5_device;
+       u32 last_raw;
+       u32 ir_key;
+       bool have_command;
 };
 
 struct budget_ci {
@@ -113,83 +123,57 @@ static void msp430_ir_interrupt(unsigned long data)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) data;
        struct input_dev *dev = budget_ci->ir.dev;
-       static int bounces = 0;
-       u32 ir_key;
        u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
-
+       u32 raw;
+
+       /*
+        * The msp430 chip can generate two different bytes, command and device
+        *
+        * type1: X1CCCCCC, C = command bits (0 - 63)
+        * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
+        *
+        * Each signal from the remote control can generate one or more command
+        * bytes and one or more device bytes. For the repeated bytes, the
+        * highest bit (X) is set. The first command byte is always generated
+        * before the first device byte. Other than that, no specific order
+        * seems to apply. To make life interesting, bytes can also be lost.
+        *
+        * Only when we have a command and device byte, a keypress is
+        * generated.
+        */
+
+       if (ir_debug)
+               printk("budget_ci: received byte 0x%02x\n", command);
+
+       /* Remove repeat bit, we use every command */
+       command = command & 0x7f;
+
+       /* Is this a RC5 command byte? */
        if (command & 0x40) {
-               ir_key = command & 0x3f;
-
-               if (ir_key != dev->repeat_key && del_timer(&dev->timer))
-                       /* We were still waiting for a keyup event but this is a new key */
-                       ir_input_nokey(dev, &budget_ci->ir.state);
-
-               if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) {
-                       /* Ignore repeated key sequences if requested */
-                       bounces--;
-                       return;
-               }
-
-               if (!timer_pending(&dev->timer))
-                       /* New keypress */
-                       bounces = debounce;
-
-               /* Prepare a keyup event sometime in the future */
-               mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
-
-               /* Generate a new or repeated keypress */
-               ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command);
-       }
-}
-
-static void msp430_ir_debounce(unsigned long data)
-{
-       struct input_dev *dev = (struct input_dev *) data;
-
-       if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
-       } else {
-               dev->rep[0] = 0;
-               dev->timer.expires = jiffies + HZ * 350 / 1000;
-               add_timer(&dev->timer);
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], 2);  /* REPEAT */
+               budget_ci->ir.have_command = true;
+               budget_ci->ir.ir_key = command & 0x3f;
+               return;
        }
-       input_sync(dev);
-}
-
-static void msp430_ir_interrupt(unsigned long data)
-{
-       struct budget_ci *budget_ci = (struct budget_ci *) data;
-       struct input_dev *dev = budget_ci->ir.dev;
-       unsigned int code =
-               ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
-
-       if (code & 0x40) {
-               code &= 0x3f;
 
-               if (timer_pending(&dev->timer)) {
-                       if (code == dev->repeat_key) {
-                               ++dev->rep[0];
-                               return;
-                       }
-                       del_timer(&dev->timer);
-                       input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
-               }
-
-               if (!key_map[code]) {
-                       printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
-                       return;
-               }
+       /* It's a RC5 device byte */
+       if (!budget_ci->ir.have_command)
+               return;
+       budget_ci->ir.have_command = false;
 
-               input_event(dev, EV_KEY, key_map[code], 1);
-               input_sync(dev);
+       if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
+           budget_ci->ir.rc5_device != (command & 0x1f))
+               return;
 
-               /* initialize debounce and repeat */
-               dev->repeat_key = code;
-               /* Zenith remote _always_ sends 2 sequences */
-               dev->rep[0] = ~0;
-               mod_timer(&dev->timer, jiffies + msecs_to_jiffies(350));
+       /* Is this a repeated key sequence? (same device, command, toggle) */
+       raw = budget_ci->ir.ir_key | (command << 8);
+       if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
+               ir_input_nokey(dev, &budget_ci->ir.state);
+               ir_input_keydown(dev, &budget_ci->ir.state,
+                                budget_ci->ir.ir_key, raw);
+               budget_ci->ir.last_raw = raw;
        }
+
+       mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
@@ -222,47 +206,65 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
                input_dev->id.vendor = saa->pci->vendor;
                input_dev->id.product = saa->pci->device;
        }
-# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
        input_dev->cdev.dev = &saa->pci->dev;
-# else
-       input_dev->dev = &saa->pci->dev;
-# endif
 
-       /* Select keymap */
+       /* Select keymap and address */
        switch (budget_ci->budget.dev->pci->subsystem_device) {
        case 0x100c:
        case 0x100f:
-       case 0x1010:
        case 0x1011:
        case 0x1012:
        case 0x1017:
                /* The hauppauge keymap is a superset of these remotes */
                ir_input_init(input_dev, &budget_ci->ir.state,
                              IR_TYPE_RC5, ir_codes_hauppauge_new);
+
+               if (rc5_device < 0)
+                       budget_ci->ir.rc5_device = 0x1f;
+               else
+                       budget_ci->ir.rc5_device = rc5_device;
+               break;
+       case 0x1010:
+               /* for the Technotrend 1500 bundled remote */
+               ir_input_init(input_dev, &budget_ci->ir.state,
+                             IR_TYPE_RC5, ir_codes_tt_1500);
+
+               if (rc5_device < 0)
+                       budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+               else
+                       budget_ci->ir.rc5_device = rc5_device;
                break;
        default:
                /* unknown remote */
                ir_input_init(input_dev, &budget_ci->ir.state,
                              IR_TYPE_RC5, ir_codes_budget_ci_old);
+
+               if (rc5_device < 0)
+                       budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+               else
+                       budget_ci->ir.rc5_device = rc5_device;
                break;
        }
 
        /* initialise the key-up timeout handler */
-       input_dev->timer.function = msp430_ir_keyup;
-       input_dev->timer.data = (unsigned long) &budget_ci->ir;
-       input_dev->rep[REP_DELAY] = 1;
-       input_dev->rep[REP_PERIOD] = 1;
-
+       init_timer(&budget_ci->ir.timer_keyup);
+       budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
+       budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
+       budget_ci->ir.last_raw = 0xffff; /* An impossible value */
        error = input_register_device(input_dev);
        if (error) {
                printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
                goto out2;
        }
 
+       /* note: these must be after input_register_device */
+       input_dev->rep[REP_DELAY] = 400;
+       input_dev->rep[REP_PERIOD] = 250;
+
        tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
                     (unsigned long) budget_ci);
 
-       saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
+       SAA7146_IER_ENABLE(saa, MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
        return 0;
@@ -278,14 +280,12 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
        struct saa7146_dev *saa = budget_ci->budget.dev;
        struct input_dev *dev = budget_ci->ir.dev;
 
-       saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
+       SAA7146_IER_DISABLE(saa, MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
        tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
-       if (del_timer(&dev->timer)) {
-               ir_input_nokey(dev, &budget_ci->ir.state);
-               input_sync(dev);
-       }
+       del_timer_sync(&dev->timer);
+       ir_input_nokey(dev, &budget_ci->ir.state);
 
        input_unregister_device(dev);
 }
@@ -486,7 +486,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
        memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
 
        // enable DEBI pins
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
+       saa7146_write(saa, MC1, MASK_27 | MASK_11);
 
        // test if it is there
        ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
@@ -538,7 +538,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
                } else {
                        saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
                }
-               saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
+               SAA7146_IER_ENABLE(saa, MASK_03);
        }
 
        // enable interface
@@ -560,7 +560,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
        return 0;
 
 error:
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+       saa7146_write(saa, MC1, MASK_27);
        return result;
 }
 
@@ -570,7 +570,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
 
        // disable CI interrupts
        if (budget_ci->ci_irq) {
-               saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
+               SAA7146_IER_DISABLE(saa, MASK_03);
                saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
                tasklet_kill(&budget_ci->ciintf_irq_tasklet);
        }
@@ -588,7 +588,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
        dvb_ca_en50221_release(&budget_ci->ca);
 
        // disable DEBI pins
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+       saa7146_write(saa, MC1, MASK_27);
 }
 
 static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
@@ -870,6 +870,17 @@ static struct tda1004x_config philips_tdm1316l_config = {
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
+static struct tda1004x_config philips_tdm1316l_config_invert = {
+
+       .demod_address = 0x8,
+       .invert = 1,
+       .invert_oclk = 0,
+       .xtal_freq = TDA10046_XTAL_4M,
+       .agc_config = TDA10046_AGC_DEFAULT,
+       .if_freq = TDA10046_FREQ_3617,
+       .request_firmware = philips_tdm1316l_request_firmware,
+};
+
 static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
@@ -893,7 +904,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
                band = 1;
        } else if (tuner_frequency < 200000000) {
                cp = 6;
-               band = 1;
+               band = 2;
        } else if (tuner_frequency < 290000000) {
                cp = 3;
                band = 2;
@@ -1093,9 +1104,8 @@ static void frontend_init(struct budget_ci *budget_ci)
 
        case 0x1012:            // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
                budget_ci->tuner_pll_address = 0x60;
-               philips_tdm1316l_config.invert = 1;
                budget_ci->budget.dvb_frontend =
-                       dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
@@ -1223,7 +1233,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
        .name = "budget_ci dvb",
-       .flags = SAA7146_I2C_SHORT_DELAY,
+       .flags = SAA7146_USE_I2C_IRQ,
 
        .module = THIS_MODULE,
        .pci_tbl = &pci_tbl[0],