void cx8800_vbi_timeout(unsigned long data) { struct cx8800_dev *dev = (struct cx8800_dev*)data; struct cx88_core *core = dev->core; struct cx88_dmaqueue *q = &dev->vbiq; struct cx88_buffer *buf; unsigned long flags; cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]); cx_clear(MO_VID_DMACNTRL, 0x88); cx_clear(VID_CAPTURE_CONTROL, 0x18); spin_lock_irqsave(&dev->slock,flags); while (!list_empty(&q->active)) { buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); list_del(&buf->vb.queue); buf->vb.state = VIDEOBUF_ERROR; wake_up(&buf->vb.done); printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name, buf, buf->vb.i, (unsigned long)buf->risc.dma); } cx8800_restart_vbi_queue(dev,q); spin_unlock_irqrestore(&dev->slock,flags); }
int cx88_video_mux(struct cx88_core *core, unsigned int input) { dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n", input, INPUT(input).vmux, INPUT(input).gpio0,INPUT(input).gpio1, INPUT(input).gpio2,INPUT(input).gpio3); core->input = input; cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14); cx_write(MO_GP3_IO, INPUT(input).gpio3); cx_write(MO_GP0_IO, INPUT(input).gpio0); cx_write(MO_GP1_IO, INPUT(input).gpio1); cx_write(MO_GP2_IO, INPUT(input).gpio2); switch (INPUT(input).type) { case CX88_VMUX_SVIDEO: cx_set(MO_AFECFG_IO, 0x00000001); cx_set(MO_INPUT_FORMAT, 0x00010010); cx_set(MO_FILTER_EVEN, 0x00002020); cx_set(MO_FILTER_ODD, 0x00002020); break; default: cx_clear(MO_AFECFG_IO, 0x00000001); cx_clear(MO_INPUT_FORMAT, 0x00010010); cx_clear(MO_FILTER_EVEN, 0x00002020); cx_clear(MO_FILTER_ODD, 0x00002020); break; } if (INPUT(input).audioroute) { if (core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { call_all(core, audio, s_routing, INPUT(input).audioroute, 0, 0); } if (INPUT(input).type != CX88_VMUX_TELEVISION ) { core->tvaudio = WW_I2SADC; cx88_set_tvaudio(core); } else { cx_write(AUD_I2SCNTL, 0x0); cx_clear(AUD_CTL, EN_I2SIN_ENABLE); } } return 0; }
void cx8800_stop_vbi_dma(struct cx8800_dev *dev) { struct cx88_core *core = dev->core; /* stop dma */ cx_clear(MO_VID_DMACNTRL, 0x88); /* disable capture */ cx_clear(VID_CAPTURE_CONTROL,0x18); /* disable irqs */ cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); cx_clear(MO_VID_INTMSK, 0x0f0088); }
static int stop_video_dma(struct cx8800_dev *dev) { struct cx88_core *core = dev->core; cx_clear(MO_VID_DMACNTRL, 0x11); cx_clear(VID_CAPTURE_CONTROL,0x06); cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); cx_clear(MO_VID_INTMSK, 0x0f0011); return 0; }
int cx8800_stop_vbi_dma(struct cx8800_dev *dev) { struct cx88_core *core = dev->core; cx_clear(MO_VID_DMACNTRL, 0x88); cx_clear(VID_CAPTURE_CONTROL,0x18); cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); cx_clear(MO_VID_INTMSK, 0x0f0088); return 0; }
static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) { struct cx23885_tsport *port = ptr; struct cx23885_dev *dev = port->dev; switch (command) { case XC2028_TUNER_RESET: /* Send the tuner in then out of reset */ /* GPIO-2 xc3028 tuner */ dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); cx_set(GP0_IO, 0x00040000); cx_clear(GP0_IO, 0x00000004); msleep(5); cx_set(GP0_IO, 0x00040004); msleep(5); break; case XC2028_RESET_CLK: dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); break; default: dprintk(1, "%s: unknown command %d, arg %d\n", __func__, command, arg); return -EINVAL; } return 0; }
static int cx88_pci_nano_callback(void *ptr, int command, int arg) { struct cx88_core *core = ptr; switch (command) { case XC2028_TUNER_RESET: /* Send the tuner in then out of reset */ dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: /* GPIO-4 xc3028 tuner */ cx_set(MO_GP0_IO, 0x00001000); cx_clear(MO_GP0_IO, 0x00000010); msleep(100); cx_set(MO_GP0_IO, 0x00000010); msleep(100); break; } break; case XC2028_RESET_CLK: dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); break; default: dprintk(1, "%s: unknown command %d, arg %d\n", __func__, command, arg); return -EINVAL; } return 0; }
/* * BOARD Specific: Handles audio IRQ */ int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask) { struct cx23885_audio_dev *chip = dev->audio_dev; if (0 == (status & mask)) return 0; cx_write(AUDIO_INT_INT_STAT, status); /* risc op code error */ if (status & AUD_INT_OPC_ERR) { printk(KERN_WARNING "%s/1: Audio risc op code error\n", dev->name); cx_clear(AUD_INT_DMA_CTL, 0x11); cx23885_sram_channel_dump(dev, &dev->sram_channels[AUDIO_SRAM_CHANNEL]); } if (status & AUD_INT_DN_SYNC) { dprintk(1, "Downstream sync error\n"); cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); return 1; } /* risc1 downstream */ if (status & AUD_INT_DN_RISCI1) { atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT)); snd_pcm_period_elapsed(chip->substream); } /* FIXME: Any other status should deserve a special handling? */ return 1; }
/* * BOARD Specific: Resets audio DMA */ static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip) { struct cx23885_dev *dev = chip->dev; dprintk(1, "Stopping audio DMA\n"); /* stop dma */ cx_clear(AUD_INT_DMA_CTL, 0x11); /* disable irqs */ cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI1); if (audio_debug) cx23885_sram_channel_dump(chip->dev, &dev->sram_channels[AUDIO_SRAM_CHANNEL]); return 0; }
static void stop_streaming(struct vb2_queue *q) { struct cx8800_dev *dev = q->drv_priv; struct cx88_core *core = dev->core; struct cx88_dmaqueue *dmaq = &dev->vbiq; unsigned long flags; cx_clear(MO_VID_DMACNTRL, 0x11); cx_clear(VID_CAPTURE_CONTROL, 0x06); cx8800_stop_vbi_dma(dev); spin_lock_irqsave(&dev->slock, flags); while (!list_empty(&dmaq->active)) { struct cx88_buffer *buf = list_entry(dmaq->active.next, struct cx88_buffer, list); list_del(&buf->list); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); }
int cx23885_tuner_callback(void *priv, int component, int command, int arg) { struct cx23885_tsport *port = priv; struct cx23885_dev *dev = port->dev; u32 bitmask = 0; if ((command == XC2028_RESET_CLK) || (command == XC2028_I2C_FLUSH)) return 0; if (command != 0) { printk(KERN_ERR "%s(): Unknown command 0x%x.\n", __func__, command); return -EINVAL; } switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: /* Tuner Reset Command */ bitmask = 0x04; break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: /* Two identical tuners on two different i2c buses, * we need to reset the correct gpio. */ if (port->nr == 1) bitmask = 0x01; else if (port->nr == 2) bitmask = 0x04; break; case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: /* Tuner Reset Command */ bitmask = 0x02; break; case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: altera_ci_tuner_reset(dev, port->nr); break; } if (bitmask) { /* Drive the tuner into reset and back out */ cx_clear(GP0_IO, bitmask); mdelay(200); cx_set(GP0_IO, bitmask); } return 0; }
void cx23885_ir_fini(struct cx23885_dev *dev) { switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: dev->pci_irqmask &= ~PCI_MSK_IR; cx_clear(PCI_INT_MSK, PCI_MSK_IR); cx23888_ir_remove(dev); dev->sd_ir = NULL; break; } }
static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; dprintk(1, "%s: index = %d\n", __func__, index); if (index == 0) cx_clear(MO_GP0_IO, 8); else cx_set(MO_GP0_IO, 8); return 0; }
static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip) { struct cx23885_audio_buffer *buf = chip->buf; struct cx23885_dev *dev = chip->dev; struct sram_channel *audio_ch = &dev->sram_channels[AUDIO_SRAM_CHANNEL]; dprintk(1, "%s()\n", __func__); /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ cx_clear(AUD_INT_DMA_CTL, 0x11); /* setup fifo + format - out channel */ cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl, buf->risc.dma); /* sets bpl size */ cx_write(AUD_INT_A_LNGTH, buf->bpl); /* This is required to get good audio (1 seems to be ok) */ cx_write(AUD_INT_A_MODE, 1); /* reset counter */ cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); atomic_set(&chip->count, 0); dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d " "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1, chip->num_periods, buf->bpl * chip->num_periods); /* Enables corresponding bits at AUD_INT_STAT */ cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI1); /* Clean any pending interrupt bits already set */ cx_write(AUDIO_INT_INT_STAT, ~0); /* enable audio irqs */ cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); /* start dma */ cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and RISC enable */ if (audio_debug) cx23885_sram_channel_dump(chip->dev, audio_ch); return 0; }
int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct cx23885_tsport *port = fe->dvb->priv; struct cx23885_dev *dev = port->dev; u8 buf[16]; buf[0] = 0x05; buf[1] = 0x38;/* write port */ buf[2] = 0x01;/* A port, lnb power */ switch (voltage) { case SEC_VOLTAGE_13: buf[3] = 0x01;/* power on */ buf[4] = 0x02;/* B port, H/V */ buf[5] = 0x00;/*13V v*/ cx_set(MC417_RWD, 0x00000200); cx_clear(MC417_RWD, 0x00000400); break; case SEC_VOLTAGE_18: buf[3] = 0x01; buf[4] = 0x02; buf[5] = 0x01;/* 18V h*/ cx_set(MC417_RWD, 0x00000200); cx_set(MC417_RWD, 0x00000400); break; case SEC_VOLTAGE_OFF: buf[3] = 0x00;/* power off */ buf[4] = 0x00; buf[5] = 0x00; cx_clear(MC417_RWD, 0x00000200); break; } return f300_xfer(fe, buf); }
void cx88_card_setup_pre_i2c(struct cx88_core *core) { switch (core->board) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */ /* We leave here with the 702 on the bus */ cx_write(MO_GP0_IO, 0x0000e780); udelay(1000); cx_clear(MO_GP0_IO, 0x00000080); udelay(50); cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ udelay(1000); break; } }
static void cx23885_stop_streaming(struct vb2_queue *q) { struct cx23885_dev *dev = q->drv_priv; struct cx23885_dmaqueue *dmaq = &dev->vbiq; unsigned long flags; cx_clear(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */ spin_lock_irqsave(&dev->slock, flags); while (!list_empty(&dmaq->active)) { struct cx23885_buffer *buf = list_entry(dmaq->active.next, struct cx23885_buffer, queue); list_del(&buf->queue); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); }
static int netup_altera_fpga_rw(void *device, int flag, int data, int read) { struct cx23885_dev *dev = (struct cx23885_dev *)device; unsigned long timeout = jiffies + msecs_to_jiffies(1); uint32_t mem = 0; mem = cx_read(MC417_RWD); if (read) cx_set(MC417_OEN, ALT_DATA); else { cx_clear(MC417_OEN, ALT_DATA);/* D0-D7 out */ mem &= ~ALT_DATA; mem |= (data & ALT_DATA); } if (flag) mem |= ALT_AD_RG; else mem &= ~ALT_AD_RG; mem &= ~ALT_CS; if (read) mem = (mem & ~ALT_RD) | ALT_WR; else mem = (mem & ~ALT_WR) | ALT_RD; cx_write(MC417_RWD, mem); /* start RW cycle */ for (;;) { mem = cx_read(MC417_RWD); if ((mem & ALT_RDY) == 0) break; if (time_after(jiffies, timeout)) break; udelay(1); } cx_set(MC417_RWD, ALT_RD | ALT_WR | ALT_CS); if (read) return mem & ALT_DATA; return 0; };
int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) { int handled = 0; u32 mask; const struct sram_channel *channel = dev->channels[chan_num].sram_channels; mask = cx_read(channel->int_msk); if (0 == (status & mask)) return handled; cx_write(channel->int_stat, status); /* risc op code error */ if (status & (1 << 16)) { pr_warn("%s, %s: video risc op code error\n", dev->name, channel->name); cx_clear(channel->dma_ctl, 0x11); cx25821_sram_channel_dump(dev, channel); } /* risc1 y */ if (status & FLD_VID_DST_RISC1) { struct cx25821_dmaqueue *dmaq = &dev->channels[channel->i].dma_vidq; struct cx25821_buffer *buf; spin_lock(&dev->slock); if (!list_empty(&dmaq->active)) { buf = list_entry(dmaq->active.next, struct cx25821_buffer, queue); buf->vb.vb2_buf.timestamp = ktime_get_ns(); buf->vb.sequence = dmaq->count++; list_del(&buf->queue); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } spin_unlock(&dev->slock); handled++; }
void cx23885_gpio_setup(struct cx23885_dev *dev) { switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: /* GPIO-0 cx24227 demodulator reset */ cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */ break; case CX23885_BOARD_HAUPPAUGE_HVR1500: /* GPIO-0 cx24227 demodulator */ /* GPIO-2 xc3028 tuner */ /* Put the parts into reset */ cx_set(GP0_IO, 0x00050000); cx_clear(GP0_IO, 0x00000005); msleep(5); /* Bring the parts out of reset */ cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1500Q: /* GPIO-0 cx24227 demodulator reset */ /* GPIO-2 xc5000 tuner reset */ cx_set(GP0_IO, 0x00050005); /* Bring the part out of reset */ break; case CX23885_BOARD_HAUPPAUGE_HVR1800: /* GPIO-0 656_CLK */ /* GPIO-1 656_D0 */ /* GPIO-2 8295A Reset */ /* GPIO-3-10 cx23417 data0-7 */ /* GPIO-11-14 cx23417 addr0-3 */ /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* GPIO-19 IR_RX */ /* CX23417 GPIO's */ /* EIO15 Zilog Reset */ /* EIO14 S5H1409/CX24227 Reset */ /* Force the TDA8295A into reset and back */ cx_set(GP0_IO, 0x00040004); mdelay(20); cx_clear(GP0_IO, 0x00000004); mdelay(20); cx_set(GP0_IO, 0x00040004); mdelay(20); break; case CX23885_BOARD_HAUPPAUGE_HVR1200: /* GPIO-0 tda10048 demodulator reset */ /* GPIO-2 tda18271 tuner reset */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); cx_clear(GP0_IO, 0x00000005); mdelay(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1700: /* GPIO-0 TDA10048 demodulator reset */ /* GPIO-2 TDA8295A Reset */ /* GPIO-3-10 cx23417 data0-7 */ /* GPIO-11-14 cx23417 addr0-3 */ /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* The following GPIO's are on the interna AVCore (cx25840) */ /* GPIO-19 IR_RX */ /* GPIO-20 IR_TX 416/DVBT Select */ /* GPIO-21 IIS DAT */ /* GPIO-22 IIS WCLK */ /* GPIO-23 IIS BCLK */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); cx_clear(GP0_IO, 0x00000005); mdelay(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1400: /* GPIO-0 Dibcom7000p demodulator reset */ /* GPIO-2 xc3028L tuner reset */ /* GPIO-13 LED */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); cx_clear(GP0_IO, 0x00000005); mdelay(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: /* GPIO-0 xc5000 tuner reset i2c bus 0 */ /* GPIO-1 s5h1409 demod reset i2c bus 0 */ /* GPIO-2 xc5000 tuner reset i2c bus 1 */ /* GPIO-3 s5h1409 demod reset i2c bus 0 */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); mdelay(20); cx_clear(GP0_IO, 0x0000000f); mdelay(20); cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: /* GPIO-0 portb xc3028 reset */ /* GPIO-1 portb zl10353 reset */ /* GPIO-2 portc xc3028 reset */ /* GPIO-3 portc zl10353 reset */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); mdelay(20); cx_clear(GP0_IO, 0x0000000f); mdelay(20); cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: /* GPIO-2 xc3028 tuner reset */ /* The following GPIO's are on the internal AVCore (cx25840) */ /* GPIO-? zl10353 demod reset */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00040000); mdelay(20); cx_clear(GP0_IO, 0x00000004); mdelay(20); cx_set(GP0_IO, 0x00040004); break; case CX23885_BOARD_TBS_6920: case CX23885_BOARD_TEVII_S470: cx_write(MC417_CTL, 0x00000036); cx_write(MC417_OEN, 0x00001000); cx_write(MC417_RWD, 0x00001800); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: /* GPIO-0 INTA from CiMax1 GPIO-1 INTB from CiMax2 GPIO-2 reset chips GPIO-3 to GPIO-10 data/addr for CA GPIO-11 ~CS0 to CiMax1 GPIO-12 ~CS1 to CiMax2 GPIO-13 ADL0 load LSB addr GPIO-14 ADL1 load MSB addr GPIO-15 ~RDY from CiMax GPIO-17 ~RD to CiMax GPIO-18 ~WR to CiMax */ cx_set(GP0_IO, 0x00040000); /* GPIO as out */ /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */ cx_clear(GP0_IO, 0x00030004); mdelay(100);/* reset delay */ cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ /* GPIO-15 IN as ~ACK, rest as OUT */ cx_write(MC417_OEN, 0x00001000); /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ cx_write(MC417_RWD, 0x0000c300); /* enable irq */ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ break; } }
static int attach_xc3028(u8 addr, struct cx8802_dev *dev) { struct dvb_frontend *fe; struct xc2028_ctrl ctl; struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, .ctrl = &ctl, .callback = cx88_tuner_callback, }; if (!dev->dvb.frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " "Can't attach xc3028\n", dev->core->name); return -EINVAL; } /* * Some xc3028 devices may be hidden by an I2C gate. This is known * to happen with some s5h1409-based devices. * Now that I2C gate is open, sets up xc3028 configuration */ cx88_setup_xc3028(dev->core, &ctl); fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->core->name); return -EINVAL; } printk(KERN_INFO "%s/2: xc3028 attached\n", dev->core->name); return 0; } static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; /* init struct videobuf_dvb */ dev->dvb.name = core->name; dev->ts_gen_cntrl = 0x0c; /* init frontend */ switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &core->i2c_adap, DVB_PLL_THOMSON_DTT759X)) goto frontend_detach; } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: case CX88_BOARD_HAUPPAUGE_HVR3000: dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* The tin box says DEE1601, but it seems to be DTT7579 * compatible, with a slightly different MT352 AGC gain. */ dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_LG_Z201)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_UNKNOWN_1)) goto frontend_detach; } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) /* MT352 is on a secondary I2C bus made from some GPIO lines */ dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } #else printk(KERN_ERR "%s/2: built without vp3054 support\n", core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_FE6600)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &core->i2c_adap); if (dev->dvb.frontend == NULL) dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, &core->i2c_adap); /* * On this board, the demod provides the I2C bus pullup. * We must not permit gate_ctrl to be performed, or * the xc3028 cannot communicate on the bus. */ if (dev->dvb.frontend) dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) return -EINVAL; break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_MICROTUNE_4042FI5)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; if (!dvb_attach(tda9887_attach, dev->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_PCHDTV_HD5500: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; if (!dvb_attach(tda9887_attach, dev->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_ATI_HDTVWONDER: dev->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, &core->i2c_adap); if (dev->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: dev->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &core->i2c_adap); if (dev->dvb.frontend) { if (!dvb_attach(isl6421_attach, dev->dvb.frontend, &core->i2c_adap, 0x08, 0x00, 0x00)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVBS_100: dev->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, &core->i2c_adap); if (dev->dvb.frontend) { core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; } break; case CX88_BOARD_GENIATECH_DVBS: dev->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, &core->i2c_adap); if (dev->dvb.frontend) { core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: dev->dvb.frontend = dvb_attach(s5h1409_attach, &pinnacle_pctv_hd_800i_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { /* tuner_config.video_dev must point to * i2c_adap.algo_data */ if (!dvb_attach(xc5000_attach, dev->dvb.frontend, &core->i2c_adap, &pinnacle_pctv_hd_800i_tuner_config, core->i2c_adap.algo_data)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: dev->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_hdtv5_pci_nano_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, .i2c_addr = 0x61, .callback = cx88_pci_nano_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", .max_len = 64, .scode_table = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_KWORLD_ATSC_120: dev->dvb.frontend = dvb_attach(s5h1409_attach, &kworld_atsc_120_config, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: dev->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_fusionhdtv7_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { /* tuner_config.video_dev must point to * i2c_adap.algo_data */ if (!dvb_attach(xc5000_attach, dev->dvb.frontend, &core->i2c_adap, &dvico_fusionhdtv7_tuner_config, core->i2c_adap.algo_data)) goto frontend_detach; } break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); break; } if (NULL == dev->dvb.frontend) { printk(KERN_ERR "%s/2: frontend initialization failed\n", core->name); return -EINVAL; } /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); /* register everything */ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, adapter_nr); frontend_detach: if (dev->dvb.frontend) { dvb_frontend_detach(dev->dvb.frontend); dev->dvb.frontend = NULL; } return -EINVAL; } /* ----------------------------------------------------------- */ /* CX8802 MPEG -> mini driver - We have been given the hardware */ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* We arrive here with either the cx23416 or the cx22702 * on the bus. Take the bus from the cx23416 and enable the * cx22702 demod */ cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; default: err = -ENODEV; } return err; } /* CX8802 MPEG -> mini driver - We no longer have the hardware */ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* Do Nothing, leave the cx22702 on the bus. */ break; default: err = -ENODEV; } return err; } static int cx8802_dvb_probe(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; int err; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", core->boardnr, core->name, core->pci_bus, core->pci_slot); err = -ENODEV; if (!(core->board.mpeg & CX88_MPEG_DVB)) goto fail_core; /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) goto fail_core; /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); err = dvb_register(dev); if (err != 0) printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", core->name, err); fail_core: return err; } static int cx8802_dvb_remove(struct cx8802_driver *drv) { struct cx8802_dev *dev = drv->core->dvbdev; /* dvb */ if (dev->dvb.frontend) videobuf_dvb_unregister(&dev->dvb); vp3054_i2c_remove(dev); return 0; } static struct cx8802_driver cx8802_dvb_driver = { .type_id = CX88_MPEG_DVB, .hw_access = CX8802_DRVCTL_SHARED, .probe = cx8802_dvb_probe, .remove = cx8802_dvb_remove, .advise_acquire = cx8802_dvb_advise_acquire, .advise_release = cx8802_dvb_advise_release, }; static int dvb_init(void) { printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); #ifdef SNAPSHOT printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif return cx8802_register_driver(&cx8802_dvb_driver); } static void dvb_fini(void) { cx8802_unregister_driver(&cx8802_dvb_driver); } module_init(dvb_init); module_exit(dvb_fini);
static int attach_xc3028(u8 addr, struct cx8802_dev *dev) { struct dvb_frontend *fe; struct videobuf_dvb_frontend *fe0 = NULL; struct xc2028_ctrl ctl; struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, .ctrl = &ctl, }; /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); if (!fe0) return -EINVAL; if (!fe0->dvb.frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " "Can't attach xc3028\n", dev->core->name); return -EINVAL; } /* * Some xc3028 devices may be hidden by an I2C gate. This is known * to happen with some s5h1409-based devices. * Now that I2C gate is open, sets up xc3028 configuration */ cx88_setup_xc3028(dev->core, &ctl); fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->core->name); dvb_frontend_detach(fe0->dvb.frontend); dvb_unregister_frontend(fe0->dvb.frontend); fe0->dvb.frontend = NULL; return -EINVAL; } printk(KERN_INFO "%s/2: xc3028 attached\n", dev->core->name); return 0; } static int cx24116_set_ts_param(struct dvb_frontend *fe, int is_punctured) { struct cx8802_dev *dev = fe->dvb->priv; dev->ts_gen_cntrl = 0x2; return 0; } static int cx24116_reset_device(struct dvb_frontend *fe) { struct cx8802_dev *dev = fe->dvb->priv; struct cx88_core *core = dev->core; /* Reset the part */ /* Put the cx24116 into reset */ cx_write(MO_SRST_IO, 0); msleep(10); /* Take the cx24116 out of reset */ cx_write(MO_SRST_IO, 1); msleep(10); return 0; } static struct cx24116_config hauppauge_hvr4000_config = { .demod_address = 0x05, .set_ts_params = cx24116_set_ts_param, .reset_device = cx24116_reset_device, }; static struct cx24116_config tevii_s460_config = { .demod_address = 0x55, .set_ts_params = cx24116_set_ts_param, .reset_device = cx24116_reset_device, }; static struct stv0299_config tevii_tuner_sharp_config = { .demod_address = 0x68, .inittab = sharp_z0194a_inittab, .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, .lock_output = 1, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = sharp_z0194a_set_symbol_rate, .set_ts_params = cx24116_set_ts_param, }; static struct stv0288_config tevii_tuner_earda_config = { .demod_address = 0x68, .min_delay_ms = 100, .set_ts_params = cx24116_set_ts_param, }; static int cx8802_alloc_frontends(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; struct videobuf_dvb_frontend *fe = NULL; int i; mutex_init(&dev->frontends.lock); INIT_LIST_HEAD(&dev->frontends.felist); if (!core->board.num_frontends) return -ENODEV; printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); for (i = 1; i <= core->board.num_frontends; i++) { fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); if (!fe) { printk(KERN_ERR "%s() failed to alloc\n", __func__); videobuf_dvb_dealloc_frontends(&dev->frontends); return -ENOMEM; } } return 0; } static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; struct videobuf_dvb_frontend *fe0, *fe1 = NULL; int mfe_shared = 0; /* bus not shared by default */ if (0 != core->i2c_rc) { printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); goto frontend_detach; } /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); if (!fe0) goto frontend_detach; /* multi-frontend gate control is undefined or defaults to fe0 */ dev->frontends.gate = 0; /* Sets the gate control callback to be used by i2c command calls */ core->gate_ctrl = cx88_dvb_gate_ctrl; /* init frontend(s) */ switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap, DVB_PLL_THOMSON_DTT759X)) goto frontend_detach; } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: fe0->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_HVR3000: /* MFE frontend 1 */ mfe_shared = 1; dev->frontends.gate = 2; /* DVB-S init */ fe0->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &dev->core->i2c_adap); if (fe0->dvb.frontend) { if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } /* MFE frontend 2 */ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); if (!fe1) goto frontend_detach; /* DVB-T init */ fe1->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &dev->core->i2c_adap); if (fe1->dvb.frontend) { fe1->dvb.frontend->id = 1; if (!dvb_attach(simple_tuner_attach, fe1->dvb.frontend, &dev->core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* The tin box says DEE1601, but it seems to be DTT7579 * compatible, with a slightly different MT352 AGC gain. */ fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_LG_Z201)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_UNKNOWN_1)) goto frontend_detach; } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) /* MT352 is on a secondary I2C bus made from some GPIO lines */ fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } #else printk(KERN_ERR "%s/2: built without vp3054 support\n", core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_FE6600)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &core->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, &core->i2c_adap); /* * On this board, the demod provides the I2C bus pullup. * We must not permit gate_ctrl to be performed, or * the xc3028 cannot communicate on the bus. */ if (fe0->dvb.frontend) fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_PCHDTV_HD3000: fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_MICROTUNE_4042FI5)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_PCHDTV_HD5500: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_ATI_HDTVWONDER: fe0->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: fe0->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &core->i2c_adap); if (fe0->dvb.frontend) { if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVBS_100: fe0->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, &core->i2c_adap); if (fe0->dvb.frontend) { core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; } break; case CX88_BOARD_GENIATECH_DVBS: fe0->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, &core->i2c_adap); if (fe0->dvb.frontend) { core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &pinnacle_pctv_hd_800i_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, &core->i2c_adap, &pinnacle_pctv_hd_800i_tuner_config)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_hdtv5_pci_nano_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .scode_table = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); if (fe0->dvb.frontend) { fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_KWORLD_ATSC_120: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &kworld_atsc_120_config, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_fusionhdtv7_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, &core->i2c_adap, &dvico_fusionhdtv7_tuner_config)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_HVR4000: /* MFE frontend 1 */ mfe_shared = 1; dev->frontends.gate = 2; /* DVB-S/S2 Init */ fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &dev->core->i2c_adap); if (fe0->dvb.frontend) { if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } /* MFE frontend 2 */ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); if (!fe1) goto frontend_detach; /* DVB-T Init */ fe1->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &dev->core->i2c_adap); if (fe1->dvb.frontend) { fe1->dvb.frontend->id = 1; if (!dvb_attach(simple_tuner_attach, fe1->dvb.frontend, &dev->core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_HVR4000LITE: fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &dev->core->i2c_adap); if (fe0->dvb.frontend) { if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } break; case CX88_BOARD_PROF_6200: case CX88_BOARD_TBS_8910: case CX88_BOARD_TEVII_S420: fe0->dvb.frontend = dvb_attach(stv0299_attach, &tevii_tuner_sharp_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_OPERA1)) goto frontend_detach; core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } else { fe0->dvb.frontend = dvb_attach(stv0288_attach, &tevii_tuner_earda_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap)) goto frontend_detach; core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } } break; case CX88_BOARD_TEVII_S460: fe0->dvb.frontend = dvb_attach(cx24116_attach, &tevii_s460_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; break; case CX88_BOARD_OMICOM_SS4_PCI: case CX88_BOARD_TBS_8920: case CX88_BOARD_PROF_7300: case CX88_BOARD_SATTRADE_ST4200: fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; break; case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_terratec_cinergy_ht_pci_mkii_config, &core->i2c_adap); if (fe0->dvb.frontend) { fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); break; } if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) { printk(KERN_ERR "%s/2: frontend initialization failed\n", core->name); goto frontend_detach; } /* define general-purpose callback pointer */ fe0->dvb.frontend->callback = cx88_tuner_callback; /* Ensure all frontends negotiate bus access */ fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; if (fe1) fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ call_all(core, tuner, s_standby); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, &dev->pci->dev, adapter_nr, mfe_shared); frontend_detach: core->gate_ctrl = NULL; videobuf_dvb_dealloc_frontends(&dev->frontends); return -EINVAL; } /* ----------------------------------------------------------- */ /* CX8802 MPEG -> mini driver - We have been given the hardware */ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* We arrive here with either the cx23416 or the cx22702 * on the bus. Take the bus from the cx23416 and enable the * cx22702 demod */ /* Toggle reset on cx22702 leaving i2c active */ cx_set(MO_GP0_IO, 0x00000080); udelay(1000); cx_clear(MO_GP0_IO, 0x00000080); udelay(50); cx_set(MO_GP0_IO, 0x00000080); udelay(1000); /* enable the cx22702 pins */ cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: /* Toggle reset on cx22702 leaving i2c active */ cx_set(MO_GP0_IO, 0x00000080); udelay(1000); cx_clear(MO_GP0_IO, 0x00000080); udelay(50); cx_set(MO_GP0_IO, 0x00000080); udelay(1000); switch (core->dvbdev->frontends.active_fe_id) { case 1: /* DVB-S/S2 Enabled */ /* tri-state the cx22702 pins */ cx_set(MO_GP0_IO, 0x00000004); /* Take the cx24116/cx24123 out of reset */ cx_write(MO_SRST_IO, 1); core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ break; case 2: /* DVB-T Enabled */ /* Put the cx24116/cx24123 into reset */ cx_write(MO_SRST_IO, 0); /* enable the cx22702 pins */ cx_clear(MO_GP0_IO, 0x00000004); core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ break; } udelay(1000); break; default: err = -ENODEV; } return err; } /* CX8802 MPEG -> mini driver - We no longer have the hardware */ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* Do Nothing, leave the cx22702 on the bus. */ break; case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: break; default: err = -ENODEV; } return err; } static int cx8802_dvb_probe(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; int err; struct videobuf_dvb_frontend *fe; int i; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", core->boardnr, core->name, core->pci_bus, core->pci_slot); err = -ENODEV; if (!(core->board.mpeg & CX88_MPEG_DVB)) goto fail_core; /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) goto fail_core; /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); dev->ts_gen_cntrl = 0x0c; err = cx8802_alloc_frontends(dev); if (err) goto fail_core; err = -ENODEV; for (i = 1; i <= core->board.num_frontends; i++) { fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); if (fe == NULL) { printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i); goto fail_probe; } videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); /* init struct videobuf_dvb */ fe->dvb.name = dev->core->name; } err = dvb_register(dev); if (err) /* frontends/adapter de-allocated in dvb_register */ printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", core->name, err); return err; fail_probe: videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends); fail_core: return err; } static int cx8802_dvb_remove(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; dprintk( 1, "%s\n", __func__); videobuf_dvb_unregister_bus(&dev->frontends); vp3054_i2c_remove(dev); core->gate_ctrl = NULL; return 0; } static struct cx8802_driver cx8802_dvb_driver = { .type_id = CX88_MPEG_DVB, .hw_access = CX8802_DRVCTL_SHARED, .probe = cx8802_dvb_probe, .remove = cx8802_dvb_remove, .advise_acquire = cx8802_dvb_advise_acquire, .advise_release = cx8802_dvb_advise_release, }; static int dvb_init(void) { printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); #ifdef SNAPSHOT printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif return cx8802_register_driver(&cx8802_dvb_driver); } static void dvb_fini(void) { cx8802_unregister_driver(&cx8802_dvb_driver); } module_init(dvb_init); module_exit(dvb_fini);
static int philips_fmd1216_pll_init(struct dvb_frontend *fe) { struct cx8802_dev *dev= fe->dvb->priv; /* this message is to set up ATC and ALC */ static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; int err; if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { if (err < 0) return err; else return -EREMOTEIO; } return 0; } static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) { struct cx8802_dev *dev= fe->dvb->priv; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, .buf = pllbuf+1, .len = 4 }; int err; /* Switch PLL to DVB mode */ err = philips_fmd1216_pll_init(fe); if (err) return err; /* Tune PLL */ pllbuf[0] = dev->core->pll_addr << 1; dvb_pll_configure(dev->core->pll_desc, pllbuf+1, params->frequency, params->u.ofdm.bandwidth); if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", __FUNCTION__, pllbuf[0], pllbuf[1], err); if (err < 0) return err; else return -EREMOTEIO; } return 0; } static struct mt352_config dntv_live_dvbt_pro_config = { .demod_address = 0x0f, .no_tuner = 1, .demod_init = dntv_live_dvbt_pro_demod_init, .pll_set = dntv_live_dvbt_pro_pll_set, }; #endif #endif #ifdef HAVE_CX22702 static struct cx22702_config connexant_refboard_config = { .demod_address = 0x43, .output_mode = CX22702_SERIAL_OUTPUT, .pll_address = 0x60, .pll_desc = &dvb_pll_thomson_dtt7579, }; static struct cx22702_config hauppauge_novat_config = { .demod_address = 0x43, .output_mode = CX22702_SERIAL_OUTPUT, .pll_address = 0x61, .pll_desc = &dvb_pll_thomson_dtt759x, }; static struct cx22702_config hauppauge_hvr1100_config = { .demod_address = 0x63, .output_mode = CX22702_SERIAL_OUTPUT, .pll_address = 0x61, .pll_desc = &dvb_pll_fmd1216me, }; #endif #ifdef HAVE_OR51132 static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; return 0; } static struct or51132_config pchdtv_hd3000 = { .demod_address = 0x15, .pll_address = 0x61, .pll_desc = &dvb_pll_thomson_dtt7610, .set_ts_params = or51132_set_ts_param, }; #endif #ifdef HAVE_LGDT330X static int lgdt330x_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { /* FIXME make this routine use the tuner-simple code. * It could probably be shared with a number of ATSC * frontends. Many share the same tuner with analog TV. */ struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; u8 buf[4]; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; int err; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err); if (err < 0) return err; else return -EREMOTEIO; } if (core->tuner_type == TUNER_LG_TDVS_H062F) { /* Set the Auxiliary Byte. */ buf[2] &= ~0x20; buf[2] |= 0x18; buf[3] = 0x50; i2c_transfer(&core->i2c_adap, &msg, 1); } return 0; } static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; dprintk(1, "%s: index = %d\n", __FUNCTION__, index); if (index == 0) cx_clear(MO_GP0_IO, 8); else cx_set(MO_GP0_IO, 8); return 0; } static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; if (is_punctured) dev->ts_gen_cntrl |= 0x04; else dev->ts_gen_cntrl &= ~0x04; return 0; } static struct lgdt330x_config fusionhdtv_3_gold = { .demod_address = 0x0e, .demod_chip = LGDT3302, .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; static struct lgdt330x_config fusionhdtv_5_gold = { .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; #endif #ifdef HAVE_NXT200X static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; return 0; } static int nxt200x_set_pll_input(u8* buf, int input) { if (input) buf[3] |= 0x08; else buf[3] &= ~0x08; return 0; } static struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, .pll_address = 0x61, .pll_desc = &dvb_pll_tuv1236d, .set_pll_input = nxt200x_set_pll_input, .set_ts_params = nxt200x_set_ts_param, }; #endif #ifdef HAVE_CX24123 static int cx24123_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = 0x2; return 0; } static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; if (on) cx_write(MO_GP0_IO, 0x000006f9); else cx_write(MO_GP0_IO, 0x000006fB); } static struct cx24123_config hauppauge_novas_config = { .demod_address = 0x55, .use_isl6421 = 1, .set_ts_params = cx24123_set_ts_param, }; static struct cx24123_config kworld_dvbs_100_config = { .demod_address = 0x15, .use_isl6421 = 0, .set_ts_params = cx24123_set_ts_param, .enable_lnb_voltage = cx24123_enable_lnb_voltage, }; #endif static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ dev->dvb.name = dev->core->name; dev->ts_gen_cntrl = 0x0c; /* init frontend */ switch (dev->core->board) { #ifdef HAVE_CX22702 case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, &dev->core->i2c_adap); break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, &dev->core->i2c_adap); break; case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, &dev->core->i2c_adap); break; #endif #ifdef HAVE_MT352 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: dev->core->pll_addr = 0x60; dev->core->pll_desc = &dvb_pll_thomson_dtt7579; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_unknown_1; dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, &dev->core->i2c_adap); break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #ifdef HAVE_VP3054_I2C dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_fmd1216me; dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, &((struct vp3054_i2c_state *)dev->card_priv)->adap); #else printk("%s: built without vp3054 support\n", dev->core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* The tin box says DEE1601, but it seems to be DTT7579 * compatible, with a slightly different MT352 AGC gain. */ dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_thomson_dtt7579; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, &dev->core->i2c_adap); break; #endif #ifdef HAVE_OR51132 case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, &dev->core->i2c_adap); break; #endif #ifdef HAVE_LGDT330X case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_microtune_4042; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_thomson_dtt761x; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_tdvs_tua6034; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, &dev->core->i2c_adap); } break; #endif #ifdef HAVE_NXT200X case CX88_BOARD_ATI_HDTVWONDER: dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, &dev->core->i2c_adap); break; #endif #ifdef HAVE_CX24123 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, &dev->core->i2c_adap); break; case CX88_BOARD_KWORLD_DVBS_100: dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, &dev->core->i2c_adap); break; #endif default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { printk("%s: frontend initialization failed\n",dev->core->name); return -1; } if (dev->core->pll_desc) { dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min; dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; } /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); /* register everything */ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); } /* ----------------------------------------------------------- */ static int __devinit dvb_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct cx8802_dev *dev; struct cx88_core *core; int err; /* general setup */ core = cx88_core_get(pci_dev); if (NULL == core) return -EINVAL; err = -ENODEV; if (!cx88_boards[core->board].dvb) goto fail_core; err = -ENOMEM; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) goto fail_core; dev->pci = pci_dev; dev->core = core; err = cx8802_init_common(dev); if (0 != err) goto fail_free; #ifdef HAVE_VP3054_I2C err = vp3054_i2c_probe(dev); if (0 != err) goto fail_free; #endif /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); err = dvb_register(dev); if (0 != err) goto fail_fini; /* Maintain a reference to cx88-video can query the 8802 device. */ core->dvbdev = dev; return 0; fail_fini: cx8802_fini_common(dev); fail_free: kfree(dev); fail_core: cx88_core_put(core,pci_dev); return err; } static void __devexit dvb_remove(struct pci_dev *pci_dev) { struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* Destroy any 8802 reference. */ dev->core->dvbdev = NULL; /* dvb */ videobuf_dvb_unregister(&dev->dvb); #ifdef HAVE_VP3054_I2C vp3054_i2c_remove(dev); #endif /* common */ cx8802_fini_common(dev); cx88_core_put(dev->core,dev->pci); kfree(dev); } static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } }; MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver dvb_pci_driver = { .name = "cx88-dvb", .id_table = cx8802_pci_tbl, .probe = dvb_probe, .remove = __devexit_p(dvb_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; static int dvb_init(void) { printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); #ifdef SNAPSHOT printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif return pci_register_driver(&dvb_pci_driver); } static void dvb_fini(void) { pci_unregister_driver(&dvb_pci_driver); } module_init(dvb_init); module_exit(dvb_fini);
void cx23885_gpio_setup(struct cx23885_dev *dev) { switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: /* GPIO-0 cx24227 demodulator reset */ cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */ break; case CX23885_BOARD_HAUPPAUGE_HVR1500: /* GPIO-0 cx24227 demodulator */ /* GPIO-2 xc3028 tuner */ /* Put the parts into reset */ cx_set(GP0_IO, 0x00050000); cx_clear(GP0_IO, 0x00000005); msleep(5); /* Bring the parts out of reset */ cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1500Q: /* GPIO-0 cx24227 demodulator reset */ /* GPIO-2 xc5000 tuner reset */ cx_set(GP0_IO, 0x00050005); /* Bring the part out of reset */ break; case CX23885_BOARD_HAUPPAUGE_HVR1800: /* GPIO-0 656_CLK */ /* GPIO-1 656_D0 */ /* GPIO-2 8295A Reset */ /* GPIO-3-10 cx23417 data0-7 */ /* GPIO-11-14 cx23417 addr0-3 */ /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* GPIO-19 IR_RX */ /* CX23417 GPIO's */ /* EIO15 Zilog Reset */ /* EIO14 S5H1409/CX24227 Reset */ mc417_gpio_enable(dev, GPIO_15 | GPIO_14, 1); /* Put the demod into reset and protect the eeprom */ mc417_gpio_clear(dev, GPIO_15 | GPIO_14); mdelay(100); /* Bring the demod and blaster out of reset */ mc417_gpio_set(dev, GPIO_15 | GPIO_14); mdelay(100); /* Force the TDA8295A into reset and back */ cx23885_gpio_enable(dev, GPIO_2, 1); cx23885_gpio_set(dev, GPIO_2); mdelay(20); cx23885_gpio_clear(dev, GPIO_2); mdelay(20); cx23885_gpio_set(dev, GPIO_2); mdelay(20); break; case CX23885_BOARD_HAUPPAUGE_HVR1200: /* GPIO-0 tda10048 demodulator reset */ /* GPIO-2 tda18271 tuner reset */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); cx_clear(GP0_IO, 0x00000005); mdelay(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1700: /* GPIO-0 TDA10048 demodulator reset */ /* GPIO-2 TDA8295A Reset */ /* GPIO-3-10 cx23417 data0-7 */ /* GPIO-11-14 cx23417 addr0-3 */ /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* The following GPIO's are on the interna AVCore (cx25840) */ /* GPIO-19 IR_RX */ /* GPIO-20 IR_TX 416/DVBT Select */ /* GPIO-21 IIS DAT */ /* GPIO-22 IIS WCLK */ /* GPIO-23 IIS BCLK */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); cx_clear(GP0_IO, 0x00000005); mdelay(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1400: /* GPIO-0 Dibcom7000p demodulator reset */ /* GPIO-2 xc3028L tuner reset */ /* GPIO-13 LED */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); cx_clear(GP0_IO, 0x00000005); mdelay(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: /* GPIO-0 xc5000 tuner reset i2c bus 0 */ /* GPIO-1 s5h1409 demod reset i2c bus 0 */ /* GPIO-2 xc5000 tuner reset i2c bus 1 */ /* GPIO-3 s5h1409 demod reset i2c bus 0 */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); mdelay(20); cx_clear(GP0_IO, 0x0000000f); mdelay(20); cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: /* GPIO-0 portb xc3028 reset */ /* GPIO-1 portb zl10353 reset */ /* GPIO-2 portc xc3028 reset */ /* GPIO-3 portc zl10353 reset */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); mdelay(20); cx_clear(GP0_IO, 0x0000000f); mdelay(20); cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: /* GPIO-2 xc3028 tuner reset */ /* The following GPIO's are on the internal AVCore (cx25840) */ /* GPIO-? zl10353 demod reset */ /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00040000); mdelay(20); cx_clear(GP0_IO, 0x00000004); mdelay(20); cx_set(GP0_IO, 0x00040004); break; case CX23885_BOARD_TBS_6920: cx_write(MC417_CTL, 0x00000036); cx_write(MC417_OEN, 0x00001000); cx_set(MC417_RWD, 0x00000002); mdelay(200); cx_clear(MC417_RWD, 0x00000800); mdelay(200); cx_set(MC417_RWD, 0x00000800); mdelay(200); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: /* GPIO-0 INTA from CiMax1 GPIO-1 INTB from CiMax2 GPIO-2 reset chips GPIO-3 to GPIO-10 data/addr for CA GPIO-11 ~CS0 to CiMax1 GPIO-12 ~CS1 to CiMax2 GPIO-13 ADL0 load LSB addr GPIO-14 ADL1 load MSB addr GPIO-15 ~RDY from CiMax GPIO-17 ~RD to CiMax GPIO-18 ~WR to CiMax */ cx_set(GP0_IO, 0x00040000); /* GPIO as out */ /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */ cx_clear(GP0_IO, 0x00030004); mdelay(100);/* reset delay */ cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ /* GPIO-15 IN as ~ACK, rest as OUT */ cx_write(MC417_OEN, 0x00001000); /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ cx_write(MC417_RWD, 0x0000c300); /* enable irq */ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ break; case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1210: /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */ /* GPIO-6 I2C Gate which can isolate the demod from the bus */ /* GPIO-9 Demod reset */ /* Put the parts into reset and back */ cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1); cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5); cx23885_gpio_clear(dev, GPIO_9); mdelay(20); cx23885_gpio_set(dev, GPIO_9); break; case CX23885_BOARD_MYGICA_X8506: case CX23885_BOARD_MAGICPRO_PROHDTVE2: /* GPIO-0 (0)Analog / (1)Digital TV */ /* GPIO-1 reset XC5000 */ /* GPIO-2 reset LGS8GL5 / LGS8G75 */ cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); mdelay(100); cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2); mdelay(100); break; case CX23885_BOARD_MYGICA_X8558PRO: /* GPIO-0 reset first ATBM8830 */ /* GPIO-1 reset second ATBM8830 */ cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1); cx23885_gpio_clear(dev, GPIO_0 | GPIO_1); mdelay(100); cx23885_gpio_set(dev, GPIO_0 | GPIO_1); mdelay(100); break; case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: /* GPIO-0 656_CLK */ /* GPIO-1 656_D0 */ /* GPIO-2 Wake# */ /* GPIO-3-10 cx23417 data0-7 */ /* GPIO-11-14 cx23417 addr0-3 */ /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* GPIO-19 IR_RX */ /* GPIO-20 C_IR_TX */ /* GPIO-21 I2S DAT */ /* GPIO-22 I2S WCLK */ /* GPIO-23 I2S BCLK */ /* ALT GPIO: EXP GPIO LATCH */ /* CX23417 GPIO's */ /* GPIO-14 S5H1411/CX24228 Reset */ /* GPIO-13 EEPROM write protect */ mc417_gpio_enable(dev, GPIO_14 | GPIO_13, 1); /* Put the demod into reset and protect the eeprom */ mc417_gpio_clear(dev, GPIO_14 | GPIO_13); mdelay(100); /* Bring the demod out of reset */ mc417_gpio_set(dev, GPIO_14); mdelay(100); /* CX24228 GPIO */ /* Connected to IF / Mux */ break; } }
static int philips_fmd1216_pll_init(struct dvb_frontend *fe) { struct cx8802_dev *dev= fe->dvb->priv; /* this message is to set up ATC and ALC */ static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; int err; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { if (err < 0) return err; else return -EREMOTEIO; } return 0; } static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct cx8802_dev *dev= fe->dvb->priv; u8 buf[4]; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; int err; /* Switch PLL to DVB mode */ err = philips_fmd1216_pll_init(fe); if (err) return err; /* Tune PLL */ dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, params->u.ofdm.bandwidth); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", __FUNCTION__, dev->core->pll_addr, buf[0], err); if (err < 0) return err; else return -EREMOTEIO; } return 0; } static struct mt352_config dntv_live_dvbt_pro_config = { .demod_address = 0x0f, .no_tuner = 1, .demod_init = dntv_live_dvbt_pro_demod_init, }; #endif static struct zl10353_config dvico_fusionhdtv_hybrid = { .demod_address = 0x0f, .no_tuner = 1, }; static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { .demod_address = 0x0f, }; static struct cx22702_config connexant_refboard_config = { .demod_address = 0x43, .output_mode = CX22702_SERIAL_OUTPUT, }; static struct cx22702_config hauppauge_hvr_config = { .demod_address = 0x63, .output_mode = CX22702_SERIAL_OUTPUT, }; static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; return 0; } static struct or51132_config pchdtv_hd3000 = { .demod_address = 0x15, .set_ts_params = or51132_set_ts_param, }; static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; dprintk(1, "%s: index = %d\n", __FUNCTION__, index); if (index == 0) cx_clear(MO_GP0_IO, 8); else cx_set(MO_GP0_IO, 8); return 0; } static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; if (is_punctured) dev->ts_gen_cntrl |= 0x04; else dev->ts_gen_cntrl &= ~0x04; return 0; } static struct lgdt330x_config fusionhdtv_3_gold = { .demod_address = 0x0e, .demod_chip = LGDT3302, .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ .set_ts_params = lgdt330x_set_ts_param, }; static struct lgdt330x_config fusionhdtv_5_gold = { .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ .set_ts_params = lgdt330x_set_ts_param, }; static struct lgdt330x_config pchdtv_hd5500 = { .demod_address = 0x59, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ .set_ts_params = lgdt330x_set_ts_param, }; static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; return 0; } static int nxt200x_set_pll_input(u8* buf, int input) { if (input) buf[3] |= 0x08; else buf[3] &= ~0x08; return 0; } static struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, .set_pll_input = nxt200x_set_pll_input, .set_ts_params = nxt200x_set_ts_param, }; static int cx24123_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = 0x02; return 0; } static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; if (voltage == SEC_VOLTAGE_OFF) cx_write(MO_GP0_IO, 0x000006fb); else cx_write(MO_GP0_IO, 0x000006f9); if (core->prev_set_voltage) return core->prev_set_voltage(fe, voltage); return 0; } static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; if (voltage == SEC_VOLTAGE_OFF) { dprintk(1,"LNB Voltage OFF\n"); cx_write(MO_GP0_IO, 0x0000efff); } if (core->prev_set_voltage) return core->prev_set_voltage(fe, voltage); return 0; } static struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, }; static struct cx24123_config hauppauge_novas_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, }; static struct cx24123_config kworld_dvbs_100_config = { .demod_address = 0x15, .set_ts_params = cx24123_set_ts_param, .lnb_polarity = 1, }; static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ dev->dvb.name = dev->core->name; dev->ts_gen_cntrl = 0x0c; /* init frontend */ switch (dev->core->board) { case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_dtt759x); } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, &dev->core->i2c_adap, &dvb_pll_thomson_dtt7579); } break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_fmd1216me); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, NULL, &dvb_pll_thomson_dtt7579); break; } /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, NULL, &dvb_pll_thomson_dtt7579); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* The tin box says DEE1601, but it seems to be DTT7579 * compatible, with a slightly different MT352 AGC gain. */ dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, &dvb_pll_thomson_dtt7579); break; } /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, &dvb_pll_thomson_dtt7579); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, &dvb_pll_lg_z201); } break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, &dvb_pll_unknown_1); } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_fmd1216me; dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &((struct vp3054_i2c_state *)dev->card_priv)->adap); if (dev->dvb.frontend != NULL) { dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; } #else printk("%s: built without vp3054 support\n", dev->core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_fe6600); } break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_dtt761x); } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_microtune_4042); } } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_dtt761x); } } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(lgh06xf_attach, dev->dvb.frontend, &dev->core->i2c_adap); } } break; case CX88_BOARD_PCHDTV_HD5500: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(lgh06xf_attach, dev->dvb.frontend, &dev->core->i2c_adap); } } break; case CX88_BOARD_ATI_HDTVWONDER: dev->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, &dvb_pll_tuv1236d); } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: dev->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &dev->core->i2c_adap); if (dev->dvb.frontend) { dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->core->i2c_adap, 0x08, 0x00, 0x00); } break; case CX88_BOARD_KWORLD_DVBS_100: dev->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, &dev->core->i2c_adap); if (dev->dvb.frontend) { dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; } break; case CX88_BOARD_GENIATECH_DVBS: dev->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, &dev->core->i2c_adap); if (dev->dvb.frontend) { dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; case CX88_BOARD_HAUPPAUGE_HVR1300: dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_fmd1216me); } break; case CX88_BOARD_HAUPPAUGE_HVR3000: dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_fmd1216me); } break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { printk("%s: frontend initialization failed\n",dev->core->name); return -1; } if (dev->core->pll_desc) { dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; } /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); /* register everything */ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); } /* ----------------------------------------------------------- */ /* CX8802 MPEG -> mini driver - We have been given the hardware */ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __FUNCTION__); switch (core->board) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* We arrive here with either the cx23416 or the cx22702 * on the bus. Take the bus from the cx23416 and enable the * cx22702 demod */ cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; default: err = -ENODEV; } return err; } /* CX8802 MPEG -> mini driver - We no longer have the hardware */ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __FUNCTION__); switch (core->board) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* Do Nothing, leave the cx22702 on the bus. */ break; default: err = -ENODEV; } return err; } static int cx8802_dvb_probe(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; int err; dprintk( 1, "%s\n", __FUNCTION__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", core->board, core->name, core->pci_bus, core->pci_slot); err = -ENODEV; if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) goto fail_core; #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) err = vp3054_i2c_probe(dev); if (0 != err) goto fail_core; #endif /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); err = dvb_register(dev); if (err != 0) printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); fail_core: return err; } static int cx8802_dvb_remove(struct cx8802_driver *drv) { struct cx8802_dev *dev = drv->core->dvbdev; /* dvb */ videobuf_dvb_unregister(&dev->dvb); #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) vp3054_i2c_remove(dev); #endif return 0; } static struct cx8802_driver cx8802_dvb_driver = { .type_id = CX88_MPEG_DVB, .hw_access = CX8802_DRVCTL_SHARED, .probe = cx8802_dvb_probe, .remove = cx8802_dvb_remove, .advise_acquire = cx8802_dvb_advise_acquire, .advise_release = cx8802_dvb_advise_release, }; static int dvb_init(void) { printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); #ifdef SNAPSHOT printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif return cx8802_register_driver(&cx8802_dvb_driver); } static void dvb_fini(void) { cx8802_unregister_driver(&cx8802_dvb_driver); } module_init(dvb_init); module_exit(dvb_fini);
static int lgdt330x_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { /* FIXME make this routine use the tuner-simple code. * It could probably be shared with a number of ATSC * frontends. Many share the same tuner with analog TV. */ struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; u8 buf[4]; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; int err; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err); if (err < 0) return err; else return -EREMOTEIO; } if (core->tuner_type == TUNER_LG_TDVS_H062F) { /* Set the Auxiliary Byte. */ buf[2] &= ~0x20; buf[2] |= 0x18; buf[3] = 0x50; i2c_transfer(&core->i2c_adap, &msg, 1); } return 0; } static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; dprintk(1, "%s: index = %d\n", __FUNCTION__, index); if (index == 0) cx_clear(MO_GP0_IO, 8); else cx_set(MO_GP0_IO, 8); return 0; } static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; if (is_punctured) dev->ts_gen_cntrl |= 0x04; else dev->ts_gen_cntrl &= ~0x04; return 0; } static struct lgdt330x_config fusionhdtv_3_gold = { .demod_address = 0x0e, .demod_chip = LGDT3302, .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; static struct lgdt330x_config fusionhdtv_5_gold = { .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; #endif static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ dev->dvb.name = dev->core->name; dev->ts_gen_cntrl = 0x0c; /* init frontend */ switch (dev->core->board) { #ifdef HAVE_CX22702 case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, &dev->core->i2c_adap); break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, &dev->core->i2c_adap); break; #endif #ifdef HAVE_MT352 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: dev->core->pll_addr = 0x60; dev->core->pll_desc = &dvb_pll_thomson_dtt7579; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_unknown_1; dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, &dev->core->i2c_adap); break; #endif #ifdef HAVE_OR51132 case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, &dev->core->i2c_adap); break; #endif #ifdef HAVE_LGDT330X case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_microtune_4042; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_thomson_dtt7611; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; { /* Do a hardware reset of chip before using it. */ struct cx88_core *core = dev->core; cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->core->pll_addr = 0x61; dev->core->pll_desc = &dvb_pll_tdvs_tua6034; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, &dev->core->i2c_adap); } break; #endif default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { printk("%s: frontend initialization failed\n",dev->core->name); return -1; } if (dev->core->pll_desc) { dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min; dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; } /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); /* register everything */ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); } /* ----------------------------------------------------------- */ static int __devinit dvb_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct cx8802_dev *dev; struct cx88_core *core; int err; /* general setup */ core = cx88_core_get(pci_dev); if (NULL == core) return -EINVAL; err = -ENODEV; if (!cx88_boards[core->board].dvb) goto fail_core; err = -ENOMEM; dev = kmalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) goto fail_core; memset(dev,0,sizeof(*dev)); dev->pci = pci_dev; dev->core = core; err = cx8802_init_common(dev); if (0 != err) goto fail_free; /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); err = dvb_register(dev); if (0 != err) goto fail_fini; return 0; fail_fini: cx8802_fini_common(dev); fail_free: kfree(dev); fail_core: cx88_core_put(core,pci_dev); return err; } static void __devexit dvb_remove(struct pci_dev *pci_dev) { struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* dvb */ videobuf_dvb_unregister(&dev->dvb); /* common */ cx8802_fini_common(dev); cx88_core_put(dev->core,dev->pci); kfree(dev); } static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } };