Commit 05439b1a authored by Shuah Khan's avatar Shuah Khan Committed by Mauro Carvalho Chehab
Browse files

[media] media: au0828 - convert to use videobuf2



Convert au0828 to use videobuf2. Tested with NTSC.
Tested video and vbi devices with xawtv, tvtime,
and vlc. Ran v4l2-compliance to ensure there are
no failures.

Video compliance test results summary:
Total: 75, Succeeded: 75, Failed: 0, Warnings: 18

Vbi compliance test results summary:
Total: 75, Succeeded: 75, Failed: 0, Warnings: 0

Signed-off-by: default avatarShuah Khan <shuahkh@osg.samsung.com>
Reviewed-by: default avatarLad, Prabhakar <prabhakar.csengg@gmail.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 9bc1022f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ config VIDEO_AU0828
	depends on I2C && INPUT && DVB_CORE && USB
	select I2C_ALGOBIT
	select VIDEO_TVEEPROM
	select VIDEOBUF_VMALLOC
	select VIDEOBUF2_VMALLOC
	select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT
	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
	select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
+39 −83
Original line number Diff line number Diff line
@@ -28,111 +28,67 @@
#include <linux/init.h>
#include <linux/slab.h>

static unsigned int vbibufs = 5;
module_param(vbibufs, int, 0644);
MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");

/* ------------------------------------------------------------------ */

static void
free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
			   unsigned int *nbuffers, unsigned int *nplanes,
			   unsigned int sizes[], void *alloc_ctxs[])
{
	struct au0828_fh     *fh  = vq->priv_data;
	struct au0828_dev    *dev = fh->dev;
	unsigned long flags = 0;
	if (in_interrupt())
		BUG();
	struct au0828_dev *dev = vb2_get_drv_priv(vq);
	unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
	unsigned long size;

	/* We used to wait for the buffer to finish here, but this didn't work
	   because, as we were keeping the state as VIDEOBUF_QUEUED,
	   videobuf_queue_cancel marked it as finished for us.
	   (Also, it could wedge forever if the hardware was misconfigured.)

	   This should be safe; by the time we get here, the buffer isn't
	   queued anymore. If we ever start marking the buffers as
	   VIDEOBUF_ACTIVE, it won't be, though.
	*/
	spin_lock_irqsave(&dev->slock, flags);
	if (dev->isoc_ctl.vbi_buf == buf)
		dev->isoc_ctl.vbi_buf = NULL;
	spin_unlock_irqrestore(&dev->slock, flags);

	videobuf_vmalloc_free(&buf->vb);
	buf->vb.state = VIDEOBUF_NEEDS_INIT;
}

static int
vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
	struct au0828_fh     *fh  = q->priv_data;
	struct au0828_dev    *dev = fh->dev;
	size = fmt ? (fmt->fmt.vbi.samples_per_line *
		(fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size;
	if (size < img_size)
		return -EINVAL;

	*size = dev->vbi_width * dev->vbi_height * 2;
	*nplanes = 1;
	sizes[0] = size;

	if (0 == *count)
		*count = vbibufs;
	if (*count < 2)
		*count = 2;
	if (*count > 32)
		*count = 32;
	return 0;
}

static int
vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
	    enum v4l2_field field)
static int vbi_buffer_prepare(struct vb2_buffer *vb)
{
	struct au0828_fh     *fh  = q->priv_data;
	struct au0828_dev    *dev = fh->dev;
	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
	int                  rc = 0;
	unsigned long size;

	buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
	size = dev->vbi_width * dev->vbi_height * 2;

	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
	if (vb2_plane_size(vb, 0) < size) {
		pr_err("%s data will not fit into plane (%lu < %lu)\n",
			__func__, vb2_plane_size(vb, 0), size);
		return -EINVAL;

	buf->vb.width  = dev->vbi_width;
	buf->vb.height = dev->vbi_height;
	buf->vb.field  = field;

	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
		rc = videobuf_iolock(q, &buf->vb, NULL);
		if (rc < 0)
			goto fail;
	}
	vb2_set_plane_payload(&buf->vb, 0, size);

	buf->vb.state = VIDEOBUF_PREPARED;
	return 0;

fail:
	free_buffer(q, buf);
	return rc;
}

static void
vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
vbi_buffer_queue(struct vb2_buffer *vb)
{
	struct au0828_buffer    *buf     = container_of(vb,
							struct au0828_buffer,
							vb);
	struct au0828_fh        *fh      = vq->priv_data;
	struct au0828_dev       *dev     = fh->dev;
	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
	struct au0828_dmaqueue *vbiq = &dev->vbiq;
	unsigned long flags = 0;

	buf->vb.state = VIDEOBUF_QUEUED;
	list_add_tail(&buf->vb.queue, &vbiq->active);
}
	buf->mem = vb2_plane_vaddr(vb, 0);
	buf->length = vb2_plane_size(vb, 0);

static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
	free_buffer(q, buf);
	spin_lock_irqsave(&dev->slock, flags);
	list_add_tail(&buf->list, &vbiq->active);
	spin_unlock_irqrestore(&dev->slock, flags);
}

