summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/cx25821/cx25821-video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/cx25821/cx25821-video.c')
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c130
1 files changed, 34 insertions, 96 deletions
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index d88316c5f5de..e7a2db158a0e 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -144,48 +144,6 @@ static int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
return 0;
}
-/* resource management */
-static int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
- unsigned int bit)
-{
- dprintk(1, "%s()\n", __func__);
- if (fh->resources & bit)
- /* have it already allocated */
- return 1;
-
- /* is it free? */
- if (dev->channels[fh->channel_id].resources & bit) {
- /* no, someone else uses it */
- return 0;
- }
- /* it's free, grab it */
- fh->resources |= bit;
- dev->channels[fh->channel_id].resources |= bit;
- dprintk(1, "res: get %d\n", bit);
- return 1;
-}
-
-static int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit)
-{
- return fh->resources & bit;
-}
-
-static int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit)
-{
- return fh->dev->channels[fh->channel_id].resources & bit;
-}
-
-static void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
- unsigned int bits)
-{
- BUG_ON((fh->resources & bits) != bits);
- dprintk(1, "%s()\n", __func__);
-
- fh->resources &= ~bits;
- dev->channels[fh->channel_id].resources &= ~bits;
- dprintk(1, "res: put %d\n", bits);
-}
-
static int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
{
struct v4l2_routing route;
@@ -503,11 +461,6 @@ static void cx25821_buffer_release(struct videobuf_queue *q,
cx25821_free_buffer(q, buf);
}
-static int cx25821_get_resource(struct cx25821_fh *fh, int resource)
-{
- return resource;
-}
-
static int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
{
struct cx25821_channel *chan = video_drvdata(file);
@@ -611,15 +564,19 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count,
struct cx25821_fh *fh = file->private_data;
struct cx25821_channel *chan = video_drvdata(file);
struct cx25821_dev *dev = fh->dev;
- int err;
+ int err = 0;
if (mutex_lock_interruptible(&dev->lock))
return -ERESTARTSYS;
- if (cx25821_res_locked(fh, RESOURCE_VIDEO0))
+ if (chan->streaming_fh && chan->streaming_fh != fh) {
err = -EBUSY;
- else
- err = videobuf_read_one(&chan->vidq, data, count, ppos,
+ goto unlock;
+ }
+ chan->streaming_fh = fh;
+
+ err = videobuf_read_one(&chan->vidq, data, count, ppos,
file->f_flags & O_NONBLOCK);
+unlock:
mutex_unlock(&dev->lock);
return err;
}
@@ -627,41 +584,25 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count,
static unsigned int video_poll(struct file *file,
struct poll_table_struct *wait)
{
- struct cx25821_fh *fh = file->private_data;
struct cx25821_channel *chan = video_drvdata(file);
- struct cx25821_buffer *buf;
- if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
- /* streaming capture */
- if (list_empty(&chan->vidq.stream))
- return POLLERR;
- buf = list_entry(chan->vidq.stream.next,
- struct cx25821_buffer, vb.stream);
- } else {
- /* read() capture */
- buf = (struct cx25821_buffer *)chan->vidq.read_buf;
- if (NULL == buf)
- return POLLERR;
- }
+ return videobuf_poll_stream(file, &chan->vidq, wait);
- poll_wait(file, &buf->vb.done, wait);
- if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
- if (buf->vb.state == VIDEOBUF_DONE) {
- struct cx25821_dev *dev = fh->dev;
-
- if (dev && chan->use_cif_resolution) {
- u8 cam_id = *((char *)buf->vb.baddr + 3);
- memcpy((char *)buf->vb.baddr,
- (char *)buf->vb.baddr + (chan->width * 2),
- (chan->width * 2));
- *((char *)buf->vb.baddr + 3) = cam_id;
- }
- }
+ /* This doesn't belong in poll(). This can be done
+ * much better with vb2. We keep this code here as a
+ * reminder.
+ if ((res & POLLIN) && buf->vb.state == VIDEOBUF_DONE) {
+ struct cx25821_dev *dev = chan->dev;
- return POLLIN | POLLRDNORM;
+ if (dev && chan->use_cif_resolution) {
+ u8 cam_id = *((char *)buf->vb.baddr + 3);
+ memcpy((char *)buf->vb.baddr,
+ (char *)buf->vb.baddr + (chan->width * 2),
+ (chan->width * 2));
+ *((char *)buf->vb.baddr + 3) = cam_id;
+ }
}
-
- return 0;
+ */
}
static int video_release(struct file *file)
@@ -677,11 +618,10 @@ static int video_release(struct file *file)
cx_write(sram_ch->dma_ctl, 0); /* FIFO and RISC disable */
/* stop video capture */
- if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+ if (chan->streaming_fh == fh) {
videobuf_queue_cancel(&chan->vidq);
- cx25821_res_free(dev, fh, RESOURCE_VIDEO0);
+ chan->streaming_fh = NULL;
}
- mutex_unlock(&dev->lock);
if (chan->vidq.read_buf) {
cx25821_buffer_release(&chan->vidq, chan->vidq.read_buf);
@@ -689,6 +629,7 @@ static int video_release(struct file *file)
}
videobuf_mmap_free(&chan->vidq);
+ mutex_unlock(&dev->lock);
v4l2_prio_close(&chan->prio, fh->prio);
file->private_data = NULL;
@@ -765,14 +706,13 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct cx25821_channel *chan = video_drvdata(file);
struct cx25821_fh *fh = priv;
- struct cx25821_dev *dev = fh->dev;
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- if (!cx25821_res_get(dev, fh,
- cx25821_get_resource(fh, RESOURCE_VIDEO0)))
+ if (chan->streaming_fh && chan->streaming_fh != fh)
return -EBUSY;
+ chan->streaming_fh = fh;
return videobuf_streamon(&chan->vidq);
}
@@ -781,18 +721,17 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct cx25821_channel *chan = video_drvdata(file);
struct cx25821_fh *fh = priv;
- struct cx25821_dev *dev = fh->dev;
- int err, res;
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- res = cx25821_get_resource(fh, RESOURCE_VIDEO0);
- err = videobuf_streamoff(&chan->vidq);
- if (err < 0)
- return err;
- cx25821_res_free(dev, fh, res);
- return 0;
+ if (chan->streaming_fh && chan->streaming_fh != fh)
+ return -EBUSY;
+ if (chan->streaming_fh == NULL)
+ return 0;
+
+ chan->streaming_fh = NULL;
+ return videobuf_streamoff(&chan->vidq);
}
static int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm)
@@ -1483,7 +1422,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
chan->sram_channels->dma_ctl, 0x11, 0);
chan->sram_channels = &cx25821_sram_channels[i];
- chan->resources = 0;
chan->width = 720;
if (dev->tvnorm & V4L2_STD_625_50)
chan->height = 576;