diff options
-rw-r--r-- | drivers/staging/media/solo6x10/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/media/solo6x10/solo6x10.h | 7 | ||||
-rw-r--r-- | drivers/staging/media/solo6x10/v4l2-enc.c | 12 | ||||
-rw-r--r-- | drivers/staging/media/solo6x10/v4l2.c | 289 |
4 files changed, 103 insertions, 207 deletions
diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig index f93b4cab9cc7..ec32776ff547 100644 --- a/drivers/staging/media/solo6x10/Kconfig +++ b/drivers/staging/media/solo6x10/Kconfig | |||
@@ -1,8 +1,8 @@ | |||
1 | config SOLO6X10 | 1 | config SOLO6X10 |
2 | tristate "Softlogic 6x10 MPEG codec cards" | 2 | tristate "Softlogic 6x10 MPEG codec cards" |
3 | depends on PCI && VIDEO_DEV && SND && I2C | 3 | depends on PCI && VIDEO_DEV && SND && I2C |
4 | select VIDEOBUF_DMA_SG | ||
5 | select VIDEOBUF2_DMA_SG | 4 | select VIDEOBUF2_DMA_SG |
5 | select VIDEOBUF2_DMA_CONTIG | ||
6 | select SND_PCM | 6 | select SND_PCM |
7 | ---help--- | 7 | ---help--- |
8 | This driver supports the Softlogic based MPEG-4 and h.264 codec | 8 | This driver supports the Softlogic based MPEG-4 and h.264 codec |
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h index d18093fac2b2..518166271acf 100644 --- a/drivers/staging/media/solo6x10/solo6x10.h +++ b/drivers/staging/media/solo6x10/solo6x10.h | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <media/v4l2-dev.h> | 39 | #include <media/v4l2-dev.h> |
40 | #include <media/v4l2-device.h> | 40 | #include <media/v4l2-device.h> |
41 | #include <media/v4l2-ctrls.h> | 41 | #include <media/v4l2-ctrls.h> |
42 | #include <media/videobuf-core.h> | ||
43 | #include <media/videobuf2-core.h> | 42 | #include <media/videobuf2-core.h> |
44 | 43 | ||
45 | #include "registers.h" | 44 | #include "registers.h" |
@@ -259,8 +258,6 @@ struct solo_dev { | |||
259 | /* Ring thread */ | 258 | /* Ring thread */ |
260 | struct task_struct *ring_thread; | 259 | struct task_struct *ring_thread; |
261 | wait_queue_head_t ring_thread_wait; | 260 | wait_queue_head_t ring_thread_wait; |
262 | atomic_t enc_users; | ||
263 | atomic_t disp_users; | ||
264 | 261 | ||
265 | /* VOP_HEADER handling */ | 262 | /* VOP_HEADER handling */ |
266 | void *vh_buf; | 263 | void *vh_buf; |
@@ -268,8 +265,10 @@ struct solo_dev { | |||
268 | int vh_size; | 265 | int vh_size; |
269 | 266 | ||
270 | /* Buffer handling */ | 267 | /* Buffer handling */ |
271 | struct videobuf_queue vidq; | 268 | struct vb2_queue vidq; |
269 | struct vb2_alloc_ctx *alloc_ctx; | ||
272 | struct task_struct *kthread; | 270 | struct task_struct *kthread; |
271 | struct mutex lock; | ||
273 | spinlock_t slock; | 272 | spinlock_t slock; |
274 | int old_write; | 273 | int old_write; |
275 | struct list_head vidq_active; | 274 | struct list_head vidq_active; |
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c index d7d96ce1006d..4dda6ecfea60 100644 --- a/drivers/staging/media/solo6x10/v4l2-enc.c +++ b/drivers/staging/media/solo6x10/v4l2-enc.c | |||
@@ -41,11 +41,6 @@ | |||
41 | #define MP4_QS 16 | 41 | #define MP4_QS 16 |
42 | #define DMA_ALIGN 4096 | 42 | #define DMA_ALIGN 4096 |
43 | 43 | ||
44 | struct solo_videobuf { | ||
45 | struct videobuf_buffer vb; | ||
46 | unsigned int flags; | ||
47 | }; | ||
48 | |||
49 | /* 6010 M4V */ | 44 | /* 6010 M4V */ |
50 | static unsigned char vop_6010_ntsc_d1[] = { | 45 | static unsigned char vop_6010_ntsc_d1[] = { |
51 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, | 46 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, |
@@ -672,9 +667,6 @@ static void solo_enc_buf_queue(struct vb2_buffer *vb) | |||
672 | 667 | ||
673 | static int solo_ring_start(struct solo_dev *solo_dev) | 668 | static int solo_ring_start(struct solo_dev *solo_dev) |
674 | { | 669 | { |
675 | if (atomic_inc_return(&solo_dev->enc_users) > 1) | ||
676 | return 0; | ||
677 | |||
678 | solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev, | 670 | solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev, |
679 | SOLO6X10_NAME "_ring"); | 671 | SOLO6X10_NAME "_ring"); |
680 | if (IS_ERR(solo_dev->ring_thread)) { | 672 | if (IS_ERR(solo_dev->ring_thread)) { |
@@ -690,9 +682,6 @@ static int solo_ring_start(struct solo_dev *solo_dev) | |||
690 | 682 | ||
691 | static void solo_ring_stop(struct solo_dev *solo_dev) | 683 | static void solo_ring_stop(struct solo_dev *solo_dev) |
692 | { | 684 | { |
693 | if (atomic_dec_return(&solo_dev->enc_users) > 0) | ||
694 | return; | ||
695 | |||
696 | if (solo_dev->ring_thread) { | 685 | if (solo_dev->ring_thread) { |
697 | kthread_stop(solo_dev->ring_thread); | 686 | kthread_stop(solo_dev->ring_thread); |
698 | solo_dev->ring_thread = NULL; | 687 | solo_dev->ring_thread = NULL; |
@@ -1279,7 +1268,6 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
1279 | { | 1268 | { |
1280 | int i; | 1269 | int i; |
1281 | 1270 | ||
1282 | atomic_set(&solo_dev->enc_users, 0); | ||
1283 | init_waitqueue_head(&solo_dev->ring_thread_wait); | 1271 | init_waitqueue_head(&solo_dev->ring_thread_wait); |
1284 | 1272 | ||
1285 | solo_dev->vh_size = sizeof(struct vop_header); | 1273 | solo_dev->vh_size = sizeof(struct vop_header); |
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c index 13b7640d8cac..d38a8fe8962d 100644 --- a/drivers/staging/media/solo6x10/v4l2.c +++ b/drivers/staging/media/solo6x10/v4l2.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <media/v4l2-ioctl.h> | 30 | #include <media/v4l2-ioctl.h> |
31 | #include <media/v4l2-common.h> | 31 | #include <media/v4l2-common.h> |
32 | #include <media/v4l2-event.h> | 32 | #include <media/v4l2-event.h> |
33 | #include <media/videobuf-dma-contig.h> | 33 | #include <media/videobuf2-dma-contig.h> |
34 | 34 | ||
35 | #include "solo6x10.h" | 35 | #include "solo6x10.h" |
36 | #include "tw28.h" | 36 | #include "tw28.h" |
@@ -192,19 +192,19 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch) | |||
192 | } | 192 | } |
193 | 193 | ||
194 | static void solo_fillbuf(struct solo_dev *solo_dev, | 194 | static void solo_fillbuf(struct solo_dev *solo_dev, |
195 | struct videobuf_buffer *vb) | 195 | struct vb2_buffer *vb) |
196 | { | 196 | { |
197 | dma_addr_t vbuf; | 197 | dma_addr_t vbuf; |
198 | unsigned int fdma_addr; | 198 | unsigned int fdma_addr; |
199 | int error = -1; | 199 | int error = -1; |
200 | int i; | 200 | int i; |
201 | 201 | ||
202 | vbuf = videobuf_to_dma_contig(vb); | 202 | vbuf = vb2_dma_contig_plane_dma_addr(vb, 0); |
203 | if (!vbuf) | 203 | if (!vbuf) |
204 | goto finish_buf; | 204 | goto finish_buf; |
205 | 205 | ||
206 | if (erase_off(solo_dev)) { | 206 | if (erase_off(solo_dev)) { |
207 | void *p = videobuf_queue_to_vaddr(&solo_dev->vidq, vb); | 207 | void *p = vb2_plane_vaddr(vb, 0); |
208 | int image_size = solo_image_size(solo_dev); | 208 | int image_size = solo_image_size(solo_dev); |
209 | for (i = 0; i < image_size; i += 2) { | 209 | for (i = 0; i < image_size; i += 2) { |
210 | ((u8 *)p)[i] = 0x80; | 210 | ((u8 *)p)[i] = 0x80; |
@@ -221,19 +221,19 @@ static void solo_fillbuf(struct solo_dev *solo_dev, | |||
221 | } | 221 | } |
222 | 222 | ||
223 | finish_buf: | 223 | finish_buf: |
224 | if (error) { | 224 | if (!error) { |
225 | vb->state = VIDEOBUF_ERROR; | 225 | vb2_set_plane_payload(vb, 0, |
226 | } else { | 226 | solo_vlines(solo_dev) * solo_bytesperline(solo_dev)); |
227 | vb->state = VIDEOBUF_DONE; | 227 | vb->v4l2_buf.sequence++; |
228 | vb->field_count++; | 228 | v4l2_get_timestamp(&vb->v4l2_buf.timestamp); |
229 | } | 229 | } |
230 | 230 | ||
231 | wake_up(&vb->done); | 231 | vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); |
232 | } | 232 | } |
233 | 233 | ||
234 | static void solo_thread_try(struct solo_dev *solo_dev) | 234 | static void solo_thread_try(struct solo_dev *solo_dev) |
235 | { | 235 | { |
236 | struct videobuf_buffer *vb; | 236 | struct solo_vb2_buf *vb; |
237 | 237 | ||
238 | /* Only "break" from this loop if slock is held, otherwise | 238 | /* Only "break" from this loop if slock is held, otherwise |
239 | * just return. */ | 239 | * just return. */ |
@@ -250,19 +250,15 @@ static void solo_thread_try(struct solo_dev *solo_dev) | |||
250 | if (list_empty(&solo_dev->vidq_active)) | 250 | if (list_empty(&solo_dev->vidq_active)) |
251 | break; | 251 | break; |
252 | 252 | ||
253 | vb = list_first_entry(&solo_dev->vidq_active, struct videobuf_buffer, | 253 | vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf, |
254 | queue); | 254 | list); |
255 | |||
256 | if (!waitqueue_active(&vb->done)) | ||
257 | break; | ||
258 | 255 | ||
259 | solo_dev->old_write = cur_write; | 256 | solo_dev->old_write = cur_write; |
260 | list_del(&vb->queue); | 257 | list_del(&vb->list); |
261 | vb->state = VIDEOBUF_ACTIVE; | ||
262 | 258 | ||
263 | spin_unlock(&solo_dev->slock); | 259 | spin_unlock(&solo_dev->slock); |
264 | 260 | ||
265 | solo_fillbuf(solo_dev, vb); | 261 | solo_fillbuf(solo_dev, &vb->vb); |
266 | } | 262 | } |
267 | 263 | ||
268 | assert_spin_locked(&solo_dev->slock); | 264 | assert_spin_locked(&solo_dev->slock); |
@@ -294,15 +290,14 @@ static int solo_start_thread(struct solo_dev *solo_dev) | |||
294 | { | 290 | { |
295 | int ret = 0; | 291 | int ret = 0; |
296 | 292 | ||
297 | if (atomic_inc_return(&solo_dev->disp_users) == 1) | ||
298 | solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN); | ||
299 | |||
300 | solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp"); | 293 | solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp"); |
301 | 294 | ||
302 | if (IS_ERR(solo_dev->kthread)) { | 295 | if (IS_ERR(solo_dev->kthread)) { |
303 | ret = PTR_ERR(solo_dev->kthread); | 296 | ret = PTR_ERR(solo_dev->kthread); |
304 | solo_dev->kthread = NULL; | 297 | solo_dev->kthread = NULL; |
298 | return ret; | ||
305 | } | 299 | } |
300 | solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN); | ||
306 | 301 | ||
307 | return ret; | 302 | return ret; |
308 | } | 303 | } |
@@ -312,116 +307,65 @@ static void solo_stop_thread(struct solo_dev *solo_dev) | |||
312 | if (!solo_dev->kthread) | 307 | if (!solo_dev->kthread) |
313 | return; | 308 | return; |
314 | 309 | ||
310 | solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN); | ||
315 | kthread_stop(solo_dev->kthread); | 311 | kthread_stop(solo_dev->kthread); |
316 | solo_dev->kthread = NULL; | 312 | solo_dev->kthread = NULL; |
317 | |||
318 | if (atomic_dec_return(&solo_dev->disp_users) == 0) | ||
319 | solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN); | ||
320 | } | 313 | } |
321 | 314 | ||
322 | static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count, | 315 | static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
323 | unsigned int *size) | 316 | unsigned int *num_buffers, unsigned int *num_planes, |
317 | unsigned int sizes[], void *alloc_ctxs[]) | ||
324 | { | 318 | { |
325 | struct solo_dev *solo_dev = vq->priv_data; | 319 | struct solo_dev *solo_dev = vb2_get_drv_priv(q); |
326 | 320 | ||
327 | *size = solo_image_size(solo_dev); | 321 | sizes[0] = solo_image_size(solo_dev); |
322 | alloc_ctxs[0] = solo_dev->alloc_ctx; | ||
323 | *num_planes = 1; | ||
328 | 324 | ||
329 | if (*count < MIN_VID_BUFFERS) | 325 | if (*num_buffers < MIN_VID_BUFFERS) |
330 | *count = MIN_VID_BUFFERS; | 326 | *num_buffers = MIN_VID_BUFFERS; |
331 | 327 | ||
332 | return 0; | 328 | return 0; |
333 | } | 329 | } |
334 | 330 | ||
335 | static int solo_buf_prepare(struct videobuf_queue *vq, | 331 | static int solo_start_streaming(struct vb2_queue *q, unsigned int count) |
336 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
337 | { | 332 | { |
338 | struct solo_dev *solo_dev = vq->priv_data; | 333 | struct solo_dev *solo_dev = vb2_get_drv_priv(q); |
339 | 334 | ||
340 | vb->size = solo_image_size(solo_dev); | 335 | return solo_start_thread(solo_dev); |
341 | if (vb->baddr != 0 && vb->bsize < vb->size) | 336 | } |
342 | return -EINVAL; | ||
343 | 337 | ||
344 | /* XXX: These properties only change when queue is idle */ | 338 | static int solo_stop_streaming(struct vb2_queue *q) |
345 | vb->width = solo_dev->video_hsize; | 339 | { |
346 | vb->height = solo_vlines(solo_dev); | 340 | struct solo_dev *solo_dev = vb2_get_drv_priv(q); |
347 | vb->bytesperline = solo_bytesperline(solo_dev); | ||
348 | vb->field = field; | ||
349 | |||
350 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | ||
351 | int rc = videobuf_iolock(vq, vb, NULL); | ||
352 | if (rc < 0) { | ||
353 | videobuf_dma_contig_free(vq, vb); | ||
354 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
355 | return rc; | ||
356 | } | ||
357 | } | ||
358 | vb->state = VIDEOBUF_PREPARED; | ||
359 | 341 | ||
342 | solo_stop_thread(solo_dev); | ||
343 | INIT_LIST_HEAD(&solo_dev->vidq_active); | ||
360 | return 0; | 344 | return 0; |
361 | } | 345 | } |
362 | 346 | ||
363 | static void solo_buf_queue(struct videobuf_queue *vq, | 347 | static void solo_buf_queue(struct vb2_buffer *vb) |
364 | struct videobuf_buffer *vb) | ||
365 | { | 348 | { |
366 | struct solo_dev *solo_dev = vq->priv_data; | 349 | struct vb2_queue *vq = vb->vb2_queue; |
350 | struct solo_dev *solo_dev = vb2_get_drv_priv(vq); | ||
351 | struct solo_vb2_buf *solo_vb = | ||
352 | container_of(vb, struct solo_vb2_buf, vb); | ||
367 | 353 | ||
368 | vb->state = VIDEOBUF_QUEUED; | 354 | spin_lock(&solo_dev->slock); |
369 | list_add_tail(&vb->queue, &solo_dev->vidq_active); | 355 | list_add_tail(&solo_vb->list, &solo_dev->vidq_active); |
356 | spin_unlock(&solo_dev->slock); | ||
370 | wake_up_interruptible(&solo_dev->disp_thread_wait); | 357 | wake_up_interruptible(&solo_dev->disp_thread_wait); |
371 | } | 358 | } |
372 | 359 | ||
373 | static void solo_buf_release(struct videobuf_queue *vq, | 360 | static const struct vb2_ops solo_video_qops = { |
374 | struct videobuf_buffer *vb) | 361 | .queue_setup = solo_queue_setup, |
375 | { | ||
376 | videobuf_dma_contig_free(vq, vb); | ||
377 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
378 | } | ||
379 | |||
380 | static const struct videobuf_queue_ops solo_video_qops = { | ||
381 | .buf_setup = solo_buf_setup, | ||
382 | .buf_prepare = solo_buf_prepare, | ||
383 | .buf_queue = solo_buf_queue, | 362 | .buf_queue = solo_buf_queue, |
384 | .buf_release = solo_buf_release, | 363 | .start_streaming = solo_start_streaming, |
364 | .stop_streaming = solo_stop_streaming, | ||
365 | .wait_prepare = vb2_ops_wait_prepare, | ||
366 | .wait_finish = vb2_ops_wait_finish, | ||
385 | }; | 367 | }; |
386 | 368 | ||
387 | static unsigned int solo_v4l2_poll(struct file *file, | ||
388 | struct poll_table_struct *wait) | ||
389 | { | ||
390 | struct solo_dev *solo_dev = video_drvdata(file); | ||
391 | unsigned long req_events = poll_requested_events(wait); | ||
392 | unsigned res = v4l2_ctrl_poll(file, wait); | ||
393 | |||
394 | if (!(req_events & (POLLIN | POLLRDNORM))) | ||
395 | return res; | ||
396 | return res | videobuf_poll_stream(file, &solo_dev->vidq, wait); | ||
397 | } | ||
398 | |||
399 | static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
400 | { | ||
401 | struct solo_dev *solo_dev = video_drvdata(file); | ||
402 | |||
403 | return videobuf_mmap_mapper(&solo_dev->vidq, vma); | ||
404 | } | ||
405 | |||
406 | static ssize_t solo_v4l2_read(struct file *file, char __user *data, | ||
407 | size_t count, loff_t *ppos) | ||
408 | { | ||
409 | struct solo_dev *solo_dev = video_drvdata(file); | ||
410 | |||
411 | return videobuf_read_stream(&solo_dev->vidq, data, count, ppos, 0, | ||
412 | file->f_flags & O_NONBLOCK); | ||
413 | } | ||
414 | |||
415 | static int solo_v4l2_release(struct file *file) | ||
416 | { | ||
417 | struct solo_dev *solo_dev = video_drvdata(file); | ||
418 | |||
419 | solo_stop_thread(solo_dev); | ||
420 | videobuf_stop(&solo_dev->vidq); | ||
421 | videobuf_mmap_free(&solo_dev->vidq); | ||
422 | return v4l2_fh_release(file); | ||
423 | } | ||
424 | |||
425 | static int solo_querycap(struct file *file, void *priv, | 369 | static int solo_querycap(struct file *file, void *priv, |
426 | struct v4l2_capability *cap) | 370 | struct v4l2_capability *cap) |
427 | { | 371 | { |
@@ -550,7 +494,7 @@ static int solo_set_fmt_cap(struct file *file, void *priv, | |||
550 | { | 494 | { |
551 | struct solo_dev *solo_dev = video_drvdata(file); | 495 | struct solo_dev *solo_dev = video_drvdata(file); |
552 | 496 | ||
553 | if (videobuf_queue_is_busy(&solo_dev->vidq)) | 497 | if (vb2_is_busy(&solo_dev->vidq)) |
554 | return -EBUSY; | 498 | return -EBUSY; |
555 | 499 | ||
556 | /* For right now, if it doesn't match our running config, | 500 | /* For right now, if it doesn't match our running config, |
@@ -576,61 +520,6 @@ static int solo_get_fmt_cap(struct file *file, void *priv, | |||
576 | return 0; | 520 | return 0; |
577 | } | 521 | } |
578 | 522 | ||
579 | static int solo_reqbufs(struct file *file, void *priv, | ||
580 | struct v4l2_requestbuffers *req) | ||
581 | { | ||
582 | struct solo_dev *solo_dev = video_drvdata(file); | ||
583 | |||
584 | return videobuf_reqbufs(&solo_dev->vidq, req); | ||
585 | } | ||
586 | |||
587 | static int solo_querybuf(struct file *file, void *priv, | ||
588 | struct v4l2_buffer *buf) | ||
589 | { | ||
590 | struct solo_dev *solo_dev = video_drvdata(file); | ||
591 | |||
592 | return videobuf_querybuf(&solo_dev->vidq, buf); | ||
593 | } | ||
594 | |||
595 | static int solo_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
596 | { | ||
597 | struct solo_dev *solo_dev = video_drvdata(file); | ||
598 | |||
599 | return videobuf_qbuf(&solo_dev->vidq, buf); | ||
600 | } | ||
601 | |||
602 | static int solo_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
603 | { | ||
604 | struct solo_dev *solo_dev = video_drvdata(file); | ||
605 | |||
606 | return videobuf_dqbuf(&solo_dev->vidq, buf, file->f_flags & O_NONBLOCK); | ||
607 | } | ||
608 | |||
609 | static int solo_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
610 | { | ||
611 | struct solo_dev *solo_dev = video_drvdata(file); | ||
612 | int ret; | ||
613 | |||
614 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
615 | return -EINVAL; | ||
616 | |||
617 | ret = solo_start_thread(solo_dev); | ||
618 | if (ret) | ||
619 | return ret; | ||
620 | |||
621 | return videobuf_streamon(&solo_dev->vidq); | ||
622 | } | ||
623 | |||
624 | static int solo_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
625 | { | ||
626 | struct solo_dev *solo_dev = video_drvdata(file); | ||
627 | |||
628 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
629 | return -EINVAL; | ||
630 | |||
631 | return videobuf_streamoff(&solo_dev->vidq); | ||
632 | } | ||
633 | |||
634 | static int solo_s_std(struct file *file, void *priv, v4l2_std_id i) | 523 | static int solo_s_std(struct file *file, void *priv, v4l2_std_id i) |
635 | { | 524 | { |
636 | return 0; | 525 | return 0; |
@@ -668,11 +557,11 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl) | |||
668 | static const struct v4l2_file_operations solo_v4l2_fops = { | 557 | static const struct v4l2_file_operations solo_v4l2_fops = { |
669 | .owner = THIS_MODULE, | 558 | .owner = THIS_MODULE, |
670 | .open = v4l2_fh_open, | 559 | .open = v4l2_fh_open, |
671 | .release = solo_v4l2_release, | 560 | .release = vb2_fop_release, |
672 | .read = solo_v4l2_read, | 561 | .read = vb2_fop_read, |
673 | .poll = solo_v4l2_poll, | 562 | .poll = vb2_fop_poll, |
674 | .mmap = solo_v4l2_mmap, | 563 | .mmap = vb2_fop_mmap, |
675 | .ioctl = video_ioctl2, | 564 | .unlocked_ioctl = video_ioctl2, |
676 | }; | 565 | }; |
677 | 566 | ||
678 | static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = { | 567 | static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = { |
@@ -688,12 +577,12 @@ static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = { | |||
688 | .vidioc_s_fmt_vid_cap = solo_set_fmt_cap, | 577 | .vidioc_s_fmt_vid_cap = solo_set_fmt_cap, |
689 | .vidioc_g_fmt_vid_cap = solo_get_fmt_cap, | 578 | .vidioc_g_fmt_vid_cap = solo_get_fmt_cap, |
690 | /* Streaming I/O */ | 579 | /* Streaming I/O */ |
691 | .vidioc_reqbufs = solo_reqbufs, | 580 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
692 | .vidioc_querybuf = solo_querybuf, | 581 | .vidioc_querybuf = vb2_ioctl_querybuf, |
693 | .vidioc_qbuf = solo_qbuf, | 582 | .vidioc_qbuf = vb2_ioctl_qbuf, |
694 | .vidioc_dqbuf = solo_dqbuf, | 583 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
695 | .vidioc_streamon = solo_streamon, | 584 | .vidioc_streamon = vb2_ioctl_streamon, |
696 | .vidioc_streamoff = solo_streamoff, | 585 | .vidioc_streamoff = vb2_ioctl_streamoff, |
697 | /* Logging and events */ | 586 | /* Logging and events */ |
698 | .vidioc_log_status = v4l2_ctrl_log_status, | 587 | .vidioc_log_status = v4l2_ctrl_log_status, |
699 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | 588 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, |
@@ -729,8 +618,10 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
729 | int ret; | 618 | int ret; |
730 | int i; | 619 | int i; |
731 | 620 | ||
732 | atomic_set(&solo_dev->disp_users, 0); | ||
733 | init_waitqueue_head(&solo_dev->disp_thread_wait); | 621 | init_waitqueue_head(&solo_dev->disp_thread_wait); |
622 | spin_lock_init(&solo_dev->slock); | ||
623 | mutex_init(&solo_dev->lock); | ||
624 | INIT_LIST_HEAD(&solo_dev->vidq_active); | ||
734 | 625 | ||
735 | solo_dev->vfd = video_device_alloc(); | 626 | solo_dev->vfd = video_device_alloc(); |
736 | if (!solo_dev->vfd) | 627 | if (!solo_dev->vfd) |
@@ -738,24 +629,37 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
738 | 629 | ||
739 | *solo_dev->vfd = solo_v4l2_template; | 630 | *solo_dev->vfd = solo_v4l2_template; |
740 | solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev; | 631 | solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev; |
632 | solo_dev->vfd->queue = &solo_dev->vidq; | ||
633 | solo_dev->vfd->lock = &solo_dev->lock; | ||
741 | v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1); | 634 | v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1); |
742 | v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL); | 635 | v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL); |
743 | if (solo_dev->disp_hdl.error) | 636 | if (solo_dev->disp_hdl.error) { |
744 | return solo_dev->disp_hdl.error; | 637 | ret = solo_dev->disp_hdl.error; |
638 | goto fail; | ||
639 | } | ||
745 | solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl; | 640 | solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl; |
746 | set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags); | 641 | set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags); |
747 | 642 | ||
748 | video_set_drvdata(solo_dev->vfd, solo_dev); | 643 | video_set_drvdata(solo_dev->vfd, solo_dev); |
749 | 644 | ||
750 | spin_lock_init(&solo_dev->slock); | 645 | solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
751 | INIT_LIST_HEAD(&solo_dev->vidq_active); | 646 | solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; |
752 | 647 | solo_dev->vidq.ops = &solo_video_qops; | |
753 | videobuf_queue_dma_contig_init(&solo_dev->vidq, &solo_video_qops, | 648 | solo_dev->vidq.mem_ops = &vb2_dma_contig_memops; |
754 | &solo_dev->pdev->dev, &solo_dev->slock, | 649 | solo_dev->vidq.drv_priv = solo_dev; |
755 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 650 | solo_dev->vidq.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
756 | V4L2_FIELD_INTERLACED, | 651 | solo_dev->vidq.gfp_flags = __GFP_DMA32; |
757 | sizeof(struct videobuf_buffer), | 652 | solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf); |
758 | solo_dev, NULL); | 653 | solo_dev->vidq.lock = &solo_dev->lock; |
654 | ret = vb2_queue_init(&solo_dev->vidq); | ||
655 | if (ret < 0) | ||
656 | goto fail; | ||
657 | |||
658 | solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev); | ||
659 | if (IS_ERR(solo_dev->alloc_ctx)) { | ||
660 | dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context"); | ||
661 | return PTR_ERR(solo_dev->alloc_ctx); | ||
662 | } | ||
759 | 663 | ||
760 | /* Cycle all the channels and clear */ | 664 | /* Cycle all the channels and clear */ |
761 | for (i = 0; i < solo_dev->nr_chans; i++) { | 665 | for (i = 0; i < solo_dev->nr_chans; i++) { |
@@ -770,11 +674,8 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
770 | /* Do nothing */; | 674 | /* Do nothing */; |
771 | 675 | ||
772 | ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr); | 676 | ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr); |
773 | if (ret < 0) { | 677 | if (ret < 0) |
774 | video_device_release(solo_dev->vfd); | 678 | goto fail; |
775 | solo_dev->vfd = NULL; | ||
776 | return ret; | ||
777 | } | ||
778 | 679 | ||
779 | snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)", | 680 | snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)", |
780 | SOLO6X10_NAME, solo_dev->vfd->num); | 681 | SOLO6X10_NAME, solo_dev->vfd->num); |
@@ -784,6 +685,13 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) | |||
784 | solo_dev->nr_chans, solo_dev->nr_ext); | 685 | solo_dev->nr_chans, solo_dev->nr_ext); |
785 | 686 | ||
786 | return 0; | 687 | return 0; |
688 | |||
689 | fail: | ||
690 | video_device_release(solo_dev->vfd); | ||
691 | vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx); | ||
692 | v4l2_ctrl_handler_free(&solo_dev->disp_hdl); | ||
693 | solo_dev->vfd = NULL; | ||
694 | return ret; | ||
787 | } | 695 | } |
788 | 696 | ||
789 | void solo_v4l2_exit(struct solo_dev *solo_dev) | 697 | void solo_v4l2_exit(struct solo_dev *solo_dev) |
@@ -792,6 +700,7 @@ void solo_v4l2_exit(struct solo_dev *solo_dev) | |||
792 | return; | 700 | return; |
793 | 701 | ||
794 | video_unregister_device(solo_dev->vfd); | 702 | video_unregister_device(solo_dev->vfd); |
703 | vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx); | ||
795 | v4l2_ctrl_handler_free(&solo_dev->disp_hdl); | 704 | v4l2_ctrl_handler_free(&solo_dev->disp_hdl); |
796 | solo_dev->vfd = NULL; | 705 | solo_dev->vfd = NULL; |
797 | } | 706 | } |