Re: [PATCHv3 17/20] dvb-frontend: enable tuner link when the FE thread starts

2015-01-08 Thread Shuah Khan
On Tue, Jan 6, 2015 at 2:08 PM, Mauro Carvalho Chehab
mche...@osg.samsung.com wrote:
 If the dvb frontend thread starts, the tuner should be switched
 to the frontend. Add a code that ensures that this will happen,
 using the media controller.

 Signed-off-by: Mauro Carvalho Chehab mche...@osg.samsung.com

 diff --git a/drivers/media/dvb-core/dvb_frontend.c 
 b/drivers/media/dvb-core/dvb_frontend.c
 index c2c559105f64..04e949ad9722 100644
 --- a/drivers/media/dvb-core/dvb_frontend.c
 +++ b/drivers/media/dvb-core/dvb_frontend.c
 @@ -590,12 +590,99 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
 wake_up_interruptible(fepriv-wait_queue);
  }

 +/**
 + * dvb_enable_media_tuner() - tries to enable the DVB tuner
 + *
 + * @fe:struct dvb_frontend pointer
 + *
 + * This function ensures that just one media tuner is enabled for a given
 + * frontend. It has two different behaviors:
 + * - For trivial devices with just one tuner:
 + *   it just enables the existing tuner-fe link
 + * - For devices with more than one tuner:
 + *   It is up to the driver to implement the logic that will enable one tuner
 + *   and disable the other ones. However, if more than one tuner is enabled 
 for
 + *   the same frontend, it will print an error message and return -EINVAL.
 + *
 + * At return, it will return the error code returned by 
 media_entity_setup_link,
 + * or 0 if everything is OK, if no tuner is linked to the frontend or if the
 + * mdev is NULL.
 + */
 +static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 +{
 +#ifdef CONFIG_MEDIA_CONTROLLER
 +   struct dvb_frontend_private *fepriv = fe-frontend_priv;
 +   struct dvb_adapter *adapter = fe-dvb;
 +   struct media_device *mdev = adapter-mdev;
 +   struct media_entity  *entity, *source;
 +   struct media_link *link, *found_link = NULL;
 +   int i, ret, n_links = 0, active_links = 0;
 +
 +   if (!mdev)
 +   return 0;
 +
 +   entity = fepriv-dvbdev-entity;
 +   for (i = 0; i  entity-num_links; i++) {
 +   link = entity-links[i];
 +   if (link-sink-entity == entity) {
 +   found_link = link;
 +   n_links++;
 +   if (link-flags  MEDIA_LNK_FL_ENABLED)
 +   active_links++;
 +   }
 +   }

Does this code path need to be protected with a mutex?

 +
 +   if (!n_links || active_links == 1 || !found_link)
 +   return 0;
 +
 +   /*
 +* If a frontend has more than one tuner linked, it is up to the 
 driver
 +* to select with one will be the active one, as the frontend core 
 can't
 +* guess. If the driver doesn't do that, it is a bug.
 +*/
 +   if (n_links  1  active_links != 1) {
 +   dev_err(fe-dvb-device,
 +   WARNING: there are %d active links among %d tuners. 
 This is a driver's bug!\n,
 +   active_links, n_links);
 +   return -EINVAL;
 +   }
 +
 +   source = found_link-source-entity;
 +   for (i = 0; i  source-num_links; i++) {
 +   struct media_entity *sink;
 +   int flags = 0;
 +
 +   link = source-links[i];
 +   sink = link-sink-entity;
 +
 +   if (sink == entity)
 +   flags = MEDIA_LNK_FL_ENABLED;
 +
 +   ret = media_entity_setup_link(link, flags);
 +   if (ret) {
 +   dev_err(fe-dvb-device,
 +   Couldn't change link %s-%s to %s. Error 
 %d\n,
 +   source-name, sink-name,
 +   flags ? enabled : disabled,
 +   ret);
 +   return ret;
 +   } else
 +   dev_dbg(fe-dvb-device,
 +   link %s-%s was %s\n,
 +   source-name, sink-name,
 +   flags ? ENABLED : disabled);
 +   }
 +#endif
 +   return 0;
 +}
 +
  static int dvb_frontend_thread(void *data)
  {
 struct dvb_frontend *fe = data;
 struct dvb_frontend_private *fepriv = fe-frontend_priv;
 fe_status_t s;
 enum dvbfe_algo algo;
 +   int ret;

 bool re_tune = false;
 bool semheld = false;
 @@ -609,6 +696,13 @@ static int dvb_frontend_thread(void *data)
 fepriv-wakeup = 0;
 fepriv-reinitialise = 0;

 +   ret = dvb_enable_media_tuner(fe);
 +   if (ret) {
 +   /* FIXME: return an error if it fails */
 +   dev_info(fe-dvb-device,
 +   proceeding with FE task\n);
 +   }
 +
 dvb_frontend_init(fe);

 set_freezable();
 --
 2.1.0

 --
 To unsubscribe from this list: send the line unsubscribe linux-media in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  

[PATCHv3 17/20] dvb-frontend: enable tuner link when the FE thread starts

2015-01-06 Thread Mauro Carvalho Chehab
If the dvb frontend thread starts, the tuner should be switched
to the frontend. Add a code that ensures that this will happen,
using the media controller.

Signed-off-by: Mauro Carvalho Chehab mche...@osg.samsung.com

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index c2c559105f64..04e949ad9722 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -590,12 +590,99 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
wake_up_interruptible(fepriv-wait_queue);
 }
 
+/**
+ * dvb_enable_media_tuner() - tries to enable the DVB tuner
+ *
+ * @fe:struct dvb_frontend pointer
+ *
+ * This function ensures that just one media tuner is enabled for a given
+ * frontend. It has two different behaviors:
+ * - For trivial devices with just one tuner:
+ *   it just enables the existing tuner-fe link
+ * - For devices with more than one tuner:
+ *   It is up to the driver to implement the logic that will enable one tuner
+ *   and disable the other ones. However, if more than one tuner is enabled for
+ *   the same frontend, it will print an error message and return -EINVAL.
+ *
+ * At return, it will return the error code returned by 
media_entity_setup_link,
+ * or 0 if everything is OK, if no tuner is linked to the frontend or if the
+ * mdev is NULL.
+ */
+static int dvb_enable_media_tuner(struct dvb_frontend *fe)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+   struct dvb_frontend_private *fepriv = fe-frontend_priv;
+   struct dvb_adapter *adapter = fe-dvb;
+   struct media_device *mdev = adapter-mdev;
+   struct media_entity  *entity, *source;
+   struct media_link *link, *found_link = NULL;
+   int i, ret, n_links = 0, active_links = 0;
+
+   if (!mdev)
+   return 0;
+
+   entity = fepriv-dvbdev-entity;
+   for (i = 0; i  entity-num_links; i++) {
+   link = entity-links[i];
+   if (link-sink-entity == entity) {
+   found_link = link;
+   n_links++;
+   if (link-flags  MEDIA_LNK_FL_ENABLED)
+   active_links++;
+   }
+   }
+
+   if (!n_links || active_links == 1 || !found_link)
+   return 0;
+
+   /*
+* If a frontend has more than one tuner linked, it is up to the driver
+* to select with one will be the active one, as the frontend core can't
+* guess. If the driver doesn't do that, it is a bug.
+*/
+   if (n_links  1  active_links != 1) {
+   dev_err(fe-dvb-device,
+   WARNING: there are %d active links among %d tuners. 
This is a driver's bug!\n,
+   active_links, n_links);
+   return -EINVAL;
+   }
+
+   source = found_link-source-entity;
+   for (i = 0; i  source-num_links; i++) {
+   struct media_entity *sink;
+   int flags = 0;
+
+   link = source-links[i];
+   sink = link-sink-entity;
+
+   if (sink == entity)
+   flags = MEDIA_LNK_FL_ENABLED;
+
+   ret = media_entity_setup_link(link, flags);
+   if (ret) {
+   dev_err(fe-dvb-device,
+   Couldn't change link %s-%s to %s. Error %d\n,
+   source-name, sink-name,
+   flags ? enabled : disabled,
+   ret);
+   return ret;
+   } else
+   dev_dbg(fe-dvb-device,
+   link %s-%s was %s\n,
+   source-name, sink-name,
+   flags ? ENABLED : disabled);
+   }
+#endif
+   return 0;
+}
+
 static int dvb_frontend_thread(void *data)
 {
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe-frontend_priv;
fe_status_t s;
enum dvbfe_algo algo;
+   int ret;
 
bool re_tune = false;
bool semheld = false;
@@ -609,6 +696,13 @@ static int dvb_frontend_thread(void *data)
fepriv-wakeup = 0;
fepriv-reinitialise = 0;
 
+   ret = dvb_enable_media_tuner(fe);
+   if (ret) {
+   /* FIXME: return an error if it fails */
+   dev_info(fe-dvb-device,
+   proceeding with FE task\n);
+   }
+
dvb_frontend_init(fe);
 
set_freezable();
-- 
2.1.0

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html