X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fcx88%2Fcx88-input.c;h=8136673fe9e8b5d8d3551748dd7bc50c2c020685;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=c255646489933f19170ec466badc8d1c896693cf;hpb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;p=linux-2.6.git diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index c25564648..8136673fe 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -107,7 +107,15 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) (gpio & ir->mask_keydown) ? " down" : "", (gpio & ir->mask_keyup) ? " up" : ""); - if (ir->mask_keydown) { + if (ir->core->board == CX88_BOARD_NORWOOD_MICRO) { + u32 gpio_key = cx_read(MO_GP0_IO); + + data = (data << 4) | ((gpio_key & 0xf0) >> 4); + + ir_input_keydown(ir->input, &ir->ir, data, data); + ir_input_nokey(ir->input, &ir->ir); + + } else if (ir->mask_keydown) { /* bit set on keydown */ if (gpio & ir->mask_keydown) { ir_input_keydown(ir->input, &ir->ir, data, data); @@ -137,9 +145,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void cx88_ir_work(void *data) +static void cx88_ir_work(struct work_struct *work) { - struct cx88_IR *ir = data; + struct cx88_IR *ir = container_of(work, struct cx88_IR, work); unsigned long timeout; cx88_ir_handle_key(ir); @@ -147,6 +155,35 @@ static void cx88_ir_work(void *data) mod_timer(&ir->timer, timeout); } +static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) +{ + if (ir->polling) { + INIT_WORK(&ir->work, cx88_ir_work); + init_timer(&ir->timer); + ir->timer.function = ir_timer; + ir->timer.data = (unsigned long)ir; + schedule_work(&ir->work); + } + if (ir->sampling) { + core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ + cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ + cx_write(MO_DDSCFG_IO, 0x5); /* enable */ + } +} + +static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) +{ + if (ir->sampling) { + cx_write(MO_DDSCFG_IO, 0x0); + core->pci_irqmask &= ~(1 << 18); + } + + if (ir->polling) { + del_timer_sync(&ir->timer); + flush_scheduled_work(); + } +} + /* ---------------------------------------------------------------------- */ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) @@ -155,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) struct input_dev *input_dev; IR_KEYTAB_TYPE *ir_codes = NULL; int ir_type = IR_TYPE_OTHER; + int err = -ENOMEM; ir = kzalloc(sizeof(*ir), GFP_KERNEL); input_dev = input_allocate_device(); - if (!ir || !input_dev) { - kfree(ir); - input_free_device(input_dev); - return -ENOMEM; - } + if (!ir || !input_dev) + goto err_out_free; ir->input = input_dev; @@ -187,18 +222,26 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_HVR1100: + case CX88_BOARD_HAUPPAUGE_HVR1300: + case CX88_BOARD_HAUPPAUGE_HVR3000: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: - case CX88_BOARD_WINFAST2000XP_EXPERT: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; ir->polling = 50; /* ms */ break; + case CX88_BOARD_WINFAST2000XP_EXPERT: + ir_codes = ir_codes_winfast; + ir->gpio_addr = MO_GP0_IO; + ir->mask_keycode = 0x8f8; + ir->mask_keyup = 0x100; + ir->polling = 1; /* ms */ + break; case CX88_BOARD_IODATA_GVBCTV7E: ir_codes = ir_codes_iodata_bctv7e; ir->gpio_addr = MO_GP0_IO; @@ -206,7 +249,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keydown = 0x02; ir->polling = 5; /* ms */ break; - case CX88_BOARD_PROLINK_PLAYTVPVR: + case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: ir_codes = ir_codes_pixelview; ir->gpio_addr = MO_GP1_IO; @@ -248,6 +291,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; + case CX88_BOARD_NORWOOD_MICRO: + ir_codes = ir_codes_norwood; + ir->gpio_addr = MO_GP1_IO; + ir->mask_keycode = 0x0e; + ir->mask_keyup = 0x80; + ir->polling = 50; /* ms */ + break; case CX88_BOARD_NPGTECH_REALTV_TOP10FM: ir_codes = ir_codes_npgtech; ir->gpio_addr = MO_GP0_IO; @@ -257,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) } if (NULL == ir_codes) { - kfree(ir); - input_free_device(input_dev); - return -ENODEV; + err = -ENODEV; + goto err_out_free; } /* init input device */ @@ -284,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->core = core; core->ir = ir; - if (ir->polling) { - INIT_WORK(&ir->work, cx88_ir_work, ir); - init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; - schedule_work(&ir->work); - } - if (ir->sampling) { - core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ - cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ - cx_write(MO_DDSCFG_IO, 0x5); /* enable */ - } + cx88_ir_start(core, ir); /* all done */ - input_register_device(ir->input); + err = input_register_device(ir->input); + if (err) + goto err_out_stop; return 0; + + err_out_stop: + cx88_ir_stop(core, ir); + core->ir = NULL; + err_out_free: + input_free_device(input_dev); + kfree(ir); + return err; } int cx88_ir_fini(struct cx88_core *core) @@ -311,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core) if (NULL == ir) return 0; - if (ir->sampling) { - cx_write(MO_DDSCFG_IO, 0x0); - core->pci_irqmask &= ~(1 << 18); - } - if (ir->polling) { - del_timer(&ir->timer); - flush_scheduled_work(); - } - + cx88_ir_stop(core, ir); input_unregister_device(ir->input); kfree(ir); @@ -402,6 +442,8 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_HVR1100: + case CX88_BOARD_HAUPPAUGE_HVR1300: + case CX88_BOARD_HAUPPAUGE_HVR3000: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); if ((ircode & 0xfffff000) != 0x3000)