diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index fcff2e2..ce9d5d4 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -268,6 +268,164 @@ static void au0828_create_media_graph(struct media_entity *new,
 #endif
 }
 
+static int au0828_enable_source(struct media_entity *entity,
+				struct media_pipeline *pipe)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct media_entity  *source;
+	struct media_entity *sink;
+	struct media_link *link, *found_link = NULL;
+	int i, ret = 0;
+	struct media_device *mdev = entity->parent;
+	struct au0828_dev *dev;
+
+	if (!mdev)
+		return -ENODEV;
+
+	/* for ALSA and Video entities, source is the decoder */
+	mutex_lock(&mdev->graph_mutex);
+
+	dev = mdev->source_priv;
+	if (!dev->tuner || !dev->decoder) {
+		ret = -ENODEV;
+		goto end;
+	}
+
+	/*
+	 * For ALSA and V4L2 entity, find the link to which decoder
+	 * is the sink. Look for an active link between decoder and
+	 * tuner, if one exists, nothing to do. If not, look for any
+	 * active links between tuner and any other entity. If one
+	 * exists, tuner is busy. If tuner is free, setup link and
+	 * start pipeline from source (tuner).
+	 * For DVB FE entity, the source for the link is the tuner.
+	 * Check if tuner is available and setup link and start
+	 * pipeline.
+	*/
+	if (entity->type != MEDIA_ENT_T_DEVNODE_DVB_FE)
+		sink = dev->decoder;
+	else
+		sink = entity;
+
+	/* Is an active link between sink and tuner */
+	if (dev->active_link) {
+		if (dev->active_link->sink->entity == sink &&
+		    dev->active_link->source->entity == dev->tuner) {
+			ret = 0;
+			goto end;
+		} else {
+			ret = -EBUSY;
+			goto end;
+		}
+	}
+
+	for (i = 0; i < sink->num_links; i++) {
+		link = &sink->links[i];
+		/* Used to check just the sink, check source too - works?? */
+		if (link->sink->entity == sink &&
+		    link->source->entity == dev->tuner) {
+			found_link = link;
+			break;
+		}
+	}
+
+	if (!found_link) {
+		ret = -ENODEV;
+		goto end;
+	}
+
+	source = found_link->source->entity;
+	for (i = 0; i < source->num_links; i++) {
+		struct media_entity *find_sink;
+		int flags = 0;
+
+		link = &source->links[i];
+		find_sink = link->sink->entity;
+
+		if (find_sink == sink)
+			flags = MEDIA_LNK_FL_ENABLED;
+
+		ret = __media_entity_setup_link(link, flags);
+		if (ret) {
+			pr_err(
+				"Change tuner link %s->%s to %s. Error %d\n",
+				source->name, find_sink->name,
+				flags ? "enabled" : "disabled",
+				ret);
+			goto end;
+		}
+		/* start pipeline */
+		if (find_sink == sink) {
+			dev->active_link = link;
+			ret = __media_entity_pipeline_start(entity, pipe);
+			if (ret) {
+				pr_err("Start Pipeline: %s->%s Error %d\n",
+					source->name, entity->name, ret);
+				goto end;
+			}
+			/* save link owner to avoid audio deactivating
+			   video owned link from disable_source and
+			   vice versa */
+			dev->active_link_owner = entity;
+			pr_info("Started Pipeline: %s->%s ret %d\n",
+				source->name, entity->name, ret);
+		}
+	}
+end:
+	mutex_unlock(&mdev->graph_mutex);
+	return ret;
+#endif
+	return 0;
+}
+
+static void au0828_disable_source(struct media_entity *entity)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct media_entity *sink;
+	int ret = 0;
+	struct media_device *mdev = entity->parent;
+	struct au0828_dev *dev;
+
+	if (!mdev)
+		return;
+
+	mutex_lock(&mdev->graph_mutex);
+
+	dev = mdev->source_priv;
+	if (!dev->tuner || !dev->decoder || !dev->active_link) {
+		ret = -ENODEV;
+		goto end;
+	}
+
+	if (entity->type != MEDIA_ENT_T_DEVNODE_DVB_FE)
+		sink = dev->decoder;
+	else
+		sink = entity;
+
+	/* link is active - stop pipeline from source (tuner) */
+	if (dev->active_link && dev->active_link->sink->entity == sink &&
+	    dev->active_link->source->entity == dev->tuner) {
+		/* prevent video from deactivating link when audio
+		   has active pipeline */
+		if (dev->active_link_owner != entity)
+			goto end;
+		__media_entity_pipeline_stop(entity);
+		pr_info("Stopped Pipeline: %s->%s entity %s\n",
+			dev->active_link->source->entity->name,
+			dev->active_link->sink->entity->name,
+			entity->name);
+		ret = __media_entity_setup_link(dev->active_link, 0);
+		if (ret)
+			pr_err("Deactive link Error %d\n", ret);
+		dev->active_link = NULL;
+		dev->active_link_owner = NULL;
+	}
+
+end:
+	mutex_unlock(&mdev->graph_mutex);
+#endif
+}
+
 static void au0828_media_device_register(struct au0828_dev *dev,
 					  struct usb_device *udev)
 {
@@ -291,6 +449,10 @@ static void au0828_media_device_register(struct au0828_dev *dev,
 				sizeof(mdev->serial));
 		strcpy(mdev->bus_info, udev->devpath);
 		mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+		/* Set enable_source and disable_source handlers and data */
+		mdev->source_priv = (void *) dev;
+		mdev->enable_source = au0828_enable_source;
+		mdev->disable_source = au0828_disable_source;
 		ret = media_device_register(mdev);
 		if (ret) {
 			dev_err(&udev->dev,
@@ -303,6 +465,13 @@ static void au0828_media_device_register(struct au0828_dev *dev,
 		dev->entity_notify.notify = au0828_create_media_graph;
 		media_device_register_entity_notify(mdev, &dev->entity_notify);
 	}
+	/* If ALSA registered the media device - set enable_source */
+	if (!mdev->enable_source) {
+		/* Set enable_source and disable_source handlers and data */
+		mdev->source_priv = (void *) dev;
+		mdev->enable_source = au0828_enable_source;
+		mdev->disable_source = au0828_disable_source;
+	}
 	dev->media_dev = mdev;
 #endif
 }
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 08cc7b8..f64dbbb 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -287,6 +287,8 @@ struct au0828_dev {
 	bool vdev_linked;
 	bool vbi_linked;
 	bool alsa_capture_linked;
+	struct media_link *active_link;
+	struct media_entity *active_link_owner;
 #endif
 };
 
