diff options
Diffstat (limited to 'linux/drivers/media/video/em28xx')
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-audio.c | 7 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-cards.c | 278 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-core.c | 51 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-dvb.c | 7 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-i2c.c | 95 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-input.c | 14 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-reg.h | 16 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-video.c | 83 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx.h | 16 |
9 files changed, 384 insertions, 183 deletions
diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index eb49a1364..089764d42 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -545,9 +545,10 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, + &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index fcb8131e6..384aead65 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -32,6 +32,8 @@ #include <media/msp3400.h> #include <media/saa7115.h> #include <media/tvp5150.h> +#include <media/tvaudio.h> +#include <media/i2c-addr.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> #include <media/v4l2-chip-ident.h> @@ -151,6 +153,16 @@ static struct em28xx_reg_seq compro_mute_gpio[] = { { -1, -1, -1, -1}, }; +/* Terratec AV350 */ +static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { + {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + { -1, -1, -1, -1}, +}; /* * Board definitions */ @@ -652,6 +664,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, + .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -676,6 +689,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, + .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -1140,6 +1154,31 @@ struct em28xx_board em28xx_boards[] = { .gpio = default_analog, } }, }, + [EM2880_BOARD_EMPIRE_DUAL_TV] = { + .name = "Empire dual TV", + .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, + .has_dvb = 1, + .dvb_gpio = default_digital, + .mts_firmware = 1, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, + } }, + }, [EM2881_BOARD_DNT_DA2_HYBRID] = { .name = "DNT DA2 Hybrid", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1303,6 +1342,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { .name = "Compro VideoMate ForYou/Stereo", .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tvaudio_addr = 0xb0, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, .adecoder = EM28XX_TVAUDIO, @@ -1382,6 +1422,42 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, + [EM2860_BOARD_TERRATEC_GRABBY] = { + .name = "Terratec Grabby", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO2, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_VIDEO2, + } }, + }, + [EM2860_BOARD_TERRATEC_AV350] = { + .name = "Terratec AV350", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_TVP5150, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .mute_gpio = terratec_av350_mute_gpio, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AUDIO_SRC_LINE, + .gpio = terratec_av350_unmute_gpio, + + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AUDIO_SRC_LINE, + .gpio = terratec_av350_unmute_gpio, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1449,6 +1525,10 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, + { USB_DEVICE(0x0ccd, 0x0084), + .driver_info = EM2860_BOARD_TERRATEC_AV350 }, + { USB_DEVICE(0x0ccd, 0x0096), + .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, { USB_DEVICE(0x185b, 0x2870), .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE }, { USB_DEVICE(0x185b, 0x2041), @@ -1501,6 +1581,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, + {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, }; /* I2C devicelist hash table for devices with generic USB IDs */ @@ -1511,6 +1592,24 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, }; +/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ +static unsigned short saa711x_addrs[] = { + 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ + I2C_CLIENT_END }; + +static unsigned short tvp5150_addrs[] = { + 0xb8 >> 1, + 0xba >> 1, + I2C_CLIENT_END +}; + +static unsigned short msp3400_addrs[] = { + 0x80 >> 1, + 0x88 >> 1, + I2C_CLIENT_END +}; + int em28xx_tuner_callback(void *ptr, int component, int command, int arg) { int rc = 0; @@ -1710,6 +1809,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->mts = em28xx_boards[dev->model].mts_firmware; switch (dev->model) { + case EM2880_BOARD_EMPIRE_DUAL_TV: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: ctl->demod = XC3028_FE_ZARLINK456; break; @@ -1739,31 +1839,55 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) } } -static void em28xx_config_tuner(struct em28xx *dev) +static void em28xx_tuner_setup(struct em28xx *dev) { - struct v4l2_priv_tun_config xc2028_cfg; struct tuner_setup tun_setup; struct v4l2_frequency f; if (dev->tuner_type == TUNER_ABSENT) return; + memset(&tun_setup, 0, sizeof(tun_setup)); + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; tun_setup.tuner_callback = em28xx_tuner_callback; - em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + if (dev->board.radio.type) { + tun_setup.type = dev->board.radio.type; + tun_setup.addr = dev->board.radio_addr; + + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); + } + + if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) { + tun_setup.type = dev->tuner_type; + tun_setup.addr = dev->tuner_addr; + + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); + } + + if (dev->tda9887_conf) { + struct v4l2_priv_tun_config tda9887_cfg; + + tda9887_cfg.tuner = TUNER_TDA9887; + tda9887_cfg.priv = &dev->tda9887_conf; + + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg); + } if (dev->tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; struct xc2028_ctrl ctl; + memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); + memset(&ctl, 0, sizeof(ctl)); + em28xx_setup_xc3028(dev, &ctl); xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; - em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg); } /* configure tuner */ @@ -1771,7 +1895,7 @@ static void em28xx_config_tuner(struct em28xx *dev) f.type = V4L2_TUNER_ANALOG_TV; f.frequency = 9076; /* just a magic number */ dev->ctl_freq = f.frequency; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); } static int em28xx_hint_board(struct em28xx *dev) @@ -1857,12 +1981,31 @@ static int em28xx_hint_board(struct em28xx *dev) } /* ----------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) +#else +void em28xx_register_i2c_ir(struct em28xx *dev) +#endif { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) if (disable_ir) { ir->get_key = NULL; return ; } +#else + struct i2c_board_info info; + struct IR_i2c_init_data init_data; + const unsigned short addr_list[] = { + 0x30, 0x47, I2C_CLIENT_END + }; + + if (disable_ir) + return; + + memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); +#endif /* detect & configure */ switch (dev->model) { @@ -1872,22 +2015,40 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) break; case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->ir_codes = ir_codes_em_terratec; ir->get_key = em28xx_get_key_terratec; - snprintf(ir->c.name, sizeof(ir->c.name), + snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Terratec)"); +#else + init_data.ir_codes = ir_codes_em_terratec; + init_data.get_key = em28xx_get_key_terratec; + init_data.name = "i2c IR (EM28XX Terratec)"; +#endif break; case (EM2820_BOARD_PINNACLE_USB_2): +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->ir_codes = ir_codes_pinnacle_grey; ir->get_key = em28xx_get_key_pinnacle_usb_grey; - snprintf(ir->c.name, sizeof(ir->c.name), + snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Pinnacle PCTV)"); +#else + init_data.ir_codes = ir_codes_pinnacle_grey; + init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; +#endif break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->ir_codes = ir_codes_hauppauge_new; ir->get_key = em28xx_get_key_em_haup; - snprintf(ir->c.name, sizeof(ir->c.name), + snprintf(ir->name, sizeof(ir->name), "i2c IR (EM2840 Hauppauge)"); +#else + init_data.ir_codes = ir_codes_hauppauge_new; + init_data.get_key = em28xx_get_key_em_haup; + init_data.name = "i2c IR (EM2840 Hauppauge)"; +#endif break; case (EM2820_BOARD_MSI_VOX_USB_2): break; @@ -1898,6 +2059,12 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) case (EM2800_BOARD_GRABBEEX_USB2800): break; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) + + if (init_data.name) + info.platform_data = &init_data; + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); +#endif } void em28xx_card_setup(struct em28xx *dev) @@ -1978,22 +2145,52 @@ void em28xx_card_setup(struct em28xx *dev) if (tuner >= 0) dev->tuner_type = tuner; -#ifdef CONFIG_MODULES /* request some modules */ if (dev->board.has_msp34xx) - request_module("msp3400"); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "msp3400", "msp3400", msp3400_addrs); + if (dev->board.decoder == EM28XX_SAA711X) - request_module("saa7115"); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "saa7115", "saa7115_auto", saa711x_addrs); + if (dev->board.decoder == EM28XX_TVP5150) - request_module("tvp5150"); - if (dev->board.tuner_type != TUNER_ABSENT) - request_module("tuner"); - if (dev->board.adecoder == EM28XX_TVAUDIO) - request_module("tvaudio"); -#endif + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tvp5150", "tvp5150", tvp5150_addrs); - em28xx_config_tuner(dev); + if (dev->board.adecoder == EM28XX_TVAUDIO) + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tvaudio", "tvaudio", dev->board.tvaudio_addr); + + if (dev->board.tuner_type != TUNER_ABSENT) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + if (dev->board.radio.type) + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tuner", "tuner", dev->board.radio_addr); + + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == 0) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + struct v4l2_subdev *sd; + + sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(type)); + + if (sd) + dev->tuner_addr = v4l2_i2c_subdev_addr(sd); + } else { + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); + } + } + em28xx_tuner_setup(dev); em28xx_ir_init(dev); } @@ -2053,6 +2250,9 @@ void em28xx_release_resources(struct em28xx *dev) em28xx_remove_from_devlist(dev); em28xx_i2c_unregister(dev); + + v4l2_device_unregister(&dev->v4l2_dev); + usb_put_dev(dev->udev); /* Mark device as unused */ @@ -2064,6 +2264,7 @@ void em28xx_release_resources(struct em28xx *dev) * allocates and inits the device structs, registers i2c bus and v4l device */ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, + struct usb_interface *interface, int minor) { struct em28xx *dev = *devhandle; @@ -2097,9 +2298,16 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } } + retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); + if (retval < 0) { + em28xx_errdev("Call to v4l2_device_register() failed!\n"); + return retval; + } + /* register i2c bus */ errCode = em28xx_i2c_register(dev); if (errCode < 0) { + v4l2_device_unregister(&dev->v4l2_dev); em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", __func__, errCode); return errCode; @@ -2111,6 +2319,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, /* Configure audio */ errCode = em28xx_audio_setup(dev); if (errCode < 0) { + v4l2_device_unregister(&dev->v4l2_dev); em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", __func__, errCode); } @@ -2158,7 +2367,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_init_extension(dev); /* Save some power by putting tuner to sleep */ - em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); return 0; @@ -2177,7 +2386,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_interface *uif; struct em28xx *dev = NULL; - int retval = -ENODEV; + int retval; int i, nr, ifnum, isoc_pipe; char *speed; char descr[255] = ""; @@ -2199,7 +2408,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, interface->altsetting[0].desc.bInterfaceClass); em28xx_devused &= ~(1<<nr); - return -ENODEV; + retval = -ENODEV; + goto err; } endpoint = &interface->cur_altsetting->endpoint[0].desc; @@ -2232,7 +2442,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, "interface not used by the driver\n"); em28xx_devused &= ~(1<<nr); - return -ENODEV; + retval = -ENODEV; + goto err; } } @@ -2275,7 +2486,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", EM28XX_MAXBOARDS); em28xx_devused &= ~(1<<nr); - return -ENOMEM; + retval = -ENOMEM; + goto err; } /* allocate memory for our device state and initialize it */ @@ -2283,7 +2495,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, if (dev == NULL) { em28xx_err(DRIVER_NAME ": out of memory!\n"); em28xx_devused &= ~(1<<nr); - return -ENOMEM; + retval = -ENOMEM; + goto err; } snprintf(dev->name, 29, "em28xx #%d", nr); @@ -2310,7 +2523,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, em28xx_errdev("out of memory!\n"); em28xx_devused &= ~(1<<nr); kfree(dev); - return -ENOMEM; + retval = -ENOMEM; + goto err; } for (i = 0; i < dev->num_alt ; i++) { @@ -2325,12 +2539,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* allocate device struct */ mutex_init(&dev->lock); mutex_lock(&dev->lock); - retval = em28xx_init_dev(&dev, udev, nr); + retval = em28xx_init_dev(&dev, udev, interface, nr); if (retval) { em28xx_devused &= ~(1<<dev->devno); kfree(dev); - - return retval; + goto err; } /* save our data pointer in this interface device */ @@ -2344,6 +2557,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, mutex_unlock(&dev->lock); return 0; + +err: + return retval; } /* @@ -2369,6 +2585,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) wake_up_interruptible_all(&dev->open); + v4l2_device_disconnect(&dev->v4l2_dev); + if (dev->users) { em28xx_warn ("device /dev/video%d is open! Deregistration and memory " diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 0d4c9fcc2..02e51af9d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -947,7 +947,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); if (!dev->isoc_ctl.transfer_buffer) { - em28xx_errdev("cannot allocate memory for usbtransfer\n"); + em28xx_errdev("cannot allocate memory for usb transfer\n"); kfree(dev->isoc_ctl.urb); return -ENOMEM; } @@ -991,7 +991,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, em28xx_irq_callback, dma_q, 1); urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; k = 0; for (j = 0; j < max_packets; j++) { @@ -1021,20 +1021,51 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, } EXPORT_SYMBOL_GPL(em28xx_init_isoc); +/* Determine the packet size for the DVB stream for the given device + (underlying value programmed into the eeprom) */ +int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) +{ + unsigned int chip_cfg2; + unsigned int packet_size = 564; + + if (dev->chip_id == CHIP_ID_EM2874) { + /* FIXME - for now assume 564 like it was before, but the + em2874 code should be added to return the proper value... */ + packet_size = 564; + } else { + /* TS max packet size stored in bits 1-0 of R01 */ + chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); + switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) { + case EM28XX_CHIPCFG2_TS_PACKETSIZE_188: + packet_size = 188; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_376: + packet_size = 376; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_564: + packet_size = 564; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_752: + packet_size = 752; + break; + } + } + + em28xx_coredbg("dvb max packet size=%d\n", packet_size); + return packet_size; +} +EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); + /* * em28xx_wake_i2c() * configure i2c attached devices */ void em28xx_wake_i2c(struct em28xx *dev) { - struct v4l2_routing route; - int zero = 0; - - route.input = INPUT(dev->ctl_input)->vmux; - route.output = 0; - em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); - em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, + INPUT(dev->ctl_input)->vmux, 0, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); } /* diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index edafe9bde..de919504f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -47,7 +47,6 @@ if (debug >= level) \ } while (0) #define EM28XX_DVB_NUM_BUFS 5 -#define EM28XX_DVB_MAX_PACKETSIZE 564 #define EM28XX_DVB_MAX_PACKETS 64 struct em28xx_dvb { @@ -143,14 +142,17 @@ static int start_streaming(struct em28xx_dvb *dvb) { int rc; struct em28xx *dev = dvb->adapter.priv; + int max_dvb_packet_size; usb_set_interface(dev->udev, 0, 1); rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); if (rc < 0) return rc; + max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); + return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, - EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, + EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, dvb_isoc_copy); } @@ -432,6 +434,7 @@ static int dvb_init(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_KWORLD_DVB_310U: + case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index e9abb2769..1cdd88361 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -451,82 +451,6 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL; } -/* - * attach_inform() - * gets called when a device attaches to the i2c bus - * does some basic configuration - */ -static int attach_inform(struct i2c_client *client) -{ - struct em28xx *dev = client->adapter->algo_data; - - switch (client->addr << 1) { - case 0x86: - case 0x84: - case 0x96: - case 0x94: - { - struct v4l2_priv_tun_config tda9887_cfg; - - struct tuner_setup tun_setup; - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = TUNER_TDA9887; - tun_setup.addr = client->addr; - - em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, - &tun_setup); - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &dev->tda9887_conf; - em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, - &tda9887_cfg); - break; - } - case 0x42: - dprintk1(1, "attach_inform: saa7114 detected.\n"); - break; - case 0x4a: - dprintk1(1, "attach_inform: saa7113 detected.\n"); - break; - case 0xa0: - dprintk1(1, "attach_inform: eeprom detected.\n"); - break; - case 0x60: - case 0x8e: - { - struct IR_i2c *ir = i2c_get_clientdata(client); - dprintk1(1, "attach_inform: IR detected (%s).\n", - ir->phys); - em28xx_set_ir(dev, ir); - break; - } - case 0x80: - case 0x88: - dprintk1(1, "attach_inform: msp34xx detected.\n"); - break; - case 0xb8: - case 0xba: - dprintk1(1, "attach_inform: tvp5150 detected.\n"); - break; - - case 0xb0: - dprintk1(1, "attach_inform: tda9874 detected\n"); - break; - - default: - if (!dev->tuner_addr) - dev->tuner_addr = client->addr; - - dprintk1(1, "attach inform: detected I2C address %x\n", - client->addr << 1); - dprintk1(1, "driver id %d\n", client->driver->id); - - } - - return 0; -} - static struct i2c_algorithm em28xx_algo = { .master_xfer = em28xx_i2c_xfer, .functionality = functionality, @@ -537,11 +461,12 @@ static struct i2c_algorithm em28xx_algo = { static struct i2c_adapter em28xx_adap_template = { .owner = THIS_MODULE, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .class = I2C_CLASS_TV_ANALOG, +#endif .name = "em28xx", .id = I2C_HW_B_EM28XX, .algo = &em28xx_algo, - .client_register = attach_inform, }; static struct i2c_client em28xx_client_template = { @@ -598,16 +523,6 @@ void em28xx_do_i2c_scan(struct em28xx *dev) } /* - * em28xx_i2c_call_clients() - * send commands to all attached i2c devices - */ -void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) -{ - BUG_ON(NULL == dev->i2c_adap.algo_data); - i2c_clients_command(&dev->i2c_adap, cmd, arg); -} - -/* * em28xx_i2c_register() * register i2c bus */ @@ -621,6 +536,7 @@ int em28xx_i2c_register(struct em28xx *dev) dev->i2c_adap.dev.parent = &dev->udev->dev; strcpy(dev->i2c_adap.name, dev->name); dev->i2c_adap.algo_data = dev; + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); retval = i2c_add_adapter(&dev->i2c_adap); if (retval < 0) { @@ -643,6 +559,11 @@ int em28xx_i2c_register(struct em28xx *dev) if (i2c_scan) em28xx_do_i2c_scan(dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) + /* Instantiate the IR receiver device, if present */ + em28xx_register_i2c_ir(dev); + +#endif return 0; } diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index 5382a6064..df58b4c5b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -41,7 +41,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); #define i2cdprintk(fmt, arg...) \ if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ } #define dprintk(fmt, arg...) \ @@ -86,7 +86,11 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) if (1 != i2c_master_recv(&ir->c, &b, 1)) { +#else + if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif i2cdprintk("read error\n"); return -EIO; } @@ -115,7 +119,11 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char code; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) if (2 != i2c_master_recv(&ir->c, buf, 2)) +#else + if (2 != i2c_master_recv(ir->c, buf, 2)) +#endif return -EIO; /* Does eliminate repeated parity code */ @@ -153,7 +161,11 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) if (3 != i2c_master_recv(&ir->c, buf, 3)) { +#else + if (3 != i2c_master_recv(ir->c, buf, 3)) { +#endif i2cdprintk("read error\n"); return -EIO; } diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 24e39c568..a2676d63c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -27,6 +27,22 @@ #define EM28XX_CHIPCFG_AC97 0x10 #define EM28XX_CHIPCFG_AUDIOMASK 0x30 +#define EM28XX_R01_CHIPCFG2 0x01 + +/* em28xx Chip Configuration 2 0x01 */ +#define EM28XX_CHIPCFG2_TS_PRESENT 0x10 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK 0x0c /* bits 3-2 */ +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF 0x00 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF 0x04 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF 0x08 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF 0x0c +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK 0x03 /* bits 0-1 */ +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188 0x00 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376 0x01 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564 0x02 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752 0x03 + + /* GPIO/GPO registers */ #define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ #define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index ef02999ec..1614e5fc4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -49,7 +49,7 @@ "Sascha Sommer <saschasommer@freenet.de>" #define DRIVER_DESC "Empia em28xx based USB video device driver" -#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 1) +#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 2) #define em28xx_videodbg(fmt, arg...) do {\ if (video_debug) \ @@ -404,7 +404,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) f.frequency = dev->ctl_freq; f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); return 0; } @@ -519,10 +519,6 @@ static struct videobuf_queue_ops em28xx_video_qops = { static void video_mux(struct em28xx *dev, int index) { - struct v4l2_routing route; - - route.input = INPUT(index)->vmux; - route.output = 0; dev->ctl_input = index; dev->ctl_ainput = INPUT(index)->amux; dev->ctl_aoutput = INPUT(index)->aout; @@ -530,25 +526,22 @@ static void video_mux(struct em28xx *dev, int index) if (!dev->ctl_aoutput) dev->ctl_aoutput = EM28XX_AOUT_MASTER; - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, + INPUT(index)->vmux, 0, 0); if (dev->board.has_msp34xx) { if (dev->i2s_speed) { - em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, - &dev->i2s_speed); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, + s_i2s_clock_freq, dev->i2s_speed); } - route.input = dev->ctl_ainput; - route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); /* Note: this is msp3400 specific */ - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, - &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, + dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); } if (dev->board.adecoder != EM28XX_NOADECODER) { - route.input = dev->ctl_ainput; - route.output = dev->ctl_aoutput; - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, - &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, + dev->ctl_ainput, dev->ctl_aoutput, 0); } em28xx_audio_analog_set(dev); @@ -833,7 +826,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_resolution_set(dev); - em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); mutex_unlock(&dev->lock); return 0; @@ -1005,8 +998,9 @@ static int vidioc_queryctrl(struct file *file, void *priv, } } } + mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); mutex_unlock(&dev->lock); if (qc->type) @@ -1030,11 +1024,11 @@ static int vidioc_g_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); if (dev->board.has_msp34xx) - em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); else { rc = em28xx_get_ctrl(dev, ctrl); if (rc < 0) { - em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); rc = 0; } } @@ -1058,7 +1052,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); if (dev->board.has_msp34xx) - em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); else { rc = 1; for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { @@ -1077,7 +1071,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, /* Control not found - try to send it to the attached devices */ if (rc == 1) { - em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); rc = 0; } @@ -1102,10 +1096,9 @@ static int vidioc_g_tuner(struct file *file, void *priv, strcpy(t->name, "Tuner"); mutex_lock(&dev->lock); - - em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); - + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); mutex_unlock(&dev->lock); + return 0; } @@ -1124,10 +1117,9 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&dev->lock); - - em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); - + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); mutex_unlock(&dev->lock); + return 0; } @@ -1167,7 +1159,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); mutex_unlock(&dev->lock); @@ -1196,7 +1188,7 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); return 0; } @@ -1221,7 +1213,7 @@ static int vidioc_g_register(struct file *file, void *priv, reg->size = 1; return 0; case V4L2_CHIP_MATCH_I2C_DRIVER: - em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* Not supported yet */ @@ -1273,7 +1265,7 @@ static int vidioc_s_register(struct file *file, void *priv, return rc; case V4L2_CHIP_MATCH_I2C_DRIVER: - em28xx_i2c_call_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* Not supported yet */ @@ -1419,13 +1411,13 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, mutex_lock(&dev->lock); f->fmt.sliced.service_set = 0; - - em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; mutex_unlock(&dev->lock); + return rc; } @@ -1441,7 +1433,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) @@ -1579,7 +1571,7 @@ static int radio_g_tuner(struct file *file, void *priv, t->type = V4L2_TUNER_RADIO; mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -1614,7 +1606,7 @@ static int radio_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -1717,7 +1709,7 @@ static int em28xx_v4l2_open(struct file *filp) #if 0 em28xx_start_radio(dev); #endif - em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); } dev->users++; @@ -1800,7 +1792,7 @@ static int em28xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); /* do this before setting alternate! */ em28xx_uninit_isoc(dev); @@ -2026,11 +2018,12 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, vfd = video_device_alloc(); if (NULL == vfd) return NULL; - *vfd = *template; - vfd->minor = -1; - vfd->parent = &dev->udev->dev; - vfd->release = video_device_release; - vfd->debug = video_debug; + + *vfd = *template; + vfd->minor = -1; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->release = video_device_release; + vfd->debug = video_debug; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c9be33aba..1c61b98e6 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -28,6 +28,7 @@ #include "compat.h" #include <linux/videodev2.h> #include <media/videobuf-vmalloc.h> +#include <media/v4l2-device.h> #include <linux/i2c.h> #include <linux/mutex.h> @@ -102,6 +103,9 @@ #define EM2860_BOARD_KAIOMY_TVNPC_U2 63 #define EM2860_BOARD_EASYCAP 64 #define EM2820_BOARD_IODATA_GVMVP_SZ 65 +#define EM2880_BOARD_EMPIRE_DUAL_TV 66 +#define EM2860_BOARD_TERRATEC_GRABBY 67 +#define EM2860_BOARD_TERRATEC_AV350 68 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -386,6 +390,8 @@ struct em28xx_board { unsigned int valid:1; unsigned char xclk, i2c_speed; + unsigned char radio_addr; + unsigned short tvaudio_addr; enum em28xx_decoder decoder; enum em28xx_adecoder adecoder; @@ -469,6 +475,7 @@ struct em28xx { int devno; /* marks the number of this device */ enum em28xx_chip_id chip_id; + struct v4l2_device v4l2_dev; struct em28xx_board board; unsigned int stream_on:1; /* Locks streams */ @@ -586,11 +593,9 @@ struct em28xx_ops { }; /* Provided by em28xx-i2c.c */ - -void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg); void em28xx_do_i2c_scan(struct em28xx *dev); -int em28xx_i2c_register(struct em28xx *dev); -int em28xx_i2c_unregister(struct em28xx *dev); +int em28xx_i2c_register(struct em28xx *dev); +int em28xx_i2c_unregister(struct em28xx *dev); /* Provided by em28xx-core.c */ @@ -622,6 +627,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, int num_bufs, int max_pkt_size, int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); void em28xx_uninit_isoc(struct em28xx *dev); +int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); void em28xx_wake_i2c(struct em28xx *dev); @@ -646,7 +652,7 @@ extern void em28xx_card_setup(struct em28xx *dev); extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; -void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); +void em28xx_register_i2c_ir(struct em28xx *dev); int em28xx_tuner_callback(void *ptr, int component, int command, int arg); void em28xx_release_resources(struct em28xx *dev); |