struct videobuf_queue_ops au0828_vbi_qops = {
	.buf_setup    = vbi_setup,
	.buf_prepare  = vbi_prepare,
	.buf_queue    = vbi_queue,
	.buf_release  = vbi_release,
struct vb2_ops au0828_vbi_qops = {
	.queue_setup     = vbi_queue_setup,
	.buf_prepare     = vbi_buffer_prepare,
	.buf_queue       = vbi_buffer_queue,
	.start_streaming = au0828_start_analog_streaming,
	.stop_streaming  = au0828_stop_vbi_streaming,
	.wait_prepare    = vb2_ops_wait_prepare,
	.wait_finish     = vb2_ops_wait_finish,
};
+370 −593

File changed.

Preview size limit exceeded, changes collapsed.

+32 −29
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@

/* Analog */
#include <linux/videodev2.h>
#include <media/videobuf-vmalloc.h>
#include <media/videobuf2-vmalloc.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
@@ -126,17 +126,7 @@ enum au0828_dev_state {
	DEV_MISCONFIGURED = 0x04
};

struct au0828_fh {
	/* must be the first field of this struct! */
	struct v4l2_fh fh;

	struct au0828_dev *dev;
	unsigned int  resources;

	struct videobuf_queue        vb_vidq;
	struct videobuf_queue        vb_vbiq;
	enum v4l2_buf_type           type;
};
struct au0828_dev;

struct au0828_usb_isoc_ctl {
		/* max packet size of isoc transaction */
@@ -177,19 +167,18 @@ struct au0828_usb_isoc_ctl {
/* buffer for one video frame */
struct au0828_buffer {
	/* common v4l buffer stuff -- must be first */
	struct videobuf_buffer vb;
	struct vb2_buffer vb;
	struct list_head list;

	struct list_head frame;
	void *mem;
	unsigned long length;
	int top_field;
	int receiving;
	/* pointer to vmalloc memory address in vb */
	char *vb_buf;
};

struct au0828_dmaqueue {
	struct list_head       active;
	struct list_head       queued;

	wait_queue_head_t          wq;

	/* Counters to control buffer fill */
	int                    pos;
};
@@ -220,14 +209,26 @@ struct au0828_dev {
	struct au0828_rc *ir;
#endif

	int users;
	unsigned int resources;	/* resources in use */
	struct video_device *vdev;
	struct video_device *vbi_dev;

	/* Videobuf2 */
	struct vb2_queue vb_vidq;
	struct vb2_queue vb_vbiq;
	struct mutex vb_queue_lock;
	struct mutex vb_vbi_queue_lock;

	unsigned int frame_count;
	unsigned int vbi_frame_count;

	struct timer_list vid_timeout;
	int vid_timeout_running;
	struct timer_list vbi_timeout;
	int vbi_timeout_running;

	int users;
	int streaming_users;

	int width;
	int height;
	int vbi_width;
@@ -242,7 +243,6 @@ struct au0828_dev {
	__u8 isoc_in_endpointaddr;
	u8 isoc_init_ok;
	int greenscreen_detected;
	unsigned int frame_count;
	int ctrl_freq;
	int input_type;
	int std_set_in_tuner_core;
@@ -277,6 +277,7 @@ struct au0828_dev {
	char *dig_transfer_buffer[URB_COUNT];
};


/* ----------------------------------------------------------- */
#define au0828_read(dev, reg) au0828_readreg(dev, reg)
#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
@@ -309,13 +310,15 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev);

/* ----------------------------------------------------------- */
/* au0828-video.c */
int au0828_analog_register(struct au0828_dev *dev,
extern int au0828_analog_register(struct au0828_dev *dev,
			   struct usb_interface *interface);
int au0828_analog_stream_disable(struct au0828_dev *d);
void au0828_analog_unregister(struct au0828_dev *dev);
extern void au0828_analog_unregister(struct au0828_dev *dev);
extern int au0828_start_analog_streaming(struct vb2_queue *vq,
						unsigned int count);
extern void au0828_stop_vbi_streaming(struct vb2_queue *vq);
#ifdef CONFIG_VIDEO_AU0828_V4L2
void au0828_v4l2_suspend(struct au0828_dev *dev);
void au0828_v4l2_resume(struct au0828_dev *dev);
extern void au0828_v4l2_suspend(struct au0828_dev *dev);
extern void au0828_v4l2_resume(struct au0828_dev *dev);
#else
static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { };
static inline void au0828_v4l2_resume(struct au0828_dev *dev) { };
@@ -329,7 +332,7 @@ void au0828_dvb_suspend(struct au0828_dev *dev);
void au0828_dvb_resume(struct au0828_dev *dev);

/* au0828-vbi.c */
extern struct videobuf_queue_ops au0828_vbi_qops;
extern struct vb2_ops au0828_vbi_qops;

#define dprintk(level, fmt, arg...)\
	do { if (au0828_debug & level)\