diff options
Diffstat (limited to 'linux/drivers/media/video/em28xx')
-rw-r--r-- | linux/drivers/media/video/em28xx/Kconfig | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-audio.c | 7 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-cards.c | 37 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-core.c | 133 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-i2c.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-video.c | 86 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx.h | 7 |
7 files changed, 170 insertions, 107 deletions
diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig index abbd38c1e..0f7a0bd86 100644 --- a/linux/drivers/media/video/em28xx/Kconfig +++ b/linux/drivers/media/video/em28xx/Kconfig @@ -13,7 +13,8 @@ config VIDEO_EM28XX module will be called em28xx config VIDEO_EM28XX_ALSA - depends on VIDEO_EM28XX + depends on VIDEO_EM28XX && SND + select SND_PCM tristate "Empia EM28xx ALSA audio module" ---help--- This is an ALSA driver for some Empia 28xx based TV cards. diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 901eeeb5c..37e893455 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -35,7 +35,7 @@ #include <linux/vmalloc.h> #include <linux/proc_fs.h> #include <linux/module.h> -#include <sound/driver.h> +#include "compat.h" #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -300,8 +300,11 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dprintk("opening device and trying to acquire exclusive lock\n"); /* Sets volume, mute, etc */ + dev->mute = 0; + mutex_lock(&dev->lock); ret = em28xx_audio_analog_set(dev); + mutex_unlock(&dev->lock); if (ret < 0) goto err; @@ -337,7 +340,9 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) dprintk("closing device\n"); dev->mute = 1; + mutex_lock(&dev->lock); em28xx_audio_analog_set(dev); + mutex_unlock(&dev->lock); if (dev->adev->users == 0 && dev->adev->shutdown == 1) { dprintk("audio users: %d\n", dev->adev->users); diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 14f8fe91e..db07cbbe3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -79,7 +79,6 @@ struct em28xx_board em28xx_boards[] = { .is_em2800 = 1, .vchannels = 2, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -94,13 +93,14 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_UNKNOWN] = { .name = "Unknown EM2750/28xx video grabber", .is_em2800 = 0, + .tuner_type = TUNER_ABSENT, }, [EM2820_BOARD_KWORLD_PVRTV2800RF] = { .name = "Kworld PVR TV 2800 RF", .is_em2800 = 0, .vchannels = 2, + .tuner_type = TUNER_TEMIC_PAL, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -117,7 +117,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -138,7 +137,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -161,7 +159,6 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE| TDA9887_PORT2_ACTIVE, - .has_tuner = 1, .decoder = EM28XX_TVP5150, .has_msp34xx = 1, /*FIXME: S-Video not tested */ @@ -181,7 +178,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, - .has_tuner = 1, .mts_firmware = 1, .decoder = EM28XX_TVP5150, .input = { { @@ -203,7 +199,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, - .has_tuner = 1, .mts_firmware = 1, .has_12mhz_i2s = 1, .decoder = EM28XX_TVP5150, @@ -228,7 +223,6 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Hybrid XS", .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, .input = { { @@ -252,7 +246,6 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Prodigy XS", .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, .input = { { @@ -276,7 +269,6 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, - .has_tuner = 1, .max_range_640_480 = 1, .decoder = EM28XX_SAA7114, @@ -300,7 +292,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -322,7 +313,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -344,7 +334,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_PHILIPS_ATSC, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -363,7 +352,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_PINNACLE_DVC_90] = { .name = "Pinnacle Dazzle DVC 90/DVC 100", .vchannels = 3, - .has_tuner = 0, + .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -381,7 +370,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -401,20 +389,20 @@ struct em28xx_board em28xx_boards[] = { .name = "Pixelview Prolink PlayTV USB 2.0", .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, + .tuner_type = TUNER_YMEC_TVF_5533MF, .decoder = EM28XX_SAA7113, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, - .amux = 1, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, - .amux = 1, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = 1, + .amux = EM28XX_AMUX_LINE_IN, } }, }, }; @@ -454,6 +442,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, + { USB_DEVICE(0x2040, 0x6502), + .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x2040, 0x6513), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, { USB_DEVICE(0x0ccd, 0x0042), @@ -552,7 +542,7 @@ static void em28xx_config_tuner(struct em28xx *dev) struct tuner_setup tun_setup; struct v4l2_frequency f; - if (!dev->has_tuner) + if (dev->tuner_type == TUNER_ABSENT) return; tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; @@ -669,7 +659,6 @@ static int em28xx_hint_board(struct em28xx *dev) static void em28xx_set_model(struct em28xx *dev) { dev->is_em2800 = em28xx_boards[dev->model].is_em2800; - dev->has_tuner = em28xx_boards[dev->model].has_tuner; dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; dev->decoder = em28xx_boards[dev->model].decoder; @@ -677,9 +666,6 @@ static void em28xx_set_model(struct em28xx *dev) dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; - - if (!em28xx_boards[dev->model].has_tuner) - dev->tuner_type = UNSET; } /* ----------------------------------------------------------------------- */ @@ -746,6 +732,7 @@ void em28xx_card_setup(struct em28xx *dev) tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); dev->tuner_type = tv.tuner_type; + if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { dev->i2s_speed = 2048000; dev->has_msp34xx = 1; @@ -778,7 +765,7 @@ void em28xx_card_setup(struct em28xx *dev) request_module("saa7115"); if (dev->decoder == EM28XX_TVP5150) request_module("tvp5150"); - if (dev->has_tuner) + if (dev->tuner_type != TUNER_ABSENT) request_module("tuner"); #endif diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index cb87e7e41..a77cb8099 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -31,7 +31,7 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); @@ -40,7 +40,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int reg_debug = 0; +static unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); @@ -49,7 +49,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int isoc_debug = 0; +static unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); @@ -114,7 +114,8 @@ u32 em28xx_request_buffers(struct em28xx *dev, u32 count) const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ void *buff = NULL; u32 i; - em28xx_coredbg("requested %i buffers with size %zi", count, imagesize); + em28xx_coredbg("requested %i buffers with size %zi\n", + count, imagesize); if (count > EM28XX_NUM_FRAMES) count = EM28XX_NUM_FRAMES; @@ -201,7 +202,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, if (reg_debug){ printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); for (byte = 0; byte < len; byte++) { - printk(" %02x", buf[byte]); + printk(" %02x", (unsigned char)buf[byte]); } printk("\n"); } @@ -228,7 +229,8 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) 0x0000, reg, &val, 1, HZ); if (reg_debug) - printk(ret < 0 ? " failed!\n" : "%02x\n", val); + printk(ret < 0 ? " failed!\n" : + "%02x\n", (unsigned char) val); if (ret < 0) return ret; @@ -288,7 +290,7 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) * sets only some bits (specified by bitmask) of a register, by first reading * the actual value */ -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, +static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, u8 bitmask) { int oldval; @@ -305,26 +307,31 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, */ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) { - int ret; + int ret, i; u8 addr = reg & 0x7f; if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) return ret; if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) return ret; - if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) - return ret; - else if (((u8) ret) & 0x01) { - em28xx_warn ("AC97 command still being executed: not handled properly!\n"); + + /* Wait up to 50 ms for AC97 command to complete */ + for (i = 0; i < 10; i++) { + if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) + return ret; + if (!((u8) ret) & 0x01) + return 0; + msleep(5); } + em28xx_warn ("AC97 command still being executed: not handled properly!\n"); return 0; } -int em28xx_set_audio_source(struct em28xx *dev) +static int em28xx_set_audio_source(struct em28xx *dev) { static char *enable = "\x08\x08"; static char *disable = "\x08\x88"; char *video = enable, *line = disable; - int ret, no_ac97; + int ret; u8 input; if (dev->is_em2800) { @@ -344,11 +351,9 @@ int em28xx_set_audio_source(struct em28xx *dev) switch (dev->ctl_ainput) { case EM28XX_AMUX_VIDEO: input = EM28XX_AUDIO_SRC_TUNER; - no_ac97 = 1; break; case EM28XX_AMUX_LINE_IN: input = EM28XX_AUDIO_SRC_LINE; - no_ac97 = 1; break; case EM28XX_AMUX_AC97_VIDEO: input = EM28XX_AUDIO_SRC_LINE; @@ -364,12 +369,11 @@ int em28xx_set_audio_source(struct em28xx *dev) ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); if (ret < 0) return ret; + msleep(5); - if (no_ac97) - return 0; - - /* Sets AC97 mixer registers */ - + /* Sets AC97 mixer registers + This is seems to be needed, even for non-ac97 configs + */ ret = em28xx_write_ac97(dev, VIDEO_AC97, video); if (ret < 0) return ret; @@ -388,9 +392,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) s[0] |= 0x1f - dev->volume; s[1] |= 0x1f - dev->volume; - if (dev->mute) - s[1] |= 0x80; + /* Mute */ + s[1] |= 0x80; ret = em28xx_write_ac97(dev, MASTER_AC97, s); + if (ret < 0) return ret; @@ -408,6 +413,11 @@ int em28xx_audio_analog_set(struct em28xx *dev) /* Selects the proper audio input */ ret = em28xx_set_audio_source(dev); + /* Unmute device */ + if (!dev->mute) + s[1] &= ~0x80; + ret = em28xx_write_ac97(dev, MASTER_AC97, s); + return ret; } EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); @@ -730,7 +740,7 @@ static void em28xx_isocIrq(struct urb *urb) continue; } if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { + urb->iso_frame_desc[i].length) { em28xx_isocdbg("packet bigger than packet size"); continue; } @@ -776,8 +786,11 @@ void em28xx_uninit_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_NUM_BUFS; i++) { if (dev->urb[i]) { usb_kill_urb(dev->urb[i]); - if (dev->transfer_buffer[i]){ - usb_buffer_free(dev->udev,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); + if (dev->transfer_buffer[i]) { + usb_buffer_free(dev->udev, + dev->urb[i]->transfer_buffer_length, + dev->transfer_buffer[i], + dev->urb[i]->transfer_dma); } usb_free_urb(dev->urb[i]); } @@ -795,7 +808,10 @@ int em28xx_init_isoc(struct em28xx *dev) { /* change interface to 3 which allows the biggest packet sizes */ int i, errCode; - const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; + int sb_size; + + em28xx_set_alternate(dev); + sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; /* reset streaming vars */ dev->frame_current = NULL; @@ -804,7 +820,7 @@ int em28xx_init_isoc(struct em28xx *dev) /* allocate urbs */ for (i = 0; i < EM28XX_NUM_BUFS; i++) { struct urb *urb; - int j, k; + int j; /* allocate transfer buffer */ urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL); if (!urb){ @@ -812,7 +828,9 @@ int em28xx_init_isoc(struct em28xx *dev) em28xx_uninit_isoc(dev); return -ENOMEM; } - dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma); + dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, + GFP_KERNEL, + &urb->transfer_dma); if (!dev->transfer_buffer[i]) { em28xx_errdev ("unable to allocate %i bytes for transfer buffer %i\n", @@ -825,22 +843,22 @@ int em28xx_init_isoc(struct em28xx *dev) urb->dev = dev->udev; urb->context = dev; urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = 1; urb->transfer_buffer = dev->transfer_buffer[i]; urb->complete = em28xx_isocIrq; urb->number_of_packets = EM28XX_NUM_PACKETS; urb->transfer_buffer_length = sb_size; - for (j = k = 0; j < EM28XX_NUM_PACKETS; - j++, k += dev->max_pkt_size) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->max_pkt_size; + for (j = 0; j < EM28XX_NUM_PACKETS; j++) { + urb->iso_frame_desc[j].offset = j * dev->max_pkt_size; + urb->iso_frame_desc[j].length = dev->max_pkt_size; } dev->urb[i] = urb; } /* submit urbs */ + em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n", + EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size); for (i = 0; i < EM28XX_NUM_BUFS; i++) { errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); if (errCode) { @@ -857,40 +875,31 @@ int em28xx_init_isoc(struct em28xx *dev) int em28xx_set_alternate(struct em28xx *dev) { int errCode, prev_alt = dev->alt; - dev->alt = alt; - if (dev->alt == 0) { - int i; -#if 1 /* Always try to get the maximum size value */ - for(i=0;i< dev->num_alt; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) - dev->alt=i; -#endif -#if 0 /* Should be dependent of horizontal size */ - if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ - for(i=0;i< dev->num_alt; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) - dev->alt=i; - }else{ - unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ - em28xx_coredbg("minimum isoc packet size: %u", min_pkt_size); - dev->alt = 7; - for (i = 0; i < dev->num_alt; i ++) - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; + int i; + unsigned int min_pkt_size = dev->bytesperline+4; + + /* When image size is bigger than a ceirtain value, + the frame size should be increased, otherwise, only + green screen will be received. + */ + if (dev->frame_size > 720*240*2) + min_pkt_size *= 2; + + for (i = 0; i < dev->num_alt; i++) + if (dev->alt_max_pkt_size[i] >= min_pkt_size) break; - } - } -#endif - } + dev->alt = i; if (dev->alt != prev_alt) { + em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", + min_pkt_size, dev->alt); dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", dev->alt, - dev->max_pkt_size); + em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", + dev->alt, dev->max_pkt_size); errCode = usb_set_interface(dev->udev, 0, dev->alt); if (errCode < 0) { em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", - dev->alt, errCode); + dev->alt, errCode); return errCode; } } diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index fc59cce34..e13743d67 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index cfec27b3a..4999897ed 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -40,6 +40,7 @@ #include "em28xx.h" #include <media/v4l2-common.h> #include <media/msp3400.h> +#include <media/tuner.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #endif @@ -93,7 +94,7 @@ MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); @@ -210,7 +211,7 @@ static void video_mux(struct em28xx *dev, int index) em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); } - em28xx_set_audio_source(dev); + em28xx_audio_analog_set(dev); } /* Usage lock check functions */ @@ -851,6 +852,63 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int em28xx_reg_len(int reg) +{ + switch (reg) { + case AC97LSB_REG: + case HSCALELOW_REG: + case VSCALELOW_REG: + return 2; + default: + return 1; + } +} + +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_register *reg) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + int ret; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + + if (em28xx_reg_len(reg->reg) == 1) { + ret = em28xx_read_reg(dev, reg->reg); + if (ret < 0) + return ret; + + reg->val = ret; + } else { + u64 val = 0; + ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, + reg->reg, (char *)&val, 2); + if (ret < 0) + return ret; + + reg->val = cpu_to_le64((__u64)val); + } + + return 0; +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_register *reg) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + u64 buf; + + buf = le64_to_cpu((__u64)reg->val); + + return em28xx_write_regs(dev, reg->reg, (char *)&buf, + em28xx_reg_len(reg->reg)); +} +#endif + + static int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cc) { @@ -953,7 +1011,7 @@ static int vidioc_querycap(struct file *file, void *priv, V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - if (dev->has_tuner) + if (dev->tuner_type != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; return 0; @@ -1353,8 +1411,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) filp->private_data = fh; if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - em28xx_set_alternate(dev); - dev->width = norm_maxw(dev); dev->height = norm_maxh(dev); dev->frame_size = dev->width * dev->height * 2; @@ -1363,6 +1419,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->hscale = 0; dev->vscale = 0; + em28xx_set_alternate(dev); em28xx_capture_start(dev, 1); em28xx_resolution_set(dev); @@ -1804,6 +1861,10 @@ static const struct video_device em28xx_video_template = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif .tvnorms = V4L2_STD_ALL, .current_norm = V4L2_STD_PAL, @@ -1826,6 +1887,10 @@ static struct video_device em28xx_radio_template = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif }; /******************************** usb interface *****************************************/ @@ -1870,10 +1935,10 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) } EXPORT_SYMBOL(em28xx_unregister_extension); -struct video_device *em28xx_vdev_init(struct em28xx *dev, - const struct video_device *template, - const int type, - const char *type_name) +static struct video_device *em28xx_vdev_init(struct em28xx *dev, + const struct video_device *template, + const int type, + const char *type_name) { struct video_device *vfd; @@ -1977,7 +2042,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_errdev("cannot allocate video_device.\n"); goto fail_unreg; } - if (dev->has_tuner) + if (dev->tuner_type != TUNER_ABSENT) dev->vdev->type |= VID_TYPE_TUNER; /* register v4l2 video video_device */ @@ -2158,6 +2223,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, snprintf(dev->name, 29, "em28xx #%d", nr); dev->devno = nr; dev->model = id->driver_info; + dev->alt = -1; /* Checks if audio is provided by some interface */ for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 6d7171a89..980989f11 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -36,7 +36,7 @@ #define UNSET -1 /* maximum number of em28xx boards */ -#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */ +#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ /* maximum number of frames that can be queued */ #define EM28XX_NUM_FRAMES 5 @@ -164,7 +164,6 @@ struct em28xx_board { unsigned int tda9887_conf; unsigned int is_em2800:1; - unsigned int has_tuner:1; unsigned int has_msp34xx:1; unsigned int mts_firmware:1; unsigned int has_12mhz_i2s:1; @@ -237,7 +236,6 @@ struct em28xx { int devno; /* marks the number of this device */ unsigned int analog_gpio; unsigned int is_em2800:1; - unsigned int has_tuner:1; unsigned int has_msp34xx:1; unsigned int has_tda9887:1; unsigned int stream_on:1; /* Locks streams */ @@ -362,9 +360,6 @@ int em28xx_read_reg(struct em28xx *dev, u16 reg); int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len); int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, - u8 bitmask); -int em28xx_set_audio_source(struct em28xx *dev); int em28xx_audio_analog_set(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev); |