diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h index 830359f3bb16..413ee10e691e 100644 --- a/drivers/staging/media/solo6x10/solo6x10.h +++ b/drivers/staging/media/solo6x10/solo6x10.h @@ -135,6 +135,11 @@ struct solo_p2m_dev { #define OSD_TEXT_MAX 44 +enum solo_enc_types { + SOLO_ENC_TYPE_STD, + SOLO_ENC_TYPE_EXT, +}; + struct solo_enc_dev { struct solo_dev *solo_dev; /* V4L2 Items */ @@ -163,8 +168,16 @@ struct solo_enc_dev { unsigned char jpeg_header[1024]; int jpeg_len; - /* File handles that are listening for buffers */ - struct list_head listeners; + u32 fmt; + u8 enc_on; + enum solo_enc_types type; + struct videobuf_queue vidq; + struct list_head vidq_active; + int desc_count; + int desc_nelts; + struct solo_p2m_desc *desc_items; + dma_addr_t desc_dma; + spinlock_t av_lock; }; /* The SOLO6x10 PCI Device */ diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c index 7cf3e7b8725f..546a18b31328 100644 --- a/drivers/staging/media/solo6x10/v4l2-enc.c +++ b/drivers/staging/media/solo6x10/v4l2-enc.c @@ -41,27 +41,6 @@ #define MP4_QS 16 #define DMA_ALIGN 4096 -enum solo_enc_types { - SOLO_ENC_TYPE_STD, - SOLO_ENC_TYPE_EXT, -}; - -struct solo_enc_fh { - struct v4l2_fh fh; - struct solo_enc_dev *enc; - u32 fmt; - u8 enc_on; - enum solo_enc_types type; - struct videobuf_queue vidq; - struct list_head vidq_active; - int desc_count; - int desc_nelts; - struct solo_p2m_desc *desc_items; - dma_addr_t desc_dma; - spinlock_t av_lock; - struct list_head list; -}; - struct solo_videobuf { struct videobuf_buffer vb; unsigned int flags; @@ -286,16 +265,15 @@ static void solo_update_mode(struct solo_enc_dev *solo_enc) } /* MUST be called with solo_enc->enable_lock held */ -static int __solo_enc_on(struct solo_enc_fh *fh) +static int __solo_enc_on(struct solo_enc_dev *solo_enc) { - struct solo_enc_dev *solo_enc = fh->enc; u8 ch = solo_enc->ch; struct solo_dev *solo_dev = solo_enc->solo_dev; u8 interval; BUG_ON(!mutex_is_locked(&solo_enc->enable_lock)); - if (fh->enc_on) + if (solo_enc->enc_on) return 0; solo_update_mode(solo_enc); @@ -308,15 +286,14 @@ static int __solo_enc_on(struct solo_enc_fh *fh) solo_dev->enc_bw_remain -= solo_enc->bw_weight; } - fh->enc_on = 1; - list_add(&fh->list, &solo_enc->listeners); + solo_enc->enc_on = 1; - if (fh->type == SOLO_ENC_TYPE_EXT) + if (solo_enc->type == SOLO_ENC_TYPE_EXT) solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1); /* Reset the encoder if we are the first mpeg reader, else only reset * on the first mjpeg reader. */ - if (fh->fmt == V4L2_PIX_FMT_MPEG) { + if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) { atomic_inc(&solo_enc->readers); if (atomic_inc_return(&solo_enc->mpeg_readers) > 1) return 0; @@ -352,32 +329,29 @@ static int __solo_enc_on(struct solo_enc_fh *fh) return 0; } -static int solo_enc_on(struct solo_enc_fh *fh) +static int solo_enc_on(struct solo_enc_dev *solo_enc) { - struct solo_enc_dev *solo_enc = fh->enc; int ret; mutex_lock(&solo_enc->enable_lock); - ret = __solo_enc_on(fh); + ret = __solo_enc_on(solo_enc); mutex_unlock(&solo_enc->enable_lock); return ret; } -static void __solo_enc_off(struct solo_enc_fh *fh) +static void __solo_enc_off(struct solo_enc_dev *solo_enc) { - struct solo_enc_dev *solo_enc = fh->enc; struct solo_dev *solo_dev = solo_enc->solo_dev; BUG_ON(!mutex_is_locked(&solo_enc->enable_lock)); - if (!fh->enc_on) + if (!solo_enc->enc_on) return; - list_del(&fh->list); - fh->enc_on = 0; + solo_enc->enc_on = 0; - if (fh->fmt == V4L2_PIX_FMT_MPEG) + if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) atomic_dec(&solo_enc->mpeg_readers); if (atomic_dec_return(&solo_enc->readers) > 0) @@ -389,12 +363,10 @@ static void __solo_enc_off(struct solo_enc_fh *fh) solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0); } -static void solo_enc_off(struct solo_enc_fh *fh) +static void solo_enc_off(struct solo_enc_dev *solo_enc) { - struct solo_enc_dev *solo_enc = fh->enc; - mutex_lock(&solo_enc->enable_lock); - __solo_enc_off(fh); + __solo_enc_off(solo_enc); mutex_unlock(&solo_enc->enable_lock); } @@ -430,11 +402,11 @@ static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma, /* Build a descriptor queue out of an SG list and send it to the P2M for * processing. */ -static int solo_send_desc(struct solo_enc_fh *fh, int skip, +static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip, struct videobuf_dmabuf *vbuf, int off, int size, unsigned int base, unsigned int base_size) { - struct solo_dev *solo_dev = fh->enc->solo_dev; + struct solo_dev *solo_dev = solo_enc->solo_dev; struct scatterlist *sg; int i; int ret; @@ -442,7 +414,7 @@ static int solo_send_desc(struct solo_enc_fh *fh, int skip, if (WARN_ON_ONCE(size > FRAME_BUF_SIZE)) return -EINVAL; - fh->desc_count = 1; + solo_enc->desc_count = 1; for_each_sg(vbuf->sglist, sg, vbuf->sglen, i) { struct solo_p2m_desc *desc; @@ -450,7 +422,7 @@ static int solo_send_desc(struct solo_enc_fh *fh, int skip, int len; int left = base_size - off; - desc = &fh->desc_items[fh->desc_count++]; + desc = &solo_enc->desc_items[solo_enc->desc_count++]; dma = sg_dma_address(sg); len = sg_dma_len(sg); @@ -486,7 +458,7 @@ static int solo_send_desc(struct solo_enc_fh *fh, int skip, if (ret) return ret; - fh->desc_count--; + solo_enc->desc_count--; } size -= len; @@ -498,27 +470,26 @@ static int solo_send_desc(struct solo_enc_fh *fh, int skip, off -= base_size; /* Because we may use two descriptors per loop */ - if (fh->desc_count >= (fh->desc_nelts - 1)) { - ret = solo_p2m_dma_desc(solo_dev, fh->desc_items, - fh->desc_dma, - fh->desc_count - 1); + if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) { + ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items, + solo_enc->desc_dma, + solo_enc->desc_count - 1); if (ret) return ret; - fh->desc_count = 1; + solo_enc->desc_count = 1; } } - if (fh->desc_count <= 1) + if (solo_enc->desc_count <= 1) return 0; - return solo_p2m_dma_desc(solo_dev, fh->desc_items, fh->desc_dma, - fh->desc_count - 1); + return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items, solo_enc->desc_dma, + solo_enc->desc_count - 1); } -static int solo_fill_jpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb, +static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, struct videobuf_buffer *vb, struct videobuf_dmabuf *vbuf, struct vop_header *vh) { - struct solo_enc_dev *solo_enc = fh->enc; struct solo_dev *solo_dev = solo_enc->solo_dev; struct solo_videobuf *svb = (struct solo_videobuf *)vb; int frame_size; @@ -539,15 +510,14 @@ static int solo_fill_jpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb, frame_size = (vh->jpeg_size + solo_enc->jpeg_len + (DMA_ALIGN - 1)) & ~(DMA_ALIGN - 1); - return solo_send_desc(fh, solo_enc->jpeg_len, vbuf, vh->jpeg_off, + return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, vh->jpeg_off, frame_size, SOLO_JPEG_EXT_ADDR(solo_dev), SOLO_JPEG_EXT_SIZE(solo_dev)); } -static int solo_fill_mpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb, +static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct videobuf_buffer *vb, struct videobuf_dmabuf *vbuf, struct vop_header *vh) { - struct solo_enc_dev *solo_enc = fh->enc; struct solo_dev *solo_dev = solo_enc->solo_dev; struct solo_videobuf *svb = (struct solo_videobuf *)vb; int frame_off, frame_size; @@ -580,16 +550,15 @@ static int solo_fill_mpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb, frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1)) & ~(DMA_ALIGN - 1); - return solo_send_desc(fh, skip, vbuf, frame_off, frame_size, + return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size, SOLO_MP4E_EXT_ADDR(solo_dev), SOLO_MP4E_EXT_SIZE(solo_dev)); } -static int solo_enc_fillbuf(struct solo_enc_fh *fh, +static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, struct videobuf_buffer *vb, struct solo_enc_buf *enc_buf) { - struct solo_enc_dev *solo_enc = fh->enc; struct solo_videobuf *svb = (struct solo_videobuf *)vb; struct videobuf_dmabuf *vbuf = NULL; struct vop_header *vh = enc_buf->vh; @@ -613,10 +582,10 @@ static int solo_enc_fillbuf(struct solo_enc_fh *fh, svb->flags |= V4L2_BUF_FLAG_MOTION_DETECTED; } - if (fh->fmt == V4L2_PIX_FMT_MPEG) - ret = solo_fill_mpeg(fh, vb, vbuf, vh); + if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) + ret = solo_fill_mpeg(solo_enc, vb, vbuf, vh); else - ret = solo_fill_jpeg(fh, vb, vbuf, vh); + ret = solo_fill_jpeg(solo_enc, vb, vbuf, vh); vbuf_error: /* On error, we push this buffer back into the queue. The @@ -625,10 +594,10 @@ static int solo_enc_fillbuf(struct solo_enc_fh *fh, if (ret) { unsigned long flags; - spin_lock_irqsave(&fh->av_lock, flags); - list_add(&vb->queue, &fh->vidq_active); + spin_lock_irqsave(&solo_enc->av_lock, flags); + list_add(&vb->queue, &solo_enc->vidq_active); vb->state = VIDEOBUF_QUEUED; - spin_unlock_irqrestore(&fh->av_lock, flags); + spin_unlock_irqrestore(&solo_enc->av_lock, flags); } else { vb->state = VIDEOBUF_DONE; vb->field_count++; @@ -644,34 +613,29 @@ static int solo_enc_fillbuf(struct solo_enc_fh *fh, static void solo_enc_handle_one(struct solo_enc_dev *solo_enc, struct solo_enc_buf *enc_buf) { - struct solo_enc_fh *fh; + struct videobuf_buffer *vb; + unsigned long flags; mutex_lock(&solo_enc->enable_lock); - list_for_each_entry(fh, &solo_enc->listeners, list) { - struct videobuf_buffer *vb; - unsigned long flags; + if (solo_enc->type != enc_buf->type) + goto unlock; - if (fh->type != enc_buf->type) - continue; + if (list_empty(&solo_enc->vidq_active)) + goto unlock; + spin_lock_irqsave(&solo_enc->av_lock, flags); - if (list_empty(&fh->vidq_active)) - continue; + vb = list_first_entry(&solo_enc->vidq_active, + struct videobuf_buffer, queue); - spin_lock_irqsave(&fh->av_lock, flags); + list_del(&vb->queue); + vb->state = VIDEOBUF_ACTIVE; - vb = list_first_entry(&fh->vidq_active, - struct videobuf_buffer, queue); - - list_del(&vb->queue); - vb->state = VIDEOBUF_ACTIVE; - - spin_unlock_irqrestore(&fh->av_lock, flags); - - solo_enc_fillbuf(fh, vb, enc_buf); - } + spin_unlock_irqrestore(&solo_enc->av_lock, flags); + solo_enc_fillbuf(solo_enc, vb, enc_buf); +unlock: mutex_unlock(&solo_enc->enable_lock); } @@ -799,10 +763,10 @@ static int solo_enc_buf_prepare(struct videobuf_queue *vq, static void solo_enc_buf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct solo_enc_fh *fh = vq->priv_data; + struct solo_enc_dev *solo_enc = vq->priv_data; vb->state = VIDEOBUF_QUEUED; - list_add_tail(&vb->queue, &fh->vidq_active); + list_add_tail(&vb->queue, &solo_enc->vidq_active); } static void solo_enc_buf_release(struct videobuf_queue *vq, @@ -824,20 +788,20 @@ static const struct videobuf_queue_ops solo_enc_video_qops = { static unsigned int solo_enc_poll(struct file *file, struct poll_table_struct *wait) { - struct solo_enc_fh *fh = file->private_data; + struct solo_enc_dev *solo_enc = video_drvdata(file); unsigned long req_events = poll_requested_events(wait); unsigned res = v4l2_ctrl_poll(file, wait); if (!(req_events & (POLLIN | POLLRDNORM))) return res; - return videobuf_poll_stream(file, &fh->vidq, wait); + return videobuf_poll_stream(file, &solo_enc->vidq, wait); } static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma) { - struct solo_enc_fh *fh = file->private_data; + struct solo_enc_dev *solo_enc = video_drvdata(file); - return videobuf_mmap_mapper(&fh->vidq, vma); + return videobuf_mmap_mapper(&solo_enc->vidq, vma); } static int solo_ring_start(struct solo_dev *solo_dev) @@ -875,91 +839,50 @@ static int solo_enc_open(struct file *file) { struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; - struct solo_enc_fh *fh; - int ret; + int ret = v4l2_fh_open(file); - ret = solo_ring_start(solo_dev); if (ret) return ret; - - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (fh == NULL) { - solo_ring_stop(solo_dev); - return -ENOMEM; + ret = solo_ring_start(solo_dev); + if (ret) { + v4l2_fh_release(file); + return ret; } - - fh->desc_nelts = 32; - fh->desc_items = pci_alloc_consistent(solo_dev->pdev, - sizeof(struct solo_p2m_desc) * - fh->desc_nelts, &fh->desc_dma); - if (fh->desc_items == NULL) { - kfree(fh); - solo_ring_stop(solo_dev); - return -ENOMEM; - } - - v4l2_fh_init(&fh->fh, video_devdata(file)); - fh->enc = solo_enc; - spin_lock_init(&fh->av_lock); - file->private_data = fh; - INIT_LIST_HEAD(&fh->vidq_active); - fh->fmt = V4L2_PIX_FMT_MPEG; - fh->type = SOLO_ENC_TYPE_STD; - - videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops, - &solo_dev->pdev->dev, - &fh->av_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct solo_videobuf), - fh, NULL); - v4l2_fh_add(&fh->fh); return 0; } static ssize_t solo_enc_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - struct solo_enc_fh *fh = file->private_data; + struct solo_enc_dev *solo_enc = video_drvdata(file); int ret; /* Make sure the encoder is on */ - ret = solo_enc_on(fh); + ret = solo_enc_on(solo_enc); if (ret) return ret; - return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, + return videobuf_read_stream(&solo_enc->vidq, data, count, ppos, 0, file->f_flags & O_NONBLOCK); } static int solo_enc_release(struct file *file) { - struct solo_enc_fh *fh = file->private_data; - struct solo_dev *solo_dev = fh->enc->solo_dev; - - solo_enc_off(fh); - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - - videobuf_stop(&fh->vidq); - videobuf_mmap_free(&fh->vidq); - - pci_free_consistent(fh->enc->solo_dev->pdev, - sizeof(struct solo_p2m_desc) * - fh->desc_nelts, fh->desc_items, fh->desc_dma); - - kfree(fh); + struct solo_enc_dev *solo_enc = video_drvdata(file); + struct solo_dev *solo_dev = solo_enc->solo_dev; + solo_enc_off(solo_enc); + videobuf_stop(&solo_enc->vidq); + videobuf_mmap_free(&solo_enc->vidq); solo_ring_stop(solo_dev); - return 0; + return v4l2_fh_release(file); } static int solo_enc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; strcpy(cap->driver, SOLO6X10_NAME); @@ -976,8 +899,7 @@ static int solo_enc_querycap(struct file *file, void *priv, static int solo_enc_enum_input(struct file *file, void *priv, struct v4l2_input *input) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; if (input->index) @@ -1039,8 +961,7 @@ static int solo_enc_enum_fmt_cap(struct file *file, void *priv, static int solo_enc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; struct v4l2_pix_format *pix = &f->fmt.pix; @@ -1081,8 +1002,7 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv, static int solo_enc_set_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; struct v4l2_pix_format *pix = &f->fmt.pix; int ret; @@ -1110,10 +1030,10 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv, solo_enc->mode = SOLO_ENC_MODE_CIF; /* This does not change the encoder at all */ - fh->fmt = pix->pixelformat; + solo_enc->fmt = pix->pixelformat; if (pix->priv) - fh->type = SOLO_ENC_TYPE_EXT; + solo_enc->type = SOLO_ENC_TYPE_EXT; mutex_unlock(&solo_enc->enable_lock); @@ -1123,13 +1043,12 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv, static int solo_enc_get_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct v4l2_pix_format *pix = &f->fmt.pix; pix->width = solo_enc->width; pix->height = solo_enc->height; - pix->pixelformat = fh->fmt; + pix->pixelformat = solo_enc->fmt; pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; pix->sizeimage = FRAME_BUF_SIZE; @@ -1142,45 +1061,45 @@ static int solo_enc_get_fmt_cap(struct file *file, void *priv, static int solo_enc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *req) { - struct solo_enc_fh *fh = priv; + struct solo_enc_dev *solo_enc = video_drvdata(file); - return videobuf_reqbufs(&fh->vidq, req); + return videobuf_reqbufs(&solo_enc->vidq, req); } static int solo_enc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct solo_enc_fh *fh = priv; + struct solo_enc_dev *solo_enc = video_drvdata(file); - return videobuf_querybuf(&fh->vidq, buf); + return videobuf_querybuf(&solo_enc->vidq, buf); } static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct solo_enc_fh *fh = priv; + struct solo_enc_dev *solo_enc = video_drvdata(file); - return videobuf_qbuf(&fh->vidq, buf); + return videobuf_qbuf(&solo_enc->vidq, buf); } static int solo_enc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct solo_enc_fh *fh = priv; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_videobuf *svb; int ret; /* Make sure the encoder is on */ - ret = solo_enc_on(fh); + ret = solo_enc_on(solo_enc); if (ret) return ret; - ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK); + ret = videobuf_dqbuf(&solo_enc->vidq, buf, file->f_flags & O_NONBLOCK); if (ret) return ret; /* Copy over the flags */ - svb = (struct solo_videobuf *)fh->vidq.bufs[buf->index]; + svb = (struct solo_videobuf *)solo_enc->vidq.bufs[buf->index]; buf->flags |= svb->flags; return 0; @@ -1189,26 +1108,26 @@ static int solo_enc_dqbuf(struct file *file, void *priv, static int solo_enc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct solo_enc_fh *fh = priv; + struct solo_enc_dev *solo_enc = video_drvdata(file); if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - return videobuf_streamon(&fh->vidq); + return videobuf_streamon(&solo_enc->vidq); } static int solo_enc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct solo_enc_fh *fh = priv; + struct solo_enc_dev *solo_enc = video_drvdata(file); int ret; if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = videobuf_streamoff(&fh->vidq); + ret = videobuf_streamoff(&solo_enc->vidq); if (!ret) - solo_enc_off(fh); + solo_enc_off(solo_enc); return ret; } @@ -1221,8 +1140,8 @@ static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id i) static int solo_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct solo_enc_fh *fh = priv; - struct solo_dev *solo_dev = fh->enc->solo_dev; + struct solo_enc_dev *solo_enc = video_drvdata(file); + struct solo_dev *solo_dev = solo_enc->solo_dev; if (fsize->pixel_format != V4L2_PIX_FMT_MPEG && fsize->pixel_format != V4L2_PIX_FMT_MJPEG) @@ -1249,8 +1168,8 @@ static int solo_enum_framesizes(struct file *file, void *priv, static int solo_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fintv) { - struct solo_enc_fh *fh = priv; - struct solo_dev *solo_dev = fh->enc->solo_dev; + struct solo_enc_dev *solo_enc = video_drvdata(file); + struct solo_dev *solo_dev = solo_enc->solo_dev; if (fintv->pixel_format != V4L2_PIX_FMT_MPEG && fintv->pixel_format != V4L2_PIX_FMT_MJPEG) @@ -1280,8 +1199,7 @@ static int solo_enum_frameintervals(struct file *file, void *priv, static int solo_g_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; struct v4l2_captureparm *cp = &sp->parm.capture; @@ -1298,8 +1216,7 @@ static int solo_g_parm(struct file *file, void *priv, static int solo_s_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) { - struct solo_enc_fh *fh = priv; - struct solo_enc_dev *solo_enc = fh->enc; + struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; struct v4l2_captureparm *cp = &sp->parm.capture; @@ -1512,45 +1429,17 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL); if (hdl->error) { ret = hdl->error; - v4l2_ctrl_handler_free(hdl); - kfree(solo_enc); - return ERR_PTR(ret); - } - - solo_enc->vfd = video_device_alloc(); - if (!solo_enc->vfd) { - v4l2_ctrl_handler_free(hdl); - kfree(solo_enc); - return ERR_PTR(-ENOMEM); + goto hdl_free; } solo_enc->solo_dev = solo_dev; solo_enc->ch = ch; - - *solo_enc->vfd = solo_enc_template; - solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev; - solo_enc->vfd->ctrl_handler = hdl; - set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags); - ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr); - if (ret < 0) { - video_device_release(solo_enc->vfd); - v4l2_ctrl_handler_free(hdl); - kfree(solo_enc); - return ERR_PTR(ret); - } - - video_set_drvdata(solo_enc->vfd, solo_enc); - - snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name), - "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num, - solo_enc->vfd->num); - - INIT_LIST_HEAD(&solo_enc->listeners); - mutex_init(&solo_enc->enable_lock); - spin_lock_init(&solo_enc->motion_lock); + spin_lock_init(&solo_enc->av_lock); + INIT_LIST_HEAD(&solo_enc->vidq_active); + solo_enc->fmt = V4L2_PIX_FMT_MPEG; + solo_enc->type = SOLO_ENC_TYPE_STD; atomic_set(&solo_enc->readers, 0); - atomic_set(&solo_enc->mpeg_readers, 0); solo_enc->qp = SOLO_DEFAULT_QP; solo_enc->gop = solo_dev->fps; @@ -1558,15 +1447,65 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, solo_enc->mode = SOLO_ENC_MODE_CIF; solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH; - mutex_lock(&solo_enc->enable_lock); + spin_lock(&solo_enc->av_lock); solo_update_mode(solo_enc); - mutex_unlock(&solo_enc->enable_lock); + spin_unlock(&solo_enc->av_lock); + + mutex_init(&solo_enc->enable_lock); + spin_lock_init(&solo_enc->motion_lock); + + atomic_set(&solo_enc->readers, 0); + atomic_set(&solo_enc->mpeg_readers, 0); /* Initialize this per encoder */ solo_enc->jpeg_len = sizeof(jpeg_header); memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len); + solo_enc->desc_nelts = 32; + solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev, + sizeof(struct solo_p2m_desc) * + solo_enc->desc_nelts, &solo_enc->desc_dma); + ret = -ENOMEM; + if (solo_enc->desc_items == NULL) + goto hdl_free; + + videobuf_queue_sg_init(&solo_enc->vidq, &solo_enc_video_qops, + &solo_dev->pdev->dev, + &solo_enc->av_lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct solo_videobuf), + solo_enc, NULL); + + solo_enc->vfd = video_device_alloc(); + if (!solo_enc->vfd) + goto pci_free; + + *solo_enc->vfd = solo_enc_template; + solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev; + solo_enc->vfd->ctrl_handler = hdl; + set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags); + video_set_drvdata(solo_enc->vfd, solo_enc); + ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr); + if (ret < 0) + goto vdev_release; + + snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name), + "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num, + solo_enc->vfd->num); + return solo_enc; + +vdev_release: + video_device_release(solo_enc->vfd); +pci_free: + pci_free_consistent(solo_enc->solo_dev->pdev, + sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts, + solo_enc->desc_items, solo_enc->desc_dma); +hdl_free: + v4l2_ctrl_handler_free(hdl); + kfree(solo_enc); + return ERR_PTR(ret); } static void solo_enc_free(struct solo_enc_dev *solo_enc) @@ -1605,6 +1544,7 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr) solo_enc_free(solo_dev->v4l2_enc[i]); pci_free_consistent(solo_dev->pdev, solo_dev->vh_size, solo_dev->vh_buf, solo_dev->vh_dma); + solo_dev->vh_buf = NULL; return ret; } @@ -1627,6 +1567,7 @@ void solo_enc_v4l2_exit(struct solo_dev *solo_dev) for (i = 0; i < solo_dev->nr_chans; i++) solo_enc_free(solo_dev->v4l2_enc[i]); - pci_free_consistent(solo_dev->pdev, solo_dev->vh_size, + if (solo_dev->vh_buf) + pci_free_consistent(solo_dev->pdev, solo_dev->vh_size, solo_dev->vh_buf, solo_dev->vh_dma); }