summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/em28xx
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/em28xx')
-rw-r--r--linux/drivers/media/video/em28xx/Kconfig3
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-audio.c7
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-cards.c37
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-core.c133
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-i2c.c4
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c86
-rw-r--r--linux/drivers/media/video/em28xx/em28xx.h7
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);