diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-03-11 05:52:27 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-24 11:51:08 -0400 |
commit | ffcc1c082fdd8e3013f25f670d1fe66f86e04138 (patch) | |
tree | 500f767b7d9ec9c6eeceb125c812fdeaf8e0c4d0 /drivers/staging | |
parent | 899eb84ce3b50dfa8de6a12e6f39f4e30fde9781 (diff) |
[media] go7007: convert to core locking and vb2
Convert this driver to videobuf2 and core locking.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/media/go7007/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-driver.c | 156 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-priv.h | 27 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-usb.c | 9 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-v4l2.c | 535 | ||||
-rw-r--r-- | drivers/staging/media/go7007/saa7134-go7007.c | 2 |
6 files changed, 205 insertions, 526 deletions
diff --git a/drivers/staging/media/go7007/Kconfig b/drivers/staging/media/go7007/Kconfig index da320319cd24..46cb7bf88ab0 100644 --- a/drivers/staging/media/go7007/Kconfig +++ b/drivers/staging/media/go7007/Kconfig | |||
@@ -2,7 +2,7 @@ config VIDEO_GO7007 | |||
2 | tristate "WIS GO7007 MPEG encoder support" | 2 | tristate "WIS GO7007 MPEG encoder support" |
3 | depends on VIDEO_DEV && PCI && I2C | 3 | depends on VIDEO_DEV && PCI && I2C |
4 | depends on SND | 4 | depends on SND |
5 | select VIDEOBUF_DMA_SG | 5 | select VIDEOBUF2_VMALLOC |
6 | depends on RC_CORE | 6 | depends on RC_CORE |
7 | select VIDEO_TUNER | 7 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c index 732b4525bb06..075de4d31484 100644 --- a/drivers/staging/media/go7007/go7007-driver.c +++ b/drivers/staging/media/go7007/go7007-driver.c | |||
@@ -363,48 +363,54 @@ start_error: | |||
363 | /* | 363 | /* |
364 | * Store a byte in the current video buffer, if there is one. | 364 | * Store a byte in the current video buffer, if there is one. |
365 | */ | 365 | */ |
366 | static inline void store_byte(struct go7007_buffer *gobuf, u8 byte) | 366 | static inline void store_byte(struct go7007_buffer *vb, u8 byte) |
367 | { | 367 | { |
368 | if (gobuf != NULL && gobuf->bytesused < GO7007_BUF_SIZE) { | 368 | if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) { |
369 | unsigned int pgidx = gobuf->offset >> PAGE_SHIFT; | 369 | u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); |
370 | unsigned int pgoff = gobuf->offset & ~PAGE_MASK; | ||
371 | 370 | ||
372 | *((u8 *)page_address(gobuf->pages[pgidx]) + pgoff) = byte; | 371 | ptr[vb->vb.v4l2_planes[0].bytesused++] = byte; |
373 | ++gobuf->offset; | ||
374 | ++gobuf->bytesused; | ||
375 | } | 372 | } |
376 | } | 373 | } |
377 | 374 | ||
378 | /* | 375 | /* |
379 | * Deliver the last video buffer and get a new one to start writing to. | 376 | * Deliver the last video buffer and get a new one to start writing to. |
380 | */ | 377 | */ |
381 | static void frame_boundary(struct go7007 *go) | 378 | static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb) |
382 | { | 379 | { |
383 | struct go7007_buffer *gobuf; | 380 | struct go7007_buffer *vb_tmp = NULL; |
381 | u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused; | ||
384 | int i; | 382 | int i; |
385 | 383 | ||
386 | if (go->active_buf) { | 384 | if (vb) { |
387 | if (go->active_buf->modet_active) { | 385 | if (vb->modet_active) { |
388 | if (go->active_buf->bytesused + 216 < GO7007_BUF_SIZE) { | 386 | if (*bytesused + 216 < GO7007_BUF_SIZE) { |
389 | for (i = 0; i < 216; ++i) | 387 | for (i = 0; i < 216; ++i) |
390 | store_byte(go->active_buf, | 388 | store_byte(vb, go->active_map[i]); |
391 | go->active_map[i]); | 389 | *bytesused -= 216; |
392 | go->active_buf->bytesused -= 216; | ||
393 | } else | 390 | } else |
394 | go->active_buf->modet_active = 0; | 391 | vb->modet_active = 0; |
395 | } | 392 | } |
396 | go->active_buf->state = BUF_STATE_DONE; | 393 | vb->vb.v4l2_buf.sequence = go->next_seq++; |
397 | wake_up_interruptible(&go->frame_waitq); | 394 | v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp); |
398 | go->active_buf = NULL; | 395 | vb_tmp = vb; |
396 | spin_lock(&go->spinlock); | ||
397 | list_del(&vb->list); | ||
398 | if (list_empty(&go->vidq_active)) | ||
399 | vb = NULL; | ||
400 | else | ||
401 | vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list); | ||
402 | go->active_buf = vb; | ||
403 | spin_unlock(&go->spinlock); | ||
404 | vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE); | ||
405 | return vb; | ||
399 | } | 406 | } |
400 | list_for_each_entry(gobuf, &go->stream, stream) | 407 | spin_lock(&go->spinlock); |
401 | if (gobuf->state == BUF_STATE_QUEUED) { | 408 | if (!list_empty(&go->vidq_active)) |
402 | gobuf->seq = go->next_seq; | 409 | vb = go->active_buf = |
403 | do_gettimeofday(&gobuf->timestamp); | 410 | list_first_entry(&go->vidq_active, struct go7007_buffer, list); |
404 | go->active_buf = gobuf; | 411 | spin_unlock(&go->spinlock); |
405 | break; | 412 | go->next_seq++; |
406 | } | 413 | return vb; |
407 | ++go->next_seq; | ||
408 | } | 414 | } |
409 | 415 | ||
410 | static void write_bitmap_word(struct go7007 *go) | 416 | static void write_bitmap_word(struct go7007 *go) |
@@ -428,10 +434,9 @@ static void write_bitmap_word(struct go7007 *go) | |||
428 | */ | 434 | */ |
429 | void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | 435 | void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) |
430 | { | 436 | { |
437 | struct go7007_buffer *vb = go->active_buf; | ||
431 | int i, seq_start_code = -1, frame_start_code = -1; | 438 | int i, seq_start_code = -1, frame_start_code = -1; |
432 | 439 | ||
433 | spin_lock(&go->spinlock); | ||
434 | |||
435 | switch (go->format) { | 440 | switch (go->format) { |
436 | case V4L2_PIX_FMT_MPEG4: | 441 | case V4L2_PIX_FMT_MPEG4: |
437 | seq_start_code = 0xB0; | 442 | seq_start_code = 0xB0; |
@@ -445,13 +450,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
445 | } | 450 | } |
446 | 451 | ||
447 | for (i = 0; i < length; ++i) { | 452 | for (i = 0; i < length; ++i) { |
448 | if (go->active_buf != NULL && | 453 | if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) { |
449 | go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) { | ||
450 | v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); | 454 | v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); |
451 | go->active_buf->offset -= go->active_buf->bytesused; | 455 | vb->vb.v4l2_planes[0].bytesused = 0; |
452 | go->active_buf->bytesused = 0; | 456 | vb->frame_offset = 0; |
453 | go->active_buf->modet_active = 0; | 457 | vb->modet_active = 0; |
454 | go->active_buf = NULL; | 458 | vb = go->active_buf = NULL; |
455 | } | 459 | } |
456 | 460 | ||
457 | switch (go->state) { | 461 | switch (go->state) { |
@@ -464,7 +468,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
464 | go->state = STATE_FF; | 468 | go->state = STATE_FF; |
465 | break; | 469 | break; |
466 | default: | 470 | default: |
467 | store_byte(go->active_buf, buf[i]); | 471 | store_byte(vb, buf[i]); |
468 | break; | 472 | break; |
469 | } | 473 | } |
470 | break; | 474 | break; |
@@ -474,12 +478,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
474 | go->state = STATE_00_00; | 478 | go->state = STATE_00_00; |
475 | break; | 479 | break; |
476 | case 0xFF: | 480 | case 0xFF: |
477 | store_byte(go->active_buf, 0x00); | 481 | store_byte(vb, 0x00); |
478 | go->state = STATE_FF; | 482 | go->state = STATE_FF; |
479 | break; | 483 | break; |
480 | default: | 484 | default: |
481 | store_byte(go->active_buf, 0x00); | 485 | store_byte(vb, 0x00); |
482 | store_byte(go->active_buf, buf[i]); | 486 | store_byte(vb, buf[i]); |
483 | go->state = STATE_DATA; | 487 | go->state = STATE_DATA; |
484 | break; | 488 | break; |
485 | } | 489 | } |
@@ -487,21 +491,21 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
487 | case STATE_00_00: | 491 | case STATE_00_00: |
488 | switch (buf[i]) { | 492 | switch (buf[i]) { |
489 | case 0x00: | 493 | case 0x00: |
490 | store_byte(go->active_buf, 0x00); | 494 | store_byte(vb, 0x00); |
491 | /* go->state remains STATE_00_00 */ | 495 | /* go->state remains STATE_00_00 */ |
492 | break; | 496 | break; |
493 | case 0x01: | 497 | case 0x01: |
494 | go->state = STATE_00_00_01; | 498 | go->state = STATE_00_00_01; |
495 | break; | 499 | break; |
496 | case 0xFF: | 500 | case 0xFF: |
497 | store_byte(go->active_buf, 0x00); | 501 | store_byte(vb, 0x00); |
498 | store_byte(go->active_buf, 0x00); | 502 | store_byte(vb, 0x00); |
499 | go->state = STATE_FF; | 503 | go->state = STATE_FF; |
500 | break; | 504 | break; |
501 | default: | 505 | default: |
502 | store_byte(go->active_buf, 0x00); | 506 | store_byte(vb, 0x00); |
503 | store_byte(go->active_buf, 0x00); | 507 | store_byte(vb, 0x00); |
504 | store_byte(go->active_buf, buf[i]); | 508 | store_byte(vb, buf[i]); |
505 | go->state = STATE_DATA; | 509 | go->state = STATE_DATA; |
506 | break; | 510 | break; |
507 | } | 511 | } |
@@ -509,10 +513,10 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
509 | case STATE_00_00_01: | 513 | case STATE_00_00_01: |
510 | if (buf[i] == 0xF8 && go->modet_enable == 0) { | 514 | if (buf[i] == 0xF8 && go->modet_enable == 0) { |
511 | /* MODET start code, but MODET not enabled */ | 515 | /* MODET start code, but MODET not enabled */ |
512 | store_byte(go->active_buf, 0x00); | 516 | store_byte(vb, 0x00); |
513 | store_byte(go->active_buf, 0x00); | 517 | store_byte(vb, 0x00); |
514 | store_byte(go->active_buf, 0x01); | 518 | store_byte(vb, 0x01); |
515 | store_byte(go->active_buf, 0xF8); | 519 | store_byte(vb, 0xF8); |
516 | go->state = STATE_DATA; | 520 | go->state = STATE_DATA; |
517 | break; | 521 | break; |
518 | } | 522 | } |
@@ -521,19 +525,14 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
521 | if ((go->format == V4L2_PIX_FMT_MPEG1 || | 525 | if ((go->format == V4L2_PIX_FMT_MPEG1 || |
522 | go->format == V4L2_PIX_FMT_MPEG2 || | 526 | go->format == V4L2_PIX_FMT_MPEG2 || |
523 | go->format == V4L2_PIX_FMT_MPEG4) && | 527 | go->format == V4L2_PIX_FMT_MPEG4) && |
524 | (buf[i] == seq_start_code || | 528 | (buf[i] == seq_start_code || |
525 | buf[i] == 0xB8 || /* GOP code */ | 529 | buf[i] == 0xB8 || /* GOP code */ |
526 | buf[i] == frame_start_code)) { | 530 | buf[i] == frame_start_code)) { |
527 | if (go->active_buf == NULL || go->seen_frame) | 531 | if (vb == NULL || go->seen_frame) |
528 | frame_boundary(go); | 532 | vb = frame_boundary(go, vb); |
529 | if (buf[i] == frame_start_code) { | 533 | go->seen_frame = buf[i] == frame_start_code; |
530 | if (go->active_buf != NULL) | 534 | if (vb && go->seen_frame) |
531 | go->active_buf->frame_offset = | 535 | vb->frame_offset = vb->vb.v4l2_planes[0].bytesused; |
532 | go->active_buf->offset; | ||
533 | go->seen_frame = 1; | ||
534 | } else { | ||
535 | go->seen_frame = 0; | ||
536 | } | ||
537 | } | 536 | } |
538 | /* Handle any special chunk types, or just write the | 537 | /* Handle any special chunk types, or just write the |
539 | * start code to the (potentially new) buffer */ | 538 | * start code to the (potentially new) buffer */ |
@@ -552,16 +551,16 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
552 | go->state = STATE_MODET_MAP; | 551 | go->state = STATE_MODET_MAP; |
553 | break; | 552 | break; |
554 | case 0xFF: /* Potential JPEG start code */ | 553 | case 0xFF: /* Potential JPEG start code */ |
555 | store_byte(go->active_buf, 0x00); | 554 | store_byte(vb, 0x00); |
556 | store_byte(go->active_buf, 0x00); | 555 | store_byte(vb, 0x00); |
557 | store_byte(go->active_buf, 0x01); | 556 | store_byte(vb, 0x01); |
558 | go->state = STATE_FF; | 557 | go->state = STATE_FF; |
559 | break; | 558 | break; |
560 | default: | 559 | default: |
561 | store_byte(go->active_buf, 0x00); | 560 | store_byte(vb, 0x00); |
562 | store_byte(go->active_buf, 0x00); | 561 | store_byte(vb, 0x00); |
563 | store_byte(go->active_buf, 0x01); | 562 | store_byte(vb, 0x01); |
564 | store_byte(go->active_buf, buf[i]); | 563 | store_byte(vb, buf[i]); |
565 | go->state = STATE_DATA; | 564 | go->state = STATE_DATA; |
566 | break; | 565 | break; |
567 | } | 566 | } |
@@ -569,20 +568,20 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
569 | case STATE_FF: | 568 | case STATE_FF: |
570 | switch (buf[i]) { | 569 | switch (buf[i]) { |
571 | case 0x00: | 570 | case 0x00: |
572 | store_byte(go->active_buf, 0xFF); | 571 | store_byte(vb, 0xFF); |
573 | go->state = STATE_00; | 572 | go->state = STATE_00; |
574 | break; | 573 | break; |
575 | case 0xFF: | 574 | case 0xFF: |
576 | store_byte(go->active_buf, 0xFF); | 575 | store_byte(vb, 0xFF); |
577 | /* go->state remains STATE_FF */ | 576 | /* go->state remains STATE_FF */ |
578 | break; | 577 | break; |
579 | case 0xD8: | 578 | case 0xD8: |
580 | if (go->format == V4L2_PIX_FMT_MJPEG) | 579 | if (go->format == V4L2_PIX_FMT_MJPEG) |
581 | frame_boundary(go); | 580 | vb = frame_boundary(go, vb); |
582 | /* fall through */ | 581 | /* fall through */ |
583 | default: | 582 | default: |
584 | store_byte(go->active_buf, 0xFF); | 583 | store_byte(vb, 0xFF); |
585 | store_byte(go->active_buf, buf[i]); | 584 | store_byte(vb, buf[i]); |
586 | go->state = STATE_DATA; | 585 | go->state = STATE_DATA; |
587 | break; | 586 | break; |
588 | } | 587 | } |
@@ -605,8 +604,8 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
605 | write_bitmap_word(go); | 604 | write_bitmap_word(go); |
606 | } else | 605 | } else |
607 | go->modet_word = buf[i] << 8; | 606 | go->modet_word = buf[i] << 8; |
608 | } else if (go->parse_length == 207 && go->active_buf) { | 607 | } else if (go->parse_length == 207 && vb) { |
609 | go->active_buf->modet_active = buf[i]; | 608 | vb->modet_active = buf[i]; |
610 | } | 609 | } |
611 | if (++go->parse_length == 208) | 610 | if (++go->parse_length == 208) |
612 | go->state = STATE_DATA; | 611 | go->state = STATE_DATA; |
@@ -617,8 +616,6 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | |||
617 | break; | 616 | break; |
618 | } | 617 | } |
619 | } | 618 | } |
620 | |||
621 | spin_unlock(&go->spinlock); | ||
622 | } | 619 | } |
623 | EXPORT_SYMBOL(go7007_parse_video_stream); | 620 | EXPORT_SYMBOL(go7007_parse_video_stream); |
624 | 621 | ||
@@ -648,14 +645,12 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) | |||
648 | go->i2c_adapter_online = 0; | 645 | go->i2c_adapter_online = 0; |
649 | go->interrupt_available = 0; | 646 | go->interrupt_available = 0; |
650 | init_waitqueue_head(&go->interrupt_waitq); | 647 | init_waitqueue_head(&go->interrupt_waitq); |
651 | go->in_use = 0; | ||
652 | go->input = 0; | 648 | go->input = 0; |
653 | go7007_update_board(go); | 649 | go7007_update_board(go); |
654 | go->encoder_h_halve = 0; | 650 | go->encoder_h_halve = 0; |
655 | go->encoder_v_halve = 0; | 651 | go->encoder_v_halve = 0; |
656 | go->encoder_subsample = 0; | 652 | go->encoder_subsample = 0; |
657 | go->format = V4L2_PIX_FMT_MJPEG; | 653 | go->format = V4L2_PIX_FMT_MJPEG; |
658 | go->streaming = 0; | ||
659 | go->bitrate = 1500000; | 654 | go->bitrate = 1500000; |
660 | go->fps_scale = 1; | 655 | go->fps_scale = 1; |
661 | go->pali = 0; | 656 | go->pali = 0; |
@@ -674,7 +669,6 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) | |||
674 | go->modet_map[i] = 0; | 669 | go->modet_map[i] = 0; |
675 | go->audio_deliver = NULL; | 670 | go->audio_deliver = NULL; |
676 | go->audio_enabled = 0; | 671 | go->audio_enabled = 0; |
677 | INIT_LIST_HEAD(&go->stream); | ||
678 | 672 | ||
679 | return go; | 673 | return go; |
680 | } | 674 | } |
diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h index 2c0afb167815..30148eba44b4 100644 --- a/drivers/staging/media/go7007/go7007-priv.h +++ b/drivers/staging/media/go7007/go7007-priv.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <media/v4l2-device.h> | 24 | #include <media/v4l2-device.h> |
25 | #include <media/v4l2-ctrls.h> | 25 | #include <media/v4l2-ctrls.h> |
26 | #include <media/v4l2-fh.h> | 26 | #include <media/v4l2-fh.h> |
27 | #include <media/videobuf2-core.h> | ||
27 | 28 | ||
28 | struct go7007; | 29 | struct go7007; |
29 | 30 | ||
@@ -125,20 +126,10 @@ struct go7007_hpi_ops { | |||
125 | #define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) | 126 | #define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) |
126 | 127 | ||
127 | struct go7007_buffer { | 128 | struct go7007_buffer { |
128 | struct go7007 *go; /* Reverse reference for VMA ops */ | 129 | struct vb2_buffer vb; |
129 | int index; /* Reverse reference for DQBUF */ | 130 | struct list_head list; |
130 | enum { BUF_STATE_IDLE, BUF_STATE_QUEUED, BUF_STATE_DONE } state; | ||
131 | u32 seq; | ||
132 | struct timeval timestamp; | ||
133 | struct list_head stream; | ||
134 | struct page *pages[GO7007_BUF_PAGES + 1]; /* extra for straddling */ | ||
135 | unsigned long user_addr; | ||
136 | unsigned int page_count; | ||
137 | unsigned int offset; | ||
138 | unsigned int bytesused; | ||
139 | unsigned int frame_offset; | 131 | unsigned int frame_offset; |
140 | u32 modet_active; | 132 | u32 modet_active; |
141 | int mapped; | ||
142 | }; | 133 | }; |
143 | 134 | ||
144 | #define GO7007_RATIO_1_1 0 | 135 | #define GO7007_RATIO_1_1 0 |
@@ -178,8 +169,7 @@ struct go7007 { | |||
178 | enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; | 169 | enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; |
179 | spinlock_t spinlock; | 170 | spinlock_t spinlock; |
180 | struct mutex hw_lock; | 171 | struct mutex hw_lock; |
181 | int streaming; | 172 | struct mutex serialize_lock; |
182 | int in_use; | ||
183 | int audio_enabled; | 173 | int audio_enabled; |
184 | struct v4l2_subdev *sd_video; | 174 | struct v4l2_subdev *sd_video; |
185 | struct v4l2_subdev *sd_audio; | 175 | struct v4l2_subdev *sd_audio; |
@@ -226,17 +216,16 @@ struct go7007 { | |||
226 | unsigned char active_map[216]; | 216 | unsigned char active_map[216]; |
227 | 217 | ||
228 | /* Video streaming */ | 218 | /* Video streaming */ |
229 | struct go7007_buffer *active_buf; | 219 | struct mutex queue_lock; |
220 | struct vb2_queue vidq; | ||
230 | enum go7007_parser_state state; | 221 | enum go7007_parser_state state; |
231 | int parse_length; | 222 | int parse_length; |
232 | u16 modet_word; | 223 | u16 modet_word; |
233 | int seen_frame; | 224 | int seen_frame; |
234 | u32 next_seq; | 225 | u32 next_seq; |
235 | struct list_head stream; | 226 | struct list_head vidq_active; |
236 | wait_queue_head_t frame_waitq; | 227 | wait_queue_head_t frame_waitq; |
237 | int buf_count; | 228 | struct go7007_buffer *active_buf; |
238 | struct go7007_buffer *bufs; | ||
239 | struct v4l2_fh *bufs_owner; | ||
240 | 229 | ||
241 | /* Audio streaming */ | 230 | /* Audio streaming */ |
242 | void (*audio_deliver)(struct go7007 *go, u8 *buf, int length); | 231 | void (*audio_deliver)(struct go7007 *go, u8 *buf, int length); |
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 5c7a19e6fb68..c95538c735d9 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c | |||
@@ -780,7 +780,7 @@ static void go7007_usb_read_video_pipe_complete(struct urb *urb) | |||
780 | struct go7007 *go = (struct go7007 *)urb->context; | 780 | struct go7007 *go = (struct go7007 *)urb->context; |
781 | int r, status = urb->status; | 781 | int r, status = urb->status; |
782 | 782 | ||
783 | if (!go->streaming) { | 783 | if (!vb2_is_streaming(&go->vidq)) { |
784 | wake_up_interruptible(&go->frame_waitq); | 784 | wake_up_interruptible(&go->frame_waitq); |
785 | return; | 785 | return; |
786 | } | 786 | } |
@@ -804,7 +804,7 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb) | |||
804 | struct go7007 *go = (struct go7007 *)urb->context; | 804 | struct go7007 *go = (struct go7007 *)urb->context; |
805 | int r, status = urb->status; | 805 | int r, status = urb->status; |
806 | 806 | ||
807 | if (!go->streaming) | 807 | if (!vb2_is_streaming(&go->vidq)) |
808 | return; | 808 | return; |
809 | if (status) { | 809 | if (status) { |
810 | printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", | 810 | 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 | { | 1316 | { |
1317 | struct go7007 *go = to_go7007(usb_get_intfdata(intf)); | 1317 | struct go7007 *go = to_go7007(usb_get_intfdata(intf)); |
1318 | 1318 | ||
1319 | mutex_lock(&go->queue_lock); | ||
1320 | mutex_lock(&go->serialize_lock); | ||
1321 | |||
1319 | if (go->audio_enabled) | 1322 | if (go->audio_enabled) |
1320 | go7007_snd_remove(go); | 1323 | go7007_snd_remove(go); |
1321 | 1324 | ||
1322 | go->status = STATUS_SHUTDOWN; | 1325 | go->status = STATUS_SHUTDOWN; |
1323 | v4l2_device_disconnect(&go->v4l2_dev); | 1326 | v4l2_device_disconnect(&go->v4l2_dev); |
1324 | video_unregister_device(go->video_dev); | 1327 | video_unregister_device(go->video_dev); |
1328 | mutex_unlock(&go->serialize_lock); | ||
1329 | mutex_unlock(&go->queue_lock); | ||
1325 | 1330 | ||
1326 | v4l2_device_put(&go->v4l2_dev); | 1331 | v4l2_device_put(&go->v4l2_dev); |
1327 | } | 1332 | } |
diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c index b10702069c3a..d210d33a4479 100644 --- a/drivers/staging/media/go7007/go7007-v4l2.c +++ b/drivers/staging/media/go7007/go7007-v4l2.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <media/v4l2-ioctl.h> | 35 | #include <media/v4l2-ioctl.h> |
36 | #include <media/v4l2-subdev.h> | 36 | #include <media/v4l2-subdev.h> |
37 | #include <media/v4l2-event.h> | 37 | #include <media/v4l2-event.h> |
38 | #include <media/videobuf2-vmalloc.h> | ||
38 | #include <media/saa7115.h> | 39 | #include <media/saa7115.h> |
39 | 40 | ||
40 | #include "go7007.h" | 41 | #include "go7007.h" |
@@ -43,66 +44,6 @@ | |||
43 | #define call_all(dev, o, f, args...) \ | 44 | #define call_all(dev, o, f, args...) \ |
44 | v4l2_device_call_until_err(dev, 0, o, f, ##args) | 45 | v4l2_device_call_until_err(dev, 0, o, f, ##args) |
45 | 46 | ||
46 | static void deactivate_buffer(struct go7007_buffer *gobuf) | ||
47 | { | ||
48 | int i; | ||
49 | |||
50 | if (gobuf->state != BUF_STATE_IDLE) { | ||
51 | list_del(&gobuf->stream); | ||
52 | gobuf->state = BUF_STATE_IDLE; | ||
53 | } | ||
54 | if (gobuf->page_count > 0) { | ||
55 | for (i = 0; i < gobuf->page_count; ++i) | ||
56 | page_cache_release(gobuf->pages[i]); | ||
57 | gobuf->page_count = 0; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static void abort_queued(struct go7007 *go) | ||
62 | { | ||
63 | struct go7007_buffer *gobuf, *next; | ||
64 | |||
65 | list_for_each_entry_safe(gobuf, next, &go->stream, stream) { | ||
66 | deactivate_buffer(gobuf); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | static int go7007_streamoff(struct go7007 *go) | ||
71 | { | ||
72 | unsigned long flags; | ||
73 | |||
74 | mutex_lock(&go->hw_lock); | ||
75 | if (go->streaming) { | ||
76 | go->streaming = 0; | ||
77 | go7007_stream_stop(go); | ||
78 | spin_lock_irqsave(&go->spinlock, flags); | ||
79 | abort_queued(go); | ||
80 | spin_unlock_irqrestore(&go->spinlock, flags); | ||
81 | go7007_reset_encoder(go); | ||
82 | } | ||
83 | mutex_unlock(&go->hw_lock); | ||
84 | v4l2_ctrl_grab(go->mpeg_video_gop_size, false); | ||
85 | v4l2_ctrl_grab(go->mpeg_video_gop_closure, false); | ||
86 | v4l2_ctrl_grab(go->mpeg_video_bitrate, false); | ||
87 | v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int go7007_release(struct file *file) | ||
92 | { | ||
93 | struct go7007 *go = video_drvdata(file); | ||
94 | |||
95 | if (file->private_data == go->bufs_owner && go->buf_count > 0) { | ||
96 | go7007_streamoff(go); | ||
97 | go->in_use = 0; | ||
98 | kfree(go->bufs); | ||
99 | go->bufs = NULL; | ||
100 | go->buf_count = 0; | ||
101 | go->bufs_owner = NULL; | ||
102 | } | ||
103 | return v4l2_fh_release(file); | ||
104 | } | ||
105 | |||
106 | static bool valid_pixelformat(u32 pixelformat) | 47 | static bool valid_pixelformat(u32 pixelformat) |
107 | { | 48 | { |
108 | switch (pixelformat) { | 49 | switch (pixelformat) { |
@@ -116,15 +57,15 @@ static bool valid_pixelformat(u32 pixelformat) | |||
116 | } | 57 | } |
117 | } | 58 | } |
118 | 59 | ||
119 | static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format) | 60 | static u32 get_frame_type_flag(struct go7007_buffer *vb, int format) |
120 | { | 61 | { |
121 | u8 *f = page_address(gobuf->pages[0]); | 62 | u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); |
122 | 63 | ||
123 | switch (format) { | 64 | switch (format) { |
124 | case V4L2_PIX_FMT_MJPEG: | 65 | case V4L2_PIX_FMT_MJPEG: |
125 | return V4L2_BUF_FLAG_KEYFRAME; | 66 | return V4L2_BUF_FLAG_KEYFRAME; |
126 | case V4L2_PIX_FMT_MPEG4: | 67 | case V4L2_PIX_FMT_MPEG4: |
127 | switch ((f[gobuf->frame_offset + 4] >> 6) & 0x3) { | 68 | switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) { |
128 | case 0: | 69 | case 0: |
129 | return V4L2_BUF_FLAG_KEYFRAME; | 70 | return V4L2_BUF_FLAG_KEYFRAME; |
130 | case 1: | 71 | case 1: |
@@ -136,7 +77,7 @@ static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format) | |||
136 | } | 77 | } |
137 | case V4L2_PIX_FMT_MPEG1: | 78 | case V4L2_PIX_FMT_MPEG1: |
138 | case V4L2_PIX_FMT_MPEG2: | 79 | case V4L2_PIX_FMT_MPEG2: |
139 | switch ((f[gobuf->frame_offset + 5] >> 3) & 0x7) { | 80 | switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) { |
140 | case 1: | 81 | case 1: |
141 | return V4L2_BUF_FLAG_KEYFRAME; | 82 | return V4L2_BUF_FLAG_KEYFRAME; |
142 | case 2: | 83 | case 2: |
@@ -412,7 +353,8 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
412 | strlcpy(cap->card, go->name, sizeof(cap->card)); | 353 | strlcpy(cap->card, go->name, sizeof(cap->card)); |
413 | strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info)); | 354 | strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info)); |
414 | 355 | ||
415 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | 356 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | |
357 | V4L2_CAP_STREAMING; | ||
416 | 358 | ||
417 | if (go->board_info->num_aud_inputs) | 359 | if (go->board_info->num_aud_inputs) |
418 | cap->device_caps |= V4L2_CAP_AUDIO; | 360 | cap->device_caps |= V4L2_CAP_AUDIO; |
@@ -485,293 +427,125 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
485 | { | 427 | { |
486 | struct go7007 *go = video_drvdata(file); | 428 | struct go7007 *go = video_drvdata(file); |
487 | 429 | ||
488 | if (go->streaming) | 430 | if (vb2_is_busy(&go->vidq)) |
489 | return -EBUSY; | 431 | return -EBUSY; |
490 | 432 | ||
491 | return set_capture_size(go, fmt, 0); | 433 | return set_capture_size(go, fmt, 0); |
492 | } | 434 | } |
493 | 435 | ||
494 | static int vidioc_reqbufs(struct file *file, void *priv, | 436 | static int go7007_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
495 | struct v4l2_requestbuffers *req) | 437 | unsigned int *num_buffers, unsigned int *num_planes, |
438 | unsigned int sizes[], void *alloc_ctxs[]) | ||
496 | { | 439 | { |
497 | struct go7007 *go = video_drvdata(file); | 440 | sizes[0] = GO7007_BUF_SIZE; |
498 | int retval = -EBUSY; | 441 | *num_planes = 1; |
499 | unsigned int count, i; | ||
500 | |||
501 | if (go->streaming) | ||
502 | return retval; | ||
503 | |||
504 | if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
505 | req->memory != V4L2_MEMORY_MMAP) | ||
506 | return -EINVAL; | ||
507 | |||
508 | for (i = 0; i < go->buf_count; ++i) | ||
509 | if (go->bufs[i].mapped > 0) | ||
510 | goto unlock_and_return; | ||
511 | |||
512 | set_formatting(go); | ||
513 | mutex_lock(&go->hw_lock); | ||
514 | if (go->in_use > 0 && go->buf_count == 0) { | ||
515 | mutex_unlock(&go->hw_lock); | ||
516 | goto unlock_and_return; | ||
517 | } | ||
518 | 442 | ||
519 | if (go->buf_count > 0) | 443 | if (*num_buffers < 2) |
520 | kfree(go->bufs); | 444 | *num_buffers = 2; |
521 | |||
522 | retval = -ENOMEM; | ||
523 | count = req->count; | ||
524 | if (count > 0) { | ||
525 | if (count < 2) | ||
526 | count = 2; | ||
527 | if (count > 32) | ||
528 | count = 32; | ||
529 | |||
530 | go->bufs = kcalloc(count, sizeof(struct go7007_buffer), | ||
531 | GFP_KERNEL); | ||
532 | |||
533 | if (!go->bufs) { | ||
534 | mutex_unlock(&go->hw_lock); | ||
535 | goto unlock_and_return; | ||
536 | } | ||
537 | |||
538 | for (i = 0; i < count; ++i) { | ||
539 | go->bufs[i].go = go; | ||
540 | go->bufs[i].index = i; | ||
541 | go->bufs[i].state = BUF_STATE_IDLE; | ||
542 | go->bufs[i].mapped = 0; | ||
543 | } | ||
544 | |||
545 | go->in_use = 1; | ||
546 | go->bufs_owner = file->private_data; | ||
547 | } else { | ||
548 | go->in_use = 0; | ||
549 | go->bufs_owner = NULL; | ||
550 | } | ||
551 | |||
552 | go->buf_count = count; | ||
553 | mutex_unlock(&go->hw_lock); | ||
554 | |||
555 | memset(req, 0, sizeof(*req)); | ||
556 | |||
557 | req->count = count; | ||
558 | req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
559 | req->memory = V4L2_MEMORY_MMAP; | ||
560 | 445 | ||
561 | return 0; | 446 | return 0; |
562 | |||
563 | unlock_and_return: | ||
564 | return retval; | ||
565 | } | 447 | } |
566 | 448 | ||
567 | static int vidioc_querybuf(struct file *file, void *priv, | 449 | static void go7007_buf_queue(struct vb2_buffer *vb) |
568 | struct v4l2_buffer *buf) | ||
569 | { | 450 | { |
570 | struct go7007 *go = video_drvdata(file); | 451 | struct vb2_queue *vq = vb->vb2_queue; |
571 | int retval = -EINVAL; | 452 | struct go7007 *go = vb2_get_drv_priv(vq); |
572 | unsigned int index; | 453 | struct go7007_buffer *go7007_vb = |
573 | 454 | container_of(vb, struct go7007_buffer, vb); | |
574 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
575 | return retval; | ||
576 | |||
577 | index = buf->index; | ||
578 | |||
579 | if (index >= go->buf_count) | ||
580 | goto unlock_and_return; | ||
581 | |||
582 | memset(buf, 0, sizeof(*buf)); | ||
583 | buf->index = index; | ||
584 | buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
585 | |||
586 | switch (go->bufs[index].state) { | ||
587 | case BUF_STATE_QUEUED: | ||
588 | buf->flags = V4L2_BUF_FLAG_QUEUED; | ||
589 | break; | ||
590 | case BUF_STATE_DONE: | ||
591 | buf->flags = V4L2_BUF_FLAG_DONE; | ||
592 | break; | ||
593 | default: | ||
594 | buf->flags = 0; | ||
595 | } | ||
596 | |||
597 | if (go->bufs[index].mapped) | ||
598 | buf->flags |= V4L2_BUF_FLAG_MAPPED; | ||
599 | buf->memory = V4L2_MEMORY_MMAP; | ||
600 | buf->m.offset = index * GO7007_BUF_SIZE; | ||
601 | buf->length = GO7007_BUF_SIZE; | ||
602 | |||
603 | return 0; | ||
604 | |||
605 | unlock_and_return: | ||
606 | return retval; | ||
607 | } | ||
608 | |||
609 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
610 | { | ||
611 | struct go7007 *go = video_drvdata(file); | ||
612 | struct go7007_buffer *gobuf; | ||
613 | unsigned long flags; | 455 | unsigned long flags; |
614 | int retval = -EINVAL; | ||
615 | int ret; | ||
616 | |||
617 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
618 | buf->memory != V4L2_MEMORY_MMAP) | ||
619 | return retval; | ||
620 | |||
621 | if (buf->index >= go->buf_count) | ||
622 | goto unlock_and_return; | ||
623 | 456 | ||
624 | gobuf = &go->bufs[buf->index]; | ||
625 | if (!gobuf->mapped) | ||
626 | goto unlock_and_return; | ||
627 | |||
628 | retval = -EBUSY; | ||
629 | if (gobuf->state != BUF_STATE_IDLE) | ||
630 | goto unlock_and_return; | ||
631 | |||
632 | /* offset will be 0 until we really support USERPTR streaming */ | ||
633 | gobuf->offset = gobuf->user_addr & ~PAGE_MASK; | ||
634 | gobuf->bytesused = 0; | ||
635 | gobuf->frame_offset = 0; | ||
636 | gobuf->modet_active = 0; | ||
637 | if (gobuf->offset > 0) | ||
638 | gobuf->page_count = GO7007_BUF_PAGES + 1; | ||
639 | else | ||
640 | gobuf->page_count = GO7007_BUF_PAGES; | ||
641 | |||
642 | retval = -ENOMEM; | ||
643 | down_read(¤t->mm->mmap_sem); | ||
644 | ret = get_user_pages(current, current->mm, | ||
645 | gobuf->user_addr & PAGE_MASK, gobuf->page_count, | ||
646 | 1, 1, gobuf->pages, NULL); | ||
647 | up_read(¤t->mm->mmap_sem); | ||
648 | |||
649 | if (ret != gobuf->page_count) { | ||
650 | int i; | ||
651 | for (i = 0; i < ret; ++i) | ||
652 | page_cache_release(gobuf->pages[i]); | ||
653 | gobuf->page_count = 0; | ||
654 | goto unlock_and_return; | ||
655 | } | ||
656 | |||
657 | gobuf->state = BUF_STATE_QUEUED; | ||
658 | spin_lock_irqsave(&go->spinlock, flags); | 457 | spin_lock_irqsave(&go->spinlock, flags); |
659 | list_add_tail(&gobuf->stream, &go->stream); | 458 | list_add_tail(&go7007_vb->list, &go->vidq_active); |
660 | spin_unlock_irqrestore(&go->spinlock, flags); | 459 | spin_unlock_irqrestore(&go->spinlock, flags); |
460 | } | ||
661 | 461 | ||
662 | return 0; | 462 | static int go7007_buf_prepare(struct vb2_buffer *vb) |
463 | { | ||
464 | struct go7007_buffer *go7007_vb = | ||
465 | container_of(vb, struct go7007_buffer, vb); | ||
663 | 466 | ||
664 | unlock_and_return: | 467 | go7007_vb->modet_active = 0; |
665 | return retval; | 468 | go7007_vb->frame_offset = 0; |
469 | vb->v4l2_planes[0].bytesused = 0; | ||
470 | return 0; | ||
666 | } | 471 | } |
667 | 472 | ||
668 | 473 | static int go7007_buf_finish(struct vb2_buffer *vb) | |
669 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
670 | { | 474 | { |
671 | struct go7007 *go = video_drvdata(file); | 475 | struct vb2_queue *vq = vb->vb2_queue; |
672 | struct go7007_buffer *gobuf; | 476 | struct go7007 *go = vb2_get_drv_priv(vq); |
673 | int retval = -EINVAL; | 477 | struct go7007_buffer *go7007_vb = |
674 | unsigned long flags; | 478 | container_of(vb, struct go7007_buffer, vb); |
675 | u32 frame_type_flag; | 479 | u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format); |
676 | DEFINE_WAIT(wait); | 480 | struct v4l2_buffer *buf = &vb->v4l2_buf; |
677 | 481 | ||
678 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 482 | buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME | |
679 | return retval; | 483 | V4L2_BUF_FLAG_PFRAME); |
680 | if (buf->memory != V4L2_MEMORY_MMAP) | 484 | buf->flags |= frame_type_flag; |
681 | return retval; | ||
682 | |||
683 | if (list_empty(&go->stream)) | ||
684 | goto unlock_and_return; | ||
685 | gobuf = list_entry(go->stream.next, | ||
686 | struct go7007_buffer, stream); | ||
687 | |||
688 | retval = -EAGAIN; | ||
689 | if (gobuf->state != BUF_STATE_DONE && | ||
690 | !(file->f_flags & O_NONBLOCK)) { | ||
691 | for (;;) { | ||
692 | prepare_to_wait(&go->frame_waitq, &wait, | ||
693 | TASK_INTERRUPTIBLE); | ||
694 | if (gobuf->state == BUF_STATE_DONE) | ||
695 | break; | ||
696 | if (signal_pending(current)) { | ||
697 | retval = -ERESTARTSYS; | ||
698 | break; | ||
699 | } | ||
700 | schedule(); | ||
701 | } | ||
702 | finish_wait(&go->frame_waitq, &wait); | ||
703 | } | ||
704 | if (gobuf->state != BUF_STATE_DONE) | ||
705 | goto unlock_and_return; | ||
706 | |||
707 | spin_lock_irqsave(&go->spinlock, flags); | ||
708 | deactivate_buffer(gobuf); | ||
709 | spin_unlock_irqrestore(&go->spinlock, flags); | ||
710 | frame_type_flag = get_frame_type_flag(gobuf, go->format); | ||
711 | gobuf->state = BUF_STATE_IDLE; | ||
712 | |||
713 | memset(buf, 0, sizeof(*buf)); | ||
714 | buf->index = gobuf->index; | ||
715 | buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
716 | buf->bytesused = gobuf->bytesused; | ||
717 | buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag; | ||
718 | buf->field = V4L2_FIELD_NONE; | 485 | buf->field = V4L2_FIELD_NONE; |
719 | buf->timestamp = gobuf->timestamp; | ||
720 | buf->sequence = gobuf->seq; | ||
721 | buf->memory = V4L2_MEMORY_MMAP; | ||
722 | buf->m.offset = gobuf->index * GO7007_BUF_SIZE; | ||
723 | buf->length = GO7007_BUF_SIZE; | ||
724 | buf->reserved = gobuf->modet_active; | ||
725 | |||
726 | return 0; | 486 | return 0; |
727 | |||
728 | unlock_and_return: | ||
729 | return retval; | ||
730 | } | 487 | } |
731 | 488 | ||
732 | static int vidioc_streamon(struct file *file, void *priv, | 489 | static int go7007_start_streaming(struct vb2_queue *q, unsigned int count) |
733 | enum v4l2_buf_type type) | ||
734 | { | 490 | { |
735 | struct go7007 *go = video_drvdata(file); | 491 | struct go7007 *go = vb2_get_drv_priv(q); |
736 | int retval = 0; | 492 | int ret; |
737 | |||
738 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
739 | return -EINVAL; | ||
740 | 493 | ||
494 | set_formatting(go); | ||
741 | mutex_lock(&go->hw_lock); | 495 | mutex_lock(&go->hw_lock); |
742 | 496 | go->next_seq = 0; | |
743 | if (!go->streaming) { | 497 | go->active_buf = NULL; |
744 | go->streaming = 1; | 498 | q->streaming = 1; |
745 | go->next_seq = 0; | 499 | if (go7007_start_encoder(go) < 0) |
746 | go->active_buf = NULL; | 500 | ret = -EIO; |
747 | if (go7007_start_encoder(go) < 0) | 501 | else |
748 | retval = -EIO; | 502 | ret = 0; |
749 | else | ||
750 | retval = 0; | ||
751 | } | ||
752 | mutex_unlock(&go->hw_lock); | 503 | mutex_unlock(&go->hw_lock); |
504 | if (ret) { | ||
505 | q->streaming = 0; | ||
506 | return ret; | ||
507 | } | ||
753 | call_all(&go->v4l2_dev, video, s_stream, 1); | 508 | call_all(&go->v4l2_dev, video, s_stream, 1); |
754 | v4l2_ctrl_grab(go->mpeg_video_gop_size, true); | 509 | v4l2_ctrl_grab(go->mpeg_video_gop_size, true); |
755 | v4l2_ctrl_grab(go->mpeg_video_gop_closure, true); | 510 | v4l2_ctrl_grab(go->mpeg_video_gop_closure, true); |
756 | v4l2_ctrl_grab(go->mpeg_video_bitrate, true); | 511 | v4l2_ctrl_grab(go->mpeg_video_bitrate, true); |
757 | v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true); | 512 | v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true); |
758 | 513 | return ret; | |
759 | return retval; | ||
760 | } | 514 | } |
761 | 515 | ||
762 | static int vidioc_streamoff(struct file *file, void *priv, | 516 | static int go7007_stop_streaming(struct vb2_queue *q) |
763 | enum v4l2_buf_type type) | ||
764 | { | 517 | { |
765 | struct go7007 *go = video_drvdata(file); | 518 | struct go7007 *go = vb2_get_drv_priv(q); |
519 | unsigned long flags; | ||
766 | 520 | ||
767 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 521 | q->streaming = 0; |
768 | return -EINVAL; | 522 | go7007_stream_stop(go); |
769 | go7007_streamoff(go); | 523 | mutex_lock(&go->hw_lock); |
524 | go7007_reset_encoder(go); | ||
525 | mutex_unlock(&go->hw_lock); | ||
770 | call_all(&go->v4l2_dev, video, s_stream, 0); | 526 | call_all(&go->v4l2_dev, video, s_stream, 0); |
771 | 527 | ||
528 | spin_lock_irqsave(&go->spinlock, flags); | ||
529 | INIT_LIST_HEAD(&go->vidq_active); | ||
530 | spin_unlock_irqrestore(&go->spinlock, flags); | ||
531 | v4l2_ctrl_grab(go->mpeg_video_gop_size, false); | ||
532 | v4l2_ctrl_grab(go->mpeg_video_gop_closure, false); | ||
533 | v4l2_ctrl_grab(go->mpeg_video_bitrate, false); | ||
534 | v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false); | ||
772 | return 0; | 535 | return 0; |
773 | } | 536 | } |
774 | 537 | ||
538 | static struct vb2_ops go7007_video_qops = { | ||
539 | .queue_setup = go7007_queue_setup, | ||
540 | .buf_queue = go7007_buf_queue, | ||
541 | .buf_prepare = go7007_buf_prepare, | ||
542 | .buf_finish = go7007_buf_finish, | ||
543 | .start_streaming = go7007_start_streaming, | ||
544 | .stop_streaming = go7007_stop_streaming, | ||
545 | .wait_prepare = vb2_ops_wait_prepare, | ||
546 | .wait_finish = vb2_ops_wait_finish, | ||
547 | }; | ||
548 | |||
775 | static int vidioc_g_parm(struct file *filp, void *priv, | 549 | static int vidioc_g_parm(struct file *filp, void *priv, |
776 | struct v4l2_streamparm *parm) | 550 | struct v4l2_streamparm *parm) |
777 | { | 551 | { |
@@ -895,7 +669,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) | |||
895 | { | 669 | { |
896 | struct go7007 *go = video_drvdata(file); | 670 | struct go7007 *go = video_drvdata(file); |
897 | 671 | ||
898 | if (go->streaming) | 672 | if (vb2_is_busy(&go->vidq)) |
899 | return -EBUSY; | 673 | return -EBUSY; |
900 | 674 | ||
901 | go->std = std; | 675 | go->std = std; |
@@ -1006,7 +780,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int input) | |||
1006 | 780 | ||
1007 | if (input >= go->board_info->num_inputs) | 781 | if (input >= go->board_info->num_inputs) |
1008 | return -EINVAL; | 782 | return -EINVAL; |
1009 | if (go->streaming) | 783 | if (vb2_is_busy(&go->vidq)) |
1010 | return -EBUSY; | 784 | return -EBUSY; |
1011 | 785 | ||
1012 | go->input = input; | 786 | go->input = input; |
@@ -1193,95 +967,6 @@ static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop * | |||
1193 | } | 967 | } |
1194 | #endif | 968 | #endif |
1195 | 969 | ||
1196 | static ssize_t go7007_read(struct file *file, char __user *data, | ||
1197 | size_t count, loff_t *ppos) | ||
1198 | { | ||
1199 | return -EINVAL; | ||
1200 | } | ||
1201 | |||
1202 | static void go7007_vm_open(struct vm_area_struct *vma) | ||
1203 | { | ||
1204 | struct go7007_buffer *gobuf = vma->vm_private_data; | ||
1205 | |||
1206 | ++gobuf->mapped; | ||
1207 | } | ||
1208 | |||
1209 | static void go7007_vm_close(struct vm_area_struct *vma) | ||
1210 | { | ||
1211 | struct go7007_buffer *gobuf = vma->vm_private_data; | ||
1212 | unsigned long flags; | ||
1213 | |||
1214 | if (--gobuf->mapped == 0) { | ||
1215 | spin_lock_irqsave(&gobuf->go->spinlock, flags); | ||
1216 | deactivate_buffer(gobuf); | ||
1217 | spin_unlock_irqrestore(&gobuf->go->spinlock, flags); | ||
1218 | } | ||
1219 | } | ||
1220 | |||
1221 | /* Copied from videobuf-dma-sg.c */ | ||
1222 | static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
1223 | { | ||
1224 | struct page *page; | ||
1225 | |||
1226 | page = alloc_page(GFP_USER | __GFP_DMA32); | ||
1227 | if (!page) | ||
1228 | return VM_FAULT_OOM; | ||
1229 | clear_user_highpage(page, (unsigned long)vmf->virtual_address); | ||
1230 | vmf->page = page; | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | static struct vm_operations_struct go7007_vm_ops = { | ||
1235 | .open = go7007_vm_open, | ||
1236 | .close = go7007_vm_close, | ||
1237 | .fault = go7007_vm_fault, | ||
1238 | }; | ||
1239 | |||
1240 | static int go7007_mmap(struct file *file, struct vm_area_struct *vma) | ||
1241 | { | ||
1242 | struct go7007 *go = video_drvdata(file); | ||
1243 | unsigned int index; | ||
1244 | |||
1245 | if (go->status != STATUS_ONLINE) | ||
1246 | return -EIO; | ||
1247 | if (!(vma->vm_flags & VM_SHARED)) | ||
1248 | return -EINVAL; /* only support VM_SHARED mapping */ | ||
1249 | if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE) | ||
1250 | return -EINVAL; /* must map exactly one full buffer */ | ||
1251 | index = vma->vm_pgoff / GO7007_BUF_PAGES; | ||
1252 | if (index >= go->buf_count) | ||
1253 | return -EINVAL; /* trying to map beyond requested buffers */ | ||
1254 | if (index * GO7007_BUF_PAGES != vma->vm_pgoff) | ||
1255 | return -EINVAL; /* offset is not aligned on buffer boundary */ | ||
1256 | if (go->bufs[index].mapped > 0) | ||
1257 | return -EBUSY; | ||
1258 | go->bufs[index].mapped = 1; | ||
1259 | go->bufs[index].user_addr = vma->vm_start; | ||
1260 | vma->vm_ops = &go7007_vm_ops; | ||
1261 | vma->vm_flags |= VM_DONTEXPAND; | ||
1262 | vma->vm_flags &= ~VM_IO; | ||
1263 | vma->vm_private_data = &go->bufs[index]; | ||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | static unsigned int go7007_poll(struct file *file, poll_table *wait) | ||
1268 | { | ||
1269 | unsigned long req_events = poll_requested_events(wait); | ||
1270 | struct go7007 *go = video_drvdata(file); | ||
1271 | struct go7007_buffer *gobuf; | ||
1272 | unsigned int res = v4l2_ctrl_poll(file, wait); | ||
1273 | |||
1274 | if (!(req_events & (POLLIN | POLLRDNORM))) | ||
1275 | return res; | ||
1276 | if (list_empty(&go->stream)) | ||
1277 | return POLLERR; | ||
1278 | gobuf = list_entry(go->stream.next, struct go7007_buffer, stream); | ||
1279 | poll_wait(file, &go->frame_waitq, wait); | ||
1280 | if (gobuf->state == BUF_STATE_DONE) | ||
1281 | return res | POLLIN | POLLRDNORM; | ||
1282 | return res; | ||
1283 | } | ||
1284 | |||
1285 | static void go7007_vfl_release(struct video_device *vfd) | 970 | static void go7007_vfl_release(struct video_device *vfd) |
1286 | { | 971 | { |
1287 | video_device_release(vfd); | 972 | video_device_release(vfd); |
@@ -1290,11 +975,11 @@ static void go7007_vfl_release(struct video_device *vfd) | |||
1290 | static struct v4l2_file_operations go7007_fops = { | 975 | static struct v4l2_file_operations go7007_fops = { |
1291 | .owner = THIS_MODULE, | 976 | .owner = THIS_MODULE, |
1292 | .open = v4l2_fh_open, | 977 | .open = v4l2_fh_open, |
1293 | .release = go7007_release, | 978 | .release = vb2_fop_release, |
1294 | .ioctl = video_ioctl2, | 979 | .unlocked_ioctl = video_ioctl2, |
1295 | .read = go7007_read, | 980 | .read = vb2_fop_read, |
1296 | .mmap = go7007_mmap, | 981 | .mmap = vb2_fop_mmap, |
1297 | .poll = go7007_poll, | 982 | .poll = vb2_fop_poll, |
1298 | }; | 983 | }; |
1299 | 984 | ||
1300 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 985 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
@@ -1303,10 +988,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1303 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 988 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1304 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 989 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1305 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 990 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1306 | .vidioc_reqbufs = vidioc_reqbufs, | 991 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1307 | .vidioc_querybuf = vidioc_querybuf, | 992 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1308 | .vidioc_qbuf = vidioc_qbuf, | 993 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1309 | .vidioc_dqbuf = vidioc_dqbuf, | 994 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1310 | .vidioc_g_std = vidioc_g_std, | 995 | .vidioc_g_std = vidioc_g_std, |
1311 | .vidioc_s_std = vidioc_s_std, | 996 | .vidioc_s_std = vidioc_s_std, |
1312 | .vidioc_querystd = vidioc_querystd, | 997 | .vidioc_querystd = vidioc_querystd, |
@@ -1316,8 +1001,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1316 | .vidioc_enumaudio = vidioc_enumaudio, | 1001 | .vidioc_enumaudio = vidioc_enumaudio, |
1317 | .vidioc_g_audio = vidioc_g_audio, | 1002 | .vidioc_g_audio = vidioc_g_audio, |
1318 | .vidioc_s_audio = vidioc_s_audio, | 1003 | .vidioc_s_audio = vidioc_s_audio, |
1319 | .vidioc_streamon = vidioc_streamon, | 1004 | .vidioc_streamon = vb2_ioctl_streamon, |
1320 | .vidioc_streamoff = vidioc_streamoff, | 1005 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1321 | .vidioc_g_tuner = vidioc_g_tuner, | 1006 | .vidioc_g_tuner = vidioc_g_tuner, |
1322 | .vidioc_s_tuner = vidioc_s_tuner, | 1007 | .vidioc_s_tuner = vidioc_s_tuner, |
1323 | .vidioc_g_frequency = vidioc_g_frequency, | 1008 | .vidioc_g_frequency = vidioc_g_frequency, |
@@ -1379,10 +1064,27 @@ int go7007_v4l2_init(struct go7007 *go) | |||
1379 | { | 1064 | { |
1380 | int rv; | 1065 | int rv; |
1381 | 1066 | ||
1067 | mutex_init(&go->serialize_lock); | ||
1068 | mutex_init(&go->queue_lock); | ||
1069 | |||
1070 | INIT_LIST_HEAD(&go->vidq_active); | ||
1071 | go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1072 | go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; | ||
1073 | go->vidq.ops = &go7007_video_qops; | ||
1074 | go->vidq.mem_ops = &vb2_vmalloc_memops; | ||
1075 | go->vidq.drv_priv = go; | ||
1076 | go->vidq.buf_struct_size = sizeof(struct go7007_buffer); | ||
1077 | go->vidq.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1078 | go->vidq.lock = &go->queue_lock; | ||
1079 | rv = vb2_queue_init(&go->vidq); | ||
1080 | if (rv) | ||
1081 | return rv; | ||
1382 | go->video_dev = video_device_alloc(); | 1082 | go->video_dev = video_device_alloc(); |
1383 | if (go->video_dev == NULL) | 1083 | if (go->video_dev == NULL) |
1384 | return -ENOMEM; | 1084 | return -ENOMEM; |
1385 | *go->video_dev = go7007_template; | 1085 | *go->video_dev = go7007_template; |
1086 | go->video_dev->lock = &go->serialize_lock; | ||
1087 | go->video_dev->queue = &go->vidq; | ||
1386 | set_bit(V4L2_FL_USE_FH_PRIO, &go->video_dev->flags); | 1088 | set_bit(V4L2_FL_USE_FH_PRIO, &go->video_dev->flags); |
1387 | video_set_drvdata(go->video_dev, go); | 1089 | video_set_drvdata(go->video_dev, go); |
1388 | go->video_dev->v4l2_dev = &go->v4l2_dev; | 1090 | go->video_dev->v4l2_dev = &go->v4l2_dev; |
@@ -1436,16 +1138,5 @@ int go7007_v4l2_init(struct go7007 *go) | |||
1436 | 1138 | ||
1437 | void go7007_v4l2_remove(struct go7007 *go) | 1139 | void go7007_v4l2_remove(struct go7007 *go) |
1438 | { | 1140 | { |
1439 | unsigned long flags; | ||
1440 | |||
1441 | mutex_lock(&go->hw_lock); | ||
1442 | if (go->streaming) { | ||
1443 | go->streaming = 0; | ||
1444 | go7007_stream_stop(go); | ||
1445 | spin_lock_irqsave(&go->spinlock, flags); | ||
1446 | abort_queued(go); | ||
1447 | spin_unlock_irqrestore(&go->spinlock, flags); | ||
1448 | } | ||
1449 | mutex_unlock(&go->hw_lock); | ||
1450 | v4l2_ctrl_handler_free(&go->hdl); | 1141 | v4l2_ctrl_handler_free(&go->hdl); |
1451 | } | 1142 | } |
diff --git a/drivers/staging/media/go7007/saa7134-go7007.c b/drivers/staging/media/go7007/saa7134-go7007.c index 4c73945172c8..fa9de3c66dce 100644 --- a/drivers/staging/media/go7007/saa7134-go7007.c +++ b/drivers/staging/media/go7007/saa7134-go7007.c | |||
@@ -236,7 +236,7 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev, | |||
236 | struct go7007 *go = video_get_drvdata(dev->empress_dev); | 236 | struct go7007 *go = video_get_drvdata(dev->empress_dev); |
237 | struct saa7134_go7007 *saa = go->hpi_context; | 237 | struct saa7134_go7007 *saa = go->hpi_context; |
238 | 238 | ||
239 | if (!go->streaming) | 239 | if (!vb2_is_streaming(&go->vidq)) |
240 | return; | 240 | return; |
241 | if (0 != (status & 0x000f0000)) | 241 | if (0 != (status & 0x000f0000)) |
242 | printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", | 242 | printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", |