static int em28xx_dvb_resume(struct em28xx *dev) { int ret = 0; if (dev->is_audio_only) return 0; if (!dev->board.has_dvb) return 0; em28xx_info("Resuming DVB extension"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; if (dvb->fe[0]) { ret = dvb_frontend_resume(dvb->fe[0]); em28xx_info("fe0 resume %d", ret); } if (dvb->fe[1]) { ret = dvb_frontend_resume(dvb->fe[1]); em28xx_info("fe1 resume %d", ret); } } return 0; }
static int em28xx_dvb_suspend(struct em28xx *dev) { int ret = 0; if (dev->is_audio_only) return 0; if (!dev->board.has_dvb) return 0; em28xx_info("Suspending DVB extension"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; if (dvb->fe[0]) { ret = dvb_frontend_suspend(dvb->fe[0]); em28xx_info("fe0 suspend %d", ret); } if (dvb->fe[1]) { dvb_frontend_suspend(dvb->fe[1]); em28xx_info("fe1 suspend %d", ret); } } return 0; }
static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) { struct dvb_frontend *fe; struct xc2028_config cfg; struct xc2028_ctrl ctl; memset(&cfg, 0, sizeof(cfg)); cfg.i2c_adap = &dev->i2c_adap[dev->def_i2c_bus]; cfg.i2c_addr = addr; memset(&ctl, 0, sizeof(ctl)); em28xx_setup_xc3028(dev, &ctl); cfg.ctrl = &ctl; if (!dev->dvb->fe[0]) { em28xx_errdev("/2: dvb frontend not attached. " "Can't attach xc3028\n"); return -EINVAL; } fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); if (!fe) { em28xx_errdev("/2: xc3028 attach failed\n"); dvb_frontend_detach(dev->dvb->fe[0]); dev->dvb->fe[0] = NULL; return -EINVAL; } em28xx_info("%s/2: xc3028 attached\n", dev->name); return 0; }
static int attach_xc3028(u8 addr, struct em28xx *dev) { struct dvb_frontend *fe; struct xc2028_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.i2c_adap = &dev->i2c_adap; cfg.i2c_addr = addr; if (!dev->dvb->frontend) { em28xx_errdev("/2: dvb frontend not attached. " "Can't attach xc3028\n"); return -EINVAL; } fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); if (!fe) { em28xx_errdev("/2: xc3028 attach failed\n"); dvb_frontend_detach(dev->dvb->frontend); dev->dvb->frontend = NULL; return -EINVAL; } em28xx_info("%s/2: xc3028 attached\n", dev->name); return 0; }
static int em28xx_dvb_fini(struct em28xx *dev) { struct em28xx_dvb *dvb; struct i2c_client *client; if (dev->is_audio_only) { /* Shouldn't initialize IR for this interface */ return 0; } if (!dev->board.has_dvb) { /* This device does not support the extension */ return 0; } if (!dev->dvb) return 0; em28xx_info("Closing DVB extension"); dvb = dev->dvb; client = dvb->i2c_client_tuner; em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); if (dev->disconnected) { /* We cannot tell the device to sleep * once it has been unplugged. */ if (dvb->fe[0]) { prevent_sleep(&dvb->fe[0]->ops); dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED; } if (dvb->fe[1]) { prevent_sleep(&dvb->fe[1]->ops); dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED; } } /* remove I2C tuner */ if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); } /* remove I2C demod */ client = dvb->i2c_client_demod; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); } em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; kref_put(&dev->ref, em28xx_free_device); return 0; }
static int em28xx_dvb_resume(struct em28xx *dev) { int ret = 0; if (dev->is_audio_only) return 0; if (!dev->board.has_dvb) return 0; em28xx_info("Resuming DVB extension"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; struct i2c_client *client = dvb->i2c_client_tuner; if (dvb->fe[0]) { ret = dvb_frontend_resume(dvb->fe[0]); em28xx_info("fe0 resume %d", ret); } if (dvb->fe[1]) { ret = dvb_frontend_resume(dvb->fe[1]); em28xx_info("fe1 resume %d", ret); } /* remove I2C tuner */ if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); } /* remove I2C demod */ client = dvb->i2c_client_demod; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); } em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; } return 0; }
void em28xx_deregister_snapshot_button(struct em28xx *dev) { if (dev->sbutton_input_dev != NULL) { em28xx_info("Deregistering snapshot button\n"); cancel_rearming_delayed_work(&dev->sbutton_query_work); input_unregister_device(dev->sbutton_input_dev); dev->sbutton_input_dev = NULL; } return; }
void em28xx_register_snapshot_button(struct em28xx *dev) { struct input_dev *input_dev; int err; em28xx_info("Registering snapshot button...\n"); input_dev = input_allocate_device(); if (!input_dev) { em28xx_errdev("input_allocate_device failed\n"); return; } usb_make_path(dev->udev, dev->snapshot_button_path, sizeof(dev->snapshot_button_path)); strlcat(dev->snapshot_button_path, "/sbutton", sizeof(dev->snapshot_button_path)); INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton); input_dev->name = "em28xx snapshot button"; input_dev->phys = dev->snapshot_button_path; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit); input_dev->keycodesize = 0; input_dev->keycodemax = 0; input_dev->id.bustype = BUS_USB; input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); input_dev->id.version = 1; input_dev->dev.parent = &dev->udev->dev; err = input_register_device(input_dev); if (err) { em28xx_errdev("input_register_device failed\n"); input_free_device(input_dev); return; } dev->sbutton_input_dev = input_dev; schedule_delayed_work(&dev->sbutton_query_work, msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); return; }
int em28xx_detect_sensor(struct em28xx *dev) { int ret; ret = em28xx_probe_sensor_micron(dev); if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) ret = em28xx_probe_sensor_omnivision(dev); /* * NOTE: the Windows driver also probes i2c addresses * 0x22 (Samsung ?) and 0x66 (Kodak ?) */ if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) { em28xx_info("No sensor detected\n"); return -ENODEV; } return 0; }
static int em28xx_dvb_init(struct em28xx *dev) { int result = 0, mfe_shared = 0; struct em28xx_dvb *dvb; if (dev->is_audio_only) { /* Shouldn't initialize IR for this interface */ return 0; } if (!dev->board.has_dvb) { /* This device does not support the extension */ return 0; } em28xx_info("Binding DVB extension\n"); dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); if (dvb == NULL) { em28xx_info("em28xx_dvb: memory allocation failed\n"); return -ENOMEM; } dev->dvb = dvb; dvb->fe[0] = dvb->fe[1] = NULL; /* pre-allocate DVB usb transfer buffers */ if (dev->dvb_xfer_bulk) { result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, dev->dvb_xfer_bulk, EM28XX_DVB_NUM_BUFS, 512, EM28XX_DVB_BULK_PACKET_MULTIPLIER); } else { result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, dev->dvb_xfer_bulk, EM28XX_DVB_NUM_BUFS, dev->dvb_max_pkt_size_isoc, EM28XX_DVB_NUM_ISOC_PACKETS); } if (result) { em28xx_errdev("em28xx_dvb: failed to pre-allocate USB transfer buffers for DVB.\n"); kfree(dvb); dev->dvb = NULL; return result; } mutex_lock(&dev->lock); em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { case EM2874_BOARD_LEADERSHIP_ISDBT: dvb->fe[0] = dvb_attach(s921_attach, &sharp_isdbt, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } break; case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_KWORLD_DVB_310U: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: case EM2882_BOARD_DIKOM_DK300: case EM2882_BOARD_KWORLD_VS_DVBT: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] == NULL) { /* This board could have either a zl10353 or a mt352. If the chip id isn't for zl10353, try mt352 */ dvb->fe[0] = dvb_attach(mt352_attach, &terratec_xs_mt352_cfg, &dev->i2c_adap[dev->def_i2c_bus]); } if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2870_BOARD_KWORLD_355U: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_no_i2c_gate_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) dvb_attach(qt1010_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_qt1010_config); break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->fe[0] = dvb_attach(s5h1409_attach, &em28xx_s5h1409_with_xc3028, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2882_BOARD_KWORLD_ATSC_315U: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x61, TUNER_THOMSON_DTT761X)) { result = -EINVAL; goto out_free; } } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, &dev->i2c_adap[dev->def_i2c_bus], &dev->udev->dev); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2870_BOARD_REDDO_DVB_C_USB_BOX: /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ dvb->fe[0] = dvb_attach(tda10023_attach, &em28xx_tda10023_config, &dev->i2c_adap[dev->def_i2c_bus], 0x48); if (dvb->fe[0]) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60, TUNER_PHILIPS_CU1216L)) { result = -EINVAL; goto out_free; } } break; case EM2870_BOARD_KWORLD_A340: dvb->fe[0] = dvb_attach(lgdt3305_attach, &em2870_lgdt3304_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &kworld_a340_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } break; case EM28174_BOARD_PCTV_290E: /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L; dvb->fe[0] = dvb_attach(cxd2820r_attach, &em28xx_cxd2820r_config, &dev->i2c_adap[dev->def_i2c_bus], &dvb->lna_gpio); if (dvb->fe[0]) { /* FE 0 attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } #ifdef CONFIG_GPIOLIB /* enable LNA for DVB-T, DVB-T2 and DVB-C */ result = gpio_request_one(dvb->lna_gpio, GPIOF_OUT_INIT_LOW, NULL); if (result) em28xx_errdev("gpio request failed %d\n", result); else gpio_free(dvb->lna_gpio); result = 0; /* continue even set LNA fails */ #endif dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna; } break; case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: { struct xc5000_config cfg; hauppauge_hvr930c_init(dev); dvb->fe[0] = dvb_attach(drxk_attach, &hauppauge_930c_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* FIXME: do we need a pll semaphore? */ dvb->fe[0]->sec_priv = dvb; sema_init(&dvb->pll_mutex, 1); dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; /* Attach xc5000 */ memset(&cfg, 0, sizeof(cfg)); cfg.i2c_address = 0x61; cfg.if_khz = 4000; if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &cfg)) { result = -EINVAL; goto out_free; } if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); break; } case EM2884_BOARD_TERRATEC_H5: terratec_h5_init(dev); dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* FIXME: do we need a pll semaphore? */ dvb->fe[0]->sec_priv = dvb; sema_init(&dvb->pll_mutex, 1); dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; /* Attach tda18271 to DVB-C frontend */ if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60)) { result = -EINVAL; goto out_free; } if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); break; case EM2884_BOARD_C3TECH_DIGITAL_DUO: dvb->fe[0] = dvb_attach(mb86a20s_attach, &c3tech_duo_mb86a20s_config, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &c3tech_duo_tda18271_config); break; case EM28174_BOARD_PCTV_460E: /* attach demod */ dvb->fe[0] = dvb_attach(tda10071_attach, &em28xx_tda10071_config, &dev->i2c_adap[dev->def_i2c_bus]); /* attach SEC */ if (dvb->fe[0]) dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config); break; case EM2874_BOARD_DELOCK_61959: case EM2874_BOARD_MAXMEDIA_UB425_TC: /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0]) { /* disable I2C-gate */ dvb->fe[0]->ops.i2c_gate_ctrl = NULL; /* attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } } break; case EM2884_BOARD_PCTV_510E: case EM2884_BOARD_PCTV_520E: pctv_520e_init(dev); /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0]) { /* attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } } break; case EM2884_BOARD_CINERGY_HTC_STICK: terratec_htc_stick_init(dev); /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* Attach the demodulator. */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { result = -EINVAL; goto out_free; } break; case EM2884_BOARD_TERRATEC_HTC_USB_XS: terratec_htc_usb_xs_init(dev); /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* Attach the demodulator. */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { result = -EINVAL; goto out_free; } break; case EM2874_BOARD_KWORLD_UB435Q_V2: dvb->fe[0] = dvb_attach(lgdt3305_attach, &em2874_lgdt3305_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* Attach the demodulator. */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &kworld_ub435q_v2_config)) { result = -EINVAL; goto out_free; } break; case EM2874_BOARD_KWORLD_UB435Q_V3: dvb->fe[0] = dvb_attach(lgdt3305_attach, &em2874_lgdt3305_nogate_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* Attach the demodulator. */ if (!dvb_attach(tda18212_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &kworld_ub435q_v3_config)) { result = -EINVAL; goto out_free; } break; case EM2874_BOARD_PCTV_HD_MINI_80E: dvb->fe[0] = dvb_attach(drx39xxj_attach, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) { dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &pinnacle_80e_dvb_config); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } } break; case EM28178_BOARD_PCTV_461E: { /* demod I2C adapter */ struct i2c_adapter *i2c_adapter; struct i2c_client *client; struct i2c_board_info info; struct m88ts2022_config m88ts2022_config = { .clock = 27000000, }; memset(&info, 0, sizeof(struct i2c_board_info)); /* attach demod */ dvb->fe[0] = dvb_attach(m88ds3103_attach, &pctv_461e_m88ds3103_config, &dev->i2c_adap[dev->def_i2c_bus], &i2c_adapter); if (dvb->fe[0] == NULL) { result = -ENODEV; goto out_free; } /* attach tuner */ m88ts2022_config.fe = dvb->fe[0]; strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &m88ts2022_config; request_module("m88ts2022"); client = i2c_new_device(i2c_adapter, &info); if (client == NULL || client->dev.driver == NULL) { dvb_frontend_detach(dvb->fe[0]); result = -ENODEV; goto out_free; } if (!try_module_get(client->dev.driver->owner)) { i2c_unregister_device(client); dvb_frontend_detach(dvb->fe[0]); result = -ENODEV; goto out_free; } /* delegate signal strength measurement to tuner */ dvb->fe[0]->ops.read_signal_strength = dvb->fe[0]->ops.tuner_ops.get_rf_strength; /* attach SEC */ if (!dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config)) { module_put(client->dev.driver->owner); i2c_unregister_device(client); dvb_frontend_detach(dvb->fe[0]); result = -ENODEV; goto out_free; } dvb->i2c_client_tuner = client; } break; case EM28178_BOARD_PCTV_292E: { struct i2c_adapter *adapter; struct i2c_client *client; struct i2c_board_info info; struct si2168_config si2168_config; struct si2157_config si2157_config; /* attach demod */ si2168_config.i2c_adapter = &adapter; si2168_config.fe = &dvb->fe[0]; memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module(info.type); client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); if (client == NULL || client->dev.driver == NULL) { result = -ENODEV; goto out_free; } if (!try_module_get(client->dev.driver->owner)) { i2c_unregister_device(client); result = -ENODEV; goto out_free; } dvb->i2c_client_demod = client; /* attach tuner */ memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dvb->fe[0]; memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module(info.type); client = i2c_new_device(adapter, &info); if (client == NULL || client->dev.driver == NULL) { module_put(dvb->i2c_client_demod->dev.driver->owner); i2c_unregister_device(dvb->i2c_client_demod); result = -ENODEV; goto out_free; } if (!try_module_get(client->dev.driver->owner)) { i2c_unregister_device(client); module_put(dvb->i2c_client_demod->dev.driver->owner); i2c_unregister_device(dvb->i2c_client_demod); result = -ENODEV; goto out_free; } dvb->i2c_client_tuner = client; dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna; } break; default: em28xx_errdev("/2: The frontend of your DVB/ATSC card" " isn't supported yet\n"); break; } if (NULL == dvb->fe[0]) { em28xx_errdev("/2: frontend initialization failed\n"); result = -EINVAL; goto out_free; } /* define general-purpose callback pointer */ dvb->fe[0]->callback = em28xx_tuner_callback; if (dvb->fe[1]) dvb->fe[1]->callback = em28xx_tuner_callback; /* register everything */ result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); if (result < 0) goto out_free; /* MFE lock */ dvb->adapter.mfe_shared = mfe_shared; em28xx_info("DVB extension successfully initialized\n"); kref_get(&dev->ref); ret: em28xx_set_mode(dev, EM28XX_SUSPEND); mutex_unlock(&dev->lock); return result; out_free: kfree(dvb); dev->dvb = NULL; goto ret; } static inline void prevent_sleep(struct dvb_frontend_ops *ops) { ops->set_voltage = NULL; ops->sleep = NULL; ops->tuner_ops.sleep = NULL; }
/* * Probes Omnivision sensors with 8 bit address and register width */ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) { int ret, i; char *name; u8 reg; u16 id; struct i2c_client client = dev->i2c_client[dev->def_i2c_bus]; dev->em28xx_sensor = EM28XX_NOSENSOR; /* NOTE: these devices have the register auto incrementation disabled * by default, so we have to use single byte reads ! */ for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) { client.addr = omnivision_sensor_addrs[i]; /* Read manufacturer ID from registers 0x1c-0x1d (BE) */ reg = 0x1c; ret = i2c_smbus_read_byte_data(&client, reg); if (ret < 0) { if (ret != -ENXIO) em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } id = ret << 8; reg = 0x1d; ret = i2c_smbus_read_byte_data(&client, reg); if (ret < 0) { em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } id += ret; /* Check manufacturer ID */ if (id != 0x7fa2) continue; /* Read product ID from registers 0x0a-0x0b (BE) */ reg = 0x0a; ret = i2c_smbus_read_byte_data(&client, reg); if (ret < 0) { em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } id = ret << 8; reg = 0x0b; ret = i2c_smbus_read_byte_data(&client, reg); if (ret < 0) { em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } id += ret; /* Check product ID */ switch (id) { case 0x2642: name = "OV2640"; dev->em28xx_sensor = EM28XX_OV2640; break; case 0x7648: name = "OV7648"; break; case 0x7660: name = "OV7660"; break; case 0x7673: name = "OV7670"; break; case 0x7720: name = "OV7720"; break; case 0x7721: name = "OV7725"; break; case 0x9648: /* Rev 2 */ case 0x9649: /* Rev 3 */ name = "OV9640"; break; case 0x9650: case 0x9652: /* OV9653 */ name = "OV9650"; break; case 0x9656: /* Rev 4 */ case 0x9657: /* Rev 5 */ name = "OV9655"; break; default: em28xx_info("unknown OmniVision sensor detected: 0x%04x\n", id); return 0; } if (dev->em28xx_sensor == EM28XX_NOSENSOR) em28xx_info("unsupported sensor detected: %s\n", name); else em28xx_info("sensor %s detected\n", name); dev->i2c_client[dev->def_i2c_bus].addr = client.addr; return 0; } return -ENODEV; }
/* * Probes Micron sensors with 8 bit address and 16 bit register width */ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; u8 reg; __be16 id_be; u16 id; struct i2c_client client = dev->i2c_client[dev->def_i2c_bus]; dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { client.addr = micron_sensor_addrs[i]; /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ reg = 0x00; ret = i2c_master_send(&client, ®, 1); if (ret < 0) { if (ret != -ENXIO) em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } ret = i2c_master_recv(&client, (u8 *)&id_be, 2); if (ret < 0) { em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } id = be16_to_cpu(id_be); /* Read chip ID from register 0xff */ reg = 0xff; ret = i2c_master_send(&client, ®, 1); if (ret < 0) { em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } ret = i2c_master_recv(&client, (u8 *)&id_be, 2); if (ret < 0) { em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; } /* Validate chip ID to be sure we have a Micron device */ if (id != be16_to_cpu(id_be)) continue; /* Check chip ID */ id = be16_to_cpu(id_be); switch (id) { case 0x1222: name = "MT9V012"; /* MI370 */ /* 640x480 */ break; case 0x1229: name = "MT9V112"; /* 640x480 */ break; case 0x1433: name = "MT9M011"; /* 1280x1024 */ break; case 0x143a: /* found in the ECS G200 */ name = "MT9M111"; /* MI1310 */ /* 1280x1024 */ dev->em28xx_sensor = EM28XX_MT9M111; break; case 0x148c: name = "MT9M112"; /* MI1320 */ /* 1280x1024 */ break; case 0x1511: name = "MT9D011"; /* MI2010 */ /* 1600x1200 */ break; case 0x8232: case 0x8243: /* rev B */ name = "MT9V011"; /* MI360 */ /* 640x480 */ dev->em28xx_sensor = EM28XX_MT9V011; break; case 0x8431: name = "MT9M001"; /* 1280x1024 */ dev->em28xx_sensor = EM28XX_MT9M001; break; default: em28xx_info("unknown Micron sensor detected: 0x%04x\n", id); return 0; } if (dev->em28xx_sensor == EM28XX_NOSENSOR) em28xx_info("unsupported sensor detected: %s\n", name); else em28xx_info("sensor %s detected\n", name); dev->i2c_client[dev->def_i2c_bus].addr = client.addr; return 0; } return -ENODEV; }
static int dvb_init(struct em28xx *dev) { int result = 0; struct em28xx_dvb *dvb; if (!dev->board.has_dvb) { /* This device does not support the extension */ printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); return 0; } dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); if (dvb == NULL) { em28xx_info("em28xx_dvb: memory allocation failed\n"); return -ENOMEM; } dev->dvb = dvb; dvb->fe[0] = dvb->fe[1] = NULL; mutex_lock(&dev->lock); em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { case EM2874_BOARD_LEADERSHIP_ISDBT: dvb->fe[0] = dvb_attach(s921_attach, &sharp_isdbt, &dev->i2c_adap); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } break; case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_KWORLD_DVB_310U: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: case EM2882_BOARD_DIKOM_DK300: case EM2882_BOARD_KWORLD_VS_DVBT: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); if (dvb->fe[0] == NULL) { /* This board could have either a zl10353 or a mt352. If the chip id isn't for zl10353, try mt352 */ dvb->fe[0] = dvb_attach(mt352_attach, &terratec_xs_mt352_cfg, &dev->i2c_adap); } if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->fe[0] = dvb_attach(s5h1409_attach, &em28xx_s5h1409_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2882_BOARD_KWORLD_ATSC_315U: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); if (dvb->fe[0] != NULL) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { result = -EINVAL; goto out_free; } } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, &dev->i2c_adap, &dev->udev->dev); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2870_BOARD_REDDO_DVB_C_USB_BOX: /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ dvb->fe[0] = dvb_attach(tda10023_attach, &em28xx_tda10023_config, &dev->i2c_adap, 0x48); if (dvb->fe[0]) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { result = -EINVAL; goto out_free; } } break; case EM2870_BOARD_KWORLD_A340: dvb->fe[0] = dvb_attach(lgdt3305_attach, &em2870_lgdt3304_dev, &dev->i2c_adap); if (dvb->fe[0] != NULL) dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap, &kworld_a340_config); break; case EM28174_BOARD_PCTV_290E: /* MFE * FE 0 = DVB-T/T2 + FE 1 = DVB-C, both sharing same tuner. */ /* FE 0 */ dvb->fe[0] = dvb_attach(cxd2820r_attach, &em28xx_cxd2820r_config, &dev->i2c_adap, NULL); if (dvb->fe[0]) { struct i2c_adapter *i2c_tuner; i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]); /* FE 0 attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, i2c_tuner, &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } /* FE 1. This dvb_attach() cannot fail. */ dvb->fe[1] = dvb_attach(cxd2820r_attach, NULL, NULL, dvb->fe[0]); dvb->fe[1]->id = 1; /* FE 1 attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60, i2c_tuner, &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[1]); /* leave FE 0 still active */ } } break; default: em28xx_errdev("/2: The frontend of your DVB/ATSC card" " isn't supported yet\n"); break; } if (NULL == dvb->fe[0]) { em28xx_errdev("/2: frontend initialization failed\n"); result = -EINVAL; goto out_free; } /* define general-purpose callback pointer */ dvb->fe[0]->callback = em28xx_tuner_callback; /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); if (result < 0) goto out_free; em28xx_info("Successfully loaded em28xx-dvb\n"); ret: em28xx_set_mode(dev, EM28XX_SUSPEND); mutex_unlock(&dev->lock); return result; out_free: kfree(dvb); dev->dvb = NULL; goto ret; }
static int em28xx_dvb_init(struct em28xx *dev) { int result = 0, mfe_shared = 0; struct em28xx_dvb *dvb; if (!dev->board.has_dvb) { /* This device does not support the extension */ printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); return 0; } dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); if (dvb == NULL) { em28xx_info("em28xx_dvb: memory allocation failed\n"); return -ENOMEM; } dev->dvb = dvb; dvb->fe[0] = dvb->fe[1] = NULL; mutex_lock(&dev->lock); em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { case EM2874_BOARD_LEADERSHIP_ISDBT: dvb->fe[0] = dvb_attach(s921_attach, &sharp_isdbt, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } break; case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_KWORLD_DVB_310U: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: case EM2882_BOARD_DIKOM_DK300: case EM2882_BOARD_KWORLD_VS_DVBT: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] == NULL) { /* This board could have either a zl10353 or a mt352. If the chip id isn't for zl10353, try mt352 */ dvb->fe[0] = dvb_attach(mt352_attach, &terratec_xs_mt352_cfg, &dev->i2c_adap[dev->def_i2c_bus]); } if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2870_BOARD_KWORLD_355U: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_no_i2c_gate_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) dvb_attach(qt1010_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_qt1010_config); break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->fe[0] = dvb_attach(s5h1409_attach, &em28xx_s5h1409_with_xc3028, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2882_BOARD_KWORLD_ATSC_315U: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x61, TUNER_THOMSON_DTT761X)) { result = -EINVAL; goto out_free; } } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, &dev->i2c_adap[dev->def_i2c_bus], &dev->udev->dev); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2870_BOARD_REDDO_DVB_C_USB_BOX: /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ dvb->fe[0] = dvb_attach(tda10023_attach, &em28xx_tda10023_config, &dev->i2c_adap[dev->def_i2c_bus], 0x48); if (dvb->fe[0]) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60, TUNER_PHILIPS_CU1216L)) { result = -EINVAL; goto out_free; } } break; case EM2870_BOARD_KWORLD_A340: dvb->fe[0] = dvb_attach(lgdt3305_attach, &em2870_lgdt3304_dev, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &kworld_a340_config); break; case EM28174_BOARD_PCTV_290E: /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L; dvb->fe[0] = dvb_attach(cxd2820r_attach, &em28xx_cxd2820r_config, &dev->i2c_adap[dev->def_i2c_bus], &dvb->lna_gpio); if (dvb->fe[0]) { /* FE 0 attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } #ifdef CONFIG_GPIOLIB /* enable LNA for DVB-T, DVB-T2 and DVB-C */ result = gpio_request_one(dvb->lna_gpio, GPIOF_OUT_INIT_LOW, NULL); if (result) em28xx_errdev("gpio request failed %d\n", result); else gpio_free(dvb->lna_gpio); result = 0; /* continue even set LNA fails */ #endif dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna; } break; case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: { struct xc5000_config cfg; hauppauge_hvr930c_init(dev); dvb->fe[0] = dvb_attach(drxk_attach, &hauppauge_930c_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* FIXME: do we need a pll semaphore? */ dvb->fe[0]->sec_priv = dvb; sema_init(&dvb->pll_mutex, 1); dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; /* Attach xc5000 */ memset(&cfg, 0, sizeof(cfg)); cfg.i2c_address = 0x61; cfg.if_khz = 4000; if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &cfg)) { result = -EINVAL; goto out_free; } if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); break; } case EM2884_BOARD_TERRATEC_H5: terratec_h5_init(dev); dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* FIXME: do we need a pll semaphore? */ dvb->fe[0]->sec_priv = dvb; sema_init(&dvb->pll_mutex, 1); dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; /* Attach tda18271 to DVB-C frontend */ if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60)) { result = -EINVAL; goto out_free; } if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); break; case EM2884_BOARD_C3TECH_DIGITAL_DUO: dvb->fe[0] = dvb_attach(mb86a20s_attach, &c3tech_duo_mb86a20s_config, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &c3tech_duo_tda18271_config); break; case EM28174_BOARD_PCTV_460E: /* attach demod */ dvb->fe[0] = dvb_attach(tda10071_attach, &em28xx_tda10071_config, &dev->i2c_adap[dev->def_i2c_bus]); /* attach SEC */ if (dvb->fe[0]) dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config); break; case EM2874_BOARD_MAXMEDIA_UB425_TC: /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0]) { /* disable I2C-gate */ dvb->fe[0]->ops.i2c_gate_ctrl = NULL; /* attach tuner */ if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } } /* TODO: we need drx-3913k firmware in order to support DVB-T */ em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ "driver version\n"); break; case EM2884_BOARD_PCTV_510E: case EM2884_BOARD_PCTV_520E: pctv_520e_init(dev); /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0]) { /* attach tuner */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { dvb_frontend_detach(dvb->fe[0]); result = -EINVAL; goto out_free; } } break; case EM2884_BOARD_CINERGY_HTC_STICK: terratec_htc_stick_init(dev); /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* Attach the demodulator. */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { result = -EINVAL; goto out_free; } break; case EM2884_BOARD_TERRATEC_HTC_USB_XS: terratec_htc_usb_xs_init(dev); /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, &dev->i2c_adap[dev->def_i2c_bus]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } /* Attach the demodulator. */ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap[dev->def_i2c_bus], &em28xx_cxd2820r_tda18271_config)) { result = -EINVAL; goto out_free; } break; default: em28xx_errdev("/2: The frontend of your DVB/ATSC card" " isn't supported yet\n"); break; } if (NULL == dvb->fe[0]) { em28xx_errdev("/2: frontend initialization failed\n"); result = -EINVAL; goto out_free; } /* define general-purpose callback pointer */ dvb->fe[0]->callback = em28xx_tuner_callback; if (dvb->fe[1]) dvb->fe[1]->callback = em28xx_tuner_callback; /* register everything */ result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); if (result < 0) goto out_free; /* MFE lock */ dvb->adapter.mfe_shared = mfe_shared; em28xx_info("Successfully loaded em28xx-dvb\n"); ret: em28xx_set_mode(dev, EM28XX_SUSPEND); mutex_unlock(&dev->lock); return result; out_free: kfree(dvb); dev->dvb = NULL; goto ret; }
static int dvb_init(struct em28xx *dev) { int result = 0; struct em28xx_dvb *dvb; if (!dev->board.has_dvb) { /* This device does not support the extension */ printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); return 0; } dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); if (dvb == NULL) { em28xx_info("em28xx_dvb: memory allocation failed\n"); return -ENOMEM; } dev->dvb = dvb; mutex_lock(&dev->lock); em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { case EM2874_LEADERSHIP_ISDBT: dvb->frontend = dvb_attach(s921_attach, &sharp_isdbt, &dev->i2c_adap); if (!dvb->frontend) { result = -EINVAL; goto out_free; } break; case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->frontend = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_KWORLD_DVB_310U: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: case EM2882_BOARD_DIKOM_DK300: case EM2882_BOARD_KWORLD_VS_DVBT: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); if (dvb->frontend == NULL) { /* This board could have either a zl10353 or a mt352. If the chip id isn't for zl10353, try mt352 */ dvb->frontend = dvb_attach(mt352_attach, &terratec_xs_mt352_cfg, &dev->i2c_adap); } if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->frontend = dvb_attach(s5h1409_attach, &em28xx_s5h1409_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; case EM2882_BOARD_KWORLD_ATSC_315U: dvb->frontend = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); if (dvb->frontend != NULL) { if (!dvb_attach(simple_tuner_attach, dvb->frontend, &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { result = -EINVAL; goto out_free; } } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: #ifdef EM28XX_DRX397XD_SUPPORT /* We don't have the config structure properly populated, so this is commented out for now */ dvb->frontend = dvb_attach(drx397xD_attach, &em28xx_drx397xD_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; } break; #endif case EM2870_BOARD_REDDO_DVB_C_USB_BOX: /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ dvb->frontend = dvb_attach(tda10023_attach, &em28xx_tda10023_config, &dev->i2c_adap, 0x48); if (dvb->frontend) { if (!dvb_attach(simple_tuner_attach, dvb->frontend, &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { result = -EINVAL; goto out_free; } } break; case EM2870_BOARD_KWORLD_A340: dvb->frontend = dvb_attach(lgdt3305_attach, &em2870_lgdt3304_dev, &dev->i2c_adap); if (dvb->frontend != NULL) dvb_attach(tda18271_attach, dvb->frontend, 0x60, &dev->i2c_adap, &kworld_a340_config); break; default: em28xx_errdev("/2: The frontend of your DVB/ATSC card" " isn't supported yet\n"); break; } if (NULL == dvb->frontend) { em28xx_errdev("/2: frontend initialization failed\n"); result = -EINVAL; goto out_free; } /* define general-purpose callback pointer */ dvb->frontend->callback = em28xx_tuner_callback; /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); if (result < 0) goto out_free; em28xx_info("Successfully loaded em28xx-dvb\n"); ret: em28xx_set_mode(dev, EM28XX_SUSPEND); mutex_unlock(&dev->lock); return result; out_free: kfree(dvb); dev->dvb = NULL; goto ret; }