diff options
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 75 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 57 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 97 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 18 |
4 files changed, 100 insertions, 147 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index e182abf476c..3c48a72eb7d 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -102,6 +102,9 @@ static void em28xx_audio_isocirq(struct urb *urb) break; } + if (atomic_read(&dev->stream_started) == 0) + return; + if (dev->adev.capture_pcm_substream) { substream = dev->adev.capture_pcm_substream; runtime = substream->runtime; @@ -217,31 +220,6 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) return 0; } -static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) -{ - dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ? - "stop" : "start"); - - switch (cmd) { - case EM28XX_CAPTURE_STREAM_EN: - if (dev->adev.capture_stream == STREAM_OFF && - arg == EM28XX_START_AUDIO) { - dev->adev.capture_stream = STREAM_ON; - em28xx_init_audio_isoc(dev); - } else if (dev->adev.capture_stream == STREAM_ON && - arg == EM28XX_STOP_AUDIO) { - dev->adev.capture_stream = STREAM_OFF; - em28xx_deinit_isoc_audio(dev); - } else { - em28xx_errdev("An underrun very likely occurred. " - "Ignoring it.\n"); - } - return 0; - default: - return -EINVAL; - } -} - static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size) { @@ -303,7 +281,6 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dev->mute = 0; mutex_lock(&dev->lock); ret = em28xx_audio_analog_set(dev); - mutex_unlock(&dev->lock); if (ret < 0) goto err; @@ -311,11 +288,10 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) if (dev->alt == 0 && dev->adev.users == 0) { int errCode; dev->alt = 7; - errCode = usb_set_interface(dev->udev, 0, 7); dprintk("changing alternate number to 7\n"); + errCode = usb_set_interface(dev->udev, 0, 7); } - mutex_lock(&dev->lock); dev->adev.users++; mutex_unlock(&dev->lock); @@ -325,6 +301,8 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) return 0; err: + mutex_unlock(&dev->lock); + em28xx_err("Error while configuring em28xx mixer\n"); return ret; } @@ -338,6 +316,11 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) dev->mute = 1; mutex_lock(&dev->lock); dev->adev.users--; + if (atomic_read(&dev->stream_started) > 0) { + atomic_set(&dev->stream_started, 0); + schedule_work(&dev->wq_trigger); + } + em28xx_audio_analog_set(dev); if (substream->runtime->dma_area) { dprintk("freeing\n"); @@ -375,8 +358,10 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) dprintk("Stop capture, if needed\n"); - if (dev->adev.capture_stream == STREAM_ON) - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO); + if (atomic_read(&dev->stream_started) > 0) { + atomic_set(&dev->stream_started, 0); + schedule_work(&dev->wq_trigger); + } return 0; } @@ -391,31 +376,37 @@ static int snd_em28xx_prepare(struct snd_pcm_substream *substream) return 0; } +static void audio_trigger(struct work_struct *work) +{ + struct em28xx *dev = container_of(work, struct em28xx, wq_trigger); + + if (atomic_read(&dev->stream_started)) { + dprintk("starting capture"); + em28xx_init_audio_isoc(dev); + } else { + dprintk("stopping capture"); + em28xx_deinit_isoc_audio(dev); + } +} + static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct em28xx *dev = snd_pcm_substream_chip(substream); int retval; - dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START) ? - "start" : "stop"); - - spin_lock(&dev->adev.slock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_START_AUDIO); - retval = 0; + atomic_set(&dev->stream_started, 1); break; case SNDRV_PCM_TRIGGER_STOP: - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO); - retval = 0; + atomic_set(&dev->stream_started, 1); break; default: retval = -EINVAL; } - - spin_unlock(&dev->adev.slock); - return retval; + schedule_work(&dev->wq_trigger); + return 0; } static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream @@ -495,6 +486,8 @@ static int em28xx_audio_init(struct em28xx *dev) strcpy(card->shortname, "Em28xx Audio"); strcpy(card->longname, "Empia Em28xx Audio"); + INIT_WORK(&dev->wq_trigger, audio_trigger); + err = snd_card_register(card); if (err < 0) { snd_card_free(card); diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index e7efb4bffab..54859233f31 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -187,6 +187,18 @@ static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = { { -1, -1, -1, -1}, }; +static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = { + {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x00, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { + {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x08, 0xff, 10}, + { -1, -1, -1, -1}, +}; + /* eb1a:2868 Reddo DVB-C USB TV Box GPIO4 - CU1216L NIM Other GPIOs seems to be don't care. */ @@ -781,22 +793,22 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, - .dvb_gpio = default_digital, + .dvb_gpio = terratec_cinergy_USB_XS_FR_digital, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, + .gpio = terratec_cinergy_USB_XS_FR_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, + .gpio = terratec_cinergy_USB_XS_FR_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, + .gpio = terratec_cinergy_USB_XS_FR_analog, } }, }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { @@ -1648,6 +1660,22 @@ struct em28xx_board em28xx_boards[] = { .gpio = terratec_av350_unmute_gpio, } }, }, + + [EM2860_BOARD_ELGATO_VIDEO_CAPTURE] = { + .name = "Elgato Video Capture", + .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, /* Capture only device */ + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, + [EM2882_BOARD_EVGA_INDTUBE] = { .name = "Evga inDtube", .tuner_type = TUNER_XC2028, @@ -1772,6 +1800,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2860_BOARD_TERRATEC_AV350 }, { USB_DEVICE(0x0ccd, 0x0096), .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, + { USB_DEVICE(0x0fd9, 0x0033), + .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, { USB_DEVICE(0x185b, 0x2870), .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE }, { USB_DEVICE(0x185b, 0x2041), @@ -2168,6 +2198,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->demod = XC3028_FE_ZARLINK456; break; case EM2880_BOARD_TERRATEC_HYBRID_XS: + case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: ctl->demod = XC3028_FE_ZARLINK456; break; @@ -2523,39 +2554,39 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->board.has_msp34xx) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "msp3400", "msp3400", 0, msp3400_addrs); + NULL, "msp3400", 0, msp3400_addrs); if (dev->board.decoder == EM28XX_SAA711X) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa7115", "saa7115_auto", 0, saa711x_addrs); + NULL, "saa7115_auto", 0, saa711x_addrs); if (dev->board.decoder == EM28XX_TVP5150) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvp5150", "tvp5150", 0, tvp5150_addrs); + NULL, "tvp5150", 0, tvp5150_addrs); if (dev->em28xx_sensor == EM28XX_MT9V011) { struct v4l2_subdev *sd; sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "mt9v011", "mt9v011", 0, mt9v011_addrs); + &dev->i2c_adap, NULL, "mt9v011", 0, mt9v011_addrs); v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); } if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", "tvaudio", dev->board.tvaudio_addr, NULL); + NULL, "tvaudio", dev->board.tvaudio_addr, NULL); if (dev->board.tuner_type != TUNER_ABSENT) { int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); if (dev->board.radio.type) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->board.radio_addr, NULL); + NULL, "tuner", dev->board.radio_addr, NULL); if (has_demod) v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "tuner", "tuner", + &dev->i2c_adap, NULL, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == 0) { enum v4l2_i2c_tuner_type type = @@ -2563,14 +2594,14 @@ void em28xx_card_setup(struct em28xx *dev) struct v4l2_subdev *sd; sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "tuner", "tuner", + &dev->i2c_adap, NULL, "tuner", 0, v4l2_i2c_tuner_addrs(type)); if (sd) dev->tuner_addr = v4l2_i2c_subdev_addr(sd); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr, NULL); + NULL, "tuner", dev->tuner_addr, NULL); } } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 7b9ec6e493e..908e3bc8830 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -277,12 +277,13 @@ static void em28xx_copy_vbi(struct em28xx *dev, { void *startwrite, *startread; int offset; - int bytesperline = dev->vbi_width; + int bytesperline; if (dev == NULL) { em28xx_isocdbg("dev is null\n"); return; } + bytesperline = dev->vbi_width; if (dma_q == NULL) { em28xx_isocdbg("dma_q is null\n"); @@ -862,17 +863,14 @@ static int res_get(struct em28xx_fh *fh, unsigned int bit) return 1; /* is it free? */ - mutex_lock(&dev->lock); if (dev->resources & bit) { /* no, someone else uses it */ - mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; dev->resources |= bit; em28xx_videodbg("res: get %d\n", bit); - mutex_unlock(&dev->lock); return 1; } @@ -892,11 +890,9 @@ static void res_free(struct em28xx_fh *fh, unsigned int bits) BUG_ON((fh->resources & bits) != bits); - mutex_lock(&dev->lock); fh->resources &= ~bits; dev->resources &= ~bits; em28xx_videodbg("res: put %d\n", bits); - mutex_unlock(&dev->lock); } static int get_ressource(struct em28xx_fh *fh) @@ -1023,8 +1019,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - mutex_lock(&dev->lock); - f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; f->fmt.pix.pixelformat = dev->format->fourcc; @@ -1038,8 +1032,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, else f->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; - - mutex_unlock(&dev->lock); return 0; } @@ -1137,22 +1129,15 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (rc < 0) return rc; - mutex_lock(&dev->lock); - vidioc_try_fmt_vid_cap(file, priv, f); if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); - rc = -EBUSY; - goto out; + return -EBUSY; } - rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, + return em28xx_set_video_format(dev, f->fmt.pix.pixelformat, f->fmt.pix.width, f->fmt.pix.height); - -out: - mutex_unlock(&dev->lock); - return rc; } static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) @@ -1181,7 +1166,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) if (rc < 0) return rc; - mutex_lock(&dev->lock); dev->norm = *norm; /* Adjusts width/height, if needed */ @@ -1197,7 +1181,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) em28xx_resolution_set(dev); v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - mutex_unlock(&dev->lock); return 0; } @@ -1302,9 +1285,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) dev->ctl_input = i; - mutex_lock(&dev->lock); video_mux(dev, dev->ctl_input); - mutex_unlock(&dev->lock); return 0; } @@ -1365,15 +1346,12 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) if (0 == INPUT(a->index)->type) return -EINVAL; - mutex_lock(&dev->lock); - dev->ctl_ainput = INPUT(a->index)->amux; dev->ctl_aoutput = INPUT(a->index)->aout; if (!dev->ctl_aoutput) dev->ctl_aoutput = EM28XX_AOUT_MASTER; - mutex_unlock(&dev->lock); return 0; } @@ -1393,17 +1371,15 @@ static int vidioc_queryctrl(struct file *file, void *priv, qc->id = id; - /* enumberate AC97 controls */ + /* enumerate AC97 controls */ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { rc = ac97_queryctrl(qc); if (!rc) return 0; } - /* enumberate V4L2 device controls */ - mutex_lock(&dev->lock); + /* enumerate V4L2 device controls */ v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); - mutex_unlock(&dev->lock); if (qc->type) return 0; @@ -1423,7 +1399,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return rc; rc = 0; - mutex_lock(&dev->lock); /* Set an AC97 control */ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) @@ -1437,7 +1412,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv, rc = 0; } - mutex_unlock(&dev->lock); return rc; } @@ -1452,8 +1426,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, if (rc < 0) return rc; - mutex_lock(&dev->lock); - /* Set an AC97 control */ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) rc = ac97_set_ctrl(dev, ctrl); @@ -1480,8 +1452,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, rc = em28xx_audio_analog_set(dev); } } - - mutex_unlock(&dev->lock); return rc; } @@ -1502,10 +1472,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, strcpy(t->name, "Tuner"); t->type = V4L2_TUNER_ANALOG_TV; - mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - mutex_unlock(&dev->lock); - return 0; } @@ -1523,10 +1490,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - mutex_unlock(&dev->lock); - return 0; } @@ -1536,11 +1500,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - mutex_lock(&dev->lock); f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; - mutex_unlock(&dev->lock); - return 0; } @@ -1563,13 +1524,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) return -EINVAL; - mutex_lock(&dev->lock); - dev->ctl_freq = f->frequency; v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); - mutex_unlock(&dev->lock); - return 0; } @@ -1610,9 +1567,7 @@ static int vidioc_g_register(struct file *file, void *priv, switch (reg->match.type) { case V4L2_CHIP_MATCH_AC97: - mutex_lock(&dev->lock); ret = em28xx_read_ac97(dev, reg->reg); - mutex_unlock(&dev->lock); if (ret < 0) return ret; @@ -1634,9 +1589,7 @@ static int vidioc_g_register(struct file *file, void *priv, /* Match host */ reg->size = em28xx_reg_len(reg->reg); if (reg->size == 1) { - mutex_lock(&dev->lock); ret = em28xx_read_reg(dev, reg->reg); - mutex_unlock(&dev->lock); if (ret < 0) return ret; @@ -1644,10 +1597,8 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = ret; } else { __le16 val = 0; - mutex_lock(&dev->lock); ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, reg->reg, (char *)&val, 2); - mutex_unlock(&dev->lock); if (ret < 0) return ret; @@ -1663,15 +1614,10 @@ static int vidioc_s_register(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; __le16 buf; - int rc; switch (reg->match.type) { case V4L2_CHIP_MATCH_AC97: - mutex_lock(&dev->lock); - rc = em28xx_write_ac97(dev, reg->reg, reg->val); - mutex_unlock(&dev->lock); - - return rc; + return em28xx_write_ac97(dev, reg->reg, reg->val); case V4L2_CHIP_MATCH_I2C_DRIVER: v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; @@ -1687,12 +1633,8 @@ static int vidioc_s_register(struct file *file, void *priv, /* Match host */ buf = cpu_to_le16(reg->val); - mutex_lock(&dev->lock); - rc = em28xx_write_regs(dev, reg->reg, (char *)&buf, + return em28xx_write_regs(dev, reg->reg, (char *)&buf, em28xx_reg_len(reg->reg)); - mutex_unlock(&dev->lock); - - return rc; } #endif @@ -1829,16 +1771,12 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, if (rc < 0) return rc; - mutex_lock(&dev->lock); - f->fmt.sliced.service_set = 0; v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; - mutex_unlock(&dev->lock); - return rc; } @@ -1853,9 +1791,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, if (rc < 0) return rc; - mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); - mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) return -EINVAL; @@ -2040,9 +1976,7 @@ static int radio_g_tuner(struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - mutex_unlock(&dev->lock); return 0; } @@ -2075,9 +2009,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - mutex_unlock(&dev->lock); return 0; } @@ -2137,8 +2069,6 @@ static int em28xx_v4l2_open(struct file *filp) break; } - mutex_lock(&dev->lock); - em28xx_videodbg("open dev=%s type=%s users=%d\n", video_device_node_name(vdev), v4l2_type_names[fh_type], dev->users); @@ -2147,7 +2077,6 @@ static int em28xx_v4l2_open(struct file *filp) fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); if (!fh) { em28xx_errdev("em28xx-video.c: Out of memory?!\n"); - mutex_unlock(&dev->lock); return -ENOMEM; } fh->dev = dev; @@ -2181,15 +2110,13 @@ static int em28xx_v4l2_open(struct file *filp) videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, field, - sizeof(struct em28xx_buffer), fh); + sizeof(struct em28xx_buffer), fh, &dev->lock); videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, NULL, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, - sizeof(struct em28xx_buffer), fh); - - mutex_unlock(&dev->lock); + sizeof(struct em28xx_buffer), fh, &dev->lock); return errCode; } @@ -2388,7 +2315,7 @@ static const struct v4l2_file_operations em28xx_v4l_fops = { .read = em28xx_v4l2_read, .poll = em28xx_v4l2_poll, .mmap = em28xx_v4l2_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -2496,6 +2423,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; + vfd->lock = &dev->lock; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); @@ -2516,6 +2444,7 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* set default norm */ dev->norm = em28xx_video_template.current_norm; + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); dev->interlaced = EM28XX_INTERLACED_DEFAULT; dev->ctl_input = 0; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 1c61a6b65d2..6a75e6a4fc2 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -25,12 +25,13 @@ #ifndef _EM28XX_H #define _EM28XX_H +#include <linux/workqueue.h> +#include <linux/i2c.h> +#include <linux/mutex.h> #include <linux/videodev2.h> + #include <media/videobuf-vmalloc.h> #include <media/v4l2-device.h> - -#include <linux/i2c.h> -#include <linux/mutex.h> #include <media/ir-kbd-i2c.h> #include <media/ir-core.h> #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) @@ -73,6 +74,7 @@ #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 #define EM2821_BOARD_USBGEAR_VD204 31 #define EM2821_BOARD_SUPERCOMP_USB_2 32 +#define EM2860_BOARD_ELGATO_VIDEO_CAPTURE 33 #define EM2860_BOARD_TERRATEC_HYBRID_XS 34 #define EM2860_BOARD_TYPHOON_DVD_MAKER 35 #define EM2860_BOARD_NETGMBH_CAM 36 @@ -184,11 +186,6 @@ enum em28xx_mode { EM28XX_DIGITAL_MODE, }; -enum em28xx_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; struct em28xx; @@ -463,7 +460,6 @@ struct em28xx_audio { struct snd_card *sndcard; int users; - enum em28xx_stream_state capture_stream; spinlock_t slock; }; @@ -505,6 +501,10 @@ struct em28xx { unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; + /* Controls audio streaming */ + struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ + atomic_t stream_started; /* stream should be running if true */ + struct em28xx_fmt *format; struct em28xx_IR *ir; |