diff options
author | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-01-06 13:26:06 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-02-13 18:10:16 -0500 |
commit | 0f0fa90bd035fa15106799b813d4f0315d99f47e (patch) | |
tree | 8d7ff91f7852d1a6702ba685dfe2ae18ee12b250 | |
parent | 9239effd53d47e3cd9c653830c8465c0a3a427dc (diff) |
[media] cx231xx: enable tuner->decoder link at videobuf start
The tuner->decoder needs to be enabled when we're about to
start streaming.
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-video.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index f3d1a488dfa7..634763535d60 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c | |||
@@ -703,6 +703,74 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) | |||
703 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 703 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
704 | } | 704 | } |
705 | 705 | ||
706 | static int cx231xx_enable_analog_tuner(struct cx231xx *dev) | ||
707 | { | ||
708 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
709 | struct media_device *mdev = dev->media_dev; | ||
710 | struct media_entity *entity, *decoder = NULL, *source; | ||
711 | struct media_link *link, *found_link = NULL; | ||
712 | int i, ret, active_links = 0; | ||
713 | |||
714 | if (!mdev) | ||
715 | return 0; | ||
716 | |||
717 | /* | ||
718 | * This will find the tuner that it is connected into the decoder. | ||
719 | * Technically, this is not 100% correct, as the device may be using an | ||
720 | * analog input instead of the tuner. However, we can't use the DVB for dvb | ||
721 | * while the DMA engine is being used for V4L2. | ||
722 | */ | ||
723 | media_device_for_each_entity(entity, mdev) { | ||
724 | if (entity->type == MEDIA_ENT_T_V4L2_SUBDEV_DECODER) { | ||
725 | decoder = entity; | ||
726 | break; | ||
727 | } | ||
728 | } | ||
729 | if (!decoder) | ||
730 | return 0; | ||
731 | |||
732 | for (i = 0; i < decoder->num_links; i++) { | ||
733 | link = &decoder->links[i]; | ||
734 | if (link->sink->entity == decoder) { | ||
735 | found_link = link; | ||
736 | if (link->flags & MEDIA_LNK_FL_ENABLED) | ||
737 | active_links++; | ||
738 | break; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | if (active_links == 1 || !found_link) | ||
743 | return 0; | ||
744 | |||
745 | source = found_link->source->entity; | ||
746 | for (i = 0; i < source->num_links; i++) { | ||
747 | struct media_entity *sink; | ||
748 | int flags = 0; | ||
749 | |||
750 | link = &source->links[i]; | ||
751 | sink = link->sink->entity; | ||
752 | |||
753 | if (sink == entity) | ||
754 | flags = MEDIA_LNK_FL_ENABLED; | ||
755 | |||
756 | ret = media_entity_setup_link(link, flags); | ||
757 | if (ret) { | ||
758 | dev_err(dev->dev, | ||
759 | "Couldn't change link %s->%s to %s. Error %d\n", | ||
760 | source->name, sink->name, | ||
761 | flags ? "enabled" : "disabled", | ||
762 | ret); | ||
763 | return ret; | ||
764 | } else | ||
765 | dev_dbg(dev->dev, | ||
766 | "link %s->%s was %s\n", | ||
767 | source->name, sink->name, | ||
768 | flags ? "ENABLED" : "disabled"); | ||
769 | } | ||
770 | #endif | ||
771 | return 0; | ||
772 | } | ||
773 | |||
706 | static int | 774 | static int |
707 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | 775 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
708 | enum v4l2_field field) | 776 | enum v4l2_field field) |
@@ -756,6 +824,9 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
756 | } | 824 | } |
757 | 825 | ||
758 | buf->vb.state = VIDEOBUF_PREPARED; | 826 | buf->vb.state = VIDEOBUF_PREPARED; |
827 | |||
828 | cx231xx_enable_analog_tuner(dev); | ||
829 | |||
759 | return 0; | 830 | return 0; |
760 | 831 | ||
761 | fail: | 832 | fail: |