#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;
}
/* 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);
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;
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)
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);
}
/* 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;
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;
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);
if (ret)
return ret;
- fh->desc_count--;
+ solo_enc->desc_count--;
}
size -= len;
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;
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;
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;
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
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++;
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 (fh->type != enc_buf->type)
- continue;
-
-
- if (list_empty(&fh->vidq_active))
- continue;
+ if (solo_enc->type != enc_buf->type)
+ goto unlock;
- spin_lock_irqsave(&fh->av_lock, flags);
+ if (list_empty(&solo_enc->vidq_active))
+ goto unlock;
- vb = list_first_entry(&fh->vidq_active,
- struct videobuf_buffer, queue);
+ spin_lock_irqsave(&solo_enc->av_lock, flags);
- list_del(&vb->queue);
- vb->state = VIDEOBUF_ACTIVE;
+ vb = list_first_entry(&solo_enc->vidq_active,
+ struct videobuf_buffer, queue);
- spin_unlock_irqrestore(&fh->av_lock, flags);
+ list_del(&vb->queue);
+ vb->state = VIDEOBUF_ACTIVE;
- 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);
}
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,
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)
{
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;
- }
-
- 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;
+ ret = solo_ring_start(solo_dev);
+ if (ret) {
+ v4l2_fh_release(file);
+ return ret;
}
-
- 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);
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)
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;
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;
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);
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;
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;
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;
}
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)
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)
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;
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;
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;
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)
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;
}
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);
}