Commit ffcc1c08 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] go7007: convert to core locking and vb2

Convert this driver to videobuf2 and core locking.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 899eb84c
...@@ -2,7 +2,7 @@ config VIDEO_GO7007 ...@@ -2,7 +2,7 @@ config VIDEO_GO7007
tristate "WIS GO7007 MPEG encoder support" tristate "WIS GO7007 MPEG encoder support"
depends on VIDEO_DEV && PCI && I2C depends on VIDEO_DEV && PCI && I2C
depends on SND depends on SND
select VIDEOBUF_DMA_SG select VIDEOBUF2_VMALLOC
depends on RC_CORE depends on RC_CORE
select VIDEO_TUNER select VIDEO_TUNER
select VIDEO_TVEEPROM select VIDEO_TVEEPROM
......
...@@ -363,48 +363,54 @@ int go7007_start_encoder(struct go7007 *go) ...@@ -363,48 +363,54 @@ int go7007_start_encoder(struct go7007 *go)
/* /*
* Store a byte in the current video buffer, if there is one. * Store a byte in the current video buffer, if there is one.
*/ */
static inline void store_byte(struct go7007_buffer *gobuf, u8 byte) static inline void store_byte(struct go7007_buffer *vb, u8 byte)
{ {
if (gobuf != NULL && gobuf->bytesused < GO7007_BUF_SIZE) { if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
unsigned int pgidx = gobuf->offset >> PAGE_SHIFT; u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
unsigned int pgoff = gobuf->offset & ~PAGE_MASK;
*((u8 *)page_address(gobuf->pages[pgidx]) + pgoff) = byte; ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
++gobuf->offset;
++gobuf->bytesused;
} }
} }
/* /*
* Deliver the last video buffer and get a new one to start writing to. * Deliver the last video buffer and get a new one to start writing to.
*/ */
static void frame_boundary(struct go7007 *go) static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
{ {
struct go7007_buffer *gobuf; struct go7007_buffer *vb_tmp = NULL;
u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
int i; int i;
if (go->active_buf) { if (vb) {
if (go->active_buf->modet_active) { if (vb->modet_active) {
if (go->active_buf->bytesused + 216 < GO7007_BUF_SIZE) { if (*bytesused + 216 < GO7007_BUF_SIZE) {
for (i = 0; i < 216; ++i) for (i = 0; i < 216; ++i)
store_byte(go->active_buf, store_byte(vb, go->active_map[i]);
go->active_map[i]); *bytesused -= 216;
go->active_buf->bytesused -= 216;
} else } else
go->active_buf->modet_active = 0; vb->modet_active = 0;
} }
go->active_buf->state = BUF_STATE_DONE; vb->vb.v4l2_buf.sequence = go->next_seq++;
wake_up_interruptible(&go->frame_waitq); v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
go->active_buf = NULL; vb_tmp = vb;
} spin_lock(&go->spinlock);
list_for_each_entry(gobuf, &go->stream, stream) list_del(&vb->list);
if (gobuf->state == BUF_STATE_QUEUED) { if (list_empty(&go->vidq_active))
gobuf->seq = go->next_seq; vb = NULL;
do_gettimeofday(&gobuf->timestamp); else
go->active_buf = gobuf; vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
break; go->active_buf = vb;
spin_unlock(&go->spinlock);
vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
return vb;
} }
++go->next_seq; spin_lock(&go->spinlock);
if (!list_empty(&go->vidq_active))
vb = go->active_buf =
list_first_entry(&go->vidq_active, struct go7007_buffer, list);
spin_unlock(&go->spinlock);
go->next_seq++;
return vb;
} }
static void write_bitmap_word(struct go7007 *go) static void write_bitmap_word(struct go7007 *go)
...@@ -428,10 +434,9 @@ static void write_bitmap_word(struct go7007 *go) ...@@ -428,10 +434,9 @@ static void write_bitmap_word(struct go7007 *go)
*/ */
void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
{ {
struct go7007_buffer *vb = go->active_buf;
int i, seq_start_code = -1, frame_start_code = -1; int i, seq_start_code = -1, frame_start_code = -1;
spin_lock(&go->spinlock);
switch (go->format) { switch (go->format) {
case V4L2_PIX_FMT_MPEG4: case V4L2_PIX_FMT_MPEG4:
seq_start_code = 0xB0; seq_start_code = 0xB0;
...@@ -445,13 +450,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -445,13 +450,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
} }
for (i = 0; i < length; ++i) { for (i = 0; i < length; ++i) {
if (go->active_buf != NULL && if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) {
v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
go->active_buf->offset -= go->active_buf->bytesused; vb->vb.v4l2_planes[0].bytesused = 0;
go->active_buf->bytesused = 0; vb->frame_offset = 0;
go->active_buf->modet_active = 0; vb->modet_active = 0;
go->active_buf = NULL; vb = go->active_buf = NULL;
} }
switch (go->state) { switch (go->state) {
...@@ -464,7 +468,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -464,7 +468,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
go->state = STATE_FF; go->state = STATE_FF;
break; break;
default: default:
store_byte(go->active_buf, buf[i]); store_byte(vb, buf[i]);
break; break;
} }
break; break;
...@@ -474,12 +478,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -474,12 +478,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
go->state = STATE_00_00; go->state = STATE_00_00;
break; break;
case 0xFF: case 0xFF:
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
go->state = STATE_FF; go->state = STATE_FF;
break; break;
default: default:
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, buf[i]); store_byte(vb, buf[i]);
go->state = STATE_DATA; go->state = STATE_DATA;
break; break;
} }
...@@ -487,21 +491,21 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -487,21 +491,21 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
case STATE_00_00: case STATE_00_00:
switch (buf[i]) { switch (buf[i]) {
case 0x00: case 0x00:
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
/* go->state remains STATE_00_00 */ /* go->state remains STATE_00_00 */
break; break;
case 0x01: case 0x01:
go->state = STATE_00_00_01; go->state = STATE_00_00_01;
break; break;
case 0xFF: case 0xFF:
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
go->state = STATE_FF; go->state = STATE_FF;
break; break;
default: default:
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, buf[i]); store_byte(vb, buf[i]);
go->state = STATE_DATA; go->state = STATE_DATA;
break; break;
} }
...@@ -509,10 +513,10 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -509,10 +513,10 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
case STATE_00_00_01: case STATE_00_00_01:
if (buf[i] == 0xF8 && go->modet_enable == 0) { if (buf[i] == 0xF8 && go->modet_enable == 0) {
/* MODET start code, but MODET not enabled */ /* MODET start code, but MODET not enabled */
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x01); store_byte(vb, 0x01);
store_byte(go->active_buf, 0xF8); store_byte(vb, 0xF8);
go->state = STATE_DATA; go->state = STATE_DATA;
break; break;
} }
...@@ -524,16 +528,11 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -524,16 +528,11 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
(buf[i] == seq_start_code || (buf[i] == seq_start_code ||
buf[i] == 0xB8 || /* GOP code */ buf[i] == 0xB8 || /* GOP code */
buf[i] == frame_start_code)) { buf[i] == frame_start_code)) {
if (go->active_buf == NULL || go->seen_frame) if (vb == NULL || go->seen_frame)
frame_boundary(go); vb = frame_boundary(go, vb);
if (buf[i] == frame_start_code) { go->seen_frame = buf[i] == frame_start_code;
if (go->active_buf != NULL) if (vb && go->seen_frame)
go->active_buf->frame_offset = vb->frame_offset = vb->vb.v4l2_planes[0].bytesused;
go->active_buf->offset;
go->seen_frame = 1;
} else {
go->seen_frame = 0;
}
} }
/* Handle any special chunk types, or just write the /* Handle any special chunk types, or just write the
* start code to the (potentially new) buffer */ * start code to the (potentially new) buffer */
...@@ -552,16 +551,16 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -552,16 +551,16 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
go->state = STATE_MODET_MAP; go->state = STATE_MODET_MAP;
break; break;
case 0xFF: /* Potential JPEG start code */ case 0xFF: /* Potential JPEG start code */
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x01); store_byte(vb, 0x01);
go->state = STATE_FF; go->state = STATE_FF;
break; break;
default: default:
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x00); store_byte(vb, 0x00);
store_byte(go->active_buf, 0x01); store_byte(vb, 0x01);
store_byte(go->active_buf, buf[i]); store_byte(vb, buf[i]);
go->state = STATE_DATA; go->state = STATE_DATA;
break; break;
} }
...@@ -569,20 +568,20 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -569,20 +568,20 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
case STATE_FF: case STATE_FF:
switch (buf[i]) { switch (buf[i]) {
case 0x00: case 0x00:
store_byte(go->active_buf, 0xFF); store_byte(vb, 0xFF);
go->state = STATE_00; go->state = STATE_00;
break; break;
case 0xFF: case 0xFF:
store_byte(go->active_buf, 0xFF); store_byte(vb, 0xFF);
/* go->state remains STATE_FF */ /* go->state remains STATE_FF */
break; break;
case 0xD8: case 0xD8:
if (go->format == V4L2_PIX_FMT_MJPEG) if (go->format == V4L2_PIX_FMT_MJPEG)
frame_boundary(go); vb = frame_boundary(go, vb);
/* fall through */ /* fall through */
default: default:
store_byte(go->active_buf, 0xFF); store_byte(vb, 0xFF);
store_byte(go->active_buf, buf[i]); store_byte(vb, buf[i]);
go->state = STATE_DATA; go->state = STATE_DATA;
break; break;
} }
...@@ -605,8 +604,8 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -605,8 +604,8 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
write_bitmap_word(go); write_bitmap_word(go);
} else } else
go->modet_word = buf[i] << 8; go->modet_word = buf[i] << 8;
} else if (go->parse_length == 207 && go->active_buf) { } else if (go->parse_length == 207 && vb) {
go->active_buf->modet_active = buf[i]; vb->modet_active = buf[i];
} }
if (++go->parse_length == 208) if (++go->parse_length == 208)
go->state = STATE_DATA; go->state = STATE_DATA;
...@@ -617,8 +616,6 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) ...@@ -617,8 +616,6 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
break; break;
} }
} }
spin_unlock(&go->spinlock);
} }
EXPORT_SYMBOL(go7007_parse_video_stream); EXPORT_SYMBOL(go7007_parse_video_stream);
...@@ -648,14 +645,12 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) ...@@ -648,14 +645,12 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
go->i2c_adapter_online = 0; go->i2c_adapter_online = 0;
go->interrupt_available = 0; go->interrupt_available = 0;
init_waitqueue_head(&go->interrupt_waitq); init_waitqueue_head(&go->interrupt_waitq);
go->in_use = 0;
go->input = 0; go->input = 0;
go7007_update_board(go); go7007_update_board(go);
go->encoder_h_halve = 0; go->encoder_h_halve = 0;
go->encoder_v_halve = 0; go->encoder_v_halve = 0;
go->encoder_subsample = 0; go->encoder_subsample = 0;
go->format = V4L2_PIX_FMT_MJPEG; go->format = V4L2_PIX_FMT_MJPEG;
go->streaming = 0;
go->bitrate = 1500000; go->bitrate = 1500000;
go->fps_scale = 1; go->fps_scale = 1;
go->pali = 0; go->pali = 0;
...@@ -674,7 +669,6 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) ...@@ -674,7 +669,6 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
go->modet_map[i] = 0; go->modet_map[i] = 0;
go->audio_deliver = NULL; go->audio_deliver = NULL;
go->audio_enabled = 0; go->audio_enabled = 0;
INIT_LIST_HEAD(&go->stream);
return go; return go;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h> #include <media/v4l2-fh.h>
#include <media/videobuf2-core.h>
struct go7007; struct go7007;
...@@ -125,20 +126,10 @@ struct go7007_hpi_ops { ...@@ -125,20 +126,10 @@ struct go7007_hpi_ops {
#define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) #define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT)
struct go7007_buffer { struct go7007_buffer {
struct go7007 *go; /* Reverse reference for VMA ops */ struct vb2_buffer vb;
int index; /* Reverse reference for DQBUF */ struct list_head list;
enum { BUF_STATE_IDLE, BUF_STATE_QUEUED, BUF_STATE_DONE } state;
u32 seq;
struct timeval timestamp;
struct list_head stream;
struct page *pages[GO7007_BUF_PAGES + 1]; /* extra for straddling */
unsigned long user_addr;
unsigned int page_count;
unsigned int offset;
unsigned int bytesused;
unsigned int frame_offset; unsigned int frame_offset;
u32 modet_active; u32 modet_active;
int mapped;
}; };
#define GO7007_RATIO_1_1 0 #define GO7007_RATIO_1_1 0
...@@ -178,8 +169,7 @@ struct go7007 { ...@@ -178,8 +169,7 @@ struct go7007 {
enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
spinlock_t spinlock; spinlock_t spinlock;
struct mutex hw_lock; struct mutex hw_lock;
int streaming; struct mutex serialize_lock;
int in_use;
int audio_enabled; int audio_enabled;
struct v4l2_subdev *sd_video; struct v4l2_subdev *sd_video;
struct v4l2_subdev *sd_audio; struct v4l2_subdev *sd_audio;
...@@ -226,17 +216,16 @@ struct go7007 { ...@@ -226,17 +216,16 @@ struct go7007 {
unsigned char active_map[216]; unsigned char active_map[216];
/* Video streaming */ /* Video streaming */
struct go7007_buffer *active_buf; struct mutex queue_lock;
struct vb2_queue vidq;
enum go7007_parser_state state; enum go7007_parser_state state;
int parse_length; int parse_length;
u16 modet_word; u16 modet_word;
int seen_frame; int seen_frame;
u32 next_seq; u32 next_seq;
struct list_head stream; struct list_head vidq_active;
wait_queue_head_t frame_waitq; wait_queue_head_t frame_waitq;
int buf_count; struct go7007_buffer *active_buf;
struct go7007_buffer *bufs;
struct v4l2_fh *bufs_owner;
/* Audio streaming */ /* Audio streaming */
void (*audio_deliver)(struct go7007 *go, u8 *buf, int length); void (*audio_deliver)(struct go7007 *go, u8 *buf, int length);
......
...@@ -780,7 +780,7 @@ static void go7007_usb_read_video_pipe_complete(struct urb *urb) ...@@ -780,7 +780,7 @@ static void go7007_usb_read_video_pipe_complete(struct urb *urb)
struct go7007 *go = (struct go7007 *)urb->context; struct go7007 *go = (struct go7007 *)urb->context;
int r, status = urb->status; int r, status = urb->status;
if (!go->streaming) { if (!vb2_is_streaming(&go->vidq)) {
wake_up_interruptible(&go->frame_waitq); wake_up_interruptible(&go->frame_waitq);
return; return;
} }
...@@ -804,7 +804,7 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb) ...@@ -804,7 +804,7 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
struct go7007 *go = (struct go7007 *)urb->context; struct go7007 *go = (struct go7007 *)urb->context;
int r, status = urb->status; int r, status = urb->status;
if (!go->streaming) if (!vb2_is_streaming(&go->vidq))
return; return;
if (status) { if (status) {
printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n",
...@@ -1316,12 +1316,17 @@ static void go7007_usb_disconnect(struct usb_interface *intf) ...@@ -1316,12 +1316,17 @@ static void go7007_usb_disconnect(struct usb_interface *intf)
{ {
struct go7007 *go = to_go7007(usb_get_intfdata(intf)); struct go7007 *go = to_go7007(usb_get_intfdata(intf));
mutex_lock(&go->queue_lock);
mutex_lock(&go->serialize_lock);
if (go->audio_enabled) if (go->audio_enabled)
go7007_snd_remove(go); go7007_snd_remove(go);
go->status = STATUS_SHUTDOWN; go->status = STATUS_SHUTDOWN;
v4l2_device_disconnect(&go->v4l2_dev); v4l2_device_disconnect(&go->v4l2_dev);
video_unregister_device(go->video_dev); video_unregister_device(go->video_dev);
mutex_unlock(&go->serialize_lock);
mutex_unlock(&go->queue_lock);
v4l2_device_put(&go->v4l2_dev); v4l2_device_put(&go->v4l2_dev);
} }
......
This diff is collapsed.
...@@ -236,7 +236,7 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev, ...@@ -236,7 +236,7 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
struct go7007 *go = video_get_drvdata(dev->empress_dev); struct go7007 *go = video_get_drvdata(dev->empress_dev);
struct saa7134_go7007 *saa = go->hpi_context; struct saa7134_go7007 *saa = go->hpi_context;
if (!go->streaming) if (!vb2_is_streaming(&go->vidq))
return; return;
if (0 != (status & 0x000f0000)) if (0 != (status & 0x000f0000))
printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment