diff options
Diffstat (limited to 'drivers/media/usb/usbvision')
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-core.c | 71 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-i2c.c | 2 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-video.c | 246 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision.h | 10 |
4 files changed, 102 insertions, 227 deletions
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 7c04ef697fb6..dc3b4d5155c5 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -1367,7 +1367,7 @@ static void usbvision_isoc_irq(struct urb *urb) int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) { int err_code = 0; - unsigned char buffer[1]; + unsigned char *buffer = usbvision->ctrl_urb_buffer; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -1; @@ -1401,10 +1401,12 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; + usbvision->ctrl_urb_buffer[0] = value; err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); + USB_RECIP_ENDPOINT, 0, (__u16) reg, + usbvision->ctrl_urb_buffer, 1, HZ); if (err_code < 0) { dev_err(&usbvision->dev->dev, @@ -1596,7 +1598,7 @@ static int usbvision_init_webcam(struct usb_usbvision *usbvision) { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 }, { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 } }; - char value[3]; + unsigned char *value = usbvision->ctrl_urb_buffer; /* the only difference between PAL and NTSC init_values */ if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC) @@ -1635,8 +1637,8 @@ static int usbvision_init_webcam(struct usb_usbvision *usbvision) static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format) { static const char proc[] = "usbvision_set_video_format"; + unsigned char *value = usbvision->ctrl_urb_buffer; int rc; - unsigned char value[2]; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; @@ -1677,7 +1679,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, int err_code = 0; int usb_width, usb_height; unsigned int frame_rate = 0, frame_drop = 0; - unsigned char value[4]; + unsigned char *value = usbvision->ctrl_urb_buffer; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; @@ -1789,10 +1791,6 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames usbvision->num_frames--; } - spin_lock_init(&usbvision->queue_lock); - init_waitqueue_head(&usbvision->wait_frame); - init_waitqueue_head(&usbvision->wait_stream); - /* Allocate all buffers */ for (i = 0; i < usbvision->num_frames; i++) { usbvision->frame[i].index = i; @@ -1872,7 +1870,7 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) { static const char proc[] = "usbvision_set_compresion_params: "; int rc; - unsigned char value[6]; + unsigned char *value = usbvision->ctrl_urb_buffer; value[0] = 0x0F; /* Intra-Compression cycle */ value[1] = 0x01; /* Reg.45 one line per strip */ @@ -1946,7 +1944,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) { static const char proc[] = "usbvision_set_input: "; int rc; - unsigned char value[8]; + unsigned char *value = usbvision->ctrl_urb_buffer; unsigned char dvi_yuv_value; if (!USBVISION_IS_OPERATIONAL(usbvision)) @@ -2062,8 +2060,8 @@ int usbvision_set_input(struct usb_usbvision *usbvision) static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) { + unsigned char *value = usbvision->ctrl_urb_buffer; int rc; - unsigned char value[8]; if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { value[0] = 0x42; @@ -2161,55 +2159,6 @@ int usbvision_power_on(struct usb_usbvision *usbvision) /* - * usbvision timer stuff - */ - -/* to call usbvision_power_off from task queue */ -static void call_usbvision_power_off(struct work_struct *work) -{ - struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work); - - PDEBUG(DBG_FUNC, ""); - if (mutex_lock_interruptible(&usbvision->v4l2_lock)) - return; - - if (usbvision->user == 0) { - usbvision_i2c_unregister(usbvision); - - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - mutex_unlock(&usbvision->v4l2_lock); -} - -static void usbvision_power_off_timer(unsigned long data) -{ - struct usb_usbvision *usbvision = (void *)data; - - PDEBUG(DBG_FUNC, ""); - del_timer(&usbvision->power_off_timer); - INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off); - (void) schedule_work(&usbvision->power_off_work); -} - -void usbvision_init_power_off_timer(struct usb_usbvision *usbvision) -{ - setup_timer(&usbvision->power_off_timer, usbvision_power_off_timer, - (unsigned long)usbvision); -} - -void usbvision_set_power_off_timer(struct usb_usbvision *usbvision) -{ - mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME); -} - -void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision) -{ - if (timer_pending(&usbvision->power_off_timer)) - del_timer(&usbvision->power_off_timer); -} - -/* * usbvision_begin_streaming() * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no * idea about the rest diff --git a/drivers/media/usb/usbvision/usbvision-i2c.c b/drivers/media/usb/usbvision/usbvision-i2c.c index 26dbcb1146af..120de2e020e1 100644 --- a/drivers/media/usb/usbvision/usbvision-i2c.c +++ b/drivers/media/usb/usbvision/usbvision-i2c.c @@ -343,7 +343,7 @@ static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, { int rc, retries; int i; - unsigned char value[6]; + unsigned char *value = usbvision->ctrl_urb_buffer; unsigned char ser_cont; ser_cont = (len & 0x07) | 0x10; diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 1c6d31f7c1b9..b693206f66dd 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -62,6 +62,7 @@ #include <media/saa7115.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-event.h> #include <media/tuner.h> #include <linux/workqueue.h> @@ -122,8 +123,6 @@ static void usbvision_release(struct usb_usbvision *usbvision); static int isoc_mode = ISOC_MODE_COMPRESS; /* Set the default Debug Mode of the device driver */ static int video_debug; -/* Set the default device to power on at startup */ -static int power_on_at_open = 1; /* Sequential Number of Video Device */ static int video_nr = -1; /* Sequential Number of Radio Device */ @@ -134,13 +133,11 @@ static int radio_nr = -1; /* Showing parameters under SYSFS */ module_param(isoc_mode, int, 0444); module_param(video_debug, int, 0444); -module_param(power_on_at_open, int, 0444); module_param(video_nr, int, 0444); module_param(radio_nr, int, 0444); MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); -MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened. Default: 1 (On)"); MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); @@ -351,11 +348,14 @@ static int usbvision_v4l2_open(struct file *file) if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; - usbvision_reset_power_off_timer(usbvision); - if (usbvision->user) + if (usbvision->user) { err_code = -EBUSY; - else { + } else { + err_code = v4l2_fh_open(file); + if (err_code) + goto unlock; + /* Allocate memory for the scratch ring buffer */ err_code = usbvision_scratch_alloc(usbvision); if (isoc_mode == ISOC_MODE_COMPRESS) { @@ -372,11 +372,6 @@ static int usbvision_v4l2_open(struct file *file) /* If so far no errors then we shall start the camera */ if (!err_code) { - if (usbvision->power == 0) { - usbvision_power_on(usbvision); - usbvision_i2c_register(usbvision); - } - /* Send init sequence only once, it's large! */ if (!usbvision->initialized) { int setup_ok = 0; @@ -392,18 +387,14 @@ static int usbvision_v4l2_open(struct file *file) err_code = usbvision_init_isoc(usbvision); /* device must be initialized before isoc transfer */ usbvision_muxsel(usbvision, 0); + + /* prepare queues */ + usbvision_empty_framequeues(usbvision); usbvision->user++; - } else { - if (power_on_at_open) { - usbvision_i2c_unregister(usbvision); - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } } } - /* prepare queues */ - usbvision_empty_framequeues(usbvision); +unlock: mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); @@ -435,23 +426,16 @@ static int usbvision_v4l2_close(struct file *file) usbvision_scratch_free(usbvision); usbvision->user--; - - if (power_on_at_open) { - /* power off in a little while - to avoid off/on every close/open short sequences */ - usbvision_set_power_off_timer(usbvision); - usbvision->initialized = 0; - } + mutex_unlock(&usbvision->v4l2_lock); if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); return 0; } - mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); - return 0; + return v4l2_fh_release(file); } @@ -503,18 +487,24 @@ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *vc) { struct usb_usbvision *usbvision = video_drvdata(file); + struct video_device *vdev = video_devdata(file); strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); strlcpy(vc->card, usbvision_device_data[usbvision->dev_model].model_string, sizeof(vc->card)); usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info)); - vc->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - vc->capabilities = vc->device_caps | V4L2_CAP_DEVICE_CAPS; + vc->device_caps = usbvision->have_tuner ? V4L2_CAP_TUNER : 0; + if (vdev->vfl_type == VFL_TYPE_GRABBER) + vc->device_caps |= V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + else + vc->device_caps |= V4L2_CAP_RADIO; + + vc->capabilities = vc->device_caps | V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; + if (usbvision_device_data[usbvision->dev_model].radio) + vc->capabilities |= V4L2_CAP_RADIO; return 0; } @@ -540,7 +530,6 @@ static int vidioc_enum_input(struct file *file, void *priv, } else { strcpy(vi->name, "Television"); vi->type = V4L2_INPUT_TYPE_TUNER; - vi->audioset = 1; vi->tuner = chan; vi->std = USBVISION_NORMS; } @@ -551,7 +540,7 @@ static int vidioc_enum_input(struct file *file, void *priv, strcpy(vi->name, "Green Video Input"); else strcpy(vi->name, "Composite Video Input"); - vi->std = V4L2_STD_PAL; + vi->std = USBVISION_NORMS; break; case 2: vi->type = V4L2_INPUT_TYPE_CAMERA; @@ -559,12 +548,12 @@ static int vidioc_enum_input(struct file *file, void *priv, strcpy(vi->name, "Yellow Video Input"); else strcpy(vi->name, "S-Video Input"); - vi->std = V4L2_STD_PAL; + vi->std = USBVISION_NORMS; break; case 3: vi->type = V4L2_INPUT_TYPE_CAMERA; strcpy(vi->name, "Red Video Input"); - vi->std = V4L2_STD_PAL; + vi->std = USBVISION_NORMS; break; } return 0; @@ -619,14 +608,13 @@ static int vidioc_g_tuner(struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - if (!usbvision->have_tuner || vt->index) /* Only tuner 0 */ + if (vt->index) /* Only tuner 0 */ return -EINVAL; - if (usbvision->radio) { + if (vt->type == V4L2_TUNER_RADIO) strcpy(vt->name, "Radio"); - vt->type = V4L2_TUNER_RADIO; - } else { + else strcpy(vt->name, "Television"); - } + /* Let clients fill in the remainder of this struct */ call_all(usbvision, tuner, g_tuner, vt); @@ -638,8 +626,8 @@ static int vidioc_s_tuner(struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - /* Only no or one tuner for now */ - if (!usbvision->have_tuner || vt->index) + /* Only one tuner for now */ + if (vt->index) return -EINVAL; /* let clients handle this */ call_all(usbvision, tuner, s_tuner, vt); @@ -652,12 +640,13 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - freq->tuner = 0; /* Only one tuner */ - if (usbvision->radio) - freq->type = V4L2_TUNER_RADIO; + /* Only one tuner */ + if (freq->tuner) + return -EINVAL; + if (freq->type == V4L2_TUNER_RADIO) + freq->frequency = usbvision->radio_freq; else - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = usbvision->freq; + freq->frequency = usbvision->tv_freq; return 0; } @@ -666,65 +655,19 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *freq) { struct usb_usbvision *usbvision = video_drvdata(file); + struct v4l2_frequency new_freq = *freq; - /* Only no or one tuner for now */ - if (!usbvision->have_tuner || freq->tuner) + /* Only one tuner for now */ + if (freq->tuner) return -EINVAL; - usbvision->freq = freq->frequency; call_all(usbvision, tuner, s_frequency, freq); - - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - if (usbvision->radio) - strcpy(a->name, "Radio"); + call_all(usbvision, tuner, g_frequency, &new_freq); + if (freq->type == V4L2_TUNER_RADIO) + usbvision->radio_freq = new_freq.frequency; else - strcpy(a->name, "TV"); - - return 0; -} + usbvision->tv_freq = new_freq.frequency; -static int vidioc_s_audio(struct file *file, void *fh, - const struct v4l2_audio *a) -{ - if (a->index) - return -EINVAL; - return 0; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *ctrl) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - call_all(usbvision, core, queryctrl, ctrl); - - if (!ctrl->type) - return -EINVAL; - - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - call_all(usbvision, core, g_ctrl, ctrl); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - call_all(usbvision, core, s_ctrl, ctrl); return 0; } @@ -937,6 +880,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; + vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ return 0; } @@ -1167,20 +1112,15 @@ static int usbvision_radio_open(struct file *file) if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + err_code = v4l2_fh_open(file); + if (err_code) + goto out; if (usbvision->user) { dev_err(&usbvision->rdev.dev, "%s: Someone tried to open an already opened USBVision Radio!\n", __func__); err_code = -EBUSY; } else { - if (power_on_at_open) { - usbvision_reset_power_off_timer(usbvision); - if (usbvision->power == 0) { - usbvision_power_on(usbvision); - usbvision_i2c_register(usbvision); - } - } - /* Alternate interface 1 is is the biggest frame size */ err_code = usbvision_set_alternate(usbvision); if (err_code < 0) { @@ -1195,14 +1135,6 @@ static int usbvision_radio_open(struct file *file) usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); usbvision->user++; } - - if (err_code) { - if (power_on_at_open) { - usbvision_i2c_unregister(usbvision); - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - } out: mutex_unlock(&usbvision->v4l2_lock); return err_code; @@ -1212,34 +1144,29 @@ out: static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int err_code = 0; PDEBUG(DBG_IO, ""); mutex_lock(&usbvision->v4l2_lock); /* Set packet size to 0 */ usbvision->iface_alt = 0; - err_code = usb_set_interface(usbvision->dev, usbvision->iface, + usb_set_interface(usbvision->dev, usbvision->iface, usbvision->iface_alt); usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; - if (power_on_at_open) { - usbvision_set_power_off_timer(usbvision); - usbvision->initialized = 0; - } - if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); + v4l2_fh_release(file); usbvision_release(usbvision); - return err_code; + return 0; } mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); - return err_code; + return v4l2_fh_release(file); } /* Video registration stuff */ @@ -1252,7 +1179,6 @@ static const struct v4l2_file_operations usbvision_fops = { .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, .unlocked_ioctl = video_ioctl2, -/* .poll = video_poll, */ }; static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { @@ -1270,17 +1196,15 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1301,23 +1225,19 @@ static const struct v4l2_file_operations usbvision_radio_fops = { .owner = THIS_MODULE, .open = usbvision_radio_open, .release = usbvision_radio_close, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { .vidioc_querycap = vidioc_querycap, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static struct video_device usbvision_radio_template = { @@ -1369,9 +1289,17 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) /* register video4linux devices */ static int usbvision_register_video(struct usb_usbvision *usbvision) { + int res = -ENOMEM; + /* Video Device: */ usbvision_vdev_init(usbvision, &usbvision->vdev, &usbvision_video_template, "USBVision Video"); + if (!usbvision->have_tuner) { + v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_G_FREQUENCY); + v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_S_TUNER); + v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_G_FREQUENCY); + v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_S_TUNER); + } if (video_register_device(&usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0) goto err_exit; printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", @@ -1395,7 +1323,7 @@ static int usbvision_register_video(struct usb_usbvision *usbvision) "USBVision[%d]: video_register_device() failed\n", usbvision->nr); usbvision_unregister_video(usbvision); - return -1; + return res; } /* @@ -1420,6 +1348,9 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev)) goto err_free; + if (v4l2_ctrl_handler_init(&usbvision->hdl, 4)) + goto err_unreg; + usbvision->v4l2_dev.ctrl_handler = &usbvision->hdl; mutex_init(&usbvision->v4l2_lock); /* prepare control urb for control messages during interrupts */ @@ -1428,11 +1359,10 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, goto err_unreg; init_waitqueue_head(&usbvision->ctrl_urb_wq); - usbvision_init_power_off_timer(usbvision); - return usbvision; err_unreg: + v4l2_ctrl_handler_free(&usbvision->hdl); v4l2_device_unregister(&usbvision->v4l2_dev); err_free: kfree(usbvision); @@ -1450,8 +1380,6 @@ static void usbvision_release(struct usb_usbvision *usbvision) { PDEBUG(DBG_PROBE, ""); - usbvision_reset_power_off_timer(usbvision); - usbvision->initialized = 0; usbvision_remove_sysfs(&usbvision->vdev); @@ -1460,6 +1388,7 @@ static void usbvision_release(struct usb_usbvision *usbvision) usb_free_urb(usbvision->ctrl_urb); + v4l2_ctrl_handler_free(&usbvision->hdl); v4l2_device_unregister(&usbvision->v4l2_dev); kfree(usbvision); @@ -1487,19 +1416,18 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) } usbvision->tvnorm_id = usbvision_device_data[model].video_norm; - usbvision->video_inputs = usbvision_device_data[model].video_channels; usbvision->ctl_input = 0; + usbvision->radio_freq = 87.5 * 16000; + usbvision->tv_freq = 400 * 16; /* This should be here to make i2c clients to be able to register */ /* first switch off audio */ if (usbvision_device_data[model].audio_channels > 0) usbvision_audio_off(usbvision); - if (!power_on_at_open) { - /* and then power up the noisy tuner */ - usbvision_power_on(usbvision); - usbvision_i2c_register(usbvision); - } + /* and then power up the tuner */ + usbvision_power_on(usbvision); + usbvision_i2c_register(usbvision); } /* @@ -1592,6 +1520,10 @@ static int usbvision_probe(struct usb_interface *intf, usbvision->nr = usbvision_nr++; + spin_lock_init(&usbvision->queue_lock); + init_waitqueue_head(&usbvision->wait_frame); + init_waitqueue_head(&usbvision->wait_stream); + usbvision->have_tuner = usbvision_device_data[model].tuner; if (usbvision->have_tuner) usbvision->tuner_type = usbvision_device_data[model].tuner_type; @@ -1646,11 +1578,7 @@ static void usbvision_disconnect(struct usb_interface *intf) usbvision_stop_isoc(usbvision); v4l2_device_disconnect(&usbvision->v4l2_dev); - - if (usbvision->power) { - usbvision_i2c_unregister(usbvision); - usbvision_power_off(usbvision); - } + usbvision_i2c_unregister(usbvision); usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ usb_put_dev(usbvision->dev); diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h index 140a1f67566e..4f2e4fde38f2 100644 --- a/drivers/media/usb/usbvision/usbvision.h +++ b/drivers/media/usb/usbvision/usbvision.h @@ -36,6 +36,7 @@ #include <linux/i2c.h> #include <linux/mutex.h> #include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> #include <media/tuner.h> #include <linux/videodev2.h> @@ -357,6 +358,7 @@ extern struct usb_device_id usbvision_table[]; struct usb_usbvision { struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler hdl; struct video_device vdev; /* Video Device */ struct video_device rdev; /* Radio Device */ @@ -376,7 +378,8 @@ struct usb_usbvision { int bridge_type; /* NT1003, NT1004, NT1005 */ int radio; int video_inputs; /* # of inputs */ - unsigned long freq; + unsigned long radio_freq; + unsigned long tv_freq; int audio_mute; int audio_channel; int isoc_mode; /* format of video data for the usb isoc-transfer */ @@ -391,8 +394,6 @@ struct usb_usbvision { unsigned char iface_alt; /* Alt settings */ unsigned char vin_reg2_preset; struct mutex v4l2_lock; - struct timer_list power_off_timer; - struct work_struct power_off_work; int power; /* is the device powered on? */ int user; /* user count for exclusive use */ int initialized; /* Had we already sent init sequence? */ @@ -510,9 +511,6 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); int usbvision_set_input(struct usb_usbvision *usbvision); int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); -void usbvision_init_power_off_timer(struct usb_usbvision *usbvision); -void usbvision_set_power_off_timer(struct usb_usbvision *usbvision); -void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision); int usbvision_power_off(struct usb_usbvision *usbvision); int usbvision_power_on(struct usb_usbvision *usbvision); |