diff options
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r-- | linux/drivers/media/video/cx25840/cx25840-core.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/cx25840/cx25840-core.h | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-cards.c | 54 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-dvb.c | 11 | ||||
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/video/s2255drv.c | 112 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-cards.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-core.c | 5 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-empress.c | 32 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-video.c | 40 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134.h | 6 | ||||
-rw-r--r-- | linux/drivers/media/video/stk-webcam.c | 23 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_ctrl.c | 15 | ||||
-rw-r--r-- | linux/drivers/media/video/zoran_card.c | 42 | ||||
-rw-r--r-- | linux/drivers/media/video/zoran_card.h | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/zoran_driver.c | 4 |
17 files changed, 249 insertions, 111 deletions
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index ecd498c70..7b48e0285 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -51,7 +51,7 @@ MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -int cx25840_debug; +static int cx25840_debug; module_param_named(debug,cx25840_debug, int, 0644); diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index f81a9a959..cd549b119 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -25,8 +25,6 @@ #include <linux/videodev2.h> #include <linux/i2c.h> -extern int cx25840_debug; - /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is present in Hauppauge PVR-150 (and possibly PVR-500) cards that have certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index aa11618ef..9510ac044 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -241,12 +241,59 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, } }, }, + [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { + .name = "AMD ATI TV Wonder HD 600", + .vchannels = 3, + .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XC2028, + .mts_firmware = 1, + .has_12mhz_i2s = 1, + .has_dvb = 1, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = 0, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = 1, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = 1, + } }, + }, + [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { + .name = "AMD ATI TV Wonder HD 600", + .vchannels = 3, + .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XC2028, + .mts_firmware = 1, + .has_12mhz_i2s = 1, + .has_dvb = 1, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = 0, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = 1, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = 1, + } }, + }, [EM2880_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS", .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, + .has_dvb = 1, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -493,6 +540,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, + { USB_DEVICE(0x0438, 0xb002), + .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); @@ -608,6 +657,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: + case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); msleep(50); @@ -640,12 +690,16 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: ctl->demod = XC3028_FE_ZARLINK456; break; + case EM2880_BOARD_TERRATEC_HYBRID_XS: + ctl->demod = XC3028_FE_ZARLINK456; + break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: /* djh - Not sure which demod we need here */ ctl->demod = XC3028_FE_DEFAULT; break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: + case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: /* FIXME: Better to specify the needed IF */ ctl->demod = XC3028_FE_DEFAULT; break; diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index adf2a6552..7edec4618 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -6,6 +6,7 @@ (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com> - Fixes for the driver to properly work with HVR-950 - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick + - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600 (c) 2008 Aidan Thornton <makosoft@googlemail.com> @@ -412,6 +413,7 @@ static int dvb_init(struct em28xx *dev) switch (dev->model) { case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: + case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->frontend = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); @@ -442,6 +444,15 @@ static int dvb_init(struct em28xx *dev) } break; #endif + case EM2880_BOARD_TERRATEC_HYBRID_XS: + dvb->frontend = dvb_attach(zl10353_attach, + &em28xx_zl10353_with_xc3028, + &dev->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" " isn't supported yet\n", diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 6db96db0f..8c97635c2 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -59,6 +59,7 @@ #define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17 #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18 #define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA 19 +#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 20 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e3b051197..88e175168 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -330,7 +330,7 @@ static const char *pvr2_fw1_names_73xxx[] = { }; static const struct pvr2_device_desc pvr2_device_73xxx = { - .description = "WinTV PVR USB2 Model Category 73xxx", + .description = "WinTV HVR-1900 Model Category 73xxx", .shortname = "73xxx", .client_modules.lst = pvr2_client_73xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx), @@ -439,7 +439,7 @@ static const char *pvr2_fw1_names_75xxx[] = { }; static const struct pvr2_device_desc pvr2_device_750xx = { - .description = "WinTV PVR USB2 Model Category 750xx", + .description = "WinTV HVR-1950 Model Category 750xx", .shortname = "750xx", .client_modules.lst = pvr2_client_75xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), @@ -461,7 +461,7 @@ static const struct pvr2_device_desc pvr2_device_750xx = { }; static const struct pvr2_device_desc pvr2_device_751xx = { - .description = "WinTV PVR USB2 Model Category 751xx", + .description = "WinTV HVR-1950 Model Category 751xx", .shortname = "751xx", .client_modules.lst = pvr2_client_75xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index f13235e31..e09b43c31 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -47,6 +47,7 @@ #include <linux/mutex.h> #include <linux/videodev2.h> #include <linux/version.h> +#include <linux/mm.h> #include <media/videobuf-vmalloc.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> @@ -186,6 +187,7 @@ struct s2255_dmaqueue { #define S2255_FW_LOADED_DSPWAIT 1 #define S2255_FW_SUCCESS 2 #define S2255_FW_FAILED 3 +#define S2255_FW_DISCONNECTING 4 struct s2255_fw { int fw_loaded; @@ -265,7 +267,6 @@ struct s2255_buffer { struct s2255_fh { struct s2255_dev *dev; - unsigned int resources; const struct s2255_fmt *fmt; unsigned int width; unsigned int height; @@ -275,14 +276,9 @@ struct s2255_fh { /* mode below is the desired mode. mode in s2255_dev is the current mode that was last set */ struct s2255_mode mode; + int resources[MAX_CHANNELS]; }; -/* - * TODO: fixme S2255_MAX_USERS. Do not limit open driver handles. - * Limit V4L to one stream at a time. - */ -#define S2255_MAX_USERS 1 - #define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */ #define S2255_MAJOR_VERSION 1 #define S2255_MINOR_VERSION 13 @@ -478,10 +474,9 @@ static void s2255_timer(unsigned long user_data) dprintk(100, "s2255 timer\n"); if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { printk(KERN_ERR "s2255: can't submit urb\n"); - if (data->fw) { - release_firmware(data->fw); - data->fw = NULL; - } + atomic_set(&data->fw_state, S2255_FW_FAILED); + /* wake up anything waiting for the firmware */ + wake_up(&data->wait_fw); return; } } @@ -511,13 +506,18 @@ static void s2255_fwchunk_complete(struct urb *urb) struct usb_device *udev = urb->dev; int len; dprintk(100, "udev %p urb %p", udev, urb); - /* TODO: fixme. reflect change in status */ if (urb->status) { dev_err(&udev->dev, "URB failed with status %d", urb->status); + atomic_set(&data->fw_state, S2255_FW_FAILED); + /* wake up anything waiting for the firmware */ + wake_up(&data->wait_fw); return; } if (data->fw_urb == NULL) { - dev_err(&udev->dev, "early disconncect\n"); + dev_err(&udev->dev, "s2255 disconnected\n"); + atomic_set(&data->fw_state, S2255_FW_FAILED); + /* wake up anything waiting for the firmware */ + wake_up(&data->wait_fw); return; } #define CHUNK_SIZE 512 @@ -791,7 +791,8 @@ static int res_get(struct s2255_dev *dev, struct s2255_fh *fh) } /* it's free, grab it */ dev->resources[fh->channel] = 1; - dprintk(1, "res: get\n"); + fh->resources[fh->channel] = 1; + dprintk(1, "s2255: res: get\n"); mutex_unlock(&dev->lock); return 1; } @@ -801,9 +802,18 @@ static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh) return dev->resources[fh->channel]; } +static int res_check(struct s2255_fh *fh) +{ + return fh->resources[fh->channel]; +} + + static void res_free(struct s2255_dev *dev, struct s2255_fh *fh) { + mutex_lock(&dev->lock); dev->resources[fh->channel] = 0; + fh->resources[fh->channel] = 0; + mutex_unlock(&dev->lock); dprintk(1, "res: put\n"); } @@ -1234,7 +1244,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) } if (!res_get(dev, fh)) { - dev_err(&dev->udev->dev, "res get busy\n"); + dev_err(&dev->udev->dev, "s2255: stream busy\n"); return -EBUSY; } @@ -1290,8 +1300,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) } s2255_stop_acquire(dev, fh->channel); res = videobuf_streamoff(&fh->vb_vidq); + if (res < 0) + return res; res_free(dev, fh); - return res; + return 0; } static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) @@ -1464,12 +1476,7 @@ static int s2255_open(struct inode *inode, struct file *file) mutex_lock(&dev->open_lock); dev->users[cur_channel]++; - if (dev->users[cur_channel] > S2255_MAX_USERS) { - dev->users[cur_channel]--; - mutex_unlock(&dev->open_lock); - printk(KERN_INFO "s2255drv: too many open handles!\n"); - return -EBUSY; - } + dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) { err("2255 firmware load failed. retrying.\n"); @@ -1480,7 +1487,8 @@ static int s2255_open(struct inode *inode, struct file *file) msecs_to_jiffies(S2255_LOAD_TIMEOUT)); if (atomic_read(&dev->fw_data->fw_state) != S2255_FW_SUCCESS) { - printk(KERN_INFO "2255 FW load failed after 2 tries\n"); + printk(KERN_INFO "2255 FW load failed.\n"); + dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); return -EFAULT; } @@ -1496,6 +1504,7 @@ static int s2255_open(struct inode *inode, struct file *file) != S2255_FW_SUCCESS) { printk(KERN_INFO "2255 firmware not loaded" "try again\n"); + dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); return -EBUSY; } @@ -1504,6 +1513,7 @@ static int s2255_open(struct inode *inode, struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { + dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); return -ENOMEM; } @@ -1563,44 +1573,48 @@ static void s2255_destroy(struct kref *kref) printk(KERN_ERR "s2255drv: kref problem\n"); return; } + + /* + * Wake up any firmware load waiting (only done in .open, + * which holds the open_lock mutex) + */ + atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); + wake_up(&dev->fw_data->wait_fw); + /* prevent s2255_disconnect from racing s2255_open */ mutex_lock(&dev->open_lock); s2255_exit_v4l(dev); - /* device unregistered so no longer possible to open. open_mutex - can be unlocked */ + /* + * device unregistered so no longer possible to open. open_mutex + * can be unlocked and timers deleted afterwards. + */ mutex_unlock(&dev->open_lock); /* board shutdown stops the read pipe if it is running */ s2255_board_shutdown(dev); /* make sure firmware still not trying to load */ + del_timer(&dev->timer); /* only started in .probe and .open */ + if (dev->fw_data->fw_urb) { dprintk(2, "kill fw_urb\n"); usb_kill_urb(dev->fw_data->fw_urb); usb_free_urb(dev->fw_data->fw_urb); dev->fw_data->fw_urb = NULL; } + /* - * TODO: fixme(above, below): potentially leaving timers alive. - * do not ignore timeout below if - * it occurs. + * delete the dsp_wait timer, which sets the firmware + * state on completion. This is done before fw_data + * is freed below. */ - /* make sure we aren't waiting for the DSP */ - if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_LOADED_DSPWAIT) { - /* if we are, wait for the wakeup for fw_success or timeout */ - wait_event_timeout(dev->fw_data->wait_fw, - (atomic_read(&dev->fw_data->fw_state) - == S2255_FW_SUCCESS), - msecs_to_jiffies(S2255_LOAD_TIMEOUT)); - } + del_timer(&dev->fw_data->dsp_wait); /* only started in .open */ - if (dev->fw_data) { - if (dev->fw_data->fw) - release_firmware(dev->fw_data->fw); - kfree(dev->fw_data->pfw_data); - kfree(dev->fw_data); - } + if (dev->fw_data->fw) + release_firmware(dev->fw_data->fw); + kfree(dev->fw_data->pfw_data); + kfree(dev->fw_data); usb_put_dev(dev->udev); dprintk(1, "%s", __func__); @@ -1617,17 +1631,23 @@ static int s2255_close(struct inode *inode, struct file *file) mutex_lock(&dev->open_lock); - if (dev->b_acquire[fh->channel]) - s2255_stop_acquire(dev, fh->channel); - res_free(dev, fh); + /* turn off stream */ + if (res_check(fh)) { + if (dev->b_acquire[fh->channel]) + s2255_stop_acquire(dev, fh->channel); + videobuf_streamoff(&fh->vb_vidq); + res_free(dev, fh); + } + videobuf_mmap_free(&fh->vb_vidq); - kfree(fh); dev->users[fh->channel]--; + mutex_unlock(&dev->open_lock); kref_put(&dev->kref, s2255_destroy); dprintk(1, "s2255: close called (minor=%d, users=%d)\n", minor, dev->users[fh->channel]); + kfree(fh); return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 8ec09c97e..dfe4f7169 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -5956,9 +5956,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) unsigned char buf; int board; - dev->tuner_type = saa7134_boards[dev->board].tuner_type; - dev->tuner_addr = saa7134_boards[dev->board].tuner_addr; - switch (dev->board) { case SAA7134_BOARD_BMK_MPEX_NOTUNER: case SAA7134_BOARD_BMK_MPEX_TUNER: diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 254a04717..e791bbd64 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1006,11 +1006,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->board = SAA7134_BOARD_UNKNOWN; } dev->autodetected = card[dev->nr] != dev->board; - dev->tuner_type = saa7134_boards[dev->board].tuner_type; + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + dev->tuner_addr = saa7134_boards[dev->board].tuner_addr; dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, dev->board, dev->autodetected ? diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 1d1c19680..4ce2ea65f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -89,14 +89,14 @@ static int ts_open(struct inode *inode, struct file *file) err = -EBUSY; if (!mutex_trylock(&dev->empress_tsq.vb_lock)) goto done; - if (dev->empress_users) + if (atomic_read(&dev->empress_users)) goto done_up; /* Unmute audio */ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6)); - dev->empress_users++; + atomic_inc(&dev->empress_users); file->private_data = dev; err = 0; @@ -110,8 +110,6 @@ static int ts_release(struct inode *inode, struct file *file) { struct saa7134_dev *dev = file->private_data; - mutex_lock(&dev->empress_tsq.vb_lock); - videobuf_stop(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq); @@ -122,9 +120,7 @@ static int ts_release(struct inode *inode, struct file *file) saa_writeb(SAA7134_AUDIO_MUTE_CTRL, saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); - dev->empress_users--; - - mutex_unlock(&dev->empress_tsq.vb_lock); + atomic_dec(&dev->empress_users); return 0; } @@ -333,6 +329,22 @@ static int empress_g_ext_ctrls(struct file *file, void *priv, return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls); } +static int empress_g_ctrl(struct file *file, void *priv, + struct v4l2_control *c) +{ + struct saa7134_dev *dev = file->private_data; + + return saa7134_g_ctrl_internal(dev, NULL, c); +} + +static int empress_s_ctrl(struct file *file, void *priv, + struct v4l2_control *c) +{ + struct saa7134_dev *dev = file->private_data; + + return saa7134_s_ctrl_internal(dev, NULL, c); +} + static int empress_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c) { @@ -419,8 +431,8 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_queryctrl = empress_queryctrl, .vidioc_querymenu = empress_querymenu, - .vidioc_g_ctrl = saa7134_g_ctrl, - .vidioc_s_ctrl = saa7134_s_ctrl, + .vidioc_g_ctrl = empress_g_ctrl, + .vidioc_s_ctrl = empress_s_ctrl, }; /* ----------------------------------------------------------- */ @@ -455,7 +467,7 @@ static void empress_signal_update(struct work_struct *work) ts_reset_encoder(dev); } else { dprintk("video signal acquired\n"); - if (dev->empress_users) + if (atomic_read(&dev->empress_users)) ts_init_encoder(dev); } } diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 7e04bfa19..350c5ff5a 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1112,10 +1112,8 @@ static struct videobuf_queue_ops video_qops = { /* ------------------------------------------------------------------ */ -int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c) +int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c) { - struct saa7134_fh *fh = priv; - struct saa7134_dev *dev = fh->dev; const struct v4l2_queryctrl* ctrl; ctrl = ctrl_by_id(c->id); @@ -1160,20 +1158,31 @@ int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c) } return 0; } -EXPORT_SYMBOL_GPL(saa7134_g_ctrl); +EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal); + +static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c) +{ + struct saa7134_fh *fh = priv; + + return saa7134_g_ctrl_internal(fh->dev, fh, c); +} -int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c) +int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c) { const struct v4l2_queryctrl* ctrl; - struct saa7134_fh *fh = f; - struct saa7134_dev *dev = fh->dev; unsigned long flags; int restart_overlay = 0; - int err = -EINVAL; + int err; - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + /* When called from the empress code fh == NULL. + That needs to be fixed somehow, but for now this is + good enough. */ + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + err = -EINVAL; mutex_lock(&dev->lock); @@ -1274,7 +1283,14 @@ error: mutex_unlock(&dev->lock); return err; } -EXPORT_SYMBOL_GPL(saa7134_s_ctrl); +EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal); + +static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c) +{ + struct saa7134_fh *fh = f; + + return saa7134_s_ctrl_internal(fh->dev, fh, c); +} /* ------------------------------------------------------------------ */ diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 053c358ff..e3ad9d9e7 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -566,7 +566,7 @@ struct saa7134_dev { /* SAA7134_MPEG_EMPRESS only */ struct video_device *empress_dev; struct videobuf_queue empress_tsq; - unsigned int empress_users; + atomic_t empress_users; struct work_struct empress_workqueue; int empress_started; @@ -668,8 +668,8 @@ extern unsigned int video_debug; extern struct video_device saa7134_video_template; extern struct video_device saa7134_radio_template; -int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c); -int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c); +int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); +int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); int saa7134_videoport_init(struct saa7134_dev *dev); diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 5daa2294d..c5f766653 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -446,18 +446,19 @@ static void stk_isoc_handler(struct urb *urb) fb->v4lbuf.bytesused = 0; fill = fb->buffer; } else if (fb->v4lbuf.bytesused == dev->frame_size) { - list_move_tail(dev->sio_avail.next, - &dev->sio_full); - wake_up(&dev->wait_frame); - if (list_empty(&dev->sio_avail)) { - (void) (printk_ratelimit() && - STK_ERROR("No buffer available\n")); - goto resubmit; + if (list_is_singular(&dev->sio_avail)) { + /* Always reuse the last buffer */ + fb->v4lbuf.bytesused = 0; + fill = fb->buffer; + } else { + list_move_tail(dev->sio_avail.next, + &dev->sio_full); + wake_up(&dev->wait_frame); + fb = list_first_entry(&dev->sio_avail, + struct stk_sio_buffer, list); + fb->v4lbuf.bytesused = 0; + fill = fb->buffer; } - fb = list_first_entry(&dev->sio_avail, - struct stk_sio_buffer, list); - fb->v4lbuf.bytesused = 0; - fill = fb->buffer; } } else { framelen -= 4; diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 3ae955126..626f4ad7e 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -195,8 +195,8 @@ static struct uvc_menu_info power_line_frequency_controls[] = { }; static struct uvc_menu_info exposure_auto_controls[] = { - { 1, "Manual Mode" }, { 2, "Auto Mode" }, + { 1, "Manual Mode" }, { 4, "Shutter Priority Mode" }, { 8, "Aperture Priority Mode" }, }; @@ -592,6 +592,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, if (ctrl == NULL) return -EINVAL; + memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); v4l2_ctrl->id = mapping->id; v4l2_ctrl->type = mapping->v4l2_type; strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); @@ -608,7 +609,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); } - if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { + switch (mapping->v4l2_type) { + case V4L2_CTRL_TYPE_MENU: v4l2_ctrl->minimum = 0; v4l2_ctrl->maximum = mapping->menu_count - 1; v4l2_ctrl->step = 1; @@ -622,6 +624,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, } return 0; + + case V4L2_CTRL_TYPE_BOOLEAN: + v4l2_ctrl->minimum = 0; + v4l2_ctrl->maximum = 1; + v4l2_ctrl->step = 1; + return 0; + + default: + break; } if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { diff --git a/linux/drivers/media/video/zoran_card.c b/linux/drivers/media/video/zoran_card.c index cc45ae5cd..6678c6de9 100644 --- a/linux/drivers/media/video/zoran_card.c +++ b/linux/drivers/media/video/zoran_card.c @@ -162,7 +162,7 @@ static struct pci_device_id zr36067_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); int zoran_num; /* number of Buzs in use */ -struct zoran zoran[BUZ_MAX]; +struct zoran *zoran[BUZ_MAX]; /* videocodec bus functions ZR36060 */ static u32 @@ -356,9 +356,15 @@ i2cid_to_modulename (u16 i2c_id) case I2C_DRIVERID_BT856: name = "bt856"; break; + case I2C_DRIVERID_BT866: + name = "bt866"; + break; case I2C_DRIVERID_VPX3220: name = "vpx3220"; break; + case I2C_DRIVERID_KS0127: + name = "ks0127"; + break; } return name; @@ -1165,7 +1171,7 @@ static void zoran_release (struct zoran *zr) { if (!zr->initialized) - return; + goto exit_free; /* unregister videocodec bus */ if (zr->codec) { struct videocodec_master *master = zr->codec->master_data; @@ -1193,6 +1199,8 @@ zoran_release (struct zoran *zr) iounmap(zr->zr36057_mem); pci_disable_device(zr->pci_dev); video_unregister_device(zr->video_dev); +exit_free: + kfree(zr); } void @@ -1270,8 +1278,14 @@ find_zr36057 (void) while (zoran_num < BUZ_MAX && (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) { card_num = card[zoran_num]; - zr = &zoran[zoran_num]; - memset(zr, 0, sizeof(struct zoran)); // Just in case if previous cycle failed + zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); + if (!zr) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - kzalloc failed\n", + ZORAN_NAME); + continue; + } zr->pci_dev = dev; //zr->zr36057_mem = NULL; zr->id = zoran_num; @@ -1279,7 +1293,7 @@ find_zr36057 (void) spin_lock_init(&zr->spinlock); mutex_init(&zr->resource_lock); if (pci_enable_device(dev)) - continue; + goto zr_free_mem; zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); @@ -1295,7 +1309,7 @@ find_zr36057 (void) KERN_ERR "%s: find_zr36057() - no card specified, please use the card=X insmod option\n", ZR_DEVNAME(zr)); - continue; + goto zr_free_mem; } } else { int i; @@ -1334,7 +1348,7 @@ find_zr36057 (void) KERN_ERR "%s: find_zr36057() - unknown card\n", ZR_DEVNAME(zr)); - continue; + goto zr_free_mem; } } } @@ -1344,7 +1358,7 @@ find_zr36057 (void) KERN_ERR "%s: find_zr36057() - invalid cardnum %d\n", ZR_DEVNAME(zr), card_num); - continue; + goto zr_free_mem; } /* even though we make this a non pointer and thus @@ -1362,7 +1376,7 @@ find_zr36057 (void) KERN_ERR "%s: find_zr36057() - ioremap failed\n", ZR_DEVNAME(zr)); - continue; + goto zr_free_mem; } result = request_irq(zr->pci_dev->irq, @@ -1531,7 +1545,7 @@ find_zr36057 (void) } /* Success so keep the pci_dev referenced */ pci_dev_get(zr->pci_dev); - zoran_num++; + zoran[zoran_num++] = zr; continue; // Init errors @@ -1550,6 +1564,8 @@ find_zr36057 (void) free_irq(zr->pci_dev->irq, zr); zr_unmap: iounmap(zr->zr36057_mem); + zr_free_mem: + kfree(zr); continue; } if (dev) /* Clean up ref count on early exit */ @@ -1621,7 +1637,7 @@ init_dc10_cards (void) /* take care of Natoma chipset and a revision 1 zr36057 */ for (i = 0; i < zoran_num; i++) { - struct zoran *zr = &zoran[i]; + struct zoran *zr = zoran[i]; if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { zr->jpg_buffers.need_contiguous = 1; @@ -1633,7 +1649,7 @@ init_dc10_cards (void) if (zr36057_init(zr) < 0) { for (i = 0; i < zoran_num; i++) - zoran_release(&zoran[i]); + zoran_release(zoran[i]); return -EIO; } zoran_proc_init(zr); @@ -1648,7 +1664,7 @@ unload_dc10_cards (void) int i; for (i = 0; i < zoran_num; i++) - zoran_release(&zoran[i]); + zoran_release(zoran[i]); } module_init(init_dc10_cards); diff --git a/linux/drivers/media/video/zoran_card.h b/linux/drivers/media/video/zoran_card.h index 1b5c4171c..e4dc9d29b 100644 --- a/linux/drivers/media/video/zoran_card.h +++ b/linux/drivers/media/video/zoran_card.h @@ -41,7 +41,7 @@ extern int zr36067_debug; /* Anybody who uses more than four? */ #define BUZ_MAX 4 extern int zoran_num; -extern struct zoran zoran[BUZ_MAX]; +extern struct zoran *zoran[BUZ_MAX]; extern struct video_device zoran_template; diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 989a6f7e0..433b469d6 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -1278,8 +1278,8 @@ zoran_open (struct inode *inode, /* find the device */ for (i = 0; i < zoran_num; i++) { - if (zoran[i].video_dev->minor == minor) { - zr = &zoran[i]; + if (zoran[i]->video_dev->minor == minor) { + zr = zoran[i]; break; } } |