diff options
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 2 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 280 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 61 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-dvb.c | 190 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-input.c | 7 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-reg.h | 5 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 14 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 8 |
8 files changed, 352 insertions, 215 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index cff0768afbf5..e2a7b77c39c7 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -193,7 +193,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) urb->dev = dev->udev; urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, 0x83); + urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 9b747c266afa..4561cd89938d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -336,6 +336,23 @@ static struct em28xx_reg_seq pctv_460e[] = { { -1, -1, -1, -1}, }; +#if 0 +static struct em28xx_reg_seq hauppauge_930c_gpio[] = { + {EM2874_R80_GPIO, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ + {EM2874_R80_GPIO, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO, 0x4f, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq hauppauge_930c_digital[] = { + {EM2874_R80_GPIO, 0xf6, 0xff, 10}, + {EM2874_R80_GPIO, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO, 0xa6, 0xff, 10}, + { -1, -1, -1, -1}, +}; +#endif + /* * Board definitions */ @@ -839,6 +856,10 @@ struct em28xx_board em28xx_boards[] = { [EM2870_BOARD_KWORLD_355U] = { .name = "Kworld 355 U DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, + .tuner_type = TUNER_ABSENT, + .tuner_gpio = default_tuner_gpio, + .has_dvb = 1, + .dvb_gpio = default_digital, }, [EM2870_BOARD_PINNACLE_PCTV_DVB] = { .name = "Pinnacle PCTV DVB-T", @@ -887,6 +908,37 @@ struct em28xx_board em28xx_boards[] = { .tuner_addr = 0x41, .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ .tuner_gpio = terratec_h5_gpio, +#else + .tuner_type = TUNER_ABSENT, +#endif + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, + [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { + .name = "Hauppauge WinTV HVR 930C", + .has_dvb = 1, +#if 0 /* FIXME: Add analog support */ + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x41, + .dvb_gpio = hauppauge_930c_digital, + .tuner_gpio = hauppauge_930c_gpio, +#else + .tuner_type = TUNER_ABSENT, +#endif + .ir_codes = RC_MAP_HAUPPAUGE, + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, + [EM2884_BOARD_CINERGY_HTC_STICK] = { + .name = "Terratec Cinergy HTC Stick", + .has_dvb = 1, +#if 0 + .tuner_type = TUNER_PHILIPS_TDA8290, + .tuner_addr = 0x41, + .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ + .tuner_gpio = terratec_h5_gpio, #endif .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_CLK_WAIT_ENABLE | @@ -1127,7 +1179,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy 200 USB", .is_em2800 = 1, .has_ir_i2c = 1, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tuner_type = TUNER_LG_TALN, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, .input = { { @@ -1218,7 +1270,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PINNACLE_DVC_90] = { .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker " - "/ Kworld DVD Maker 2", + "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { @@ -1840,6 +1892,22 @@ struct em28xx_board em28xx_boards[] = { .has_dvb = 1, .ir_codes = RC_MAP_PINNACLE_PCTV_HD, }, + /* eb1a:5006 Honestech VIDBOX NW03 + * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */ + [EM2860_BOARD_HT_VIDBOX_NW03] = { + .name = "Honestech Vidbox NW03", + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs confirming */ + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1899,6 +1967,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, { USB_DEVICE(0xeb1a, 0xe357), .driver_info = EM2870_BOARD_KWORLD_355U }, + { USB_DEVICE(0xeb1a, 0xe359), + .driver_info = EM2870_BOARD_KWORLD_355U }, { USB_DEVICE(0x1b80, 0xe302), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ { USB_DEVICE(0x1b80, 0xe304), @@ -1914,17 +1984,23 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0043), + .driver_info = EM2870_BOARD_TERRATEC_XS }, + { USB_DEVICE(0x0ccd, 0x008e), /* Cinergy HTC USB XS Rev. 1 */ + .driver_info = EM2884_BOARD_TERRATEC_H5 }, + { USB_DEVICE(0x0ccd, 0x00ac), /* Cinergy HTC USB XS Rev. 2 */ + .driver_info = EM2884_BOARD_TERRATEC_H5 }, + { USB_DEVICE(0x0ccd, 0x10a2), /* H5 Rev. 1 */ .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10a2), /* Rev. 1 */ + { USB_DEVICE(0x0ccd, 0x10ad), /* H5 Rev. 2 */ .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10ad), /* Rev. 2 */ - .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(0x0ccd, 0x10AF), .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, + { USB_DEVICE(0x0ccd, 0x00b2), + .driver_info = EM2884_BOARD_CINERGY_HTC_STICK }, { USB_DEVICE(0x0fd9, 0x0033), .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, { USB_DEVICE(0x185b, 0x2870), @@ -1963,6 +2039,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, { USB_DEVICE(0x0413, 0x6023), .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, + { USB_DEVICE(0x093b, 0xa003), + .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x093b, 0xa005), .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, { USB_DEVICE(0x04bb, 0x0515), @@ -1975,6 +2053,12 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM28174_BOARD_PCTV_290E }, { USB_DEVICE(0x2013, 0x024c), .driver_info = EM28174_BOARD_PCTV_460E }, + { USB_DEVICE(0x2040, 0x1605), + .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C }, + { USB_DEVICE(0xeb1a, 0x5006), + .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, + { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ + .driver_info = EM2860_BOARD_EASYCAP }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); @@ -2028,10 +2112,10 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) int rc = 0; struct em28xx *dev = ptr; - if (dev->tuner_type != TUNER_XC2028) + if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000) return 0; - if (command != XC2028_TUNER_RESET) + if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET) return 0; rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); @@ -2203,7 +2287,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* Set the initial XCLK and I2C clock values based on the board definition */ em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); + if (!dev->board.is_em2800) + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); msleep(50); /* request some modules */ @@ -2832,11 +2917,10 @@ void em28xx_release_resources(struct em28xx *dev) * em28xx_init_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, +static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, struct usb_interface *interface, int minor) { - struct em28xx *dev = *devhandle; int retval; dev->udev = udev; @@ -2931,7 +3015,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (!dev->board.is_em2800) { /* Resets I2C speed */ - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); + retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); if (retval < 0) { em28xx_errdev("%s: em28xx_write_reg failed!" " retval [%d]\n", @@ -3031,12 +3115,11 @@ unregister_dev: static int em28xx_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - const struct usb_endpoint_descriptor *endpoint; struct usb_device *udev; struct em28xx *dev = NULL; int retval; - bool is_audio_only = false, has_audio = false; - int i, nr, isoc_pipe; + bool has_audio = false, has_video = false, has_dvb = false; + int i, nr; const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; char *speed; char descr[255] = ""; @@ -3068,54 +3151,65 @@ static int em28xx_usb_probe(struct usb_interface *interface, goto err; } + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + em28xx_err(DRIVER_NAME ": out of memory!\n"); + retval = -ENOMEM; + goto err; + } + + /* compute alternate max packet sizes */ + dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * + interface->num_altsetting, GFP_KERNEL); + if (dev->alt_max_pkt_size == NULL) { + em28xx_errdev("out of memory!\n"); + kfree(dev); + retval = -ENOMEM; + goto err; + } + /* Get endpoints */ for (i = 0; i < interface->num_altsetting; i++) { int ep; for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { - struct usb_host_endpoint *e; - e = &interface->altsetting[i].endpoint[ep]; - - if (e->desc.bEndpointAddress == 0x83) - has_audio = true; + const struct usb_endpoint_descriptor *e; + int sizedescr, size; + + e = &interface->altsetting[i].endpoint[ep].desc; + + sizedescr = le16_to_cpu(e->wMaxPacketSize); + size = sizedescr & 0x7ff; + + if (udev->speed == USB_SPEED_HIGH) + size = size * hb_mult(sizedescr); + + if (usb_endpoint_xfer_isoc(e) && + usb_endpoint_dir_in(e)) { + switch (e->bEndpointAddress) { + case EM28XX_EP_AUDIO: + has_audio = true; + break; + case EM28XX_EP_ANALOG: + has_video = true; + dev->alt_max_pkt_size[i] = size; + break; + case EM28XX_EP_DIGITAL: + has_dvb = true; + if (size > dev->dvb_max_pkt_size) { + dev->dvb_max_pkt_size = size; + dev->dvb_alt = i; + } + break; + } + } } } - endpoint = &interface->cur_altsetting->endpoint[0].desc; - - /* check if the device has the iso in endpoint at the correct place */ - if (usb_endpoint_xfer_isoc(endpoint) - && - (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { - /* It's a newer em2874/em2875 device */ - isoc_pipe = 0; - } else { - int check_interface = 1; - isoc_pipe = 1; - endpoint = &interface->cur_altsetting->endpoint[1].desc; - if (!usb_endpoint_xfer_isoc(endpoint)) - check_interface = 0; - - if (usb_endpoint_dir_out(endpoint)) - check_interface = 0; - - if (!check_interface) { - if (has_audio) { - is_audio_only = true; - } else { - em28xx_err(DRIVER_NAME " video device (%04x:%04x): " - "interface %i, class %i found.\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting[0].desc.bInterfaceClass); - em28xx_err(DRIVER_NAME " This is an anciliary " - "interface not used by the driver\n"); - - retval = -ENODEV; - goto err; - } - } + if (!(has_audio || has_video || has_dvb)) { + retval = -ENODEV; + goto err_free; } switch (udev->speed) { @@ -3141,6 +3235,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, strlcat(descr, " ", sizeof(descr)); strlcat(descr, udev->product, sizeof(descr)); } + if (*descr) strlcat(descr, " ", sizeof(descr)); @@ -3157,6 +3252,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, printk(KERN_INFO DRIVER_NAME ": Audio Vendor Class interface %i found\n", ifnum); + if (has_video) + printk(KERN_INFO DRIVER_NAME + ": Video interface %i found\n", + ifnum); + if (has_dvb) + printk(KERN_INFO DRIVER_NAME + ": DVB interface %i found\n", + ifnum); /* * Make sure we have 480 Mbps of bandwidth, otherwise things like @@ -3168,22 +3271,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, printk(DRIVER_NAME ": Device must be connected to a high-speed" " USB 2.0 port.\n"); retval = -ENODEV; - goto err; - } - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - em28xx_err(DRIVER_NAME ": out of memory!\n"); - retval = -ENOMEM; - goto err; + goto err_free; } snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); dev->devno = nr; dev->model = id->driver_info; dev->alt = -1; - dev->is_audio_only = is_audio_only; + dev->is_audio_only = has_audio && !(has_video || has_dvb); dev->has_alsa_audio = has_audio; dev->audio_ifnum = ifnum; @@ -3196,26 +3291,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, } } - /* compute alternate max packet sizes */ dev->num_alt = interface->num_altsetting; - dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); - - if (dev->alt_max_pkt_size == NULL) { - em28xx_errdev("out of memory!\n"); - kfree(dev); - retval = -ENOMEM; - goto err; - } - - for (i = 0; i < dev->num_alt ; i++) { - u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); - unsigned int size = tmp & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(tmp); - - dev->alt_max_pkt_size[i] = size; - } if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) dev->model = card[nr]; @@ -3226,12 +3302,9 @@ 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, interface, nr); + retval = em28xx_init_dev(dev, udev, interface, nr); if (retval) { - mutex_unlock(&dev->lock); - kfree(dev->alt_max_pkt_size); - kfree(dev); - goto err; + goto unlock_and_free; } request_modules(dev); @@ -3250,6 +3323,13 @@ static int em28xx_usb_probe(struct usb_interface *interface, return 0; +unlock_and_free: + mutex_unlock(&dev->lock); + +err_free: + kfree(dev->alt_max_pkt_size); + kfree(dev); + err: clear_bit(nr, &em28xx_devused); @@ -3325,26 +3405,4 @@ static struct usb_driver em28xx_usb_driver = { .id_table = em28xx_id_table, }; -static int __init em28xx_module_init(void) -{ - int result; - - /* register this driver with the USB subsystem */ - result = usb_register(&em28xx_usb_driver); - if (result) - em28xx_err(DRIVER_NAME - " usb_register failed. Error number %d.\n", result); - - printk(KERN_INFO DRIVER_NAME " driver loaded\n"); - - return result; -} - -static void __exit em28xx_module_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&em28xx_usb_driver); -} - -module_init(em28xx_module_init); -module_exit(em28xx_module_exit); +module_usb_driver(em28xx_usb_driver); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 804a4ab47ac6..0aacc96f9a23 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -568,7 +568,7 @@ int em28xx_audio_setup(struct em28xx *dev) em28xx_warn("AC97 features = 0x%04x\n", feat); /* Try to identify what audio processor we have */ - if ((vid == 0xffffffff) && (feat == 0x6a90)) + if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90)) dev->audio_mode.ac97 = EM28XX_AC97_EM202; else if ((vid >> 8) == 0x838476) dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL; @@ -1070,7 +1070,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, should also be using 'desc.bInterval' */ pipe = usb_rcvisocpipe(dev->udev, - dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84); + dev->mode == EM28XX_ANALOG_MODE ? + EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); usb_fill_int_urb(urb, dev->udev, pipe, dev->isoc_ctl.transfer_buffer[i], sb_size, @@ -1108,62 +1109,6 @@ 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; - - switch (dev->chip_id) { - case CHIP_ID_EM2710: - case CHIP_ID_EM2750: - case CHIP_ID_EM2800: - case CHIP_ID_EM2820: - case CHIP_ID_EM2840: - case CHIP_ID_EM2860: - /* No DVB support */ - return -EINVAL; - case CHIP_ID_EM2870: - case CHIP_ID_EM2883: - /* 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; - } - break; - case CHIP_ID_EM2874: - /* - * FIXME: for now assumes 564 like it was before, but the - * em2874 code should be added to return the proper value - */ - packet_size = 564; - break; - case CHIP_ID_EM2884: - case CHIP_ID_EM28174: - default: - /* - * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T - * but not enough for 44 Mbit DVB-C. - */ - packet_size = 752; - } - - return packet_size; -} -EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); - /* * em28xx_wake_i2c() * configure i2c attached devices diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cef7a2d409cb..9449423098e0 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -44,6 +44,7 @@ #include "drxk.h" #include "tda10071.h" #include "a8293.h" +#include "qt1010.h" MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); @@ -163,12 +164,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) struct em28xx *dev = dvb->adapter.priv; int max_dvb_packet_size; - usb_set_interface(dev->udev, 0, 1); + usb_set_interface(dev->udev, 0, dev->dvb_alt); rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); if (rc < 0) return rc; - max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); + max_dvb_packet_size = dev->dvb_max_pkt_size; if (max_dvb_packet_size < 0) return max_dvb_packet_size; dprintk(1, "Using %d buffers each with %d bytes\n", @@ -302,10 +303,12 @@ static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { }; static struct drxd_config em28xx_drxd = { - .index = 0, .demod_address = 0x70, .demod_revision = 0xa2, - .demoda_address = 0x00, .pll_address = 0x00, - .pll_type = DRXD_PLL_NONE, .clock = 12000, .insert_rs_byte = 1, - .pll_set = NULL, .osc_deviation = NULL, .IF = 42800000, + .demod_address = 0x70, + .demod_revision = 0xa2, + .pll_type = DRXD_PLL_NONE, + .clock = 12000, + .insert_rs_byte = 1, + .IF = 42800000, .disable_i2c_gate_ctrl = 1, }; @@ -316,6 +319,14 @@ struct drxk_config terratec_h5_drxk = { .microcode_name = "dvb-usb-terratec-h5-drxk.fw", }; +struct drxk_config hauppauge_930c_drxk = { + .adr = 0x29, + .single_master = 1, + .no_i2c_bridge = 1, + .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", + .chunk_size = 56, +}; + static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct em28xx_dvb *dvb = fe->sec_priv; @@ -334,6 +345,73 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) return status; } +static void hauppauge_hvr930c_init(struct em28xx *dev) +{ + int i; + + struct em28xx_reg_seq hauppauge_hvr930c_init[] = { + {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, + {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, + { -1, -1, -1, -1}, + }; + struct em28xx_reg_seq hauppauge_hvr930c_end[] = { + {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, + + {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, + + { -1, -1, -1, -1}, + }; + + struct { + unsigned char r[4]; + int len; + } regs[] = { + {{ 0x06, 0x02, 0x00, 0x31 }, 4}, + {{ 0x01, 0x02 }, 2}, + {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, + {{ 0x01, 0x00 }, 2}, + {{ 0x01, 0x00, 0xff, 0xaf }, 4}, + {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, + {{ 0x01, 0x00 }, 2}, + {{ 0x01, 0x00, 0x73, 0xaf }, 4}, + {{ 0x04, 0x00 }, 2}, + {{ 0x00, 0x04 }, 2}, + {{ 0x00, 0x04, 0x00, 0x0a }, 4}, + {{ 0x04, 0x14 }, 2}, + {{ 0x04, 0x14, 0x00, 0x00 }, 4}, + }; + + em28xx_gpio_set(dev, hauppauge_hvr930c_init); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); + msleep(10); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); + msleep(10); + + dev->i2c_client.addr = 0x82 >> 1; + + for (i = 0; i < ARRAY_SIZE(regs); i++) + i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); + em28xx_gpio_set(dev, hauppauge_hvr930c_end); + + msleep(100); + + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); + msleep(30); + + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); + msleep(10); + +} + static void terratec_h5_init(struct em28xx *dev) { int i; @@ -425,13 +503,6 @@ static struct tda10023_config em28xx_tda10023_config = { static struct cxd2820r_config em28xx_cxd2820r_config = { .i2c_address = (0xd8 >> 1), .ts_mode = CXD2820R_TS_SERIAL, - .if_dvbt_6 = 3300, - .if_dvbt_7 = 3500, - .if_dvbt_8 = 4000, - .if_dvbt2_6 = 3300, - .if_dvbt2_7 = 3500, - .if_dvbt2_8 = 4000, - .if_dvbc = 5000, /* enable LNA for DVB-T2 and DVB-C */ .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, @@ -456,6 +527,17 @@ static const struct a8293_config em28xx_a8293_config = { .i2c_addr = 0x08, /* (0x10 >> 1) */ }; +static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { + .demod_address = (0x1e >> 1), + .disable_i2c_gate_ctrl = 1, + .no_tuner = 1, + .parallel_ts = 1, +}; +static struct qt1010_config em28xx_qt1010_config = { + .i2c_address = 0x62 + +}; + /* ------------------------------------------------------------------ */ static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) @@ -708,6 +790,14 @@ static int em28xx_dvb_init(struct em28xx *dev) 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); + if (dvb->fe[0] != NULL) + dvb_attach(qt1010_attach, dvb->fe[0], + &dev->i2c_adap, &em28xx_qt1010_config); + break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->fe[0] = dvb_attach(s5h1409_attach, @@ -761,50 +851,72 @@ static int em28xx_dvb_init(struct em28xx *dev) &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); + &em28xx_cxd2820r_config, + &dev->i2c_adap, + NULL); if (dvb->fe[0]) { /* FE 0 attach tuner */ - if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) { + if (!dvb_attach(tda18271_attach, + dvb->fe[0], + 0x60, + &dev->i2c_adap, + &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, - &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) { - dvb_frontend_detach(dvb->fe[1]); - /* leave FE 0 still active */ - } + } + 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); + 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; - mfe_shared = 1; + /* 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, + &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: + case EM2884_BOARD_CINERGY_HTC_STICK: terratec_h5_init(dev); - dvb->dont_attach_fe1 = 1; - - dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]); + dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap); 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; - dvb->fe[1]->id = 1; /* Attach tda18271 to DVB-C frontend */ if (dvb->fe[0]->ops.i2c_gate_ctrl) @@ -816,12 +928,6 @@ static int em28xx_dvb_init(struct em28xx *dev) if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); - /* Hack - needed by drxk/tda18271c2dd */ - dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv; - memcpy(&dvb->fe[1]->ops.tuner_ops, - &dvb->fe[0]->ops.tuner_ops, - sizeof(dvb->fe[0]->ops.tuner_ops)); - break; case EM28174_BOARD_PCTV_460E: /* attach demod */ @@ -845,6 +951,8 @@ static int em28xx_dvb_init(struct em28xx *dev) } /* 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); diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 679da4804281..2630b265b0e8 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -306,7 +306,8 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) poll_result.rc_data[0], poll_result.toggle_bit); - if (ir->dev->chip_id == CHIP_ID_EM2874) + if (ir->dev->chip_id == CHIP_ID_EM2874 || + ir->dev->chip_id == CHIP_ID_EM2884) /* The em2874 clears the readcount field every time the register is read. The em2860/2880 datasheet says that it is supposed to clear the readcount, but it doesn't. So with @@ -371,13 +372,15 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) case CHIP_ID_EM2883: ir->get_key = default_polling_getkey; break; + case CHIP_ID_EM2884: case CHIP_ID_EM2874: case CHIP_ID_EM28174: ir->get_key = em2874_polling_getkey; em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); break; default: - printk("Unrecognized em28xx chip id: IR not supported\n"); + printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", + dev->chip_id); rc = -EINVAL; } diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 66f792361b97..2f6268505726 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h @@ -12,6 +12,11 @@ #define EM_GPO_2 (1 << 2) #define EM_GPO_3 (1 << 3) +/* em28xx endpoints */ +#define EM28XX_EP_ANALOG 0x82 +#define EM28XX_EP_AUDIO 0x83 +#define EM28XX_EP_DIGITAL 0x84 + /* em2800 registers */ #define EM2800_R08_AUDIOSRC 0x08 diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 9b4557a2f6d0..613300b51a9e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1070,6 +1070,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; + /* MaxPacketSize for em2800 is too small to capture at full resolution + * use half of maxw as the scaler can only scale to 50% */ + if (width == maxw && height == maxh) + width /= 2; } else { /* width must even because of the YUYV format height must be even because of interlacing */ @@ -2503,6 +2507,7 @@ int em28xx_register_analog_devices(struct em28xx *dev) { u8 val; int ret; + unsigned int maxw; printk(KERN_INFO "%s: v4l2 driver version %s\n", dev->name, EM28XX_VERSION); @@ -2515,8 +2520,15 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* Analog specific initialization */ dev->format = &format[0]; + + maxw = norm_maxw(dev); + /* MaxPacketSize for em2800 is too small to capture at full resolution + * use half of maxw as the scaler can only scale to 50% */ + if (dev->board.is_em2800) + maxw /= 2; + em28xx_set_video_format(dev, format[0].fourcc, - norm_maxw(dev), norm_maxh(dev)); + maxw, norm_maxh(dev)); video_mux(dev, dev->ctl_input); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 2a2cb7ed0014..22e252bcc41e 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -38,6 +38,7 @@ #include <media/videobuf-dvb.h> #endif #include "tuner-xc2028.h" +#include "xc5000.h" #include "em28xx-reg.h" /* Boards supported by driver */ @@ -121,6 +122,9 @@ #define EM28174_BOARD_PCTV_290E 78 #define EM2884_BOARD_TERRATEC_H5 79 #define EM28174_BOARD_PCTV_460E 80 +#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 +#define EM2884_BOARD_CINERGY_HTC_STICK 82 +#define EM2860_BOARD_HT_VIDBOX_NW03 83 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -594,6 +598,8 @@ struct em28xx { int max_pkt_size; /* max packet size of isoc transaction */ int num_alt; /* Number of alternative settings */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + int dvb_alt; /* alternate for DVB */ + unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ @@ -825,7 +831,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev) if (dev->board.is_webcam) return dev->sensor_xres; - if (dev->board.max_range_640_480 || dev->board.is_em2800) + if (dev->board.max_range_640_480) return 640; return 720; |