diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 3 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 149 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 20 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 8 |
6 files changed, 143 insertions, 50 deletions
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index b35411160f0..8b21457111b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -847,7 +847,8 @@ static int set_tvaudio(struct cx88_core *core) { v4l2_std_id norm = core->tvnorm; - if (CX88_VMUX_TELEVISION != INPUT(core->input).type) + if (CX88_VMUX_TELEVISION != INPUT(core->input).type && + CX88_VMUX_CABLE != INPUT(core->input).type) return 0; if (V4L2_STD_PAL_BG & norm) { diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 94ab862f021..faa8e8163a4 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -1231,7 +1231,7 @@ static int dvb_register(struct cx8802_dev *dev) fe->ops.tuner_ops.set_config(fe, &ctl); } break; - case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_PINNACLE_HYBRID_PCTV: case CX88_BOARD_WINFAST_DTV1800H: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 6b6abf062c2..e185289e446 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -32,12 +32,18 @@ #include "cx88.h" #include <media/ir-common.h> +#define MODULE_NAME "cx88xx" + /* ---------------------------------------------------------------------- */ struct cx88_IR { struct cx88_core *core; struct input_dev *input; struct ir_input_state ir; + struct ir_dev_props props; + + int users; + char name[32]; char phys[32]; @@ -159,8 +165,16 @@ static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) return HRTIMER_RESTART; } -void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) +static int __cx88_ir_start(void *priv) { + struct cx88_core *core = priv; + struct cx88_IR *ir; + + if (!core || !core->ir) + return -EINVAL; + + ir = core->ir; + if (ir->polling) { hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ir->timer.function = cx88_ir_work; @@ -173,10 +187,18 @@ void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ cx_write(MO_DDSCFG_IO, 0x5); /* enable */ } + return 0; } -void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) +static void __cx88_ir_stop(void *priv) { + struct cx88_core *core = priv; + struct cx88_IR *ir; + + if (!core || !core->ir) + return; + + ir = core->ir; if (ir->sampling) { cx_write(MO_DDSCFG_IO, 0x0); core->pci_irqmask &= ~PCI_INT_IR_SMPINT; @@ -186,15 +208,49 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) hrtimer_cancel(&ir->timer); } +int cx88_ir_start(struct cx88_core *core) +{ + if (core->ir->users) + return __cx88_ir_start(core); + + return 0; +} + +void cx88_ir_stop(struct cx88_core *core) +{ + if (core->ir->users) + __cx88_ir_stop(core); +} + +static int cx88_ir_open(void *priv) +{ + struct cx88_core *core = priv; + + core->ir->users++; + return __cx88_ir_start(core); +} + +static void cx88_ir_close(void *priv) +{ + struct cx88_core *core = priv; + + core->ir->users--; + if (!core->ir->users) + __cx88_ir_stop(core); +} + /* ---------------------------------------------------------------------- */ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) { struct cx88_IR *ir; struct input_dev *input_dev; - struct ir_scancode_table *ir_codes = NULL; + char *ir_codes = NULL; u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; + u32 hardware_mask = 0; /* For devices with a hardware mask, when + * used with a full-code IR table + */ ir = kzalloc(sizeof(*ir), GFP_KERNEL); input_dev = input_allocate_device(); @@ -208,15 +264,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_KWORLD_DVB_T_CX22702: - ir_codes = &ir_codes_dntv_live_dvb_t_table; + ir_codes = RC_MAP_DNTV_LIVE_DVB_T; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 50; /* ms */ break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - ir_codes = &ir_codes_cinergy_1400_table; - ir_type = IR_TYPE_PD; + ir_codes = RC_MAP_CINERGY_1400; + ir_type = IR_TYPE_NEC; ir->sampling = 0xeb04; /* address */ break; case CX88_BOARD_HAUPPAUGE: @@ -230,14 +286,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: case CX88_BOARD_HAUPPAUGE_IRONLY: - ir_codes = &ir_codes_hauppauge_new_table; + ir_codes = RC_MAP_HAUPPAUGE_NEW; ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: - ir_codes = &ir_codes_winfast_table; + ir_codes = RC_MAP_WINFAST; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; @@ -246,14 +302,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_WINFAST2000XP_EXPERT: case CX88_BOARD_WINFAST_DTV1000: case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - ir_codes = &ir_codes_winfast_table; + ir_codes = RC_MAP_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_table; + ir_codes = RC_MAP_IODATA_BCTV7E; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfd; ir->mask_keydown = 0x02; @@ -261,36 +317,43 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: - ir_codes = &ir_codes_pixelview_table; + /* + * It seems that this hardware is paired with NEC extended + * address 0x866b. So, unfortunately, its usage with other + * IR's with different address won't work. Still, there are + * other IR's from the same manufacturer that works, like the + * 002-T mini RC, provided with newer PV hardware + */ + ir_codes = RC_MAP_PIXELVIEW_MK12; ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x1f; ir->mask_keyup = 0x80; - ir->polling = 1; /* ms */ + ir->polling = 10; /* ms */ + hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */ break; case CX88_BOARD_PROLINK_PV_8000GT: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - ir_codes = &ir_codes_pixelview_new_table; + ir_codes = RC_MAP_PIXELVIEW_NEW; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x3f; ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; case CX88_BOARD_KWORLD_LTV883: - ir_codes = &ir_codes_pixelview_table; + ir_codes = RC_MAP_PIXELVIEW; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 1; /* ms */ break; case CX88_BOARD_ADSTECH_DVB_T_PCI: - ir_codes = &ir_codes_adstech_dvb_t_pci_table; + ir_codes = RC_MAP_ADSTECH_DVB_T_PCI; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0xbf; ir->mask_keyup = 0x40; ir->polling = 50; /* ms */ break; case CX88_BOARD_MSI_TVANYWHERE_MASTER: - ir_codes = &ir_codes_msi_tvanywhere_table; + ir_codes = RC_MAP_MSI_TVANYWHERE; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x40; @@ -298,7 +361,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_AVERTV_303: case CX88_BOARD_AVERTV_STUDIO_303: - ir_codes = &ir_codes_avertv_303_table; + ir_codes = RC_MAP_AVERTV_303; ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0xfb; ir->mask_keydown = 0x02; @@ -311,41 +374,41 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PROF_7300: case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: - ir_codes = &ir_codes_tbs_nec_table; - ir_type = IR_TYPE_PD; + ir_codes = RC_MAP_TBS_NEC; + ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: - ir_codes = &ir_codes_tevii_nec_table; - ir_type = IR_TYPE_PD; + ir_codes = RC_MAP_TEVII_NEC; + ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - ir_codes = &ir_codes_dntv_live_dvbt_pro_table; - ir_type = IR_TYPE_PD; + ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; + ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: - ir_codes = &ir_codes_norwood_table; + ir_codes = RC_MAP_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_table; + ir_codes = RC_MAP_NPGTECH; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfa; ir->polling = 50; /* ms */ break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ir_codes = &ir_codes_pinnacle_pctv_hd_table; + ir_codes = RC_MAP_PINNACLE_PCTV_HD; ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - ir_codes = &ir_codes_powercolor_real_angel_table; + ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL; ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0x7e; ir->polling = 100; /* ms */ @@ -357,6 +420,21 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) goto err_out_free; } + /* + * The usage of mask_keycode were very convenient, due to several + * reasons. Among others, the scancode tables were using the scancode + * as the index elements. So, the less bits it was used, the smaller + * the table were stored. After the input changes, the better is to use + * the full scancodes, since it allows replacing the IR remote by + * another one. Unfortunately, there are still some hardware, like + * Pixelview Ultra Pro, where only part of the scancode is sent via + * GPIO. So, there's no way to get the full scancode. Due to that, + * hardware_mask were introduced here: it represents those hardware + * that has such limits. + */ + if (hardware_mask && !ir->mask_keycode) + ir->mask_keycode = hardware_mask; + /* init input device */ snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); @@ -381,19 +459,20 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->core = core; core->ir = ir; - cx88_ir_start(core, ir); + ir->props.priv = core; + ir->props.open = cx88_ir_open; + ir->props.close = cx88_ir_close; + ir->props.scanmask = hardware_mask; /* all done */ - err = ir_input_register(ir->input, ir_codes, NULL); + err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); if (err) - goto err_out_stop; + goto err_out_free; return 0; - err_out_stop: - cx88_ir_stop(core, ir); - core->ir = NULL; err_out_free: + core->ir = NULL; kfree(ir); return err; } @@ -406,7 +485,7 @@ int cx88_ir_fini(struct cx88_core *core) if (NULL == ir) return 0; - cx88_ir_stop(core, ir); + cx88_ir_stop(core); ir_input_unregister(ir->input); kfree(ir); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6aba7af9160..499f8d512ad 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -599,13 +599,22 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board static int cx8802_request_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; + unsigned int i; /* Fail a request for hardware if the device is busy. */ if (core->active_type_id != CX88_BOARD_NONE && core->active_type_id != drv->type_id) return -EBUSY; - core->input = CX88_VMUX_DVB; + core->input = 0; + for (i = 0; + i < (sizeof(core->board.input) / sizeof(struct cx88_input)); + i++) { + if (core->board.input[i].type == CX88_VMUX_DVB) { + core->input = i; + break; + } + } if (drv->advise_acquire) { diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 48c450f4a85..0fab65c3ab3 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -426,12 +426,13 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) if (core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { call_all(core, audio, s_routing, - INPUT(input).audioroute, 0, 0); + INPUT(input).audioroute, 0, 0); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with chroma, so an external must be used for baseband audio */ - if (INPUT(input).type != CX88_VMUX_TELEVISION ) { + if (INPUT(input).type != CX88_VMUX_TELEVISION && + INPUT(input).type != CX88_VMUX_CABLE) { /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; cx88_set_tvaudio(core); @@ -561,8 +562,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) *size = fh->fmt->depth*fh->width*fh->height >> 3; if (0 == *count) *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; return 0; } @@ -1537,9 +1538,12 @@ static int radio_queryctrl (struct file *file, void *priv, c->id >= V4L2_CID_LASTP1) return -EINVAL; if (c->id == V4L2_CID_AUDIO_MUTE) { - for (i = 0; i < CX8800_CTLS; i++) + for (i = 0; i < CX8800_CTLS; i++) { if (cx8800_ctls[i].v.id == c->id) break; + } + if (i == CX8800_CTLS) + return -EINVAL; *c = cx8800_ctls[i].v; } else *c = no_ctl; @@ -1977,7 +1981,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) } if (core->ir) - cx88_ir_stop(core, core->ir); + cx88_ir_stop(core); cx88_shutdown(core); /* FIXME */ pci_disable_device(pci_dev); @@ -2015,7 +2019,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) spin_unlock(&dev->slock); if (core->ir) - cx88_ir_stop(core, core->ir); + cx88_ir_stop(core); /* FIXME -- shutdown device */ cx88_shutdown(core); @@ -2056,7 +2060,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) /* FIXME: re-initialize hardware */ cx88_reset(core); if (core->ir) - cx88_ir_start(core, core->ir); + cx88_ir_start(core); cx_set(MO_PCI_INTMSK, core->pci_irqmask); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 48b6c04fb49..bdb03d33653 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -41,7 +41,7 @@ #include <linux/version.h> #include <linux/mutex.h> -#define CX88_VERSION_CODE KERNEL_VERSION(0,0,7) +#define CX88_VERSION_CODE KERNEL_VERSION(0, 0, 8) #define UNSET (-1U) @@ -290,7 +290,7 @@ struct cx88_subid { #define RESOURCE_VIDEO 2 #define RESOURCE_VBI 4 -#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ +#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* buffer for one video frame */ struct cx88_buffer { @@ -683,8 +683,8 @@ s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core); int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); int cx88_ir_fini(struct cx88_core *core); void cx88_ir_irq(struct cx88_core *core); -void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir); -void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir); +int cx88_ir_start(struct cx88_core *core); +void cx88_ir_stop(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ |