+ av7110->card_name = (char*) pci_ext->ext_priv;
+ av7110->dev = dev;
+ dev->ext_priv = av7110;
+
+ ret = get_firmware(av7110);
+ if (ret < 0)
+ goto err_kfree_0;
+
+ ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
+ THIS_MODULE, &dev->pci->dev);
+ if (ret < 0)
+ goto err_put_firmware_1;
+
+ /* the Siemens DVB needs this if you want to have the i2c chips
+ get recognized before the main driver is fully loaded */
+ saa7146_write(dev, GPIO_CTRL, 0x500000);
+
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+ av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
+#else
+ av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+#endif
+ strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
+
+ saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
+
+ ret = i2c_add_adapter(&av7110->i2c_adap);
+ if (ret < 0)
+ goto err_dvb_unregister_adapter_2;
+
+ ttpci_eeprom_parse_mac(&av7110->i2c_adap,
+ av7110->dvb_adapter.proposed_mac);
+ ret = -ENOMEM;
+
+ if (budgetpatch) {
+ spin_lock_init(&av7110->feedlock1);
+ av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
+ &av7110->pt);
+ if (!av7110->grabbing)
+ goto err_i2c_del_3;
+
+ saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+ /* set dd1 stream a & b */
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, DD1_INIT, 0x03000200);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+ saa7146_write(dev, BRS_CTRL, 0x60000000);
+ saa7146_write(dev, BASE_ODD3, 0);
+ saa7146_write(dev, BASE_EVEN3, 0);
+ saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
+
+ saa7146_write(dev, PITCH3, TS_WIDTH);
+ saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
+
+ /* upload all */
+ saa7146_write(dev, MC2, 0x077c077c);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
+#if RPS_IRQ
+ /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
+ * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
+ * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
+ */
+ saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
+ /* set event counter 1 treshold to maximum allowed value (rEC p55) */
+ saa7146_write(dev, ECT1R, 0x3fff );
+#endif
+ /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
+ count = 0;
+
+ /* Wait Source Line Counter Threshold (p36) */
+ WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
+ /* Set GPIO3=1 (p42) */
+ WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
+ WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
+ WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
+#if RPS_IRQ
+ /* issue RPS1 interrupt */
+ WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+#endif
+ /* Wait reset Source Line Counter Threshold (p36) */
+ WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
+ /* Set GPIO3=0 (p42) */
+ WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
+ WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
+ WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
+#if RPS_IRQ
+ /* issue RPS1 interrupt */
+ WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+#endif
+ /* Jump to begin of RPS program (p37) */
+ WRITE_RPS1(cpu_to_le32(CMD_JUMP));
+ WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
+
+ /* Fix VSYNC level */
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ /* Set RPS1 Address register to point to RPS code (r108 p42) */
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+ /* Set Source Line Counter Threshold, using BRS (rCC p43)
+ * It generates HS event every TS_HEIGHT lines
+ * this is related to TS_WIDTH set in register
+ * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
+ * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
+ * then RPS_THRESH1 should be set to trigger
+ * every TS_HEIGHT (512) lines.
+ */
+ saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
+
+ /* Enable RPS1 (rFC p33) */
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
+ /* end of budgetpatch register initialization */
+ tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
+ } else {
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+ /* set dd1 stream a & b */
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, DD1_INIT, 0x03000000);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ /* upload all */
+ saa7146_write(dev, MC2, 0x077c077c);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
+ }
+
+ tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
+ tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
+
+ mutex_init(&av7110->pid_mutex);
+
+ /* locks for data transfers from/to AV7110 */
+ spin_lock_init(&av7110->debilock);
+ mutex_init(&av7110->dcomlock);
+ av7110->debitype = -1;
+
+ /* default OSD window */
+ av7110->osdwin = 1;
+ mutex_init(&av7110->osd_mutex);
+
+ /* TV standard */
+ av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
+
+ /* ARM "watchdog" */
+ init_waitqueue_head(&av7110->arm_wait);
+ av7110->arm_thread = NULL;
+
+ /* allocate and init buffers */
+ av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
+ if (!av7110->debi_virt)
+ goto err_saa71466_vfree_4;
+
+
+ av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
+ if (!av7110->iobuf)
+ goto err_pci_free_5;
+
+ ret = av7110_av_init(av7110);
+ if (ret < 0)
+ goto err_iobuf_vfree_6;
+
+ /* init BMP buffer */
+ av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
+ init_waitqueue_head(&av7110->bmpq);
+
+ ret = av7110_ca_init(av7110);
+ if (ret < 0)
+ goto err_av7110_av_exit_7;
+
+ /* load firmware into AV7110 cards */
+ ret = av7110_bootarm(av7110);
+ if (ret < 0)
+ goto err_av7110_ca_exit_8;
+
+ ret = av7110_firmversion(av7110);
+ if (ret < 0)
+ goto err_stop_arm_9;
+
+ if (FW_VERSION(av7110->arm_app)<0x2501)
+ printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
+ "System might be unstable!\n", FW_VERSION(av7110->arm_app));
+
+ ret = kernel_thread(arm_thread, (void *) av7110, 0);
+ if (ret < 0)
+ goto err_stop_arm_9;
+
+ /* set initial volume in mixer struct */
+ av7110->mixer.volume_left = volume;
+ av7110->mixer.volume_right = volume;
+
+ init_av7110_av(av7110);
+
+ ret = av7110_register(av7110);
+ if (ret < 0)
+ goto err_arm_thread_stop_10;
+