V4L/DVB (4876): budget-ci IR: support EVIOCGPHYS
[pandora-kernel.git] / drivers / media / dvb / ttpci / budget-ci.c
index ffbbb3e..0809fb9 100644 (file)
 #include "bsbe1.h"
 #include "bsru6.h"
 
-#define DEBIADDR_IR            0x1234
+/*
+ * Regarding DEBIADDR_IR:
+ * Some CI modules hang if random addresses are read.
+ * Using address 0x4000 for the IR read means that we
+ * use the same address as for CI version, which should
+ * be a safe default.
+ */
+#define DEBIADDR_IR            0x4000
 #define DEBIADDR_CICONTROL     0x0000
 #define DEBIADDR_CIVERSION     0x4000
 #define DEBIADDR_IO            0x1000
 #define SLOTSTATUS_READY       8
 #define SLOTSTATUS_OCCUPIED    (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
+struct budget_ci_ir {
+       struct input_dev *dev;
+       struct tasklet_struct msp430_irq_tasklet;
+       char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
+       char phys[32];
+};
+
 struct budget_ci {
        struct budget budget;
-       struct input_dev *input_dev;
-       struct tasklet_struct msp430_irq_tasklet;
        struct tasklet_struct ciintf_irq_tasklet;
        int slot_status;
        int ci_irq;
        struct dvb_ca_en50221 ca;
-       char ir_dev_name[50];
+       struct budget_ci_ir ir;
        u8 tuner_pll_address; /* used for philips_tdm1316l configs */
 };
 
@@ -136,20 +148,20 @@ 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);
-               return;
+               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 */
        }
-
-       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 */
+       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->input_dev;
+       struct input_dev *dev = budget_ci->ir.dev;
        unsigned int code =
                ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
@@ -162,7 +174,7 @@ static void msp430_ir_interrupt(unsigned long data)
                                return;
                        }
                        del_timer(&dev->timer);
-                       input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+                       input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
                }
 
                if (!key_map[code]) {
@@ -170,38 +182,63 @@ static void msp430_ir_interrupt(unsigned long data)
                        return;
                }
 
+               input_event(dev, EV_KEY, key_map[code], 1);
+               input_sync(dev);
+
                /* initialize debounce and repeat */
                dev->repeat_key = code;
                /* Zenith remote _always_ sends 2 sequences */
                dev->rep[0] = ~0;
-               /* 350 milliseconds */
-               dev->timer.expires = jiffies + HZ * 350 / 1000;
-               /* MAKE */
-               input_event(dev, EV_KEY, key_map[code], !0);
-               add_timer(&dev->timer);
+               mod_timer(&dev->timer, jiffies + msecs_to_jiffies(350));
        }
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
 {
        struct saa7146_dev *saa = budget_ci->budget.dev;
-       struct input_dev *input_dev;
+       struct input_dev *input_dev = budget_ci->ir.dev;
        int i;
+       int err;
 
-       budget_ci->input_dev = input_dev = input_allocate_device();
+       budget_ci->ir.dev = input_dev = input_allocate_device();
        if (!input_dev)
                return -ENOMEM;
 
-       sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
+       snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
+                "Budget-CI dvb ir receiver %s", saa->name);
+       snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
+                "pci-%s/ir0", pci_name(saa->pci));
 
-       input_dev->name = budget_ci->ir_dev_name;
+       input_dev->name = budget_ci->ir.name;
+
+       input_dev->phys = budget_ci->ir.phys;
+       input_dev->id.bustype = BUS_PCI;
+       input_dev->id.version = 1;
+       if (saa->pci->subsystem_vendor) {
+               input_dev->id.vendor = saa->pci->subsystem_vendor;
+               input_dev->id.product = saa->pci->subsystem_device;
+       } else {
+               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
 
        set_bit(EV_KEY, input_dev->evbit);
        for (i = 0; i < ARRAY_SIZE(key_map); i++)
                if (key_map[i])
                        set_bit(key_map[i], input_dev->keybit);
 
-       input_register_device(budget_ci->input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       input_register_device(budget_ci->ir.dev);
 
        input_dev->timer.function = msp430_ir_debounce;
 
@@ -214,13 +251,15 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
 static void msp430_ir_deinit(struct budget_ci *budget_ci)
 {
        struct saa7146_dev *saa = budget_ci->budget.dev;
-       struct input_dev *dev = budget_ci->input_dev;
+       struct input_dev *dev = budget_ci->ir.dev;
 
        saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 
-       if (del_timer(&dev->timer))
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+       if (del_timer(&dev->timer)) {
+               input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
+               input_sync(dev);
+       }
 
        input_unregister_device(dev);
 }
@@ -533,7 +572,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
        dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
 
        if (*isr & MASK_06)
-               tasklet_schedule(&budget_ci->msp430_irq_tasklet);
+               tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
 
        if (*isr & MASK_10)
                ttpci_budget_irq10_handler(dev, isr);
@@ -749,17 +788,17 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
        // setup PLL filter and TDA9889
        switch (params->u.ofdm.bandwidth) {
        case BANDWIDTH_6_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0x14);
+               tda1004x_writereg(fe, 0x0C, 0x14);
                filter = 0;
                break;
 
        case BANDWIDTH_7_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0x80);
+               tda1004x_writereg(fe, 0x0C, 0x80);
                filter = 0;
                break;
 
        case BANDWIDTH_8_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0x14);
+               tda1004x_writereg(fe, 0x0C, 0x14);
                filter = 1;
                break;
 
@@ -988,7 +1027,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        switch (budget_ci->budget.dev->pci->subsystem_device) {
        case 0x100c:            // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
                budget_ci->budget.dvb_frontend =
-                       stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
                        budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
@@ -998,7 +1037,7 @@ static void frontend_init(struct budget_ci *budget_ci)
 
        case 0x100f:            // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
                budget_ci->budget.dvb_frontend =
-                       stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
                        break;
@@ -1008,7 +1047,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        case 0x1010:            // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
                budget_ci->tuner_pll_address = 0x61;
                budget_ci->budget.dvb_frontend =
-                       stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
                        break;
@@ -1018,7 +1057,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        case 0x1011:            // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
                budget_ci->tuner_pll_address = 0x63;
                budget_ci->budget.dvb_frontend =
-                       tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(tda10045_attach, &philips_tdm1316l_config, &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;
@@ -1028,8 +1067,9 @@ 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 =
-                       tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(tda10046_attach, &philips_tdm1316l_config, &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;
@@ -1038,16 +1078,15 @@ static void frontend_init(struct budget_ci *budget_ci)
                break;
 
        case 0x1017:            // TT S-1500 PCI
-               budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap);
+               budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
                        budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
 
                        budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
-                       if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
+                       if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
                                printk("%s: No LNBP21 found!\n", __FUNCTION__);
-                               if (budget_ci->budget.dvb_frontend->ops.release)
-                                       budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
+                               dvb_frontend_detach(budget_ci->budget.dvb_frontend);
                                budget_ci->budget.dvb_frontend = NULL;
                        }
                }
@@ -1065,8 +1104,7 @@ static void frontend_init(struct budget_ci *budget_ci)
                if (dvb_register_frontend
                    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
                        printk("budget-ci: Frontend registration failed!\n");
-                       if (budget_ci->budget.dvb_frontend->ops.release)
-                               budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
+                       dvb_frontend_detach(budget_ci->budget.dvb_frontend);
                        budget_ci->budget.dvb_frontend = NULL;
                }
        }
@@ -1091,7 +1129,7 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
                return err;
        }
 
-       tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
+       tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
                     (unsigned long) budget_ci);
 
        msp430_ir_init(budget_ci);
@@ -1114,11 +1152,13 @@ static int budget_ci_detach(struct saa7146_dev *dev)
 
        if (budget_ci->budget.ci_present)
                ciintf_deinit(budget_ci);
-       if (budget_ci->budget.dvb_frontend)
+       if (budget_ci->budget.dvb_frontend) {
                dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
+               dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+       }
        err = ttpci_budget_deinit(&budget_ci->budget);
 
-       tasklet_kill(&budget_ci->msp430_irq_tasklet);
+       tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
        msp430_ir_deinit(budget_ci);
 
@@ -1153,7 +1193,7 @@ static struct pci_device_id pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
-       .name = "budget_ci dvb\0",
+       .name = "budget_ci dvb",
        .flags = SAA7146_I2C_SHORT_DELAY,
 
        .module = THIS_MODULE,