All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/22] Sharing media resources across ALSA and au0828 drivers
@ 2016-02-04  4:03 ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

This patch series updates ALSA driver, and au0828 core
driver to use Managed Media controller API and Media
Controller API to share media resource (tuner).

This Patch v2 series is based on linux_media master.
This work addresses Mauro and Takashi's comments.

Composite or S-Video connector is the input case
is still under discussion and isn't addressed in
this series.

Patches 3 and 4 need documentation updates and will
be sent later this week.

Shuah Khan (22):
  uapi/media.h: Declare interface types for ALSA
  media: Add ALSA Media Controller function entities
  media: Media Controller register/unregister entity_notify API
  media: Media Controller enable/disable source handler API
  media: Media Controller export non locking __media_entity_setup_link()
  media: Media Controller non-locking
    __media_entity_pipeline_start/stop()
  media: v4l-core add enable/disable source common interfaces
  media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
  media: au8522 change to create MC pad for ALSA Audio Out
  media: Change v4l-core to check if source is free
  media: dvb-frontend invoke enable/disable_source handlers
  media: au0828 video remove au0828_enable_analog_tuner()
  media: au0828 video change to use v4l_enable_media_source()
  media: au0828 change to use Managed Media Controller API
  media: au0828 handle media_init and media_register window
  media: au0828 create tuner to decoder link in disabled state
  media: au0828 disable tuner to demod link
  media: au0828 Use au8522_media_pads enum for pad defines
  media: au0828-core register entity_notify hook
  media: au0828 add enable, disable source handlers
  sound/usb: Use Media Controller API to share media resources
  media: Ensure media device unregister is done only once

 drivers/media/dvb-core/dvb_frontend.c        | 139 ++----------
 drivers/media/dvb-core/dvb_frontend.h        |   3 +
 drivers/media/dvb-frontends/au8522.h         |   8 +
 drivers/media/dvb-frontends/au8522_decoder.c |   1 +
 drivers/media/dvb-frontends/au8522_priv.h    |   8 -
 drivers/media/media-device.c                 |  73 +++++-
 drivers/media/media-devnode.c                |  15 +-
 drivers/media/media-entity.c                 |  51 ++++-
 drivers/media/usb/au0828/au0828-core.c       | 272 +++++++++++++++++++++--
 drivers/media/usb/au0828/au0828-video.c      |  75 +------
 drivers/media/usb/au0828/au0828.h            |   4 +
 drivers/media/v4l2-core/Makefile             |   2 +-
 drivers/media/v4l2-core/v4l2-fh.c            |   2 +
 drivers/media/v4l2-core/v4l2-ioctl.c         |  30 +++
 drivers/media/v4l2-core/v4l2-mc.c            |  60 +++++
 drivers/media/v4l2-core/videobuf2-core.c     |   4 +
 include/media/media-device.h                 |  44 ++++
 include/media/media-devnode.h                |  17 ++
 include/media/media-entity.h                 |  12 +
 include/media/v4l2-dev.h                     |   1 +
 include/media/v4l2-mc.h                      |  52 +++++
 include/uapi/linux/media.h                   |  33 +++
 sound/usb/Kconfig                            |   4 +
 sound/usb/Makefile                           |   2 +
 sound/usb/card.c                             |  14 ++
 sound/usb/card.h                             |   1 +
 sound/usb/media.c                            | 319 +++++++++++++++++++++++++++
 sound/usb/media.h                            |  72 ++++++
 sound/usb/mixer.h                            |   1 +
 sound/usb/pcm.c                              |  28 ++-
 sound/usb/quirks-table.h                     |   1 +
 sound/usb/stream.c                           |   2 +
 sound/usb/usbaudio.h                         |   3 +
 33 files changed, 1117 insertions(+), 236 deletions(-)
 create mode 100644 drivers/media/v4l2-core/v4l2-mc.c
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

-- 
2.5.0

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 00/22] Sharing media resources across ALSA and au0828 drivers
@ 2016-02-04  4:03 ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab-JPH+aEBZ4P+UEJcrhfAQsw, tiwai-IBi9RG/b67k,
	clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw
  Cc: Shuah Khan, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs-mcfjX3dozePR7s880joybQ,
	johan-v8HUHnYb0Yo, klock.android-Re5JQEeQqe8AvxtiuMwx3w,
	nenggun.kim-Sze3O3UU22JBDgjK7y7TUQ,
	j.anaszewski-Sze3O3UU22JBDgjK7y7TUQ, geliangtang

This patch series updates ALSA driver, and au0828 core
driver to use Managed Media controller API and Media
Controller API to share media resource (tuner).

This Patch v2 series is based on linux_media master.
This work addresses Mauro and Takashi's comments.

Composite or S-Video connector is the input case
is still under discussion and isn't addressed in
this series.

Patches 3 and 4 need documentation updates and will
be sent later this week.

Shuah Khan (22):
  uapi/media.h: Declare interface types for ALSA
  media: Add ALSA Media Controller function entities
  media: Media Controller register/unregister entity_notify API
  media: Media Controller enable/disable source handler API
  media: Media Controller export non locking __media_entity_setup_link()
  media: Media Controller non-locking
    __media_entity_pipeline_start/stop()
  media: v4l-core add enable/disable source common interfaces
  media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
  media: au8522 change to create MC pad for ALSA Audio Out
  media: Change v4l-core to check if source is free
  media: dvb-frontend invoke enable/disable_source handlers
  media: au0828 video remove au0828_enable_analog_tuner()
  media: au0828 video change to use v4l_enable_media_source()
  media: au0828 change to use Managed Media Controller API
  media: au0828 handle media_init and media_register window
  media: au0828 create tuner to decoder link in disabled state
  media: au0828 disable tuner to demod link
  media: au0828 Use au8522_media_pads enum for pad defines
  media: au0828-core register entity_notify hook
  media: au0828 add enable, disable source handlers
  sound/usb: Use Media Controller API to share media resources
  media: Ensure media device unregister is done only once

 drivers/media/dvb-core/dvb_frontend.c        | 139 ++----------
 drivers/media/dvb-core/dvb_frontend.h        |   3 +
 drivers/media/dvb-frontends/au8522.h         |   8 +
 drivers/media/dvb-frontends/au8522_decoder.c |   1 +
 drivers/media/dvb-frontends/au8522_priv.h    |   8 -
 drivers/media/media-device.c                 |  73 +++++-
 drivers/media/media-devnode.c                |  15 +-
 drivers/media/media-entity.c                 |  51 ++++-
 drivers/media/usb/au0828/au0828-core.c       | 272 +++++++++++++++++++++--
 drivers/media/usb/au0828/au0828-video.c      |  75 +------
 drivers/media/usb/au0828/au0828.h            |   4 +
 drivers/media/v4l2-core/Makefile             |   2 +-
 drivers/media/v4l2-core/v4l2-fh.c            |   2 +
 drivers/media/v4l2-core/v4l2-ioctl.c         |  30 +++
 drivers/media/v4l2-core/v4l2-mc.c            |  60 +++++
 drivers/media/v4l2-core/videobuf2-core.c     |   4 +
 include/media/media-device.h                 |  44 ++++
 include/media/media-devnode.h                |  17 ++
 include/media/media-entity.h                 |  12 +
 include/media/v4l2-dev.h                     |   1 +
 include/media/v4l2-mc.h                      |  52 +++++
 include/uapi/linux/media.h                   |  33 +++
 sound/usb/Kconfig                            |   4 +
 sound/usb/Makefile                           |   2 +
 sound/usb/card.c                             |  14 ++
 sound/usb/card.h                             |   1 +
 sound/usb/media.c                            | 319 +++++++++++++++++++++++++++
 sound/usb/media.h                            |  72 ++++++
 sound/usb/mixer.h                            |   1 +
 sound/usb/pcm.c                              |  28 ++-
 sound/usb/quirks-table.h                     |   1 +
 sound/usb/stream.c                           |   2 +
 sound/usb/usbaudio.h                         |   3 +
 33 files changed, 1117 insertions(+), 236 deletions(-)
 create mode 100644 drivers/media/v4l2-core/v4l2-mc.c
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

-- 
2.5.0

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 01/22] uapi/media.h: Declare interface types for ALSA
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Declare the interface types to be used on alsa for
the new G_TOPOLOGY ioctl.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-entity.c | 16 ++++++++++++++++
 include/uapi/linux/media.h   | 22 ++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index f2e4360..6179543 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -65,6 +65,22 @@ static inline const char *intf_type(struct media_interface *intf)
 		return "v4l2-subdev";
 	case MEDIA_INTF_T_V4L_SWRADIO:
 		return "swradio";
+	case MEDIA_INTF_T_ALSA_PCM_CAPTURE:
+		return "pcm-capture";
+	case MEDIA_INTF_T_ALSA_PCM_PLAYBACK:
+		return "pcm-playback";
+	case MEDIA_INTF_T_ALSA_CONTROL:
+		return "alsa-control";
+	case MEDIA_INTF_T_ALSA_COMPRESS:
+		return "compress";
+	case MEDIA_INTF_T_ALSA_RAWMIDI:
+		return "rawmidi";
+	case MEDIA_INTF_T_ALSA_HWDEP:
+		return "hwdep";
+	case MEDIA_INTF_T_ALSA_SEQUENCER:
+		return "sequencer";
+	case MEDIA_INTF_T_ALSA_TIMER:
+		return "timer";
 	default:
 		return "unknown-intf";
 	}
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index c9eb42a..ee020e8 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -265,6 +265,7 @@ struct media_links_enum {
 
 #define MEDIA_INTF_T_DVB_BASE	0x00000100
 #define MEDIA_INTF_T_V4L_BASE	0x00000200
+#define MEDIA_INTF_T_ALSA_BASE	0x00000300
 
 /* Interface types */
 
@@ -280,6 +281,27 @@ struct media_links_enum {
 #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
 #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
 
+/**
+ * DOC: Media Controller Next Generation ALSA Interface Types
+ *
+ * MEDIA_INTF_T_ALSA_PCM_CAPTURE - PCM Capture Interface (pcm-capture)
+ * MEDIA_INTF_T_ALSA_PCM_PLAYBACK -  PCM Playback Interface (pcm-playback)
+ * MEDIA_INTF_T_ALSA_CONTROL -  ALSA Control Interface (alsa-control)
+ * MEDIA_INTF_T_ALSA_COMPRESS - ALSA Compression Interface (compress)
+ * MEDIA_INTF_T_ALSA_RAWMIDI - ALSA Raw MIDI Interface (rawmidi)
+ * MEDIA_INTF_T_ALSA_HWDEP - ALSA Hardware Dependent Interface (hwdep)
+ * MEDIA_INTF_T_ALSA_SEQUENCER - ALSA Sequencer (sequencer)
+ * MEDIA_INTF_T_ALSA_TIMER - ALSA Timer (timer)
+ */
+#define MEDIA_INTF_T_ALSA_PCM_CAPTURE   (MEDIA_INTF_T_ALSA_BASE)
+#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK  (MEDIA_INTF_T_ALSA_BASE + 1)
+#define MEDIA_INTF_T_ALSA_CONTROL       (MEDIA_INTF_T_ALSA_BASE + 2)
+#define MEDIA_INTF_T_ALSA_COMPRESS      (MEDIA_INTF_T_ALSA_BASE + 3)
+#define MEDIA_INTF_T_ALSA_RAWMIDI       (MEDIA_INTF_T_ALSA_BASE + 4)
+#define MEDIA_INTF_T_ALSA_HWDEP         (MEDIA_INTF_T_ALSA_BASE + 5)
+#define MEDIA_INTF_T_ALSA_SEQUENCER     (MEDIA_INTF_T_ALSA_BASE + 6)
+#define MEDIA_INTF_T_ALSA_TIMER         (MEDIA_INTF_T_ALSA_BASE + 7)
+
 /*
  * MC next gen API definitions
  *
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 01/22] uapi/media.h: Declare interface types for ALSA
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Declare the interface types to be used on alsa for
the new G_TOPOLOGY ioctl.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-entity.c | 16 ++++++++++++++++
 include/uapi/linux/media.h   | 22 ++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index f2e4360..6179543 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -65,6 +65,22 @@ static inline const char *intf_type(struct media_interface *intf)
 		return "v4l2-subdev";
 	case MEDIA_INTF_T_V4L_SWRADIO:
 		return "swradio";
+	case MEDIA_INTF_T_ALSA_PCM_CAPTURE:
+		return "pcm-capture";
+	case MEDIA_INTF_T_ALSA_PCM_PLAYBACK:
+		return "pcm-playback";
+	case MEDIA_INTF_T_ALSA_CONTROL:
+		return "alsa-control";
+	case MEDIA_INTF_T_ALSA_COMPRESS:
+		return "compress";
+	case MEDIA_INTF_T_ALSA_RAWMIDI:
+		return "rawmidi";
+	case MEDIA_INTF_T_ALSA_HWDEP:
+		return "hwdep";
+	case MEDIA_INTF_T_ALSA_SEQUENCER:
+		return "sequencer";
+	case MEDIA_INTF_T_ALSA_TIMER:
+		return "timer";
 	default:
 		return "unknown-intf";
 	}
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index c9eb42a..ee020e8 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -265,6 +265,7 @@ struct media_links_enum {
 
 #define MEDIA_INTF_T_DVB_BASE	0x00000100
 #define MEDIA_INTF_T_V4L_BASE	0x00000200
+#define MEDIA_INTF_T_ALSA_BASE	0x00000300
 
 /* Interface types */
 
@@ -280,6 +281,27 @@ struct media_links_enum {
 #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
 #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
 
+/**
+ * DOC: Media Controller Next Generation ALSA Interface Types
+ *
+ * MEDIA_INTF_T_ALSA_PCM_CAPTURE - PCM Capture Interface (pcm-capture)
+ * MEDIA_INTF_T_ALSA_PCM_PLAYBACK -  PCM Playback Interface (pcm-playback)
+ * MEDIA_INTF_T_ALSA_CONTROL -  ALSA Control Interface (alsa-control)
+ * MEDIA_INTF_T_ALSA_COMPRESS - ALSA Compression Interface (compress)
+ * MEDIA_INTF_T_ALSA_RAWMIDI - ALSA Raw MIDI Interface (rawmidi)
+ * MEDIA_INTF_T_ALSA_HWDEP - ALSA Hardware Dependent Interface (hwdep)
+ * MEDIA_INTF_T_ALSA_SEQUENCER - ALSA Sequencer (sequencer)
+ * MEDIA_INTF_T_ALSA_TIMER - ALSA Timer (timer)
+ */
+#define MEDIA_INTF_T_ALSA_PCM_CAPTURE   (MEDIA_INTF_T_ALSA_BASE)
+#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK  (MEDIA_INTF_T_ALSA_BASE + 1)
+#define MEDIA_INTF_T_ALSA_CONTROL       (MEDIA_INTF_T_ALSA_BASE + 2)
+#define MEDIA_INTF_T_ALSA_COMPRESS      (MEDIA_INTF_T_ALSA_BASE + 3)
+#define MEDIA_INTF_T_ALSA_RAWMIDI       (MEDIA_INTF_T_ALSA_BASE + 4)
+#define MEDIA_INTF_T_ALSA_HWDEP         (MEDIA_INTF_T_ALSA_BASE + 5)
+#define MEDIA_INTF_T_ALSA_SEQUENCER     (MEDIA_INTF_T_ALSA_BASE + 6)
+#define MEDIA_INTF_T_ALSA_TIMER         (MEDIA_INTF_T_ALSA_BASE + 7)
+
 /*
  * MC next gen API definitions
  *
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 02/22] media: Add ALSA Media Controller function entities
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add ALSA Media Controller capture, playback, and mixer
function entity defines.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 include/uapi/linux/media.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index ee020e8..7d50480 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -98,6 +98,17 @@ struct media_device_info {
 #define MEDIA_ENT_F_IF_AUD_DECODER	(MEDIA_ENT_F_BASE + 42)
 
 /*
+ * DOC: Media Controller Next Generation ALSA Function Entities
+ *
+ * MEDIA_ENT_F_AUDIO_CAPTURE - Audio Capture Function
+ * MEDIA_ENT_F_AUDIO_PLAYBACK - Audio Play Back Function
+ * MEDIA_ENT_F_AUDIO_MIXER - Audio Mixer Function
+*/
+#define MEDIA_ENT_F_AUDIO_CAPTURE	(MEDIA_ENT_F_BASE + 200)
+#define MEDIA_ENT_F_AUDIO_PLAYBACK	(MEDIA_ENT_F_BASE + 201)
+#define MEDIA_ENT_F_AUDIO_MIXER		(MEDIA_ENT_F_BASE + 202)
+
+/*
  * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and
  * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility
  * with the legacy v1 API.The number range is out of range by purpose:
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 02/22] media: Add ALSA Media Controller function entities
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab-JPH+aEBZ4P+UEJcrhfAQsw, tiwai-IBi9RG/b67k,
	clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw
  Cc: Shuah Khan, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs-mcfjX3dozePR7s880joybQ,
	johan-v8HUHnYb0Yo, klock.android-Re5JQEeQqe8AvxtiuMwx3w,
	nenggun.kim-Sze3O3UU22JBDgjK7y7TUQ,
	j.anaszewski-Sze3O3UU22JBDgjK7y7TUQ, geliangtang

Add ALSA Media Controller capture, playback, and mixer
function entity defines.

Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
---
 include/uapi/linux/media.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index ee020e8..7d50480 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -98,6 +98,17 @@ struct media_device_info {
 #define MEDIA_ENT_F_IF_AUD_DECODER	(MEDIA_ENT_F_BASE + 42)
 
 /*
+ * DOC: Media Controller Next Generation ALSA Function Entities
+ *
+ * MEDIA_ENT_F_AUDIO_CAPTURE - Audio Capture Function
+ * MEDIA_ENT_F_AUDIO_PLAYBACK - Audio Play Back Function
+ * MEDIA_ENT_F_AUDIO_MIXER - Audio Mixer Function
+*/
+#define MEDIA_ENT_F_AUDIO_CAPTURE	(MEDIA_ENT_F_BASE + 200)
+#define MEDIA_ENT_F_AUDIO_PLAYBACK	(MEDIA_ENT_F_BASE + 201)
+#define MEDIA_ENT_F_AUDIO_MIXER		(MEDIA_ENT_F_BASE + 202)
+
+/*
  * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and
  * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility
  * with the legacy v1 API.The number range is out of range by purpose:
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 03/22] media: Media Controller register/unregister entity_notify API
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add new interfaces to register and unregister entity_notify
hook to media device. These interfaces allow drivers to add
hooks to take appropriate actions when new entities get added
to a shared media device. For example, au0828 bridge driver
registers an entity_notify hook to create links as needed
between media graph nodes.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 include/media/media-device.h | 25 ++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 4d1c13d..1f5d67e 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -536,6 +536,7 @@ static void media_device_release(struct media_devnode *mdev)
 int __must_check media_device_register_entity(struct media_device *mdev,
 					      struct media_entity *entity)
 {
+	struct media_entity_notify *notify, *next;
 	unsigned int i;
 	int ret;
 
@@ -575,6 +576,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
 			       &entity->pads[i].graph_obj);
 
+	/* invoke entity_notify callbacks */
+	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
+		(notify)->notify(entity, notify->notify_data);
+	}
+
 	spin_unlock(&mdev->lock);
 
 	return 0;
@@ -608,6 +614,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
 	/* Remove the entity */
 	media_gobj_destroy(&entity->graph_obj);
 
+	/* invoke entity_notify callbacks to handle entity removal?? */
+
 	entity->graph_obj.mdev = NULL;
 }
 
@@ -640,6 +648,7 @@ void media_device_init(struct media_device *mdev)
 	INIT_LIST_HEAD(&mdev->interfaces);
 	INIT_LIST_HEAD(&mdev->pads);
 	INIT_LIST_HEAD(&mdev->links);
+	INIT_LIST_HEAD(&mdev->entity_notify);
 	spin_lock_init(&mdev->lock);
 	mutex_init(&mdev->graph_mutex);
 	ida_init(&mdev->entity_internal_idx);
@@ -685,11 +694,59 @@ int __must_check __media_device_register(struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
 
+/**
+ * media_device_register_entity_notify - Register a media entity notify
+ * callback with a media device. When a new entity is registered, all
+ * the registered media_entity_notify callbacks are invoked.
+ * @mdev:      The media device
+ * @nptr:      The media_entity_notify
+ */
+int __must_check media_device_register_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	spin_lock(&mdev->lock);
+	list_add_tail(&nptr->list, &mdev->entity_notify);
+	spin_unlock(&mdev->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
+
+/**
+ * __media_device_unregister_entity_notify - Unregister a media entity notify
+ * callback with a media device. When a new entity is registered, all
+ * the registered media_entity_notify callbacks are invoked.
+ * @mdev:      The media device
+ * @nptr:      The media_entity_notify
+ * Non-locking version. Should be called with mdev->lock held.
+ */
+static void __media_device_unregister_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	list_del(&nptr->list);
+}
+
+/**
+ * media_device_unregister_entity_notify - Unregister a media entity notify
+ * callback with a media device. When a new entity is registered, all
+ * the registered media_entity_notify callbacks are invoked.
+ * @mdev:      The media device
+ * @nptr:      The media_entity_notify
+ */
+void media_device_unregister_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	spin_lock(&mdev->lock);
+	__media_device_unregister_entity_notify(mdev, nptr);
+	spin_unlock(&mdev->lock);
+}
+EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
+
 void media_device_unregister(struct media_device *mdev)
 {
 	struct media_entity *entity;
 	struct media_entity *next;
 	struct media_interface *intf, *tmp_intf;
+	struct media_entity_notify *notify, *nextp;
 
 	if (mdev == NULL)
 		return;
@@ -706,6 +763,10 @@ void media_device_unregister(struct media_device *mdev)
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		__media_device_unregister_entity(entity);
 
+	/* Remove all entity_notify callbacks from the media device */
+	list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
+		__media_device_unregister_entity_notify(mdev, notify);
+
 	/* Remove all interfaces from the media device */
 	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
 				 graph_obj.list) {
diff --git a/include/media/media-device.h b/include/media/media-device.h
index d385589..bad8242a 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -264,6 +264,12 @@
 struct ida;
 struct device;
 
+struct media_entity_notify {
+	struct list_head list;
+	void *notify_data;
+	void (*notify)(struct media_entity *entity, void *notify_data);
+};
+
 /**
  * struct media_device - Media device
  * @dev:	Parent device
@@ -319,6 +325,9 @@ struct media_device {
 	struct list_head pads;
 	struct list_head links;
 
+	/* notify callback list invoked when a new entity is registered */
+	struct list_head entity_notify;
+
 	/* Protects the graph objects creation/removal */
 	spinlock_t lock;
 	/* Serializes graph operations. */
@@ -497,6 +506,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
  */
 void media_device_unregister_entity(struct media_entity *entity);
 
+int __must_check media_device_register_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr);
+void media_device_unregister_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr);
+
 /**
  * media_device_get_devres() -	get media device as device resource
  *				creates if one doesn't exist
@@ -552,6 +566,17 @@ static inline int media_device_register_entity(struct media_device *mdev,
 static inline void media_device_unregister_entity(struct media_entity *entity)
 {
 }
+static inline int media_device_register_entity_notify(
+					struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	return 0;
+}
+static inline void media_device_unregister_entity_notify(
+					struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+}
 static inline struct media_device *media_device_get_devres(struct device *dev)
 {
 	return NULL;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 03/22] media: Media Controller register/unregister entity_notify API
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Add new interfaces to register and unregister entity_notify
hook to media device. These interfaces allow drivers to add
hooks to take appropriate actions when new entities get added
to a shared media device. For example, au0828 bridge driver
registers an entity_notify hook to create links as needed
between media graph nodes.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 include/media/media-device.h | 25 ++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 4d1c13d..1f5d67e 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -536,6 +536,7 @@ static void media_device_release(struct media_devnode *mdev)
 int __must_check media_device_register_entity(struct media_device *mdev,
 					      struct media_entity *entity)
 {
+	struct media_entity_notify *notify, *next;
 	unsigned int i;
 	int ret;
 
@@ -575,6 +576,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
 			       &entity->pads[i].graph_obj);
 
+	/* invoke entity_notify callbacks */
+	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
+		(notify)->notify(entity, notify->notify_data);
+	}
+
 	spin_unlock(&mdev->lock);
 
 	return 0;
@@ -608,6 +614,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
 	/* Remove the entity */
 	media_gobj_destroy(&entity->graph_obj);
 
+	/* invoke entity_notify callbacks to handle entity removal?? */
+
 	entity->graph_obj.mdev = NULL;
 }
 
@@ -640,6 +648,7 @@ void media_device_init(struct media_device *mdev)
 	INIT_LIST_HEAD(&mdev->interfaces);
 	INIT_LIST_HEAD(&mdev->pads);
 	INIT_LIST_HEAD(&mdev->links);
+	INIT_LIST_HEAD(&mdev->entity_notify);
 	spin_lock_init(&mdev->lock);
 	mutex_init(&mdev->graph_mutex);
 	ida_init(&mdev->entity_internal_idx);
@@ -685,11 +694,59 @@ int __must_check __media_device_register(struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
 
+/**
+ * media_device_register_entity_notify - Register a media entity notify
+ * callback with a media device. When a new entity is registered, all
+ * the registered media_entity_notify callbacks are invoked.
+ * @mdev:      The media device
+ * @nptr:      The media_entity_notify
+ */
+int __must_check media_device_register_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	spin_lock(&mdev->lock);
+	list_add_tail(&nptr->list, &mdev->entity_notify);
+	spin_unlock(&mdev->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
+
+/**
+ * __media_device_unregister_entity_notify - Unregister a media entity notify
+ * callback with a media device. When a new entity is registered, all
+ * the registered media_entity_notify callbacks are invoked.
+ * @mdev:      The media device
+ * @nptr:      The media_entity_notify
+ * Non-locking version. Should be called with mdev->lock held.
+ */
+static void __media_device_unregister_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	list_del(&nptr->list);
+}
+
+/**
+ * media_device_unregister_entity_notify - Unregister a media entity notify
+ * callback with a media device. When a new entity is registered, all
+ * the registered media_entity_notify callbacks are invoked.
+ * @mdev:      The media device
+ * @nptr:      The media_entity_notify
+ */
+void media_device_unregister_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	spin_lock(&mdev->lock);
+	__media_device_unregister_entity_notify(mdev, nptr);
+	spin_unlock(&mdev->lock);
+}
+EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
+
 void media_device_unregister(struct media_device *mdev)
 {
 	struct media_entity *entity;
 	struct media_entity *next;
 	struct media_interface *intf, *tmp_intf;
+	struct media_entity_notify *notify, *nextp;
 
 	if (mdev == NULL)
 		return;
@@ -706,6 +763,10 @@ void media_device_unregister(struct media_device *mdev)
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		__media_device_unregister_entity(entity);
 
+	/* Remove all entity_notify callbacks from the media device */
+	list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
+		__media_device_unregister_entity_notify(mdev, notify);
+
 	/* Remove all interfaces from the media device */
 	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
 				 graph_obj.list) {
diff --git a/include/media/media-device.h b/include/media/media-device.h
index d385589..bad8242a 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -264,6 +264,12 @@
 struct ida;
 struct device;
 
+struct media_entity_notify {
+	struct list_head list;
+	void *notify_data;
+	void (*notify)(struct media_entity *entity, void *notify_data);
+};
+
 /**
  * struct media_device - Media device
  * @dev:	Parent device
@@ -319,6 +325,9 @@ struct media_device {
 	struct list_head pads;
 	struct list_head links;
 
+	/* notify callback list invoked when a new entity is registered */
+	struct list_head entity_notify;
+
 	/* Protects the graph objects creation/removal */
 	spinlock_t lock;
 	/* Serializes graph operations. */
@@ -497,6 +506,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
  */
 void media_device_unregister_entity(struct media_entity *entity);
 
+int __must_check media_device_register_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr);
+void media_device_unregister_entity_notify(struct media_device *mdev,
+					struct media_entity_notify *nptr);
+
 /**
  * media_device_get_devres() -	get media device as device resource
  *				creates if one doesn't exist
@@ -552,6 +566,17 @@ static inline int media_device_register_entity(struct media_device *mdev,
 static inline void media_device_unregister_entity(struct media_entity *entity)
 {
 }
+static inline int media_device_register_entity_notify(
+					struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+	return 0;
+}
+static inline void media_device_unregister_entity_notify(
+					struct media_device *mdev,
+					struct media_entity_notify *nptr)
+{
+}
 static inline struct media_device *media_device_get_devres(struct device *dev)
 {
 	return NULL;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 04/22] media: Media Controller enable/disable source handler API
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add new fields to struct media_device to add enable_source, and
disable_source handlers, and source_priv to stash driver private
data that is used to run these handlers. The enable_source handler
finds source entity for the passed in entity and checks if it is
available. When link is found, it activates it. Disable source
handler deactivates the link.

Bridge driver is expected to implement and set these handlers.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 include/media/media-device.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/media/media-device.h b/include/media/media-device.h
index bad8242a..9415f1b 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -333,6 +333,25 @@ struct media_device {
 	/* Serializes graph operations. */
 	struct mutex graph_mutex;
 
+	/* Handlers to find source entity for the sink entity and
+	 * check if it is available, and activate the link using
+	 * media_entity_setup_link() interface and start pipeline
+	 * from the source to the entity.
+	 * Bridge driver is expected to implement and set the
+	 * handler when media_device is registered or when
+	 * bridge driver finds the media_device during probe.
+	 * Bridge driver sets source_priv with information
+	 * necessary to run enable/disable source handlers.
+	 *
+	 * Use-case: find tuner entity connected to the decoder
+	 * entity and check if it is available, and activate the
+	 * using media_entity_setup_link() if it is available.
+	*/
+	void *source_priv;
+	int (*enable_source)(struct media_entity *entity,
+			     struct media_pipeline *pipe);
+	void (*disable_source)(struct media_entity *entity);
+
 	int (*link_notify)(struct media_link *link, u32 flags,
 			   unsigned int notification);
 };
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 04/22] media: Media Controller enable/disable source handler API
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Add new fields to struct media_device to add enable_source, and
disable_source handlers, and source_priv to stash driver private
data that is used to run these handlers. The enable_source handler
finds source entity for the passed in entity and checks if it is
available. When link is found, it activates it. Disable source
handler deactivates the link.

Bridge driver is expected to implement and set these handlers.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 include/media/media-device.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/media/media-device.h b/include/media/media-device.h
index bad8242a..9415f1b 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -333,6 +333,25 @@ struct media_device {
 	/* Serializes graph operations. */
 	struct mutex graph_mutex;
 
+	/* Handlers to find source entity for the sink entity and
+	 * check if it is available, and activate the link using
+	 * media_entity_setup_link() interface and start pipeline
+	 * from the source to the entity.
+	 * Bridge driver is expected to implement and set the
+	 * handler when media_device is registered or when
+	 * bridge driver finds the media_device during probe.
+	 * Bridge driver sets source_priv with information
+	 * necessary to run enable/disable source handlers.
+	 *
+	 * Use-case: find tuner entity connected to the decoder
+	 * entity and check if it is available, and activate the
+	 * using media_entity_setup_link() if it is available.
+	*/
+	void *source_priv;
+	int (*enable_source)(struct media_entity *entity,
+			     struct media_pipeline *pipe);
+	void (*disable_source)(struct media_entity *entity);
+
 	int (*link_notify)(struct media_link *link, u32 flags,
 			   unsigned int notification);
 };
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 05/22] media: Media Controller export non locking __media_entity_setup_link()
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Export __media_entity_setup_link() to be used from code paths
that hold the graph_mutex.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-entity.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 6179543..9b4d712 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -805,6 +805,7 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(__media_entity_setup_link);
 
 int media_entity_setup_link(struct media_link *link, u32 flags)
 {
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 05/22] media: Media Controller export non locking __media_entity_setup_link()
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Export __media_entity_setup_link() to be used from code paths
that hold the graph_mutex.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-entity.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 6179543..9b4d712 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -805,6 +805,7 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(__media_entity_setup_link);
 
 int media_entity_setup_link(struct media_link *link, u32 flags)
 {
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop()
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add non-locking __media_entity_pipeline_start/stop() interfaces
to be called from code paths that hold the graph_mutex. For this
change, the media_entity_pipeline_start() routine is renamed to
__media_entity_pipeline_start() minus the graph_mutex lock and
unlock. media_entity_pipeline_start() now calls the non-locking
__media_entity_pipeline_start() holding the graph_lock. The stop
interface, media_entity_pipeline_stop() routine is renamed to
__media_entity_pipeline_stop() minus the graph_mutex lock and
unlock. media_entity_pipeline_stop() now calls the non-locking
__media_entity_pipeline_stop() holding the graph_lock.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
 include/media/media-entity.h | 12 ++++++++++++
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 9b4d712..b78e4c2 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -365,8 +365,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
  * Pipeline management
  */
 
-__must_check int media_entity_pipeline_start(struct media_entity *entity,
-					     struct media_pipeline *pipe)
+__must_check int __media_entity_pipeline_start(struct media_entity *entity,
+					       struct media_pipeline *pipe)
 {
 	struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_entity_graph *graph = &pipe->graph;
@@ -374,8 +374,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 	struct media_link *link;
 	int ret;
 
-	mutex_lock(&mdev->graph_mutex);
-
 	if (!pipe->streaming_count++) {
 		ret = media_entity_graph_walk_init(&pipe->graph, mdev);
 		if (ret)
@@ -456,8 +454,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 		}
 	}
 
-	mutex_unlock(&mdev->graph_mutex);
-
 	return 0;
 
 error:
@@ -487,19 +483,28 @@ error_graph_walk_start:
 	if (!--pipe->streaming_count)
 		media_entity_graph_walk_cleanup(graph);
 
-	mutex_unlock(&mdev->graph_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__media_entity_pipeline_start);
 
+__must_check int media_entity_pipeline_start(struct media_entity *entity,
+					     struct media_pipeline *pipe)
+{
+	struct media_device *mdev = entity->graph_obj.mdev;
+	int ret;
+
+	mutex_lock(&mdev->graph_mutex);
+	ret = __media_entity_pipeline_start(entity, pipe);
+	mutex_unlock(&mdev->graph_mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
 
-void media_entity_pipeline_stop(struct media_entity *entity)
+void __media_entity_pipeline_stop(struct media_entity *entity)
 {
-	struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_entity_graph *graph = &entity->pipe->graph;
 	struct media_pipeline *pipe = entity->pipe;
 
-	mutex_lock(&mdev->graph_mutex);
 
 	WARN_ON(!pipe->streaming_count);
 	media_entity_graph_walk_start(graph, entity);
@@ -516,6 +521,15 @@ void media_entity_pipeline_stop(struct media_entity *entity)
 	if (!--pipe->streaming_count)
 		media_entity_graph_walk_cleanup(graph);
 
+}
+EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop);
+
+void media_entity_pipeline_stop(struct media_entity *entity)
+{
+	struct media_device *mdev = entity->graph_obj.mdev;
+
+	mutex_lock(&mdev->graph_mutex);
+	__media_entity_pipeline_stop(entity);
 	mutex_unlock(&mdev->graph_mutex);
 }
 EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index fe485d3..c7583db 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -832,6 +832,12 @@ media_entity_graph_walk_next(struct media_entity_graph *graph);
  */
 __must_check int media_entity_pipeline_start(struct media_entity *entity,
 					     struct media_pipeline *pipe);
+/**
+ * non-locking __media_entity_pipeline_start() can be called from
+ * code paths that hold the graph_mutex
+ */
+__must_check int __media_entity_pipeline_start(struct media_entity *entity,
+					       struct media_pipeline *pipe);
 
 /**
  * media_entity_pipeline_stop - Mark a pipeline as not streaming
@@ -848,6 +854,12 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 void media_entity_pipeline_stop(struct media_entity *entity);
 
 /**
+ * non-locking __media_entity_pipeline_stop() can be called from
+ * code paths that hold the graph_mutex
+ */
+void __media_entity_pipeline_stop(struct media_entity *entity);
+
+/**
  * media_devnode_create() - creates and initializes a device node interface
  *
  * @mdev:	pointer to struct &media_device
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop()
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Add non-locking __media_entity_pipeline_start/stop() interfaces
to be called from code paths that hold the graph_mutex. For this
change, the media_entity_pipeline_start() routine is renamed to
__media_entity_pipeline_start() minus the graph_mutex lock and
unlock. media_entity_pipeline_start() now calls the non-locking
__media_entity_pipeline_start() holding the graph_lock. The stop
interface, media_entity_pipeline_stop() routine is renamed to
__media_entity_pipeline_stop() minus the graph_mutex lock and
unlock. media_entity_pipeline_stop() now calls the non-locking
__media_entity_pipeline_stop() holding the graph_lock.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
 include/media/media-entity.h | 12 ++++++++++++
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 9b4d712..b78e4c2 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -365,8 +365,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
  * Pipeline management
  */
 
-__must_check int media_entity_pipeline_start(struct media_entity *entity,
-					     struct media_pipeline *pipe)
+__must_check int __media_entity_pipeline_start(struct media_entity *entity,
+					       struct media_pipeline *pipe)
 {
 	struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_entity_graph *graph = &pipe->graph;
@@ -374,8 +374,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 	struct media_link *link;
 	int ret;
 
-	mutex_lock(&mdev->graph_mutex);
-
 	if (!pipe->streaming_count++) {
 		ret = media_entity_graph_walk_init(&pipe->graph, mdev);
 		if (ret)
@@ -456,8 +454,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 		}
 	}
 
-	mutex_unlock(&mdev->graph_mutex);
-
 	return 0;
 
 error:
@@ -487,19 +483,28 @@ error_graph_walk_start:
 	if (!--pipe->streaming_count)
 		media_entity_graph_walk_cleanup(graph);
 
-	mutex_unlock(&mdev->graph_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__media_entity_pipeline_start);
 
+__must_check int media_entity_pipeline_start(struct media_entity *entity,
+					     struct media_pipeline *pipe)
+{
+	struct media_device *mdev = entity->graph_obj.mdev;
+	int ret;
+
+	mutex_lock(&mdev->graph_mutex);
+	ret = __media_entity_pipeline_start(entity, pipe);
+	mutex_unlock(&mdev->graph_mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
 
-void media_entity_pipeline_stop(struct media_entity *entity)
+void __media_entity_pipeline_stop(struct media_entity *entity)
 {
-	struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_entity_graph *graph = &entity->pipe->graph;
 	struct media_pipeline *pipe = entity->pipe;
 
-	mutex_lock(&mdev->graph_mutex);
 
 	WARN_ON(!pipe->streaming_count);
 	media_entity_graph_walk_start(graph, entity);
@@ -516,6 +521,15 @@ void media_entity_pipeline_stop(struct media_entity *entity)
 	if (!--pipe->streaming_count)
 		media_entity_graph_walk_cleanup(graph);
 
+}
+EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop);
+
+void media_entity_pipeline_stop(struct media_entity *entity)
+{
+	struct media_device *mdev = entity->graph_obj.mdev;
+
+	mutex_lock(&mdev->graph_mutex);
+	__media_entity_pipeline_stop(entity);
 	mutex_unlock(&mdev->graph_mutex);
 }
 EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index fe485d3..c7583db 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -832,6 +832,12 @@ media_entity_graph_walk_next(struct media_entity_graph *graph);
  */
 __must_check int media_entity_pipeline_start(struct media_entity *entity,
 					     struct media_pipeline *pipe);
+/**
+ * non-locking __media_entity_pipeline_start() can be called from
+ * code paths that hold the graph_mutex
+ */
+__must_check int __media_entity_pipeline_start(struct media_entity *entity,
+					       struct media_pipeline *pipe);
 
 /**
  * media_entity_pipeline_stop - Mark a pipeline as not streaming
@@ -848,6 +854,12 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 void media_entity_pipeline_stop(struct media_entity *entity);
 
 /**
+ * non-locking __media_entity_pipeline_stop() can be called from
+ * code paths that hold the graph_mutex
+ */
+void __media_entity_pipeline_stop(struct media_entity *entity);
+
+/**
  * media_devnode_create() - creates and initializes a device node interface
  *
  * @mdev:	pointer to struct &media_device
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add a new interfaces to be used by v4l-core to invoke enable
source and disable_source handlers in the media_device. The
enable_source helper function invokes the enable_source handler
to find media source entity connected to the entity and check
is it is available or busy. If source is available, link is
activated and pipeline is started. The disable_source helper
function invokes the disable_source handler to deactivate and
stop the pipeline.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/v4l2-core/Makefile  |  2 +-
 drivers/media/v4l2-core/v4l2-mc.c | 60 +++++++++++++++++++++++++++++++++++++++
 include/media/v4l2-dev.h          |  1 +
 include/media/v4l2-mc.h           | 52 +++++++++++++++++++++++++++++++++
 4 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/v4l2-core/v4l2-mc.c

diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index 1dc8bba..c6acc01 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -6,7 +6,7 @@ tuner-objs	:=	tuner-core.o
 
 videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
 			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \
-			v4l2-async.o
+			v4l2-async.o v4l2-mc.o
 ifeq ($(CONFIG_COMPAT),y)
   videodev-objs += v4l2-compat-ioctl32.o
 endif
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
new file mode 100644
index 0000000..87416df
--- /dev/null
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -0,0 +1,60 @@
+/*
+ * v4l2-mc.c - Media Controller V4L2 Common Interfaces
+ *
+ * Copyright (C) 2016 Shuah Khan <shuahkh@osg.samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/v4l2-mc.h>
+#include <media/media-device.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-fh.h>
+
+int v4l_enable_media_source(struct video_device *vdev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct media_device *mdev = vdev->entity.graph_obj.mdev;
+	int ret;
+
+	if (!mdev || !mdev->enable_source)
+		return 0;
+	ret = mdev->enable_source(&vdev->entity, &vdev->pipe);
+	if (ret)
+		return -EBUSY;
+	return 0;
+#endif /* CONFIG_MEDIA_CONTROLLER */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l_enable_media_source);
+
+void v4l_disable_media_source(struct video_device *vdev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct media_device *mdev = vdev->entity.graph_obj.mdev;
+
+	if (mdev && mdev->disable_source)
+		mdev->disable_source(&vdev->entity);
+#endif /* CONFIG_MEDIA_CONTROLLER */
+}
+EXPORT_SYMBOL_GPL(v4l_disable_media_source);
+
+int v4l_vb2q_enable_media_source(struct vb2_queue *q)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct v4l2_fh *fh = q->owner;
+
+	return v4l_enable_media_source(fh->vdev);
+#endif /* CONFIG_MEDIA_CONTROLLER */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
+
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index eeabf20..76056ab 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -87,6 +87,7 @@ struct video_device
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	struct media_entity entity;
 	struct media_intf_devnode *intf_devnode;
+	struct media_pipeline pipe;
 #endif
 	/* device ops */
 	const struct v4l2_file_operations *fops;
diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
index df11519..df1a98f 100644
--- a/include/media/v4l2-mc.h
+++ b/include/media/v4l2-mc.h
@@ -14,6 +14,11 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _V4L2_MC_H
+#define _V4L2_MC_H
+
+#include <media/v4l2-dev.h>
+
 /**
  * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER
  *
@@ -89,3 +94,50 @@ enum demod_pad_index {
 	DEMOD_PAD_VBI_OUT,
 	DEMOD_NUM_PADS
 };
+
+/**
+ * v4l_enable_media_source() -	Hold media source for exclusive use
+ *				if free
+ *
+ * @vdev - poniter to struct video_device
+ *
+ * This interface calls enable_source handler to determine if
+ * media source is free for use. The enable_source handler is
+ * responsible for checking is the media source is free and
+ * start a pipeline between the media source and the media
+ * entity associated with the video device. This interface
+ * should be called from v4l2-core and dvb-core interfaces
+ * that change the source configuration.
+ *
+ * Return: returns zero on success or a negative error code.
+ */
+int v4l_enable_media_source(struct video_device *vdev);
+
+/**
+ * v4l_disable_media_source() -	Release media source
+ *
+ * @vdev - poniter to struct video_device
+ *
+ * This interface calls disable_source handler to release
+ * the media source. The disable_source handler stops the
+ * active media pipeline between the media source and the
+ * media entity associated with the video device.
+ *
+ * Return: returns zero on success or a negative error code.
+ */
+void v4l_disable_media_source(struct video_device *vdev);
+/*
+ * v4l_vb2q_enable_media_tuner -  Hold media source for exclusive use
+ *				  if free.
+ * @q - pointer to struct vb2_queue
+ *
+ * Wrapper for v4l_enable_media_source(). This function should
+ * be called from v4l2-core to enable the media source with
+ * pointer to struct vb2_queue as the input argument. Some
+ * v4l2-core interfaces don't have access to video device and
+ * this interface finds the struct video_device for the q and
+ * calls v4l_enable_media_source().
+ */
+int v4l_vb2q_enable_media_source(struct vb2_queue *q);
+
+#endif /* _V4L2_MC_H */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Add a new interfaces to be used by v4l-core to invoke enable
source and disable_source handlers in the media_device. The
enable_source helper function invokes the enable_source handler
to find media source entity connected to the entity and check
is it is available or busy. If source is available, link is
activated and pipeline is started. The disable_source helper
function invokes the disable_source handler to deactivate and
stop the pipeline.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/v4l2-core/Makefile  |  2 +-
 drivers/media/v4l2-core/v4l2-mc.c | 60 +++++++++++++++++++++++++++++++++++++++
 include/media/v4l2-dev.h          |  1 +
 include/media/v4l2-mc.h           | 52 +++++++++++++++++++++++++++++++++
 4 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/v4l2-core/v4l2-mc.c

diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index 1dc8bba..c6acc01 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -6,7 +6,7 @@ tuner-objs	:=	tuner-core.o
 
 videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
 			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \
-			v4l2-async.o
+			v4l2-async.o v4l2-mc.o
 ifeq ($(CONFIG_COMPAT),y)
   videodev-objs += v4l2-compat-ioctl32.o
 endif
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
new file mode 100644
index 0000000..87416df
--- /dev/null
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -0,0 +1,60 @@
+/*
+ * v4l2-mc.c - Media Controller V4L2 Common Interfaces
+ *
+ * Copyright (C) 2016 Shuah Khan <shuahkh@osg.samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/v4l2-mc.h>
+#include <media/media-device.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-fh.h>
+
+int v4l_enable_media_source(struct video_device *vdev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct media_device *mdev = vdev->entity.graph_obj.mdev;
+	int ret;
+
+	if (!mdev || !mdev->enable_source)
+		return 0;
+	ret = mdev->enable_source(&vdev->entity, &vdev->pipe);
+	if (ret)
+		return -EBUSY;
+	return 0;
+#endif /* CONFIG_MEDIA_CONTROLLER */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l_enable_media_source);
+
+void v4l_disable_media_source(struct video_device *vdev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct media_device *mdev = vdev->entity.graph_obj.mdev;
+
+	if (mdev && mdev->disable_source)
+		mdev->disable_source(&vdev->entity);
+#endif /* CONFIG_MEDIA_CONTROLLER */
+}
+EXPORT_SYMBOL_GPL(v4l_disable_media_source);
+
+int v4l_vb2q_enable_media_source(struct vb2_queue *q)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct v4l2_fh *fh = q->owner;
+
+	return v4l_enable_media_source(fh->vdev);
+#endif /* CONFIG_MEDIA_CONTROLLER */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
+
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index eeabf20..76056ab 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -87,6 +87,7 @@ struct video_device
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	struct media_entity entity;
 	struct media_intf_devnode *intf_devnode;
+	struct media_pipeline pipe;
 #endif
 	/* device ops */
 	const struct v4l2_file_operations *fops;
diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
index df11519..df1a98f 100644
--- a/include/media/v4l2-mc.h
+++ b/include/media/v4l2-mc.h
@@ -14,6 +14,11 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _V4L2_MC_H
+#define _V4L2_MC_H
+
+#include <media/v4l2-dev.h>
+
 /**
  * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER
  *
@@ -89,3 +94,50 @@ enum demod_pad_index {
 	DEMOD_PAD_VBI_OUT,
 	DEMOD_NUM_PADS
 };
+
+/**
+ * v4l_enable_media_source() -	Hold media source for exclusive use
+ *				if free
+ *
+ * @vdev - poniter to struct video_device
+ *
+ * This interface calls enable_source handler to determine if
+ * media source is free for use. The enable_source handler is
+ * responsible for checking is the media source is free and
+ * start a pipeline between the media source and the media
+ * entity associated with the video device. This interface
+ * should be called from v4l2-core and dvb-core interfaces
+ * that change the source configuration.
+ *
+ * Return: returns zero on success or a negative error code.
+ */
+int v4l_enable_media_source(struct video_device *vdev);
+
+/**
+ * v4l_disable_media_source() -	Release media source
+ *
+ * @vdev - poniter to struct video_device
+ *
+ * This interface calls disable_source handler to release
+ * the media source. The disable_source handler stops the
+ * active media pipeline between the media source and the
+ * media entity associated with the video device.
+ *
+ * Return: returns zero on success or a negative error code.
+ */
+void v4l_disable_media_source(struct video_device *vdev);
+/*
+ * v4l_vb2q_enable_media_tuner -  Hold media source for exclusive use
+ *				  if free.
+ * @q - pointer to struct vb2_queue
+ *
+ * Wrapper for v4l_enable_media_source(). This function should
+ * be called from v4l2-core to enable the media source with
+ * pointer to struct vb2_queue as the input argument. Some
+ * v4l2-core interfaces don't have access to video device and
+ * this interface finds the struct video_device for the q and
+ * calls v4l_enable_media_source().
+ */
+int v4l_vb2q_enable_media_source(struct vb2_queue *q);
+
+#endif /* _V4L2_MC_H */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 08/22] media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Move the au8522_media_pads enum to au8522.h
from au8522_priv.h to export them. This will
allow au0828-core to use these defines instead
of hard-coding them them.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/dvb-frontends/au8522.h      | 7 +++++++
 drivers/media/dvb-frontends/au8522_priv.h | 8 --------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
index dde6158..3c72f40 100644
--- a/drivers/media/dvb-frontends/au8522.h
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -90,4 +90,11 @@ enum au8522_audio_input {
 	AU8522_AUDIO_SIF,
 };
 
+enum au8522_media_pads {
+	AU8522_PAD_INPUT,
+	AU8522_PAD_VID_OUT,
+	AU8522_PAD_VBI_OUT,
+
+	AU8522_NUM_PADS
+};
 #endif /* __AU8522_H__ */
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index 404a0cb..505215a 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -39,14 +39,6 @@
 #define AU8522_DIGITAL_MODE 1
 #define AU8522_SUSPEND_MODE 2
 
-enum au8522_media_pads {
-	AU8522_PAD_INPUT,
-	AU8522_PAD_VID_OUT,
-	AU8522_PAD_VBI_OUT,
-
-	AU8522_NUM_PADS
-};
-
 struct au8522_state {
 	struct i2c_client *c;
 	struct i2c_adapter *i2c;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 08/22] media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Move the au8522_media_pads enum to au8522.h
from au8522_priv.h to export them. This will
allow au0828-core to use these defines instead
of hard-coding them them.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/dvb-frontends/au8522.h      | 7 +++++++
 drivers/media/dvb-frontends/au8522_priv.h | 8 --------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
index dde6158..3c72f40 100644
--- a/drivers/media/dvb-frontends/au8522.h
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -90,4 +90,11 @@ enum au8522_audio_input {
 	AU8522_AUDIO_SIF,
 };
 
+enum au8522_media_pads {
+	AU8522_PAD_INPUT,
+	AU8522_PAD_VID_OUT,
+	AU8522_PAD_VBI_OUT,
+
+	AU8522_NUM_PADS
+};
 #endif /* __AU8522_H__ */
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index 404a0cb..505215a 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -39,14 +39,6 @@
 #define AU8522_DIGITAL_MODE 1
 #define AU8522_SUSPEND_MODE 2
 
-enum au8522_media_pads {
-	AU8522_PAD_INPUT,
-	AU8522_PAD_VID_OUT,
-	AU8522_PAD_VBI_OUT,
-
-	AU8522_NUM_PADS
-};
-
 struct au8522_state {
 	struct i2c_client *c;
 	struct i2c_adapter *i2c;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 09/22] media: au8522 change to create MC pad for ALSA Audio Out
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add new pad for ALSA Audio Out to au8522_media_pads.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/dvb-frontends/au8522.h         | 1 +
 drivers/media/dvb-frontends/au8522_decoder.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
index 3c72f40..d7a997f 100644
--- a/drivers/media/dvb-frontends/au8522.h
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -94,6 +94,7 @@ enum au8522_media_pads {
 	AU8522_PAD_INPUT,
 	AU8522_PAD_VID_OUT,
 	AU8522_PAD_VBI_OUT,
+	AU8522_PAD_AUDIO_OUT,
 
 	AU8522_NUM_PADS
 };
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 73612c5..0ab9f1e 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -766,6 +766,7 @@ static int au8522_probe(struct i2c_client *client,
 	state->pads[AU8522_PAD_INPUT].flags = MEDIA_PAD_FL_SINK;
 	state->pads[AU8522_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
 	state->pads[AU8522_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[AU8522_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE;
 	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
 
 	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads),
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 09/22] media: au8522 change to create MC pad for ALSA Audio Out
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Add new pad for ALSA Audio Out to au8522_media_pads.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/dvb-frontends/au8522.h         | 1 +
 drivers/media/dvb-frontends/au8522_decoder.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
index 3c72f40..d7a997f 100644
--- a/drivers/media/dvb-frontends/au8522.h
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -94,6 +94,7 @@ enum au8522_media_pads {
 	AU8522_PAD_INPUT,
 	AU8522_PAD_VID_OUT,
 	AU8522_PAD_VBI_OUT,
+	AU8522_PAD_AUDIO_OUT,
 
 	AU8522_NUM_PADS
 };
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 73612c5..0ab9f1e 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -766,6 +766,7 @@ static int au8522_probe(struct i2c_client *client,
 	state->pads[AU8522_PAD_INPUT].flags = MEDIA_PAD_FL_SINK;
 	state->pads[AU8522_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
 	state->pads[AU8522_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[AU8522_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE;
 	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
 
 	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads),
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 10/22] media: Change v4l-core to check if source is free
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change s_input, s_fmt, s_tuner, s_frequency, querystd,
s_hw_freq_seek, and vb2_core_streamon interfaces that
alter the tuner configuration to check if it is free,
by calling v4l_enable_media_source(). If source isn't
free, return -EBUSY. v4l_disable_media_source() is
called from v4l2_fh_exit() to release tuner (source).
vb2_core_streamon() uses v4l_vb2q_enable_media_source().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/v4l2-core/v4l2-fh.c        |  2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c     | 30 ++++++++++++++++++++++++++++++
 drivers/media/v4l2-core/videobuf2-core.c |  4 ++++
 3 files changed, 36 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
index c97067a..c183f09 100644
--- a/drivers/media/v4l2-core/v4l2-fh.c
+++ b/drivers/media/v4l2-core/v4l2-fh.c
@@ -29,6 +29,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
 
 void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
 {
@@ -92,6 +93,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh)
 {
 	if (fh->vdev == NULL)
 		return;
+	v4l_disable_media_source(fh->vdev);
 	v4l2_event_unsubscribe_all(fh);
 	fh->vdev = NULL;
 }
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 8a018c6..ceaa44a 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -27,6 +27,7 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-device.h>
 #include <media/videobuf2-v4l2.h>
+#include <media/v4l2-mc.h>
 
 #include <trace/events/v4l2.h>
 
@@ -1041,6 +1042,12 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
 static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
+	struct video_device *vfd = video_devdata(file);
+	int ret;
+
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	return ops->vidioc_s_input(file, fh, *(unsigned int *)arg);
 }
 
@@ -1448,6 +1455,9 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	v4l_sanitize_format(p);
 
 	switch (p->type) {
@@ -1637,7 +1647,11 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_tuner *p = arg;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	return ops->vidioc_s_tuner(file, fh, p);
@@ -1691,7 +1705,11 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
 	struct video_device *vfd = video_devdata(file);
 	const struct v4l2_frequency *p = arg;
 	enum v4l2_tuner_type type;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	if (vfd->vfl_type == VFL_TYPE_SDR) {
 		if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
 			return -EINVAL;
@@ -1746,7 +1764,11 @@ static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	v4l2_std_id id = *(v4l2_std_id *)arg, norm;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	norm = id & vfd->tvnorms;
 	if (vfd->tvnorms && !norm)	/* Check if std is supported */
 		return -EINVAL;
@@ -1760,7 +1782,11 @@ static int v4l_querystd(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	v4l2_std_id *p = arg;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	/*
 	 * If no signal is detected, then the driver should return
 	 * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with
@@ -1779,7 +1805,11 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_hw_freq_seek *p = arg;
 	enum v4l2_tuner_type type;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	/* s_hw_freq_seek is not supported for SDR for now */
 	if (vfd->vfl_type == VFL_TYPE_SDR)
 		return -EINVAL;
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index ec5b78e..d381478 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -25,6 +25,7 @@
 #include <linux/kthread.h>
 
 #include <media/videobuf2-core.h>
+#include <media/v4l2-mc.h>
 
 #include <trace/events/vb2.h>
 
@@ -1873,6 +1874,9 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
 	 * are available.
 	 */
 	if (q->queued_count >= q->min_buffers_needed) {
+		ret = v4l_vb2q_enable_media_source(q);
+		if (ret)
+			return ret;
 		ret = vb2_start_streaming(q);
 		if (ret) {
 			__vb2_queue_cancel(q);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 10/22] media: Change v4l-core to check if source is free
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Change s_input, s_fmt, s_tuner, s_frequency, querystd,
s_hw_freq_seek, and vb2_core_streamon interfaces that
alter the tuner configuration to check if it is free,
by calling v4l_enable_media_source(). If source isn't
free, return -EBUSY. v4l_disable_media_source() is
called from v4l2_fh_exit() to release tuner (source).
vb2_core_streamon() uses v4l_vb2q_enable_media_source().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/v4l2-core/v4l2-fh.c        |  2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c     | 30 ++++++++++++++++++++++++++++++
 drivers/media/v4l2-core/videobuf2-core.c |  4 ++++
 3 files changed, 36 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
index c97067a..c183f09 100644
--- a/drivers/media/v4l2-core/v4l2-fh.c
+++ b/drivers/media/v4l2-core/v4l2-fh.c
@@ -29,6 +29,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
 
 void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
 {
@@ -92,6 +93,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh)
 {
 	if (fh->vdev == NULL)
 		return;
+	v4l_disable_media_source(fh->vdev);
 	v4l2_event_unsubscribe_all(fh);
 	fh->vdev = NULL;
 }
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 8a018c6..ceaa44a 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -27,6 +27,7 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-device.h>
 #include <media/videobuf2-v4l2.h>
+#include <media/v4l2-mc.h>
 
 #include <trace/events/v4l2.h>
 
@@ -1041,6 +1042,12 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
 static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
+	struct video_device *vfd = video_devdata(file);
+	int ret;
+
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	return ops->vidioc_s_input(file, fh, *(unsigned int *)arg);
 }
 
@@ -1448,6 +1455,9 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	v4l_sanitize_format(p);
 
 	switch (p->type) {
@@ -1637,7 +1647,11 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_tuner *p = arg;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	return ops->vidioc_s_tuner(file, fh, p);
@@ -1691,7 +1705,11 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
 	struct video_device *vfd = video_devdata(file);
 	const struct v4l2_frequency *p = arg;
 	enum v4l2_tuner_type type;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	if (vfd->vfl_type == VFL_TYPE_SDR) {
 		if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
 			return -EINVAL;
@@ -1746,7 +1764,11 @@ static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	v4l2_std_id id = *(v4l2_std_id *)arg, norm;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	norm = id & vfd->tvnorms;
 	if (vfd->tvnorms && !norm)	/* Check if std is supported */
 		return -EINVAL;
@@ -1760,7 +1782,11 @@ static int v4l_querystd(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	v4l2_std_id *p = arg;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	/*
 	 * If no signal is detected, then the driver should return
 	 * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with
@@ -1779,7 +1805,11 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_hw_freq_seek *p = arg;
 	enum v4l2_tuner_type type;
+	int ret;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
 	/* s_hw_freq_seek is not supported for SDR for now */
 	if (vfd->vfl_type == VFL_TYPE_SDR)
 		return -EINVAL;
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index ec5b78e..d381478 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -25,6 +25,7 @@
 #include <linux/kthread.h>
 
 #include <media/videobuf2-core.h>
+#include <media/v4l2-mc.h>
 
 #include <trace/events/vb2.h>
 
@@ -1873,6 +1874,9 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
 	 * are available.
 	 */
 	if (q->queued_count >= q->min_buffers_needed) {
+		ret = v4l_vb2q_enable_media_source(q);
+		if (ret)
+			return ret;
 		ret = vb2_start_streaming(q);
 		if (ret) {
 			__vb2_queue_cancel(q);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change dvb frontend to check if tuner is free when
device opened in RW mode. Call to enable_source
handler either returns with an active pipeline to
tuner or error if tuner is busy. Tuner is released
when frontend is released calling the disable_source
handler.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
 drivers/media/dvb-core/dvb_frontend.h |   3 +
 2 files changed, 24 insertions(+), 118 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 03cc508..2b17e8b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -131,11 +131,6 @@ struct dvb_frontend_private {
 	int quality;
 	unsigned int check_wrapped;
 	enum dvbfe_search algo_status;
-
-#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
-	struct media_pipeline pipe;
-	struct media_entity *pipe_start_entity;
-#endif
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -596,104 +591,12 @@ 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.
- */
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-static int dvb_enable_media_tuner(struct dvb_frontend *fe)
-{
-	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 ret, n_links = 0, active_links = 0;
-
-	fepriv->pipe_start_entity = NULL;
-
-	if (!mdev)
-		return 0;
-
-	entity = fepriv->dvbdev->entity;
-	fepriv->pipe_start_entity = entity;
-
-	list_for_each_entry(link, &entity->links, list) {
-		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;
-	fepriv->pipe_start_entity = source;
-	list_for_each_entry(link, &source->links, list) {
-		struct media_entity *sink;
-		int flags = 0;
-
-		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");
-	}
-	return 0;
-}
-#endif
-
 static int dvb_frontend_thread(void *data)
 {
 	struct dvb_frontend *fe = data;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	enum fe_status s;
 	enum dvbfe_algo algo;
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-	int ret;
-#endif
-
 	bool re_tune = false;
 	bool semheld = false;
 
@@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)
 	fepriv->wakeup = 0;
 	fepriv->reinitialise = 0;
 
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-	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");
-	} else if (fepriv->pipe_start_entity) {
-		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
-						  &fepriv->pipe);
-		if (ret)
-			return ret;
-	}
-#endif
-
 	dvb_frontend_init(fe);
 
 	set_freezable();
@@ -829,12 +718,6 @@ restart:
 		}
 	}
 
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-	if (fepriv->pipe_start_entity)
-		media_entity_pipeline_stop(fepriv->pipe_start_entity);
-	fepriv->pipe_start_entity = NULL;
-#endif
-
 	if (dvb_powerdown_on_sleep) {
 		if (fe->ops.set_voltage)
 			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
@@ -2612,9 +2495,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 		fepriv->tone = -1;
 		fepriv->voltage = -1;
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+		if (fe->dvb->mdev && fe->dvb->mdev->enable_source) {
+			ret = fe->dvb->mdev->enable_source(dvbdev->entity,
+							   &fe->pipe);
+			if (ret) {
+				dev_err(fe->dvb->device,
+					"Tuner is busy. Error %d\n", ret);
+				goto err2;
+			}
+		}
+#endif
 		ret = dvb_frontend_start (fe);
 		if (ret)
-			goto err2;
+			goto err3;
 
 		/*  empty event queue */
 		fepriv->events.eventr = fepriv->events.eventw = 0;
@@ -2624,7 +2518,12 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 		mutex_unlock (&adapter->mfe_lock);
 	return ret;
 
+err3:
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
+		fe->dvb->mdev->disable_source(dvbdev->entity);
 err2:
+#endif
 	dvb_generic_release(inode, file);
 err1:
 	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
@@ -2653,6 +2552,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
 
 	if (dvbdev->users == -1) {
 		wake_up(&fepriv->wait_queue);
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+		if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
+			fe->dvb->mdev->disable_source(dvbdev->entity);
+#endif
 		if (fe->exit != DVB_FE_NO_EXIT)
 			wake_up(&dvbdev->wait_queue);
 		if (fe->ops.ts_bus_ctrl)
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 458bcce..9466906 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -686,6 +686,9 @@ struct dvb_frontend {
 	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
 	int id;
 	unsigned int exit;
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	struct media_pipeline pipe;
+#endif
 };
 
 /**
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab-JPH+aEBZ4P+UEJcrhfAQsw, tiwai-IBi9RG/b67k,
	clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw
  Cc: Shuah Khan, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs-mcfjX3dozePR7s880joybQ,
	johan-v8HUHnYb0Yo, klock.android-Re5JQEeQqe8AvxtiuMwx3w,
	nenggun.kim-Sze3O3UU22JBDgjK7y7TUQ,
	j.anaszewski-Sze3O3UU22JBDgjK7y7TUQ, geliangtang

Change dvb frontend to check if tuner is free when
device opened in RW mode. Call to enable_source
handler either returns with an active pipeline to
tuner or error if tuner is busy. Tuner is released
when frontend is released calling the disable_source
handler.

Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
---
 drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
 drivers/media/dvb-core/dvb_frontend.h |   3 +
 2 files changed, 24 insertions(+), 118 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 03cc508..2b17e8b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -131,11 +131,6 @@ struct dvb_frontend_private {
 	int quality;
 	unsigned int check_wrapped;
 	enum dvbfe_search algo_status;
-
-#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
-	struct media_pipeline pipe;
-	struct media_entity *pipe_start_entity;
-#endif
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -596,104 +591,12 @@ 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.
- */
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-static int dvb_enable_media_tuner(struct dvb_frontend *fe)
-{
-	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 ret, n_links = 0, active_links = 0;
-
-	fepriv->pipe_start_entity = NULL;
-
-	if (!mdev)
-		return 0;
-
-	entity = fepriv->dvbdev->entity;
-	fepriv->pipe_start_entity = entity;
-
-	list_for_each_entry(link, &entity->links, list) {
-		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;
-	fepriv->pipe_start_entity = source;
-	list_for_each_entry(link, &source->links, list) {
-		struct media_entity *sink;
-		int flags = 0;
-
-		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");
-	}
-	return 0;
-}
-#endif
-
 static int dvb_frontend_thread(void *data)
 {
 	struct dvb_frontend *fe = data;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	enum fe_status s;
 	enum dvbfe_algo algo;
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-	int ret;
-#endif
-
 	bool re_tune = false;
 	bool semheld = false;
 
@@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)
 	fepriv->wakeup = 0;
 	fepriv->reinitialise = 0;
 
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-	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");
-	} else if (fepriv->pipe_start_entity) {
-		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
-						  &fepriv->pipe);
-		if (ret)
-			return ret;
-	}
-#endif
-
 	dvb_frontend_init(fe);
 
 	set_freezable();
@@ -829,12 +718,6 @@ restart:
 		}
 	}
 
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-	if (fepriv->pipe_start_entity)
-		media_entity_pipeline_stop(fepriv->pipe_start_entity);
-	fepriv->pipe_start_entity = NULL;
-#endif
-
 	if (dvb_powerdown_on_sleep) {
 		if (fe->ops.set_voltage)
 			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
@@ -2612,9 +2495,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 		fepriv->tone = -1;
 		fepriv->voltage = -1;
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+		if (fe->dvb->mdev && fe->dvb->mdev->enable_source) {
+			ret = fe->dvb->mdev->enable_source(dvbdev->entity,
+							   &fe->pipe);
+			if (ret) {
+				dev_err(fe->dvb->device,
+					"Tuner is busy. Error %d\n", ret);
+				goto err2;
+			}
+		}
+#endif
 		ret = dvb_frontend_start (fe);
 		if (ret)
-			goto err2;
+			goto err3;
 
 		/*  empty event queue */
 		fepriv->events.eventr = fepriv->events.eventw = 0;
@@ -2624,7 +2518,12 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 		mutex_unlock (&adapter->mfe_lock);
 	return ret;
 
+err3:
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
+		fe->dvb->mdev->disable_source(dvbdev->entity);
 err2:
+#endif
 	dvb_generic_release(inode, file);
 err1:
 	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
@@ -2653,6 +2552,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
 
 	if (dvbdev->users == -1) {
 		wake_up(&fepriv->wait_queue);
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+		if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
+			fe->dvb->mdev->disable_source(dvbdev->entity);
+#endif
 		if (fe->exit != DVB_FE_NO_EXIT)
 			wake_up(&dvbdev->wait_queue);
 		if (fe->ops.ts_bus_ctrl)
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 458bcce..9466906 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -686,6 +686,9 @@ struct dvb_frontend {
 	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
 	int id;
 	unsigned int exit;
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	struct media_pipeline pipe;
+#endif
 };
 
 /**
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner()
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Remove au0828_enable_analog_tuner() as it is
no longer needed because v4l2-core implements
common interfaces to check for media source
availability.

In addition, queue_setup() no longer needs the
tuner availability check since v4l2-core does it.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
 1 file changed, 61 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 8c54fd2..81952c8 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -638,64 +638,6 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 	return rc;
 }
 
-static int au0828_enable_analog_tuner(struct au0828_dev *dev)
-{
-#ifdef CONFIG_MEDIA_CONTROLLER
-	struct media_device *mdev = dev->media_dev;
-	struct media_entity *source;
-	struct media_link *link, *found_link = NULL;
-	int ret, active_links = 0;
-
-	if (!mdev || !dev->decoder)
-		return 0;
-
-	/*
-	 * This will find the tuner that is connected into the decoder.
-	 * Technically, this is not 100% correct, as the device may be
-	 * using an analog input instead of the tuner. However, as we can't
-	 * do DVB streaming while the DMA engine is being used for V4L2,
-	 * this should be enough for the actual needs.
-	 */
-	list_for_each_entry(link, &dev->decoder->links, list) {
-		if (link->sink->entity == dev->decoder) {
-			found_link = link;
-			if (link->flags & MEDIA_LNK_FL_ENABLED)
-				active_links++;
-			break;
-		}
-	}
-
-	if (active_links == 1 || !found_link)
-		return 0;
-
-	source = found_link->source->entity;
-	list_for_each_entry(link, &source->links, list) {
-		struct media_entity *sink;
-		int flags = 0;
-
-		sink = link->sink->entity;
-
-		if (sink == dev->decoder)
-			flags = MEDIA_LNK_FL_ENABLED;
-
-		ret = media_entity_setup_link(link, flags);
-		if (ret) {
-			pr_err(
-				"Couldn't change link %s->%s to %s. Error %d\n",
-				source->name, sink->name,
-				flags ? "enabled" : "disabled",
-				ret);
-			return ret;
-		} else
-			au0828_isocdbg(
-				"link %s->%s was %s\n",
-				source->name, sink->name,
-				flags ? "ENABLED" : "disabled");
-	}
-#endif
-	return 0;
-}
-
 static int queue_setup(struct vb2_queue *vq,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
@@ -707,9 +649,6 @@ static int queue_setup(struct vb2_queue *vq,
 		return sizes[0] < size ? -EINVAL : 0;
 	*nplanes = 1;
 	sizes[0] = size;
-
-	au0828_enable_analog_tuner(dev);
-
 	return 0;
 }
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner()
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Remove au0828_enable_analog_tuner() as it is
no longer needed because v4l2-core implements
common interfaces to check for media source
availability.

In addition, queue_setup() no longer needs the
tuner availability check since v4l2-core does it.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
 1 file changed, 61 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 8c54fd2..81952c8 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -638,64 +638,6 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 	return rc;
 }
 
-static int au0828_enable_analog_tuner(struct au0828_dev *dev)
-{
-#ifdef CONFIG_MEDIA_CONTROLLER
-	struct media_device *mdev = dev->media_dev;
-	struct media_entity *source;
-	struct media_link *link, *found_link = NULL;
-	int ret, active_links = 0;
-
-	if (!mdev || !dev->decoder)
-		return 0;
-
-	/*
-	 * This will find the tuner that is connected into the decoder.
-	 * Technically, this is not 100% correct, as the device may be
-	 * using an analog input instead of the tuner. However, as we can't
-	 * do DVB streaming while the DMA engine is being used for V4L2,
-	 * this should be enough for the actual needs.
-	 */
-	list_for_each_entry(link, &dev->decoder->links, list) {
-		if (link->sink->entity == dev->decoder) {
-			found_link = link;
-			if (link->flags & MEDIA_LNK_FL_ENABLED)
-				active_links++;
-			break;
-		}
-	}
-
-	if (active_links == 1 || !found_link)
-		return 0;
-
-	source = found_link->source->entity;
-	list_for_each_entry(link, &source->links, list) {
-		struct media_entity *sink;
-		int flags = 0;
-
-		sink = link->sink->entity;
-
-		if (sink == dev->decoder)
-			flags = MEDIA_LNK_FL_ENABLED;
-
-		ret = media_entity_setup_link(link, flags);
-		if (ret) {
-			pr_err(
-				"Couldn't change link %s->%s to %s. Error %d\n",
-				source->name, sink->name,
-				flags ? "enabled" : "disabled",
-				ret);
-			return ret;
-		} else
-			au0828_isocdbg(
-				"link %s->%s was %s\n",
-				source->name, sink->name,
-				flags ? "ENABLED" : "disabled");
-	}
-#endif
-	return 0;
-}
-
 static int queue_setup(struct vb2_queue *vq,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
@@ -707,9 +649,6 @@ static int queue_setup(struct vb2_queue *vq,
 		return sizes[0] < size ? -EINVAL : 0;
 	*nplanes = 1;
 	sizes[0] = size;
-
-	au0828_enable_analog_tuner(dev);
-
 	return 0;
 }
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 13/22] media: au0828 video change to use v4l_enable_media_source()
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change au0828 to check if tuner is free or not
before changing tuner configuration.

vidioc_g_tuner(), and au0828_v4l2_close() now call
v4l-core interface v4l_enable_media_source() before
changing tuner configuration.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-video.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 81952c8..8087215 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -1006,8 +1006,12 @@ static int au0828_v4l2_close(struct file *filp)
 		goto end;
 
 	if (dev->users == 1) {
-		/* Save some power by putting tuner to sleep */
-		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+		/* Save some power by putting tuner to sleep, if it is free */
+		/* What happens when radio is using tuner?? */
+		ret = v4l_enable_media_source(vdev);
+		if (ret == 0)
+			v4l2_device_call_all(&dev->v4l2_dev, 0, core,
+					     s_power, 0);
 		dev->std_set_in_tuner_core = 0;
 
 		/* When close the device, set the usb intf0 into alt0 to free
@@ -1408,10 +1412,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
 static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
 	struct au0828_dev *dev = video_drvdata(file);
+	struct video_device *vfd = video_devdata(file);
+	int ret;
 
 	if (t->index != 0)
 		return -EINVAL;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
+
 	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
 		dev->std_set_in_tuner_core, dev->dev_state);
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 13/22] media: au0828 video change to use v4l_enable_media_source()
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab-JPH+aEBZ4P+UEJcrhfAQsw, tiwai-IBi9RG/b67k,
	clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw
  Cc: Shuah Khan, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs-mcfjX3dozePR7s880joybQ,
	johan-v8HUHnYb0Yo, klock.android-Re5JQEeQqe8AvxtiuMwx3w,
	nenggun.kim-Sze3O3UU22JBDgjK7y7TUQ,
	j.anaszewski-Sze3O3UU22JBDgjK7y7TUQ, geliangtang

Change au0828 to check if tuner is free or not
before changing tuner configuration.

vidioc_g_tuner(), and au0828_v4l2_close() now call
v4l-core interface v4l_enable_media_source() before
changing tuner configuration.

Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
---
 drivers/media/usb/au0828/au0828-video.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 81952c8..8087215 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -1006,8 +1006,12 @@ static int au0828_v4l2_close(struct file *filp)
 		goto end;
 
 	if (dev->users == 1) {
-		/* Save some power by putting tuner to sleep */
-		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+		/* Save some power by putting tuner to sleep, if it is free */
+		/* What happens when radio is using tuner?? */
+		ret = v4l_enable_media_source(vdev);
+		if (ret == 0)
+			v4l2_device_call_all(&dev->v4l2_dev, 0, core,
+					     s_power, 0);
 		dev->std_set_in_tuner_core = 0;
 
 		/* When close the device, set the usb intf0 into alt0 to free
@@ -1408,10 +1412,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
 static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
 	struct au0828_dev *dev = video_drvdata(file);
+	struct video_device *vfd = video_devdata(file);
+	int ret;
 
 	if (t->index != 0)
 		return -EINVAL;
 
+	ret = v4l_enable_media_source(vfd);
+	if (ret)
+		return ret;
+
 	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
 		dev->std_set_in_tuner_core, dev->dev_state);
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change au0828 to use Managed Media Controller API to
share media device and coordinate creating/deleting
the shared media device with the snd-usb-audio driver.
The shared media device is created as device resource
of the parent usb device of the two drivers.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index df2bc3f..b8c4bdd 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -134,10 +134,10 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
 {
 
 #ifdef CONFIG_MEDIA_CONTROLLER
-	if (dev->media_dev) {
+	if (dev->media_dev &&
+		media_devnode_is_registered(&dev->media_dev->devnode)) {
 		media_device_unregister(dev->media_dev);
 		media_device_cleanup(dev->media_dev);
-		kfree(dev->media_dev);
 		dev->media_dev = NULL;
 	}
 #endif
@@ -223,23 +223,24 @@ static int au0828_media_device_init(struct au0828_dev *dev,
 #ifdef CONFIG_MEDIA_CONTROLLER
 	struct media_device *mdev;
 
-	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	mdev = media_device_get_devres(&udev->dev);
 	if (!mdev)
 		return -ENOMEM;
 
-	mdev->dev = &udev->dev;
+	if (!media_devnode_is_registered(&mdev->devnode)) {
+		mdev->dev = &udev->dev;
 
-	if (!dev->board.name)
-		strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model));
-	else
-		strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
-	if (udev->serial)
-		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
-	strcpy(mdev->bus_info, udev->devpath);
-	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
-	mdev->driver_version = LINUX_VERSION_CODE;
+		if (udev->product)
+			strlcpy(mdev->model, udev->product,
+				sizeof(mdev->model));
+		if (udev->serial)
+			strlcpy(mdev->serial, udev->serial,
+				sizeof(mdev->serial));
+		strcpy(mdev->bus_info, udev->devpath);
+		mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
 
-	media_device_init(mdev);
+		media_device_init(mdev);
+	}
 
 	dev->media_dev = mdev;
 #endif
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Change au0828 to use Managed Media Controller API to
share media device and coordinate creating/deleting
the shared media device with the snd-usb-audio driver.
The shared media device is created as device resource
of the parent usb device of the two drivers.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index df2bc3f..b8c4bdd 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -134,10 +134,10 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
 {
 
 #ifdef CONFIG_MEDIA_CONTROLLER
-	if (dev->media_dev) {
+	if (dev->media_dev &&
+		media_devnode_is_registered(&dev->media_dev->devnode)) {
 		media_device_unregister(dev->media_dev);
 		media_device_cleanup(dev->media_dev);
-		kfree(dev->media_dev);
 		dev->media_dev = NULL;
 	}
 #endif
@@ -223,23 +223,24 @@ static int au0828_media_device_init(struct au0828_dev *dev,
 #ifdef CONFIG_MEDIA_CONTROLLER
 	struct media_device *mdev;
 
-	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	mdev = media_device_get_devres(&udev->dev);
 	if (!mdev)
 		return -ENOMEM;
 
-	mdev->dev = &udev->dev;
+	if (!media_devnode_is_registered(&mdev->devnode)) {
+		mdev->dev = &udev->dev;
 
-	if (!dev->board.name)
-		strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model));
-	else
-		strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
-	if (udev->serial)
-		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
-	strcpy(mdev->bus_info, udev->devpath);
-	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
-	mdev->driver_version = LINUX_VERSION_CODE;
+		if (udev->product)
+			strlcpy(mdev->model, udev->product,
+				sizeof(mdev->model));
+		if (udev->serial)
+			strlcpy(mdev->serial, udev->serial,
+				sizeof(mdev->serial));
+		strcpy(mdev->bus_info, udev->devpath);
+		mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
 
-	media_device_init(mdev);
+		media_device_init(mdev);
+	}
 
 	dev->media_dev = mdev;
 #endif
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 15/22] media: au0828 handle media_init and media_register window
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Media device initialization and registration
steps are split. There is a window between
media device init and media device register
during usb probe.

au0828 bridge driver and snd-usb-audio could
try to initialize the media device, if they
simply checked, whether the device has been
registered. They also need to check whether
the device has been initialized.

Change the au0828-core to check if media device
is already initialized during initialization step
and check if media device is already registered
during the registration step.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index b8c4bdd..e43618d 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -227,7 +227,8 @@ static int au0828_media_device_init(struct au0828_dev *dev,
 	if (!mdev)
 		return -ENOMEM;
 
-	if (!media_devnode_is_registered(&mdev->devnode)) {
+	/* check if media device is already initialized */
+	if (!mdev->dev) {
 		mdev->dev = &udev->dev;
 
 		if (udev->product)
@@ -325,6 +326,27 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 	return 0;
 }
 
+static int au0828_media_device_register(struct au0828_dev *dev,
+					struct usb_device *udev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	int ret;
+
+	if (dev->media_dev &&
+		!media_devnode_is_registered(&dev->media_dev->devnode)) {
+
+		/* register media device */
+		ret = media_device_register(dev->media_dev);
+		if (ret) {
+			dev_err(&udev->dev,
+				"Media Device Register Error: %d\n", ret);
+			return ret;
+		}
+	}
+#endif
+	return 0;
+}
+
 static int au0828_usb_probe(struct usb_interface *interface,
 	const struct usb_device_id *id)
 {
@@ -452,7 +474,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
 	}
 
 #ifdef CONFIG_MEDIA_CONTROLLER
-	retval = media_device_register(dev->media_dev);
+	retval = au0828_media_device_register(dev, usbdev);
 #endif
 
 done:
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 15/22] media: au0828 handle media_init and media_register window
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Media device initialization and registration
steps are split. There is a window between
media device init and media device register
during usb probe.

au0828 bridge driver and snd-usb-audio could
try to initialize the media device, if they
simply checked, whether the device has been
registered. They also need to check whether
the device has been initialized.

Change the au0828-core to check if media device
is already initialized during initialization step
and check if media device is already registered
during the registration step.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index b8c4bdd..e43618d 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -227,7 +227,8 @@ static int au0828_media_device_init(struct au0828_dev *dev,
 	if (!mdev)
 		return -ENOMEM;
 
-	if (!media_devnode_is_registered(&mdev->devnode)) {
+	/* check if media device is already initialized */
+	if (!mdev->dev) {
 		mdev->dev = &udev->dev;
 
 		if (udev->product)
@@ -325,6 +326,27 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 	return 0;
 }
 
+static int au0828_media_device_register(struct au0828_dev *dev,
+					struct usb_device *udev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	int ret;
+
+	if (dev->media_dev &&
+		!media_devnode_is_registered(&dev->media_dev->devnode)) {
+
+		/* register media device */
+		ret = media_device_register(dev->media_dev);
+		if (ret) {
+			dev_err(&udev->dev,
+				"Media Device Register Error: %d\n", ret);
+			return ret;
+		}
+	}
+#endif
+	return 0;
+}
+
 static int au0828_usb_probe(struct usb_interface *interface,
 	const struct usb_device_id *id)
 {
@@ -452,7 +474,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
 	}
 
 #ifdef CONFIG_MEDIA_CONTROLLER
-	retval = media_device_register(dev->media_dev);
+	retval = au0828_media_device_register(dev, usbdev);
 #endif
 
 done:
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 16/22] media: au0828 create tuner to decoder link in disabled state
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Create tuner to demod pad link in disabled state to
avoid disable step when tuner resource is requested
by dvb.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index e43618d..868babe 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -278,9 +278,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		return -EINVAL;
 
 	if (tuner) {
+		/* create tuner to decoder link in deactivated state */
 		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
-					    decoder, 0,
-					    MEDIA_LNK_FL_ENABLED);
+					    decoder, 0, 0);
 		if (ret)
 			return ret;
 	}
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 16/22] media: au0828 create tuner to decoder link in disabled state
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Create tuner to demod pad link in disabled state to
avoid disable step when tuner resource is requested
by dvb.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index e43618d..868babe 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -278,9 +278,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		return -EINVAL;
 
 	if (tuner) {
+		/* create tuner to decoder link in deactivated state */
 		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
-					    decoder, 0,
-					    MEDIA_LNK_FL_ENABLED);
+					    decoder, 0, 0);
 		if (ret)
 			return ret;
 	}
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 17/22] media: au0828 disable tuner to demod link
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change au0828_create_media_graph() to find and disable
tuner and demod link. This helps avoid an additional
disable step when tuner is requested by video or audio.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 868babe..b02a122 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -254,7 +254,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 #ifdef CONFIG_MEDIA_CONTROLLER
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity *entity;
-	struct media_entity *tuner = NULL, *decoder = NULL;
+	struct media_entity *tuner = NULL, *decoder = NULL, *demod = NULL;
 	int i, ret;
 
 	if (!mdev)
@@ -268,6 +268,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		case MEDIA_ENT_F_ATV_DECODER:
 			decoder = entity;
 			break;
+		case MEDIA_ENT_F_DTV_DEMOD:
+			demod = entity;
+			break;
 		}
 	}
 
@@ -322,6 +325,21 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 			break;
 		}
 	}
+
+	/*
+	 * Disable tuner to demod link to avoid disable step
+	 * when tuner is requested by video or audio
+	*/
+	if (tuner && demod) {
+		struct media_link *link;
+
+		list_for_each_entry(link, &demod->links, list) {
+			if (link->sink->entity == demod &&
+			    link->source->entity == tuner) {
+				media_entity_setup_link(link, 0);
+			}
+		}
+	}
 #endif
 	return 0;
 }
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 17/22] media: au0828 disable tuner to demod link
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Change au0828_create_media_graph() to find and disable
tuner and demod link. This helps avoid an additional
disable step when tuner is requested by video or audio.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 868babe..b02a122 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -254,7 +254,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 #ifdef CONFIG_MEDIA_CONTROLLER
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity *entity;
-	struct media_entity *tuner = NULL, *decoder = NULL;
+	struct media_entity *tuner = NULL, *decoder = NULL, *demod = NULL;
 	int i, ret;
 
 	if (!mdev)
@@ -268,6 +268,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		case MEDIA_ENT_F_ATV_DECODER:
 			decoder = entity;
 			break;
+		case MEDIA_ENT_F_DTV_DEMOD:
+			demod = entity;
+			break;
 		}
 	}
 
@@ -322,6 +325,21 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 			break;
 		}
 	}
+
+	/*
+	 * Disable tuner to demod link to avoid disable step
+	 * when tuner is requested by video or audio
+	*/
+	if (tuner && demod) {
+		struct media_link *link;
+
+		list_for_each_entry(link, &demod->links, list) {
+			if (link->sink->entity == demod &&
+			    link->source->entity == tuner) {
+				media_entity_setup_link(link, 0);
+			}
+		}
+	}
 #endif
 	return 0;
 }
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 18/22] media: au0828 Use au8522_media_pads enum for pad defines
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change au0828-core to use au8522_media_pads enum defines
instead of hard-coding the pad values.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index b02a122..92d22ed 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -20,6 +20,7 @@
  */
 
 #include "au0828.h"
+#include "au8522.h"
 
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -287,11 +288,13 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		if (ret)
 			return ret;
 	}
-	ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+	ret = media_create_pad_link(decoder, AU8522_PAD_VID_OUT,
+				    &dev->vdev.entity, 0,
 				    MEDIA_LNK_FL_ENABLED);
 	if (ret)
 		return ret;
-	ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+	ret = media_create_pad_link(decoder, AU8522_PAD_VBI_OUT,
+				    &dev->vbi_dev.entity, 0,
 				    MEDIA_LNK_FL_ENABLED);
 	if (ret)
 		return ret;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 18/22] media: au0828 Use au8522_media_pads enum for pad defines
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Change au0828-core to use au8522_media_pads enum defines
instead of hard-coding the pad values.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index b02a122..92d22ed 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -20,6 +20,7 @@
  */
 
 #include "au0828.h"
+#include "au8522.h"
 
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -287,11 +288,13 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		if (ret)
 			return ret;
 	}
-	ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+	ret = media_create_pad_link(decoder, AU8522_PAD_VID_OUT,
+				    &dev->vdev.entity, 0,
 				    MEDIA_LNK_FL_ENABLED);
 	if (ret)
 		return ret;
-	ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+	ret = media_create_pad_link(decoder, AU8522_PAD_VBI_OUT,
+				    &dev->vbi_dev.entity, 0,
 				    MEDIA_LNK_FL_ENABLED);
 	if (ret)
 		return ret;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 19/22] media: au0828-core register entity_notify hook
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Register entity_notify async hook to create links
between existing bridge driver entities and a newly
added non-bridge driver entities. For example, this
handler creates link between V4L decoder entity and
ALSA mixer entity.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 43 ++++++++++++++++++++++++++++++++--
 drivers/media/usb/au0828/au0828.h      |  1 +
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 92d22ed..4c90f28 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -347,14 +347,42 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 	return 0;
 }
 
+void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct au0828_dev *dev = (struct au0828_dev *) notify_data;
+	int ret;
+
+	if (!dev->decoder)
+		return;
+
+	switch (new->function) {
+	case MEDIA_ENT_F_AUDIO_MIXER:
+		ret = media_create_pad_link(dev->decoder,
+					    AU8522_PAD_AUDIO_OUT,
+					    new, 0,
+					    MEDIA_LNK_FL_ENABLED);
+		if (ret)
+			dev_err(&dev->usbdev->dev,
+				"Mixer Pad Link Create Error: %d\n",
+				ret);
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
 static int au0828_media_device_register(struct au0828_dev *dev,
 					struct usb_device *udev)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER
 	int ret;
 
-	if (dev->media_dev &&
-		!media_devnode_is_registered(&dev->media_dev->devnode)) {
+	if (!dev->media_dev)
+		return 0;
+
+	if (!media_devnode_is_registered(&dev->media_dev->devnode)) {
 
 		/* register media device */
 		ret = media_device_register(dev->media_dev);
@@ -364,6 +392,17 @@ static int au0828_media_device_register(struct au0828_dev *dev,
 			return ret;
 		}
 	}
+	/* register entity_notify callback */
+	dev->entity_notify.notify_data = (void *) dev;
+	dev->entity_notify.notify = (void *) au0828_media_graph_notify;
+	ret = media_device_register_entity_notify(dev->media_dev,
+						  &dev->entity_notify);
+	if (ret) {
+		dev_err(&udev->dev,
+			"Media Device register entity_notify Error: %d\n",
+			ret);
+		return ret;
+	}
 #endif
 	return 0;
 }
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 8276072..54379ec 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -283,6 +283,7 @@ struct au0828_dev {
 	struct media_entity *decoder;
 	struct media_entity input_ent[AU0828_MAX_INPUT];
 	struct media_pad input_pad[AU0828_MAX_INPUT];
+	struct media_entity_notify entity_notify;
 #endif
 };
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 19/22] media: au0828-core register entity_notify hook
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Register entity_notify async hook to create links
between existing bridge driver entities and a newly
added non-bridge driver entities. For example, this
handler creates link between V4L decoder entity and
ALSA mixer entity.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 43 ++++++++++++++++++++++++++++++++--
 drivers/media/usb/au0828/au0828.h      |  1 +
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 92d22ed..4c90f28 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -347,14 +347,42 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 	return 0;
 }
 
+void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct au0828_dev *dev = (struct au0828_dev *) notify_data;
+	int ret;
+
+	if (!dev->decoder)
+		return;
+
+	switch (new->function) {
+	case MEDIA_ENT_F_AUDIO_MIXER:
+		ret = media_create_pad_link(dev->decoder,
+					    AU8522_PAD_AUDIO_OUT,
+					    new, 0,
+					    MEDIA_LNK_FL_ENABLED);
+		if (ret)
+			dev_err(&dev->usbdev->dev,
+				"Mixer Pad Link Create Error: %d\n",
+				ret);
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
 static int au0828_media_device_register(struct au0828_dev *dev,
 					struct usb_device *udev)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER
 	int ret;
 
-	if (dev->media_dev &&
-		!media_devnode_is_registered(&dev->media_dev->devnode)) {
+	if (!dev->media_dev)
+		return 0;
+
+	if (!media_devnode_is_registered(&dev->media_dev->devnode)) {
 
 		/* register media device */
 		ret = media_device_register(dev->media_dev);
@@ -364,6 +392,17 @@ static int au0828_media_device_register(struct au0828_dev *dev,
 			return ret;
 		}
 	}
+	/* register entity_notify callback */
+	dev->entity_notify.notify_data = (void *) dev;
+	dev->entity_notify.notify = (void *) au0828_media_graph_notify;
+	ret = media_device_register_entity_notify(dev->media_dev,
+						  &dev->entity_notify);
+	if (ret) {
+		dev_err(&udev->dev,
+			"Media Device register entity_notify Error: %d\n",
+			ret);
+		return ret;
+	}
 #endif
 	return 0;
 }
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 8276072..54379ec 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -283,6 +283,7 @@ struct au0828_dev {
 	struct media_entity *decoder;
 	struct media_entity input_ent[AU0828_MAX_INPUT];
 	struct media_pad input_pad[AU0828_MAX_INPUT];
+	struct media_entity_notify entity_notify;
 #endif
 };
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 20/22] media: au0828 add enable, disable source handlers
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Add enable_source and disable_source handlers.
The enable source handler is called from
v4l2-core, dvb-core, and ALSA drivers to check
if the shared media source is free. The disable
source handler is called to release the shared
media source.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
 drivers/media/usb/au0828/au0828.h      |   3 +
 2 files changed, 152 insertions(+)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 4c90f28..fd2265c 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		return -EINVAL;
 
 	if (tuner) {
+		dev->tuner = tuner;
 		/* create tuner to decoder link in deactivated state */
 		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
 					    decoder, 0, 0);
@@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
 #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 ret = 0;
+	struct media_device *mdev = entity->graph_obj.mdev;
+	struct au0828_dev *dev;
+
+	if (!mdev)
+		return -ENODEV;
+
+	/* for Audio 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 Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
+		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;
+		}
+	}
+
+	list_for_each_entry(link, &sink->links, list) {
+		/* Check sink, and source */
+		if (link->sink->entity == sink &&
+		    link->source->entity == dev->tuner) {
+			found_link = link;
+			break;
+		}
+	}
+
+	if (!found_link) {
+		ret = -ENODEV;
+		goto end;
+	}
+
+	/* activate link between source and sink and start pipeline */
+	source = found_link->source->entity;
+	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
+	if (ret) {
+		pr_err(
+			"Activate tuner link %s->%s. Error %d\n",
+			source->name, sink->name, ret);
+		goto end;
+	}
+
+	ret = __media_entity_pipeline_start(entity, pipe);
+	if (ret) {
+		pr_err("Start Pipeline: %s->%s Error %d\n",
+			source->name, entity->name, ret);
+		ret = __media_entity_setup_link(found_link, 0);
+		pr_err("Deactive link Error %d\n", ret);
+		goto end;
+	}
+	/*
+	 * save active link and active link owner to avoid audio
+	 * deactivating video owned link from disable_source and
+	 * vice versa
+	*/
+	dev->active_link = found_link;
+	dev->active_link_owner = entity;
+end:
+	mutex_unlock(&mdev->graph_mutex);
+	pr_debug("au0828_enable_source() end %s %d %d\n",
+		entity->name, entity->function, ret);
+	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->graph_obj.mdev;
+	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->function != MEDIA_ENT_F_DTV_DEMOD)
+		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);
+		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 int au0828_media_device_register(struct au0828_dev *dev,
 					struct usb_device *udev)
 {
@@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
 			ret);
 		return ret;
 	}
+	/* set enable_source */
+	dev->media_dev->source_priv = (void *) dev;
+	dev->media_dev->enable_source = au0828_enable_source;
+	dev->media_dev->disable_source = au0828_disable_source;
 #endif
 	return 0;
 }
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 54379ec..a7c88a1 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -284,6 +284,9 @@ struct au0828_dev {
 	struct media_entity input_ent[AU0828_MAX_INPUT];
 	struct media_pad input_pad[AU0828_MAX_INPUT];
 	struct media_entity_notify entity_notify;
+	struct media_entity *tuner;
+	struct media_link *active_link;
+	struct media_entity *active_link_owner;
 #endif
 };
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 20/22] media: au0828 add enable, disable source handlers
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Add enable_source and disable_source handlers.
The enable source handler is called from
v4l2-core, dvb-core, and ALSA drivers to check
if the shared media source is free. The disable
source handler is called to release the shared
media source.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
 drivers/media/usb/au0828/au0828.h      |   3 +
 2 files changed, 152 insertions(+)

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 4c90f28..fd2265c 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		return -EINVAL;
 
 	if (tuner) {
+		dev->tuner = tuner;
 		/* create tuner to decoder link in deactivated state */
 		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
 					    decoder, 0, 0);
@@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
 #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 ret = 0;
+	struct media_device *mdev = entity->graph_obj.mdev;
+	struct au0828_dev *dev;
+
+	if (!mdev)
+		return -ENODEV;
+
+	/* for Audio 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 Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
+		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;
+		}
+	}
+
+	list_for_each_entry(link, &sink->links, list) {
+		/* Check sink, and source */
+		if (link->sink->entity == sink &&
+		    link->source->entity == dev->tuner) {
+			found_link = link;
+			break;
+		}
+	}
+
+	if (!found_link) {
+		ret = -ENODEV;
+		goto end;
+	}
+
+	/* activate link between source and sink and start pipeline */
+	source = found_link->source->entity;
+	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
+	if (ret) {
+		pr_err(
+			"Activate tuner link %s->%s. Error %d\n",
+			source->name, sink->name, ret);
+		goto end;
+	}
+
+	ret = __media_entity_pipeline_start(entity, pipe);
+	if (ret) {
+		pr_err("Start Pipeline: %s->%s Error %d\n",
+			source->name, entity->name, ret);
+		ret = __media_entity_setup_link(found_link, 0);
+		pr_err("Deactive link Error %d\n", ret);
+		goto end;
+	}
+	/*
+	 * save active link and active link owner to avoid audio
+	 * deactivating video owned link from disable_source and
+	 * vice versa
+	*/
+	dev->active_link = found_link;
+	dev->active_link_owner = entity;
+end:
+	mutex_unlock(&mdev->graph_mutex);
+	pr_debug("au0828_enable_source() end %s %d %d\n",
+		entity->name, entity->function, ret);
+	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->graph_obj.mdev;
+	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->function != MEDIA_ENT_F_DTV_DEMOD)
+		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);
+		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 int au0828_media_device_register(struct au0828_dev *dev,
 					struct usb_device *udev)
 {
@@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
 			ret);
 		return ret;
 	}
+	/* set enable_source */
+	dev->media_dev->source_priv = (void *) dev;
+	dev->media_dev->enable_source = au0828_enable_source;
+	dev->media_dev->disable_source = au0828_disable_source;
 #endif
 	return 0;
 }
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 54379ec..a7c88a1 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -284,6 +284,9 @@ struct au0828_dev {
 	struct media_entity input_ent[AU0828_MAX_INPUT];
 	struct media_pad input_pad[AU0828_MAX_INPUT];
 	struct media_entity_notify entity_notify;
+	struct media_entity *tuner;
+	struct media_link *active_link;
+	struct media_entity *active_link_owner;
 #endif
 };
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Change ALSA driver to use Media Controller API to
share media resources with DVB and V4L2 drivers
on a AU0828 media device. Media Controller specific
initialization is done after sound card is registered.
ALSA creates Media interface and entity function graph
nodes for Control, Mixer, PCM Playback, and PCM Capture
devices.

snd_usb_hw_params() will call Media Controller enable
source handler interface to request the media resource.
If resource request is granted, it will release it from
snd_usb_hw_free(). If resource is busy, -EBUSY is returned.

Media specific cleanup is done in usb_audio_disconnect().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 sound/usb/Kconfig        |   4 +
 sound/usb/Makefile       |   2 +
 sound/usb/card.c         |  14 +++
 sound/usb/card.h         |   1 +
 sound/usb/media.c        | 319 +++++++++++++++++++++++++++++++++++++++++++++++
 sound/usb/media.h        |  72 +++++++++++
 sound/usb/mixer.h        |   1 +
 sound/usb/pcm.c          |  28 ++++-
 sound/usb/quirks-table.h |   1 +
 sound/usb/stream.c       |   2 +
 sound/usb/usbaudio.h     |   3 +
 11 files changed, 442 insertions(+), 5 deletions(-)
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index a452ad7..1a71d93 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -15,6 +15,7 @@ config SND_USB_AUDIO
 	select SND_RAWMIDI
 	select SND_PCM
 	select BITREVERSE
+	select SND_USB_AUDIO_USE_MEDIA_CONTROLLER	if MEDIA_CONTROLLER
 	help
 	  Say Y here to include support for USB audio and USB MIDI
 	  devices.
@@ -22,6 +23,9 @@ config SND_USB_AUDIO
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-audio.
 
+config SND_USB_AUDIO_USE_MEDIA_CONTROLLER
+	bool
+
 config SND_USB_UA101
 	tristate "Edirol UA-101/UA-1000 driver"
 	select SND_PCM
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 2d2d122..8dca3c4 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -15,6 +15,8 @@ snd-usb-audio-objs := 	card.o \
 			quirks.o \
 			stream.o
 
+snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o
+
 snd-usbmidi-lib-objs := midi.o
 
 # Toplevel Module Dependency
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 1f09d95..35fe256 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -66,6 +66,7 @@
 #include "format.h"
 #include "power.h"
 #include "stream.h"
+#include "media.h"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
@@ -561,6 +562,11 @@ static int usb_audio_probe(struct usb_interface *intf,
 	if (err < 0)
 		goto __error;
 
+	if (quirk->media_device) {
+		/* don't want to fail when media_device_create() fails */
+		media_device_create(chip, intf);
+	}
+
 	usb_chip[chip->index] = chip;
 	chip->num_interfaces++;
 	usb_set_intfdata(intf, chip);
@@ -617,6 +623,14 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		list_for_each(p, &chip->midi_list) {
 			snd_usbmidi_disconnect(p);
 		}
+		/*
+		 * Nice to check quirk && quirk->media_device
+		 * need some special handlings. Doesn't look like
+		 * we have access to quirk here
+		 * Acceses mixer_list
+		*/
+		media_device_delete(chip);
+
 		/* release mixer resources */
 		list_for_each_entry(mixer, &chip->mixer_list, list) {
 			snd_usb_mixer_disconnect(mixer);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 71778ca..c15a03c 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -156,6 +156,7 @@ struct snd_usb_substream {
 	} dsd_dop;
 
 	bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
+	void *media_ctl;
 };
 
 struct snd_usb_stream {
diff --git a/sound/usb/media.c b/sound/usb/media.c
new file mode 100644
index 0000000..8fef48e
--- /dev/null
+++ b/sound/usb/media.c
@@ -0,0 +1,319 @@
+/*
+ * media.c - Media Controller specific ALSA driver code
+ *
+ * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * This file is released under the GPLv2.
+ */
+
+/*
+ * This file adds Media Controller support to ALSA driver
+ * to use the Media Controller API to share tuner with DVB
+ * and V4L2 drivers that control media device. Media device
+ * is created based on existing quirks framework. Using this
+ * approach, the media controller API usage can be added for
+ * a specific device.
+*/
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <sound/pcm.h>
+#include <sound/core.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "mixer.h"
+#include "media.h"
+
+static int media_enable_source(struct media_ctl *mctl)
+{
+	if (mctl && mctl->media_dev->enable_source)
+		return mctl->media_dev->enable_source(&mctl->media_entity,
+						      &mctl->media_pipe);
+	return 0;
+}
+
+static void media_disable_source(struct media_ctl *mctl)
+{
+	if (mctl && mctl->media_dev->disable_source)
+		mctl->media_dev->disable_source(&mctl->media_entity);
+}
+
+int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
+			int stream)
+{
+	struct media_device *mdev;
+	struct media_ctl *mctl;
+	struct device *pcm_dev = &pcm->streams[stream].dev;
+	u32 intf_type;
+	int ret = 0;
+	u16 mixer_pad;
+	struct media_entity *entity;
+
+	mdev = subs->stream->chip->media_dev;
+	if (!mdev)
+		return -ENODEV;
+
+	if (subs->media_ctl)
+		return 0;
+
+	/* allocate media_ctl */
+	mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
+	if (!mctl)
+		return -ENOMEM;
+
+	mctl->media_dev = mdev;
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK;
+		mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE;
+		mixer_pad = 1;
+	} else {
+		intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
+		mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
+		mixer_pad = 2;
+	}
+	mctl->media_entity.name = pcm->name;
+	media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
+	ret =  media_device_register_entity(mctl->media_dev,
+					    &mctl->media_entity);
+	if (ret)
+		goto err1;
+
+	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
+						  MAJOR(pcm_dev->devt),
+						  MINOR(pcm_dev->devt));
+	if (!mctl->intf_devnode) {
+		ret = -ENOMEM;
+		goto err2;
+	}
+	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
+						 &mctl->intf_devnode->intf,
+						 MEDIA_LNK_FL_ENABLED);
+	if (!mctl->intf_link) {
+		ret = -ENOMEM;
+		goto err3;
+	}
+
+	/* create link between mixer and audio */
+	media_device_for_each_entity(entity, mdev) {
+		switch (entity->function) {
+		case MEDIA_ENT_F_AUDIO_MIXER:
+			ret = media_create_pad_link(entity, mixer_pad,
+						    &mctl->media_entity, 0,
+						    MEDIA_LNK_FL_ENABLED);
+			if (ret)
+				goto err4;
+			break;
+		}
+	}
+
+	subs->media_ctl = mctl;
+	return 0;
+
+err4:
+	media_remove_intf_link(mctl->intf_link);
+err3:
+	media_devnode_remove(mctl->intf_devnode);
+err2:
+	media_device_unregister_entity(&mctl->media_entity);
+err1:
+	kfree(mctl);
+	return ret;
+}
+
+void media_stream_delete(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = subs->media_ctl;
+
+	if (mctl && mctl->media_dev) {
+		struct media_device *mdev;
+
+		mdev = subs->stream->chip->media_dev;
+		if (mdev && media_devnode_is_registered(&mdev->devnode)) {
+			media_devnode_remove(mctl->intf_devnode);
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+		}
+		kfree(mctl);
+		subs->media_ctl = NULL;
+	}
+}
+
+int media_start_pipeline(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = subs->media_ctl;
+
+	if (mctl)
+		return media_enable_source(mctl);
+	return 0;
+}
+
+void media_stop_pipeline(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = subs->media_ctl;
+
+	if (mctl)
+		media_disable_source(mctl);
+}
+
+int media_mixer_init(struct snd_usb_audio *chip)
+{
+	struct device *ctl_dev = &chip->card->ctl_dev;
+	struct media_intf_devnode *ctl_intf;
+	struct usb_mixer_interface *mixer;
+	struct media_device *mdev = chip->media_dev;
+	struct media_mixer_ctl *mctl;
+	u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
+	int ret;
+
+	if (!mdev)
+		return -ENODEV;
+
+	ctl_intf = chip->ctl_intf_media_devnode;
+	if (!ctl_intf) {
+		ctl_intf = (void *) media_devnode_create(mdev,
+							 intf_type, 0,
+							 MAJOR(ctl_dev->devt),
+							 MINOR(ctl_dev->devt));
+		if (!ctl_intf)
+			return -ENOMEM;
+		chip->ctl_intf_media_devnode = ctl_intf;
+	}
+
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+
+		if (mixer->media_mixer_ctl)
+			continue;
+
+		/* allocate media_mixer_ctl */
+		mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
+		if (!mctl)
+			return -ENOMEM;
+
+		mctl->media_dev = mdev;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
+		mctl->media_entity.name = chip->card->mixername;
+		mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
+		mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
+		mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
+		media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
+				  mctl->media_pad);
+		ret =  media_device_register_entity(mctl->media_dev,
+						    &mctl->media_entity);
+		if (ret) {
+			kfree(mctl);
+			return ret;
+		}
+
+		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
+							 &ctl_intf->intf,
+							 MEDIA_LNK_FL_ENABLED);
+		if (!mctl->intf_link) {
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+			kfree(mctl);
+			return -ENOMEM;
+		}
+		mctl->intf_devnode = ctl_intf;
+		mixer->media_mixer_ctl = mctl;
+	}
+	return 0;
+}
+
+static void media_mixer_delete(struct snd_usb_audio *chip)
+{
+	struct usb_mixer_interface *mixer;
+	struct media_device *mdev = chip->media_dev;
+
+	if (!mdev)
+		return;
+
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+		struct media_mixer_ctl *mctl;
+
+		mctl = mixer->media_mixer_ctl;
+		if (!mixer->media_mixer_ctl)
+			continue;
+
+		if (media_devnode_is_registered(&mdev->devnode)) {
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+		}
+		kfree(mctl);
+		mixer->media_mixer_ctl = NULL;
+	}
+	if (media_devnode_is_registered(&mdev->devnode))
+		media_devnode_remove(chip->ctl_intf_media_devnode);
+	chip->ctl_intf_media_devnode = NULL;
+}
+
+int media_device_create(struct snd_usb_audio *chip,
+			struct usb_interface *iface)
+{
+	struct media_device *mdev;
+	struct usb_device *usbdev = interface_to_usbdev(iface);
+	int ret;
+
+	mdev = media_device_get_devres(&usbdev->dev);
+	if (!mdev)
+		return -ENOMEM;
+	if (!mdev->dev) {
+		/* register media device */
+		mdev->dev = &usbdev->dev;
+		if (usbdev->product)
+			strlcpy(mdev->model, usbdev->product,
+				sizeof(mdev->model));
+		if (usbdev->serial)
+			strlcpy(mdev->serial, usbdev->serial,
+				sizeof(mdev->serial));
+		strcpy(mdev->bus_info, usbdev->devpath);
+		mdev->hw_revision = le16_to_cpu(usbdev->descriptor.bcdDevice);
+		media_device_init(mdev);
+	}
+	if (!media_devnode_is_registered(&mdev->devnode)) {
+		ret = media_device_register(mdev);
+		if (ret) {
+			dev_err(&usbdev->dev,
+				"Couldn't register media device. Error: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	/* save media device - avoid lookups */
+	chip->media_dev = mdev;
+
+	/* Create media entities for mixer and control dev */
+	ret = media_mixer_init(chip);
+	if (ret) {
+		dev_err(&usbdev->dev,
+			"Couldn't create media mixer entities. Error: %d\n",
+			ret);
+
+		/* clear saved media_dev */
+		chip->media_dev = NULL;
+
+		return ret;
+	}
+	return 0;
+}
+
+void media_device_delete(struct snd_usb_audio *chip)
+{
+	struct media_device *mdev = chip->media_dev;
+
+	media_mixer_delete(chip);
+
+	if (mdev) {
+		if (media_devnode_is_registered(&mdev->devnode))
+			media_device_unregister(mdev);
+		chip->media_dev = NULL;
+	}
+}
diff --git a/sound/usb/media.h b/sound/usb/media.h
new file mode 100644
index 0000000..b5f451a
--- /dev/null
+++ b/sound/usb/media.h
@@ -0,0 +1,72 @@
+/*
+ * media.h - Media Controller specific ALSA driver code
+ *
+ * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * This file is released under the GPLv2.
+ */
+
+/*
+ * This file adds Media Controller support to ALSA driver
+ * to use the Media Controller API to share tuner with DVB
+ * and V4L2 drivers that control media device. Media device
+ * is created based on existing quirks framework. Using this
+ * approach, the media controller API usage can be added for
+ * a specific device.
+*/
+#ifndef __MEDIA_H
+
+#ifdef CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER
+
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <sound/asound.h>
+
+struct media_ctl {
+	struct media_device *media_dev;
+	struct media_entity media_entity;
+	struct media_intf_devnode *intf_devnode;
+	struct media_link *intf_link;
+	struct media_pad media_pad;
+	struct media_pipeline media_pipe;
+};
+
+/*
+ * One source pad each for SNDRV_PCM_STREAM_CAPTURE and
+ * SNDRV_PCM_STREAM_PLAYBACK. One for sink pad to link
+ * to AUDIO Source
+*/
+#define MEDIA_MIXER_PAD_MAX    (SNDRV_PCM_STREAM_LAST + 2)
+
+struct media_mixer_ctl {
+	struct media_device *media_dev;
+	struct media_entity media_entity;
+	struct media_intf_devnode *intf_devnode;
+	struct media_link *intf_link;
+	struct media_pad media_pad[MEDIA_MIXER_PAD_MAX];
+	struct media_pipeline media_pipe;
+};
+
+int media_device_create(struct snd_usb_audio *chip,
+			struct usb_interface *iface);
+void media_device_delete(struct snd_usb_audio *chip);
+int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
+			int stream);
+void media_stream_delete(struct snd_usb_substream *subs);
+int media_start_pipeline(struct snd_usb_substream *subs);
+void media_stop_pipeline(struct snd_usb_substream *subs);
+#else
+static inline int media_device_create(struct snd_usb_audio *chip,
+				      struct usb_interface *iface)
+						{ return 0; }
+static inline void media_device_delete(struct snd_usb_audio *chip) { }
+static inline int media_stream_init(struct snd_usb_substream *subs,
+					struct snd_pcm *pcm, int stream)
+						{ return 0; }
+static inline void media_stream_delete(struct snd_usb_substream *subs) { }
+static inline int media_start_pipeline(struct snd_usb_substream *subs)
+					{ return 0; }
+static inline void media_stop_pipeline(struct snd_usb_substream *subs) { }
+#endif
+#endif /* __MEDIA_H */
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 3417ef3..787b352 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -22,6 +22,7 @@ struct usb_mixer_interface {
 	struct urb *rc_urb;
 	struct usb_ctrlrequest *rc_setup_packet;
 	u8 rc_buffer[6];
+	void *media_mixer_ctl;
 };
 
 #define MAX_CHANNELS	16	/* max logical channels */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 9245f52..c3b8486 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -35,6 +35,7 @@
 #include "pcm.h"
 #include "clock.h"
 #include "power.h"
+#include "media.h"
 
 #define SUBSTREAM_FLAG_DATA_EP_STARTED	0
 #define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
@@ -715,10 +716,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	struct audioformat *fmt;
 	int ret;
 
+	ret = media_start_pipeline(subs);
+	if (ret)
+		return ret;
+
 	ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 					       params_buffer_bytes(hw_params));
 	if (ret < 0)
-		return ret;
+		goto err_ret;
 
 	subs->pcm_format = params_format(hw_params);
 	subs->period_bytes = params_period_bytes(hw_params);
@@ -732,22 +737,27 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 		dev_dbg(&subs->dev->dev,
 			"cannot set format: format = %#x, rate = %d, channels = %d\n",
 			   subs->pcm_format, subs->cur_rate, subs->channels);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_ret;
 	}
 
 	ret = snd_usb_lock_shutdown(subs->stream->chip);
 	if (ret < 0)
-		return ret;
+		goto err_ret;
 	ret = set_format(subs, fmt);
 	snd_usb_unlock_shutdown(subs->stream->chip);
 	if (ret < 0)
-		return ret;
+		goto err_ret;
 
 	subs->interface = fmt->iface;
 	subs->altset_idx = fmt->altset_idx;
 	subs->need_setup_ep = true;
 
 	return 0;
+
+err_ret:
+	media_stop_pipeline(subs);
+	return ret;
 }
 
 /*
@@ -759,6 +769,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 {
 	struct snd_usb_substream *subs = substream->runtime->private_data;
 
+	media_stop_pipeline(subs);
 	subs->cur_audiofmt = NULL;
 	subs->cur_rate = 0;
 	subs->period_bytes = 0;
@@ -1219,6 +1230,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_usb_substream *subs = &as->substream[direction];
+	int ret;
 
 	subs->interface = -1;
 	subs->altset_idx = 0;
@@ -1232,7 +1244,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 	subs->dsd_dop.channel = 0;
 	subs->dsd_dop.marker = 1;
 
-	return setup_hw_info(runtime, subs);
+	ret = setup_hw_info(runtime, subs);
+	if (ret == 0)
+		ret = media_stream_init(subs, as->pcm, direction);
+	if (ret)
+		snd_usb_autosuspend(subs->stream->chip);
+	return ret;
 }
 
 static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
@@ -1241,6 +1258,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
 	struct snd_usb_substream *subs = &as->substream[direction];
 
 	stop_endpoints(subs, true);
+	media_stop_pipeline(subs);
 
 	if (subs->interface >= 0 &&
 	    !snd_usb_lock_shutdown(subs->stream->chip)) {
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c60a776..9d087b1 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2886,6 +2886,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		.product_name = pname, \
 		.ifnum = QUIRK_ANY_INTERFACE, \
 		.type = QUIRK_AUDIO_ALIGN_TRANSFER, \
+		.media_device = 1, \
 	} \
 }
 
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index c4dc577..6c7f5c1 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -36,6 +36,7 @@
 #include "format.h"
 #include "clock.h"
 #include "stream.h"
+#include "media.h"
 
 /*
  * free a substream
@@ -52,6 +53,7 @@ static void free_substream(struct snd_usb_substream *subs)
 		kfree(fp);
 	}
 	kfree(subs->rate_list.list);
+	media_stream_delete(subs);
 }
 
 
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b665d85..0c0a86c 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -60,6 +60,8 @@ struct snd_usb_audio {
 	bool autoclock;			/* from the 'autoclock' module param */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
+	void *media_dev;
+	void *ctl_intf_media_devnode;
 };
 
 #define usb_audio_err(chip, fmt, args...) \
@@ -110,6 +112,7 @@ struct snd_usb_audio_quirk {
 	const char *product_name;
 	int16_t ifnum;
 	uint16_t type;
+	bool media_device;
 	const void *data;
 };
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

Change ALSA driver to use Media Controller API to
share media resources with DVB and V4L2 drivers
on a AU0828 media device. Media Controller specific
initialization is done after sound card is registered.
ALSA creates Media interface and entity function graph
nodes for Control, Mixer, PCM Playback, and PCM Capture
devices.

snd_usb_hw_params() will call Media Controller enable
source handler interface to request the media resource.
If resource request is granted, it will release it from
snd_usb_hw_free(). If resource is busy, -EBUSY is returned.

Media specific cleanup is done in usb_audio_disconnect().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 sound/usb/Kconfig        |   4 +
 sound/usb/Makefile       |   2 +
 sound/usb/card.c         |  14 +++
 sound/usb/card.h         |   1 +
 sound/usb/media.c        | 319 +++++++++++++++++++++++++++++++++++++++++++++++
 sound/usb/media.h        |  72 +++++++++++
 sound/usb/mixer.h        |   1 +
 sound/usb/pcm.c          |  28 ++++-
 sound/usb/quirks-table.h |   1 +
 sound/usb/stream.c       |   2 +
 sound/usb/usbaudio.h     |   3 +
 11 files changed, 442 insertions(+), 5 deletions(-)
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index a452ad7..1a71d93 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -15,6 +15,7 @@ config SND_USB_AUDIO
 	select SND_RAWMIDI
 	select SND_PCM
 	select BITREVERSE
+	select SND_USB_AUDIO_USE_MEDIA_CONTROLLER	if MEDIA_CONTROLLER
 	help
 	  Say Y here to include support for USB audio and USB MIDI
 	  devices.
@@ -22,6 +23,9 @@ config SND_USB_AUDIO
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-audio.
 
+config SND_USB_AUDIO_USE_MEDIA_CONTROLLER
+	bool
+
 config SND_USB_UA101
 	tristate "Edirol UA-101/UA-1000 driver"
 	select SND_PCM
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 2d2d122..8dca3c4 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -15,6 +15,8 @@ snd-usb-audio-objs := 	card.o \
 			quirks.o \
 			stream.o
 
+snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o
+
 snd-usbmidi-lib-objs := midi.o
 
 # Toplevel Module Dependency
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 1f09d95..35fe256 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -66,6 +66,7 @@
 #include "format.h"
 #include "power.h"
 #include "stream.h"
+#include "media.h"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
@@ -561,6 +562,11 @@ static int usb_audio_probe(struct usb_interface *intf,
 	if (err < 0)
 		goto __error;
 
+	if (quirk->media_device) {
+		/* don't want to fail when media_device_create() fails */
+		media_device_create(chip, intf);
+	}
+
 	usb_chip[chip->index] = chip;
 	chip->num_interfaces++;
 	usb_set_intfdata(intf, chip);
@@ -617,6 +623,14 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		list_for_each(p, &chip->midi_list) {
 			snd_usbmidi_disconnect(p);
 		}
+		/*
+		 * Nice to check quirk && quirk->media_device
+		 * need some special handlings. Doesn't look like
+		 * we have access to quirk here
+		 * Acceses mixer_list
+		*/
+		media_device_delete(chip);
+
 		/* release mixer resources */
 		list_for_each_entry(mixer, &chip->mixer_list, list) {
 			snd_usb_mixer_disconnect(mixer);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 71778ca..c15a03c 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -156,6 +156,7 @@ struct snd_usb_substream {
 	} dsd_dop;
 
 	bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
+	void *media_ctl;
 };
 
 struct snd_usb_stream {
diff --git a/sound/usb/media.c b/sound/usb/media.c
new file mode 100644
index 0000000..8fef48e
--- /dev/null
+++ b/sound/usb/media.c
@@ -0,0 +1,319 @@
+/*
+ * media.c - Media Controller specific ALSA driver code
+ *
+ * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * This file is released under the GPLv2.
+ */
+
+/*
+ * This file adds Media Controller support to ALSA driver
+ * to use the Media Controller API to share tuner with DVB
+ * and V4L2 drivers that control media device. Media device
+ * is created based on existing quirks framework. Using this
+ * approach, the media controller API usage can be added for
+ * a specific device.
+*/
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <sound/pcm.h>
+#include <sound/core.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "mixer.h"
+#include "media.h"
+
+static int media_enable_source(struct media_ctl *mctl)
+{
+	if (mctl && mctl->media_dev->enable_source)
+		return mctl->media_dev->enable_source(&mctl->media_entity,
+						      &mctl->media_pipe);
+	return 0;
+}
+
+static void media_disable_source(struct media_ctl *mctl)
+{
+	if (mctl && mctl->media_dev->disable_source)
+		mctl->media_dev->disable_source(&mctl->media_entity);
+}
+
+int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
+			int stream)
+{
+	struct media_device *mdev;
+	struct media_ctl *mctl;
+	struct device *pcm_dev = &pcm->streams[stream].dev;
+	u32 intf_type;
+	int ret = 0;
+	u16 mixer_pad;
+	struct media_entity *entity;
+
+	mdev = subs->stream->chip->media_dev;
+	if (!mdev)
+		return -ENODEV;
+
+	if (subs->media_ctl)
+		return 0;
+
+	/* allocate media_ctl */
+	mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
+	if (!mctl)
+		return -ENOMEM;
+
+	mctl->media_dev = mdev;
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK;
+		mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE;
+		mixer_pad = 1;
+	} else {
+		intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
+		mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
+		mixer_pad = 2;
+	}
+	mctl->media_entity.name = pcm->name;
+	media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
+	ret =  media_device_register_entity(mctl->media_dev,
+					    &mctl->media_entity);
+	if (ret)
+		goto err1;
+
+	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
+						  MAJOR(pcm_dev->devt),
+						  MINOR(pcm_dev->devt));
+	if (!mctl->intf_devnode) {
+		ret = -ENOMEM;
+		goto err2;
+	}
+	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
+						 &mctl->intf_devnode->intf,
+						 MEDIA_LNK_FL_ENABLED);
+	if (!mctl->intf_link) {
+		ret = -ENOMEM;
+		goto err3;
+	}
+
+	/* create link between mixer and audio */
+	media_device_for_each_entity(entity, mdev) {
+		switch (entity->function) {
+		case MEDIA_ENT_F_AUDIO_MIXER:
+			ret = media_create_pad_link(entity, mixer_pad,
+						    &mctl->media_entity, 0,
+						    MEDIA_LNK_FL_ENABLED);
+			if (ret)
+				goto err4;
+			break;
+		}
+	}
+
+	subs->media_ctl = mctl;
+	return 0;
+
+err4:
+	media_remove_intf_link(mctl->intf_link);
+err3:
+	media_devnode_remove(mctl->intf_devnode);
+err2:
+	media_device_unregister_entity(&mctl->media_entity);
+err1:
+	kfree(mctl);
+	return ret;
+}
+
+void media_stream_delete(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = subs->media_ctl;
+
+	if (mctl && mctl->media_dev) {
+		struct media_device *mdev;
+
+		mdev = subs->stream->chip->media_dev;
+		if (mdev && media_devnode_is_registered(&mdev->devnode)) {
+			media_devnode_remove(mctl->intf_devnode);
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+		}
+		kfree(mctl);
+		subs->media_ctl = NULL;
+	}
+}
+
+int media_start_pipeline(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = subs->media_ctl;
+
+	if (mctl)
+		return media_enable_source(mctl);
+	return 0;
+}
+
+void media_stop_pipeline(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = subs->media_ctl;
+
+	if (mctl)
+		media_disable_source(mctl);
+}
+
+int media_mixer_init(struct snd_usb_audio *chip)
+{
+	struct device *ctl_dev = &chip->card->ctl_dev;
+	struct media_intf_devnode *ctl_intf;
+	struct usb_mixer_interface *mixer;
+	struct media_device *mdev = chip->media_dev;
+	struct media_mixer_ctl *mctl;
+	u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
+	int ret;
+
+	if (!mdev)
+		return -ENODEV;
+
+	ctl_intf = chip->ctl_intf_media_devnode;
+	if (!ctl_intf) {
+		ctl_intf = (void *) media_devnode_create(mdev,
+							 intf_type, 0,
+							 MAJOR(ctl_dev->devt),
+							 MINOR(ctl_dev->devt));
+		if (!ctl_intf)
+			return -ENOMEM;
+		chip->ctl_intf_media_devnode = ctl_intf;
+	}
+
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+
+		if (mixer->media_mixer_ctl)
+			continue;
+
+		/* allocate media_mixer_ctl */
+		mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
+		if (!mctl)
+			return -ENOMEM;
+
+		mctl->media_dev = mdev;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
+		mctl->media_entity.name = chip->card->mixername;
+		mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
+		mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
+		mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
+		media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
+				  mctl->media_pad);
+		ret =  media_device_register_entity(mctl->media_dev,
+						    &mctl->media_entity);
+		if (ret) {
+			kfree(mctl);
+			return ret;
+		}
+
+		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
+							 &ctl_intf->intf,
+							 MEDIA_LNK_FL_ENABLED);
+		if (!mctl->intf_link) {
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+			kfree(mctl);
+			return -ENOMEM;
+		}
+		mctl->intf_devnode = ctl_intf;
+		mixer->media_mixer_ctl = mctl;
+	}
+	return 0;
+}
+
+static void media_mixer_delete(struct snd_usb_audio *chip)
+{
+	struct usb_mixer_interface *mixer;
+	struct media_device *mdev = chip->media_dev;
+
+	if (!mdev)
+		return;
+
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+		struct media_mixer_ctl *mctl;
+
+		mctl = mixer->media_mixer_ctl;
+		if (!mixer->media_mixer_ctl)
+			continue;
+
+		if (media_devnode_is_registered(&mdev->devnode)) {
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+		}
+		kfree(mctl);
+		mixer->media_mixer_ctl = NULL;
+	}
+	if (media_devnode_is_registered(&mdev->devnode))
+		media_devnode_remove(chip->ctl_intf_media_devnode);
+	chip->ctl_intf_media_devnode = NULL;
+}
+
+int media_device_create(struct snd_usb_audio *chip,
+			struct usb_interface *iface)
+{
+	struct media_device *mdev;
+	struct usb_device *usbdev = interface_to_usbdev(iface);
+	int ret;
+
+	mdev = media_device_get_devres(&usbdev->dev);
+	if (!mdev)
+		return -ENOMEM;
+	if (!mdev->dev) {
+		/* register media device */
+		mdev->dev = &usbdev->dev;
+		if (usbdev->product)
+			strlcpy(mdev->model, usbdev->product,
+				sizeof(mdev->model));
+		if (usbdev->serial)
+			strlcpy(mdev->serial, usbdev->serial,
+				sizeof(mdev->serial));
+		strcpy(mdev->bus_info, usbdev->devpath);
+		mdev->hw_revision = le16_to_cpu(usbdev->descriptor.bcdDevice);
+		media_device_init(mdev);
+	}
+	if (!media_devnode_is_registered(&mdev->devnode)) {
+		ret = media_device_register(mdev);
+		if (ret) {
+			dev_err(&usbdev->dev,
+				"Couldn't register media device. Error: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	/* save media device - avoid lookups */
+	chip->media_dev = mdev;
+
+	/* Create media entities for mixer and control dev */
+	ret = media_mixer_init(chip);
+	if (ret) {
+		dev_err(&usbdev->dev,
+			"Couldn't create media mixer entities. Error: %d\n",
+			ret);
+
+		/* clear saved media_dev */
+		chip->media_dev = NULL;
+
+		return ret;
+	}
+	return 0;
+}
+
+void media_device_delete(struct snd_usb_audio *chip)
+{
+	struct media_device *mdev = chip->media_dev;
+
+	media_mixer_delete(chip);
+
+	if (mdev) {
+		if (media_devnode_is_registered(&mdev->devnode))
+			media_device_unregister(mdev);
+		chip->media_dev = NULL;
+	}
+}
diff --git a/sound/usb/media.h b/sound/usb/media.h
new file mode 100644
index 0000000..b5f451a
--- /dev/null
+++ b/sound/usb/media.h
@@ -0,0 +1,72 @@
+/*
+ * media.h - Media Controller specific ALSA driver code
+ *
+ * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * This file is released under the GPLv2.
+ */
+
+/*
+ * This file adds Media Controller support to ALSA driver
+ * to use the Media Controller API to share tuner with DVB
+ * and V4L2 drivers that control media device. Media device
+ * is created based on existing quirks framework. Using this
+ * approach, the media controller API usage can be added for
+ * a specific device.
+*/
+#ifndef __MEDIA_H
+
+#ifdef CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER
+
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <sound/asound.h>
+
+struct media_ctl {
+	struct media_device *media_dev;
+	struct media_entity media_entity;
+	struct media_intf_devnode *intf_devnode;
+	struct media_link *intf_link;
+	struct media_pad media_pad;
+	struct media_pipeline media_pipe;
+};
+
+/*
+ * One source pad each for SNDRV_PCM_STREAM_CAPTURE and
+ * SNDRV_PCM_STREAM_PLAYBACK. One for sink pad to link
+ * to AUDIO Source
+*/
+#define MEDIA_MIXER_PAD_MAX    (SNDRV_PCM_STREAM_LAST + 2)
+
+struct media_mixer_ctl {
+	struct media_device *media_dev;
+	struct media_entity media_entity;
+	struct media_intf_devnode *intf_devnode;
+	struct media_link *intf_link;
+	struct media_pad media_pad[MEDIA_MIXER_PAD_MAX];
+	struct media_pipeline media_pipe;
+};
+
+int media_device_create(struct snd_usb_audio *chip,
+			struct usb_interface *iface);
+void media_device_delete(struct snd_usb_audio *chip);
+int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
+			int stream);
+void media_stream_delete(struct snd_usb_substream *subs);
+int media_start_pipeline(struct snd_usb_substream *subs);
+void media_stop_pipeline(struct snd_usb_substream *subs);
+#else
+static inline int media_device_create(struct snd_usb_audio *chip,
+				      struct usb_interface *iface)
+						{ return 0; }
+static inline void media_device_delete(struct snd_usb_audio *chip) { }
+static inline int media_stream_init(struct snd_usb_substream *subs,
+					struct snd_pcm *pcm, int stream)
+						{ return 0; }
+static inline void media_stream_delete(struct snd_usb_substream *subs) { }
+static inline int media_start_pipeline(struct snd_usb_substream *subs)
+					{ return 0; }
+static inline void media_stop_pipeline(struct snd_usb_substream *subs) { }
+#endif
+#endif /* __MEDIA_H */
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 3417ef3..787b352 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -22,6 +22,7 @@ struct usb_mixer_interface {
 	struct urb *rc_urb;
 	struct usb_ctrlrequest *rc_setup_packet;
 	u8 rc_buffer[6];
+	void *media_mixer_ctl;
 };
 
 #define MAX_CHANNELS	16	/* max logical channels */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 9245f52..c3b8486 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -35,6 +35,7 @@
 #include "pcm.h"
 #include "clock.h"
 #include "power.h"
+#include "media.h"
 
 #define SUBSTREAM_FLAG_DATA_EP_STARTED	0
 #define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
@@ -715,10 +716,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	struct audioformat *fmt;
 	int ret;
 
+	ret = media_start_pipeline(subs);
+	if (ret)
+		return ret;
+
 	ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 					       params_buffer_bytes(hw_params));
 	if (ret < 0)
-		return ret;
+		goto err_ret;
 
 	subs->pcm_format = params_format(hw_params);
 	subs->period_bytes = params_period_bytes(hw_params);
@@ -732,22 +737,27 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 		dev_dbg(&subs->dev->dev,
 			"cannot set format: format = %#x, rate = %d, channels = %d\n",
 			   subs->pcm_format, subs->cur_rate, subs->channels);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_ret;
 	}
 
 	ret = snd_usb_lock_shutdown(subs->stream->chip);
 	if (ret < 0)
-		return ret;
+		goto err_ret;
 	ret = set_format(subs, fmt);
 	snd_usb_unlock_shutdown(subs->stream->chip);
 	if (ret < 0)
-		return ret;
+		goto err_ret;
 
 	subs->interface = fmt->iface;
 	subs->altset_idx = fmt->altset_idx;
 	subs->need_setup_ep = true;
 
 	return 0;
+
+err_ret:
+	media_stop_pipeline(subs);
+	return ret;
 }
 
 /*
@@ -759,6 +769,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 {
 	struct snd_usb_substream *subs = substream->runtime->private_data;
 
+	media_stop_pipeline(subs);
 	subs->cur_audiofmt = NULL;
 	subs->cur_rate = 0;
 	subs->period_bytes = 0;
@@ -1219,6 +1230,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_usb_substream *subs = &as->substream[direction];
+	int ret;
 
 	subs->interface = -1;
 	subs->altset_idx = 0;
@@ -1232,7 +1244,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 	subs->dsd_dop.channel = 0;
 	subs->dsd_dop.marker = 1;
 
-	return setup_hw_info(runtime, subs);
+	ret = setup_hw_info(runtime, subs);
+	if (ret == 0)
+		ret = media_stream_init(subs, as->pcm, direction);
+	if (ret)
+		snd_usb_autosuspend(subs->stream->chip);
+	return ret;
 }
 
 static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
@@ -1241,6 +1258,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
 	struct snd_usb_substream *subs = &as->substream[direction];
 
 	stop_endpoints(subs, true);
+	media_stop_pipeline(subs);
 
 	if (subs->interface >= 0 &&
 	    !snd_usb_lock_shutdown(subs->stream->chip)) {
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c60a776..9d087b1 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2886,6 +2886,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		.product_name = pname, \
 		.ifnum = QUIRK_ANY_INTERFACE, \
 		.type = QUIRK_AUDIO_ALIGN_TRANSFER, \
+		.media_device = 1, \
 	} \
 }
 
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index c4dc577..6c7f5c1 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -36,6 +36,7 @@
 #include "format.h"
 #include "clock.h"
 #include "stream.h"
+#include "media.h"
 
 /*
  * free a substream
@@ -52,6 +53,7 @@ static void free_substream(struct snd_usb_substream *subs)
 		kfree(fp);
 	}
 	kfree(subs->rate_list.list);
+	media_stream_delete(subs);
 }
 
 
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b665d85..0c0a86c 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -60,6 +60,8 @@ struct snd_usb_audio {
 	bool autoclock;			/* from the 'autoclock' module param */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
+	void *media_dev;
+	void *ctl_intf_media_devnode;
 };
 
 #define usb_audio_err(chip, fmt, args...) \
@@ -110,6 +112,7 @@ struct snd_usb_audio_quirk {
 	const char *product_name;
 	int16_t ifnum;
 	uint16_t type;
+	bool media_device;
 	const void *data;
 };
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 22/22] media: Ensure media device unregister is done only once
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04  4:03   ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

media_device_unregister() checks if the media device
is registered or not as the first step. However, the
MEDIA_FLAG_REGISTERED bit doesn't get cleared until
the end leaving a large window for two drivers to
attempt media device unregister.

The above leads to general protection faults when
device is removed.

Fix the problem with two phase media device unregister.
Add a new interface media_devnode_start_unregister()
to clear the MEDIA_FLAG_REGISTERED bit. Change
media_device_unregister() call this interface to mark
the start of unregister. This will ensure that media
device unregister is done only once.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-device.c  | 12 ++++++------
 drivers/media/media-devnode.c | 15 ++++++++++-----
 include/media/media-devnode.h | 17 +++++++++++++++++
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 1f5d67e..584d46e 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -747,17 +747,17 @@ void media_device_unregister(struct media_device *mdev)
 	struct media_entity *next;
 	struct media_interface *intf, *tmp_intf;
 	struct media_entity_notify *notify, *nextp;
+	int ret;
 
 	if (mdev == NULL)
 		return;
 
-	spin_lock(&mdev->lock);
-
-	/* Check if mdev was ever registered at all */
-	if (!media_devnode_is_registered(&mdev->devnode)) {
-		spin_unlock(&mdev->lock);
+	/* Start unregister - continue if necessary */
+	ret = media_devnode_start_unregister(&mdev->devnode);
+	if (ret)
 		return;
-	}
+
+	spin_lock(&mdev->lock);
 
 	/* Remove all entities from the media device */
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 29409f4..c27f9e7 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -272,15 +272,20 @@ error:
 	return ret;
 }
 
-void media_devnode_unregister(struct media_devnode *mdev)
+int __must_check media_devnode_start_unregister(struct media_devnode *mdev)
 {
-	/* Check if mdev was ever registered at all */
-	if (!media_devnode_is_registered(mdev))
-		return;
-
 	mutex_lock(&media_devnode_lock);
+	if (!media_devnode_is_registered(mdev)) {
+		mutex_unlock(&media_devnode_lock);
+		return -EINVAL;
+	}
 	clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
 	mutex_unlock(&media_devnode_lock);
+	return 0;
+}
+
+void media_devnode_unregister(struct media_devnode *mdev)
+{
 	device_unregister(&mdev->dev);
 }
 
diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
index fe42f08..6f08677 100644
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -120,6 +120,23 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
 					struct module *owner);
 
 /**
+ * media_devnode_start_unregister - start unregister on a media device node
+ * @mdev: the device node to start unregister
+ *
+ * This clears the MEDIA_FLAG_REGISTERED bit to indicate that unregister
+ * is in progress.
+ *
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ *
+ * Zero is returned on success.
+ *
+ * -EINVAL is returned if the device node has never been
+ * registered or has already been unregistered.
+ */
+int __must_check media_devnode_start_unregister(struct media_devnode *mdev);
+
+/**
  * media_devnode_unregister - unregister a media device node
  * @mdev: the device node to unregister
  *
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 22/22] media: Ensure media device unregister is done only once
@ 2016-02-04  4:03   ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04  4:03 UTC (permalink / raw)
  To: mchehab, tiwai, clemens, hans.verkuil, laurent.pinchart,
	sakari.ailus, javier
  Cc: Shuah Khan, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang

media_device_unregister() checks if the media device
is registered or not as the first step. However, the
MEDIA_FLAG_REGISTERED bit doesn't get cleared until
the end leaving a large window for two drivers to
attempt media device unregister.

The above leads to general protection faults when
device is removed.

Fix the problem with two phase media device unregister.
Add a new interface media_devnode_start_unregister()
to clear the MEDIA_FLAG_REGISTERED bit. Change
media_device_unregister() call this interface to mark
the start of unregister. This will ensure that media
device unregister is done only once.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-device.c  | 12 ++++++------
 drivers/media/media-devnode.c | 15 ++++++++++-----
 include/media/media-devnode.h | 17 +++++++++++++++++
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 1f5d67e..584d46e 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -747,17 +747,17 @@ void media_device_unregister(struct media_device *mdev)
 	struct media_entity *next;
 	struct media_interface *intf, *tmp_intf;
 	struct media_entity_notify *notify, *nextp;
+	int ret;
 
 	if (mdev == NULL)
 		return;
 
-	spin_lock(&mdev->lock);
-
-	/* Check if mdev was ever registered at all */
-	if (!media_devnode_is_registered(&mdev->devnode)) {
-		spin_unlock(&mdev->lock);
+	/* Start unregister - continue if necessary */
+	ret = media_devnode_start_unregister(&mdev->devnode);
+	if (ret)
 		return;
-	}
+
+	spin_lock(&mdev->lock);
 
 	/* Remove all entities from the media device */
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 29409f4..c27f9e7 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -272,15 +272,20 @@ error:
 	return ret;
 }
 
-void media_devnode_unregister(struct media_devnode *mdev)
+int __must_check media_devnode_start_unregister(struct media_devnode *mdev)
 {
-	/* Check if mdev was ever registered at all */
-	if (!media_devnode_is_registered(mdev))
-		return;
-
 	mutex_lock(&media_devnode_lock);
+	if (!media_devnode_is_registered(mdev)) {
+		mutex_unlock(&media_devnode_lock);
+		return -EINVAL;
+	}
 	clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
 	mutex_unlock(&media_devnode_lock);
+	return 0;
+}
+
+void media_devnode_unregister(struct media_devnode *mdev)
+{
 	device_unregister(&mdev->dev);
 }
 
diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
index fe42f08..6f08677 100644
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -120,6 +120,23 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
 					struct module *owner);
 
 /**
+ * media_devnode_start_unregister - start unregister on a media device node
+ * @mdev: the device node to start unregister
+ *
+ * This clears the MEDIA_FLAG_REGISTERED bit to indicate that unregister
+ * is in progress.
+ *
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ *
+ * Zero is returned on success.
+ *
+ * -EINVAL is returned if the device node has never been
+ * registered or has already been unregistered.
+ */
+int __must_check media_devnode_start_unregister(struct media_devnode *mdev);
+
+/**
  * media_devnode_unregister - unregister a media device node
  * @mdev: the device node to unregister
  *
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces
@ 2016-02-04  6:29     ` kbuild test robot
  0 siblings, 0 replies; 94+ messages in thread
From: kbuild test robot @ 2016-02-04  6:29 UTC (permalink / raw)
  To: Shuah Khan
  Cc: kbuild-all, mchehab, tiwai, clemens, hans.verkuil,
	laurent.pinchart, sakari.ailus, javier, Shuah Khan, pawel,
	m.szyprowski, kyungmin.park, perex, arnd, dan.carpenter,
	tvboxspy, crope, ruchandani.tina, corbet, chehabrafael,
	k.kozlowski, stefanr, inki.dae, jh1009.sung, elfring,
	prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda, labbott,
	pierre-louis.bossart, ricard.wanderlof, julian, takamichiho,
	dominic.sacre, misterpib, daniel, gtmkramer, normalperson, joe,
	linuxbugs, johan, klock.android, nenggun.kim, j.anaszewski,
	geliangtang, linux-kernel, linux-media, linux-api, alsa-devel

[-- Attachment #1: Type: text/plain, Size: 3384 bytes --]

Hi Shuah,

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on next-20160203]
[cannot apply to v4.5-rc2]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Shuah-Khan/Sharing-media-resources-across-ALSA-and-au0828-drivers/20160204-121414
base:   git://linuxtv.org/media_tree.git master
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/init.h:1: warning: no structured comments found
   kernel/sys.c:1: warning: no structured comments found
   drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found
   drivers/dma-buf/reservation.c:1: warning: no structured comments found
   include/linux/reservation.h:1: warning: no structured comments found
>> include/media/v4l2-mc.h:114: warning: No description found for parameter 'vdev'
   include/media/v4l2-mc.h:128: warning: No description found for parameter 'vdev'
   include/media/media-device.h:357: warning: No description found for parameter 'entity_notify'
   include/media/media-device.h:357: warning: No description found for parameter 'source_priv'
   include/media/media-device.h:357: warning: No description found for parameter 'enable_source'
   include/media/media-device.h:357: warning: No description found for parameter 'disable_source'
   include/media/media-device.h:357: warning: No description found for parameter 'entity_notify'
   include/media/media-device.h:357: warning: No description found for parameter 'source_priv'
   include/media/media-device.h:357: warning: No description found for parameter 'enable_source'
   include/media/media-device.h:357: warning: No description found for parameter 'disable_source'
   include/media/media-entity.h:840: warning: No description found for parameter 'entity'
   include/media/media-entity.h:840: warning: No description found for parameter 'pipe'
   include/media/media-entity.h:860: warning: No description found for parameter 'entity'
   include/linux/spi/spi.h:540: warning: No description found for parameter 'max_transfer_size'

vim +/vdev +114 include/media/v4l2-mc.h

    98	/**
    99	 * v4l_enable_media_source() -	Hold media source for exclusive use
   100	 *				if free
   101	 *
   102	 * @vdev - poniter to struct video_device
   103	 *
   104	 * This interface calls enable_source handler to determine if
   105	 * media source is free for use. The enable_source handler is
   106	 * responsible for checking is the media source is free and
   107	 * start a pipeline between the media source and the media
   108	 * entity associated with the video device. This interface
   109	 * should be called from v4l2-core and dvb-core interfaces
   110	 * that change the source configuration.
   111	 *
   112	 * Return: returns zero on success or a negative error code.
   113	 */
 > 114	int v4l_enable_media_source(struct video_device *vdev);
   115	
   116	/**
   117	 * v4l_disable_media_source() -	Release media source
   118	 *
   119	 * @vdev - poniter to struct video_device
   120	 *
   121	 * This interface calls disable_source handler to release
   122	 * the media source. The disable_source handler stops the

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6230 bytes --]

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces
@ 2016-02-04  6:29     ` kbuild test robot
  0 siblings, 0 replies; 94+ messages in thread
From: kbuild test robot @ 2016-02-04  6:29 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, mchehab-JPH+aEBZ4P+UEJcrhfAQsw,
	tiwai-IBi9RG/b67k, clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, Shuah Khan,
	pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel

[-- Attachment #1: Type: text/plain, Size: 3384 bytes --]

Hi Shuah,

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on next-20160203]
[cannot apply to v4.5-rc2]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Shuah-Khan/Sharing-media-resources-across-ALSA-and-au0828-drivers/20160204-121414
base:   git://linuxtv.org/media_tree.git master
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/init.h:1: warning: no structured comments found
   kernel/sys.c:1: warning: no structured comments found
   drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found
   drivers/dma-buf/reservation.c:1: warning: no structured comments found
   include/linux/reservation.h:1: warning: no structured comments found
>> include/media/v4l2-mc.h:114: warning: No description found for parameter 'vdev'
   include/media/v4l2-mc.h:128: warning: No description found for parameter 'vdev'
   include/media/media-device.h:357: warning: No description found for parameter 'entity_notify'
   include/media/media-device.h:357: warning: No description found for parameter 'source_priv'
   include/media/media-device.h:357: warning: No description found for parameter 'enable_source'
   include/media/media-device.h:357: warning: No description found for parameter 'disable_source'
   include/media/media-device.h:357: warning: No description found for parameter 'entity_notify'
   include/media/media-device.h:357: warning: No description found for parameter 'source_priv'
   include/media/media-device.h:357: warning: No description found for parameter 'enable_source'
   include/media/media-device.h:357: warning: No description found for parameter 'disable_source'
   include/media/media-entity.h:840: warning: No description found for parameter 'entity'
   include/media/media-entity.h:840: warning: No description found for parameter 'pipe'
   include/media/media-entity.h:860: warning: No description found for parameter 'entity'
   include/linux/spi/spi.h:540: warning: No description found for parameter 'max_transfer_size'

vim +/vdev +114 include/media/v4l2-mc.h

    98	/**
    99	 * v4l_enable_media_source() -	Hold media source for exclusive use
   100	 *				if free
   101	 *
   102	 * @vdev - poniter to struct video_device
   103	 *
   104	 * This interface calls enable_source handler to determine if
   105	 * media source is free for use. The enable_source handler is
   106	 * responsible for checking is the media source is free and
   107	 * start a pipeline between the media source and the media
   108	 * entity associated with the video device. This interface
   109	 * should be called from v4l2-core and dvb-core interfaces
   110	 * that change the source configuration.
   111	 *
   112	 * Return: returns zero on success or a negative error code.
   113	 */
 > 114	int v4l_enable_media_source(struct video_device *vdev);
   115	
   116	/**
   117	 * v4l_disable_media_source() -	Release media source
   118	 *
   119	 * @vdev - poniter to struct video_device
   120	 *
   121	 * This interface calls disable_source handler to release
   122	 * the media source. The disable_source handler stops the

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6230 bytes --]

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/22] uapi/media.h: Declare interface types for ALSA
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04  8:38     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  8:38 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:33 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Declare the interface types to be used on alsa for
> the new G_TOPOLOGY ioctl.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-entity.c | 16 ++++++++++++++++
>  include/uapi/linux/media.h   | 22 ++++++++++++++++++++++
>  2 files changed, 38 insertions(+)
> 
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index f2e4360..6179543 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -65,6 +65,22 @@ static inline const char *intf_type(struct media_interface *intf)
>  		return "v4l2-subdev";
>  	case MEDIA_INTF_T_V4L_SWRADIO:
>  		return "swradio";
> +	case MEDIA_INTF_T_ALSA_PCM_CAPTURE:
> +		return "pcm-capture";
> +	case MEDIA_INTF_T_ALSA_PCM_PLAYBACK:
> +		return "pcm-playback";
> +	case MEDIA_INTF_T_ALSA_CONTROL:
> +		return "alsa-control";
> +	case MEDIA_INTF_T_ALSA_COMPRESS:
> +		return "compress";
> +	case MEDIA_INTF_T_ALSA_RAWMIDI:
> +		return "rawmidi";
> +	case MEDIA_INTF_T_ALSA_HWDEP:
> +		return "hwdep";
> +	case MEDIA_INTF_T_ALSA_SEQUENCER:
> +		return "sequencer";
> +	case MEDIA_INTF_T_ALSA_TIMER:
> +		return "timer";
>  	default:
>  		return "unknown-intf";
>  	}
> diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
> index c9eb42a..ee020e8 100644
> --- a/include/uapi/linux/media.h
> +++ b/include/uapi/linux/media.h
> @@ -265,6 +265,7 @@ struct media_links_enum {
>  
>  #define MEDIA_INTF_T_DVB_BASE	0x00000100
>  #define MEDIA_INTF_T_V4L_BASE	0x00000200
> +#define MEDIA_INTF_T_ALSA_BASE	0x00000300
>  
>  /* Interface types */
>  
> @@ -280,6 +281,27 @@ struct media_links_enum {
>  #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
>  #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
>  
> +/**
> + * DOC: Media Controller Next Generation ALSA Interface Types
> + *
> + * MEDIA_INTF_T_ALSA_PCM_CAPTURE - PCM Capture Interface (pcm-capture)
> + * MEDIA_INTF_T_ALSA_PCM_PLAYBACK -  PCM Playback Interface (pcm-playback)
> + * MEDIA_INTF_T_ALSA_CONTROL -  ALSA Control Interface (alsa-control)
> + * MEDIA_INTF_T_ALSA_COMPRESS - ALSA Compression Interface (compress)
> + * MEDIA_INTF_T_ALSA_RAWMIDI - ALSA Raw MIDI Interface (rawmidi)
> + * MEDIA_INTF_T_ALSA_HWDEP - ALSA Hardware Dependent Interface (hwdep)
> + * MEDIA_INTF_T_ALSA_SEQUENCER - ALSA Sequencer (sequencer)
> + * MEDIA_INTF_T_ALSA_TIMER - ALSA Timer (timer)
> + */

We don't document the userspace API using kernel-doc, as it is too
poor for that. Also, we migrated the uAPI documentation from LaTex
(at DVB side) and from a separate DocBook document. Migrating those to
kernel-doc would need some rich documentation markup language, and
someone with lots of spare time.

Instead, we document them at a separate DocBook volume:
	Documentation/DocBook/media_api.tmpl

The actual DocBook documents are at:
	Documentation/DocBook/media/dvb - for the DVB side
	Documentation/DocBook/media/v4l - for V4L2, RC and Media Controller

In the specific case of the Media Controller, the description of those
defines are at:
	Documentation/DocBook/media/v4l/media-types.xml

Just edit it with some text editor and add the new fields there at the
right places.

Please test if the documentation is producing the right data, by using
the enclosed small script. The extra xmllint lines validate the syntax,
helping to identify hidden missing tags. The last line will produce a
single html file, instead of one html file per page (with is the default
for make htmldocs).

Regards,
Mauro

#!/bin/bash
LC_ALL=en_US.UTF-8
make cleanmediadocs
make DOCBOOKS=media_api.xml htmldocs 2>&1 | grep -v "element.*: validity error : ID .* already defined"
xmllint --noent --postvalid "$PWD/Documentation/DocBook/media_api.xml" >/tmp/x.xml 2>/dev/null
xmllint --noent --postvalid --noout /tmp/x.xml
xmlto html-nochunks -m ./Documentation/DocBook/stylesheet.xsl -o Documentation/DocBook/media Documentation/DocBook/media_api.xml >/dev/null 2>&1

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/22] uapi/media.h: Declare interface types for ALSA
@ 2016-02-04  8:38     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  8:38 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:33 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Declare the interface types to be used on alsa for
> the new G_TOPOLOGY ioctl.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-entity.c | 16 ++++++++++++++++
>  include/uapi/linux/media.h   | 22 ++++++++++++++++++++++
>  2 files changed, 38 insertions(+)
> 
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index f2e4360..6179543 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -65,6 +65,22 @@ static inline const char *intf_type(struct media_interface *intf)
>  		return "v4l2-subdev";
>  	case MEDIA_INTF_T_V4L_SWRADIO:
>  		return "swradio";
> +	case MEDIA_INTF_T_ALSA_PCM_CAPTURE:
> +		return "pcm-capture";
> +	case MEDIA_INTF_T_ALSA_PCM_PLAYBACK:
> +		return "pcm-playback";
> +	case MEDIA_INTF_T_ALSA_CONTROL:
> +		return "alsa-control";
> +	case MEDIA_INTF_T_ALSA_COMPRESS:
> +		return "compress";
> +	case MEDIA_INTF_T_ALSA_RAWMIDI:
> +		return "rawmidi";
> +	case MEDIA_INTF_T_ALSA_HWDEP:
> +		return "hwdep";
> +	case MEDIA_INTF_T_ALSA_SEQUENCER:
> +		return "sequencer";
> +	case MEDIA_INTF_T_ALSA_TIMER:
> +		return "timer";
>  	default:
>  		return "unknown-intf";
>  	}
> diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
> index c9eb42a..ee020e8 100644
> --- a/include/uapi/linux/media.h
> +++ b/include/uapi/linux/media.h
> @@ -265,6 +265,7 @@ struct media_links_enum {
>  
>  #define MEDIA_INTF_T_DVB_BASE	0x00000100
>  #define MEDIA_INTF_T_V4L_BASE	0x00000200
> +#define MEDIA_INTF_T_ALSA_BASE	0x00000300
>  
>  /* Interface types */
>  
> @@ -280,6 +281,27 @@ struct media_links_enum {
>  #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
>  #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
>  
> +/**
> + * DOC: Media Controller Next Generation ALSA Interface Types
> + *
> + * MEDIA_INTF_T_ALSA_PCM_CAPTURE - PCM Capture Interface (pcm-capture)
> + * MEDIA_INTF_T_ALSA_PCM_PLAYBACK -  PCM Playback Interface (pcm-playback)
> + * MEDIA_INTF_T_ALSA_CONTROL -  ALSA Control Interface (alsa-control)
> + * MEDIA_INTF_T_ALSA_COMPRESS - ALSA Compression Interface (compress)
> + * MEDIA_INTF_T_ALSA_RAWMIDI - ALSA Raw MIDI Interface (rawmidi)
> + * MEDIA_INTF_T_ALSA_HWDEP - ALSA Hardware Dependent Interface (hwdep)
> + * MEDIA_INTF_T_ALSA_SEQUENCER - ALSA Sequencer (sequencer)
> + * MEDIA_INTF_T_ALSA_TIMER - ALSA Timer (timer)
> + */

We don't document the userspace API using kernel-doc, as it is too
poor for that. Also, we migrated the uAPI documentation from LaTex
(at DVB side) and from a separate DocBook document. Migrating those to
kernel-doc would need some rich documentation markup language, and
someone with lots of spare time.

Instead, we document them at a separate DocBook volume:
	Documentation/DocBook/media_api.tmpl

The actual DocBook documents are at:
	Documentation/DocBook/media/dvb - for the DVB side
	Documentation/DocBook/media/v4l - for V4L2, RC and Media Controller

In the specific case of the Media Controller, the description of those
defines are at:
	Documentation/DocBook/media/v4l/media-types.xml

Just edit it with some text editor and add the new fields there at the
right places.

Please test if the documentation is producing the right data, by using
the enclosed small script. The extra xmllint lines validate the syntax,
helping to identify hidden missing tags. The last line will produce a
single html file, instead of one html file per page (with is the default
for make htmldocs).

Regards,
Mauro

#!/bin/bash
LC_ALL=en_US.UTF-8
make cleanmediadocs
make DOCBOOKS=media_api.xml htmldocs 2>&1 | grep -v "element.*: validity error : ID .* already defined"
xmllint --noent --postvalid "$PWD/Documentation/DocBook/media_api.xml" >/tmp/x.xml 2>/dev/null
xmllint --noent --postvalid --noout /tmp/x.xml
xmlto html-nochunks -m ./Documentation/DocBook/stylesheet.xsl -o Documentation/DocBook/media Documentation/DocBook/media_api.xml >/dev/null 2>&1

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 02/22] media: Add ALSA Media Controller function entities
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04  8:40     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  8:40 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:34 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add ALSA Media Controller capture, playback, and mixer
> function entity defines.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  include/uapi/linux/media.h | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
> index ee020e8..7d50480 100644
> --- a/include/uapi/linux/media.h
> +++ b/include/uapi/linux/media.h
> @@ -98,6 +98,17 @@ struct media_device_info {
>  #define MEDIA_ENT_F_IF_AUD_DECODER	(MEDIA_ENT_F_BASE + 42)
>  
>  /*
> + * DOC: Media Controller Next Generation ALSA Function Entities
> + *
> + * MEDIA_ENT_F_AUDIO_CAPTURE - Audio Capture Function
> + * MEDIA_ENT_F_AUDIO_PLAYBACK - Audio Play Back Function
> + * MEDIA_ENT_F_AUDIO_MIXER - Audio Mixer Function
> +*/

Wrong way to document it. Please see my comments to patch 01/22.

> +#define MEDIA_ENT_F_AUDIO_CAPTURE	(MEDIA_ENT_F_BASE + 200)
> +#define MEDIA_ENT_F_AUDIO_PLAYBACK	(MEDIA_ENT_F_BASE + 201)
> +#define MEDIA_ENT_F_AUDIO_MIXER		(MEDIA_ENT_F_BASE + 202)
> +
> +/*
>   * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and
>   * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility
>   * with the legacy v1 API.The number range is out of range by purpose:

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 02/22] media: Add ALSA Media Controller function entities
@ 2016-02-04  8:40     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  8:40 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:34 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add ALSA Media Controller capture, playback, and mixer
> function entity defines.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  include/uapi/linux/media.h | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
> index ee020e8..7d50480 100644
> --- a/include/uapi/linux/media.h
> +++ b/include/uapi/linux/media.h
> @@ -98,6 +98,17 @@ struct media_device_info {
>  #define MEDIA_ENT_F_IF_AUD_DECODER	(MEDIA_ENT_F_BASE + 42)
>  
>  /*
> + * DOC: Media Controller Next Generation ALSA Function Entities
> + *
> + * MEDIA_ENT_F_AUDIO_CAPTURE - Audio Capture Function
> + * MEDIA_ENT_F_AUDIO_PLAYBACK - Audio Play Back Function
> + * MEDIA_ENT_F_AUDIO_MIXER - Audio Mixer Function
> +*/

Wrong way to document it. Please see my comments to patch 01/22.

> +#define MEDIA_ENT_F_AUDIO_CAPTURE	(MEDIA_ENT_F_BASE + 200)
> +#define MEDIA_ENT_F_AUDIO_PLAYBACK	(MEDIA_ENT_F_BASE + 201)
> +#define MEDIA_ENT_F_AUDIO_MIXER		(MEDIA_ENT_F_BASE + 202)
> +
> +/*
>   * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and
>   * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility
>   * with the legacy v1 API.The number range is out of range by purpose:

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 03/22] media: Media Controller register/unregister entity_notify API
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04  9:03     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:03 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:35 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add new interfaces to register and unregister entity_notify
> hook to media device. These interfaces allow drivers to add
> hooks to take appropriate actions when new entities get added
> to a shared media device. For example, au0828 bridge driver
> registers an entity_notify hook to create links as needed
> between media graph nodes.

Shuah,

It seems you didn't address the documentation issues I pointed on the
last review. While not ideal, I'll accept, in this specific case,
although this requires an extra time for me (as I want to read the
documentation *before* actually reviewing the patches), I'm OK
if you send the documentation a the end of the series, but please
send it *together* with the patch series.

That affect not only me, but others that build documentation and
gets lots of errors if something is not documented at the right
place.

See below for some notes. I won't be commenting documentation on
the rest of this patch series.

> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
>  include/media/media-device.h | 25 ++++++++++++++++++
>  2 files changed, 86 insertions(+)
> 
> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> index 4d1c13d..1f5d67e 100644
> --- a/drivers/media/media-device.c
> +++ b/drivers/media/media-device.c
> @@ -536,6 +536,7 @@ static void media_device_release(struct media_devnode *mdev)
>  int __must_check media_device_register_entity(struct media_device *mdev,
>  					      struct media_entity *entity)
>  {
> +	struct media_entity_notify *notify, *next;
>  	unsigned int i;
>  	int ret;
>  
> @@ -575,6 +576,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
>  		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
>  			       &entity->pads[i].graph_obj);
>  
> +	/* invoke entity_notify callbacks */
> +	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> +		(notify)->notify(entity, notify->notify_data);
> +	}
> +
>  	spin_unlock(&mdev->lock);
>  
>  	return 0;
> @@ -608,6 +614,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
>  	/* Remove the entity */
>  	media_gobj_destroy(&entity->graph_obj);
>  
> +	/* invoke entity_notify callbacks to handle entity removal?? */
> +
>  	entity->graph_obj.mdev = NULL;
>  }
>  
> @@ -640,6 +648,7 @@ void media_device_init(struct media_device *mdev)
>  	INIT_LIST_HEAD(&mdev->interfaces);
>  	INIT_LIST_HEAD(&mdev->pads);
>  	INIT_LIST_HEAD(&mdev->links);
> +	INIT_LIST_HEAD(&mdev->entity_notify);
>  	spin_lock_init(&mdev->lock);
>  	mutex_init(&mdev->graph_mutex);
>  	ida_init(&mdev->entity_internal_idx);
> @@ -685,11 +694,59 @@ int __must_check __media_device_register(struct media_device *mdev,
>  }
>  EXPORT_SYMBOL_GPL(__media_device_register);
>  
> +/**
> + * media_device_register_entity_notify - Register a media entity notify
> + * callback with a media device. When a new entity is registered, all
> + * the registered media_entity_notify callbacks are invoked.
> + * @mdev:      The media device
> + * @nptr:      The media_entity_notify
> + */


Please split the comments into a short description and a detailed
description, and add blank lines to make it easier to be read by
mortals.

The short description appears at the index of the html page:
	https://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/ch06s04.html

So, we want it to be short ;)

The detailed description appears at the end:
	https://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/API-dvb-create-media-graph.html

Btw, in the above comment, you don't have actually a detailed description,
but, instead, a note. So, the best would be do to it as:

/**
 * media_device_register_entity_notify() - Register a media entity notify
 *	 callback with a media device.
 *
 * @mdev:      The media device
 * @nptr:      The media_entity_notify
 *
 * NOTE: When a new entity is registered, all the registered
 * media_entity_notify callbacks are invoked.
 */

The "NOTE: foo" will appear as:
	https://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/API-media-device-register-entity.html

P.S.: Don't forget to test if everything is OK with:
	rm Documentation/DocBook/device-drivers.aux.xml  Documentation/DocBook/device-drivers.xml
	LC_ALL=en_US.UTF-8 make DOCBOOKS=device-drivers.xml htmldocs

The same note applied to the other DocBook tags you added.

Btw, add the documentation *only* at the .h.

> +int __must_check media_device_register_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	spin_lock(&mdev->lock);
> +	list_add_tail(&nptr->list, &mdev->entity_notify);
> +	spin_unlock(&mdev->lock);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
> +
> +/**
> + * __media_device_unregister_entity_notify - Unregister a media entity notify
> + * callback with a media device. When a new entity is registered, all
> + * the registered media_entity_notify callbacks are invoked.
> + * @mdev:      The media device
> + * @nptr:      The media_entity_notify
> + * Non-locking version. Should be called with mdev->lock held.
> + */
> +static void __media_device_unregister_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	list_del(&nptr->list);
> +}
> +
> +/**
> + * media_device_unregister_entity_notify - Unregister a media entity notify
> + * callback with a media device. When a new entity is registered, all
> + * the registered media_entity_notify callbacks are invoked.
> + * @mdev:      The media device
> + * @nptr:      The media_entity_notify
> + */
> +void media_device_unregister_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	spin_lock(&mdev->lock);
> +	__media_device_unregister_entity_notify(mdev, nptr);
> +	spin_unlock(&mdev->lock);
> +}
> +EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
> +
>  void media_device_unregister(struct media_device *mdev)
>  {
>  	struct media_entity *entity;
>  	struct media_entity *next;
>  	struct media_interface *intf, *tmp_intf;
> +	struct media_entity_notify *notify, *nextp;
>  
>  	if (mdev == NULL)
>  		return;
> @@ -706,6 +763,10 @@ void media_device_unregister(struct media_device *mdev)
>  	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
>  		__media_device_unregister_entity(entity);
>  
> +	/* Remove all entity_notify callbacks from the media device */
> +	list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
> +		__media_device_unregister_entity_notify(mdev, notify);
> +
>  	/* Remove all interfaces from the media device */
>  	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
>  				 graph_obj.list) {
> diff --git a/include/media/media-device.h b/include/media/media-device.h
> index d385589..bad8242a 100644
> --- a/include/media/media-device.h
> +++ b/include/media/media-device.h
> @@ -264,6 +264,12 @@
>  struct ida;
>  struct device;
>  
> +struct media_entity_notify {
> +	struct list_head list;
> +	void *notify_data;
> +	void (*notify)(struct media_entity *entity, void *notify_data);
> +};
> +

Documentation is missing.

>  /**
>   * struct media_device - Media device
>   * @dev:	Parent device
> @@ -319,6 +325,9 @@ struct media_device {
>  	struct list_head pads;
>  	struct list_head links;
>  
> +	/* notify callback list invoked when a new entity is registered */
> +	struct list_head entity_notify;
> +

Documentation is missing. You should have noticed if you tried to
generate the docbook, as it would produce an error like:

   include/media/media-device.h:357: warning: No description found for parameter 'entity_notify'

as reported by kbuild test robot.

>  	/* Protects the graph objects creation/removal */
>  	spinlock_t lock;
>  	/* Serializes graph operations. */
> @@ -497,6 +506,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
>   */
>  void media_device_unregister_entity(struct media_entity *entity);
>  
> +int __must_check media_device_register_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr);
> +void media_device_unregister_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr);
> +

Documentation is missing.

>  /**
>   * media_device_get_devres() -	get media device as device resource
>   *				creates if one doesn't exist
> @@ -552,6 +566,17 @@ static inline int media_device_register_entity(struct media_device *mdev,
>  static inline void media_device_unregister_entity(struct media_entity *entity)
>  {
>  }
> +static inline int media_device_register_entity_notify(
> +					struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	return 0;
> +}
> +static inline void media_device_unregister_entity_notify(
> +					struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +}

Documentation is missing.

>  static inline struct media_device *media_device_get_devres(struct device *dev)
>  {
>  	return NULL;

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 03/22] media: Media Controller register/unregister entity_notify API
@ 2016-02-04  9:03     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:03 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:35 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add new interfaces to register and unregister entity_notify
> hook to media device. These interfaces allow drivers to add
> hooks to take appropriate actions when new entities get added
> to a shared media device. For example, au0828 bridge driver
> registers an entity_notify hook to create links as needed
> between media graph nodes.

Shuah,

It seems you didn't address the documentation issues I pointed on the
last review. While not ideal, I'll accept, in this specific case,
although this requires an extra time for me (as I want to read the
documentation *before* actually reviewing the patches), I'm OK
if you send the documentation a the end of the series, but please
send it *together* with the patch series.

That affect not only me, but others that build documentation and
gets lots of errors if something is not documented at the right
place.

See below for some notes. I won't be commenting documentation on
the rest of this patch series.

> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-device.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
>  include/media/media-device.h | 25 ++++++++++++++++++
>  2 files changed, 86 insertions(+)
> 
> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> index 4d1c13d..1f5d67e 100644
> --- a/drivers/media/media-device.c
> +++ b/drivers/media/media-device.c
> @@ -536,6 +536,7 @@ static void media_device_release(struct media_devnode *mdev)
>  int __must_check media_device_register_entity(struct media_device *mdev,
>  					      struct media_entity *entity)
>  {
> +	struct media_entity_notify *notify, *next;
>  	unsigned int i;
>  	int ret;
>  
> @@ -575,6 +576,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
>  		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
>  			       &entity->pads[i].graph_obj);
>  
> +	/* invoke entity_notify callbacks */
> +	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> +		(notify)->notify(entity, notify->notify_data);
> +	}
> +
>  	spin_unlock(&mdev->lock);
>  
>  	return 0;
> @@ -608,6 +614,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
>  	/* Remove the entity */
>  	media_gobj_destroy(&entity->graph_obj);
>  
> +	/* invoke entity_notify callbacks to handle entity removal?? */
> +
>  	entity->graph_obj.mdev = NULL;
>  }
>  
> @@ -640,6 +648,7 @@ void media_device_init(struct media_device *mdev)
>  	INIT_LIST_HEAD(&mdev->interfaces);
>  	INIT_LIST_HEAD(&mdev->pads);
>  	INIT_LIST_HEAD(&mdev->links);
> +	INIT_LIST_HEAD(&mdev->entity_notify);
>  	spin_lock_init(&mdev->lock);
>  	mutex_init(&mdev->graph_mutex);
>  	ida_init(&mdev->entity_internal_idx);
> @@ -685,11 +694,59 @@ int __must_check __media_device_register(struct media_device *mdev,
>  }
>  EXPORT_SYMBOL_GPL(__media_device_register);
>  
> +/**
> + * media_device_register_entity_notify - Register a media entity notify
> + * callback with a media device. When a new entity is registered, all
> + * the registered media_entity_notify callbacks are invoked.
> + * @mdev:      The media device
> + * @nptr:      The media_entity_notify
> + */


Please split the comments into a short description and a detailed
description, and add blank lines to make it easier to be read by
mortals.

The short description appears at the index of the html page:
	https://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/ch06s04.html

So, we want it to be short ;)

The detailed description appears at the end:
	https://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/API-dvb-create-media-graph.html

Btw, in the above comment, you don't have actually a detailed description,
but, instead, a note. So, the best would be do to it as:

/**
 * media_device_register_entity_notify() - Register a media entity notify
 *	 callback with a media device.
 *
 * @mdev:      The media device
 * @nptr:      The media_entity_notify
 *
 * NOTE: When a new entity is registered, all the registered
 * media_entity_notify callbacks are invoked.
 */

The "NOTE: foo" will appear as:
	https://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/API-media-device-register-entity.html

P.S.: Don't forget to test if everything is OK with:
	rm Documentation/DocBook/device-drivers.aux.xml  Documentation/DocBook/device-drivers.xml
	LC_ALL=en_US.UTF-8 make DOCBOOKS=device-drivers.xml htmldocs

The same note applied to the other DocBook tags you added.

Btw, add the documentation *only* at the .h.

> +int __must_check media_device_register_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	spin_lock(&mdev->lock);
> +	list_add_tail(&nptr->list, &mdev->entity_notify);
> +	spin_unlock(&mdev->lock);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
> +
> +/**
> + * __media_device_unregister_entity_notify - Unregister a media entity notify
> + * callback with a media device. When a new entity is registered, all
> + * the registered media_entity_notify callbacks are invoked.
> + * @mdev:      The media device
> + * @nptr:      The media_entity_notify
> + * Non-locking version. Should be called with mdev->lock held.
> + */
> +static void __media_device_unregister_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	list_del(&nptr->list);
> +}
> +
> +/**
> + * media_device_unregister_entity_notify - Unregister a media entity notify
> + * callback with a media device. When a new entity is registered, all
> + * the registered media_entity_notify callbacks are invoked.
> + * @mdev:      The media device
> + * @nptr:      The media_entity_notify
> + */
> +void media_device_unregister_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	spin_lock(&mdev->lock);
> +	__media_device_unregister_entity_notify(mdev, nptr);
> +	spin_unlock(&mdev->lock);
> +}
> +EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
> +
>  void media_device_unregister(struct media_device *mdev)
>  {
>  	struct media_entity *entity;
>  	struct media_entity *next;
>  	struct media_interface *intf, *tmp_intf;
> +	struct media_entity_notify *notify, *nextp;
>  
>  	if (mdev == NULL)
>  		return;
> @@ -706,6 +763,10 @@ void media_device_unregister(struct media_device *mdev)
>  	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
>  		__media_device_unregister_entity(entity);
>  
> +	/* Remove all entity_notify callbacks from the media device */
> +	list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
> +		__media_device_unregister_entity_notify(mdev, notify);
> +
>  	/* Remove all interfaces from the media device */
>  	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
>  				 graph_obj.list) {
> diff --git a/include/media/media-device.h b/include/media/media-device.h
> index d385589..bad8242a 100644
> --- a/include/media/media-device.h
> +++ b/include/media/media-device.h
> @@ -264,6 +264,12 @@
>  struct ida;
>  struct device;
>  
> +struct media_entity_notify {
> +	struct list_head list;
> +	void *notify_data;
> +	void (*notify)(struct media_entity *entity, void *notify_data);
> +};
> +

Documentation is missing.

>  /**
>   * struct media_device - Media device
>   * @dev:	Parent device
> @@ -319,6 +325,9 @@ struct media_device {
>  	struct list_head pads;
>  	struct list_head links;
>  
> +	/* notify callback list invoked when a new entity is registered */
> +	struct list_head entity_notify;
> +

Documentation is missing. You should have noticed if you tried to
generate the docbook, as it would produce an error like:

   include/media/media-device.h:357: warning: No description found for parameter 'entity_notify'

as reported by kbuild test robot.

>  	/* Protects the graph objects creation/removal */
>  	spinlock_t lock;
>  	/* Serializes graph operations. */
> @@ -497,6 +506,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
>   */
>  void media_device_unregister_entity(struct media_entity *entity);
>  
> +int __must_check media_device_register_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr);
> +void media_device_unregister_entity_notify(struct media_device *mdev,
> +					struct media_entity_notify *nptr);
> +

Documentation is missing.

>  /**
>   * media_device_get_devres() -	get media device as device resource
>   *				creates if one doesn't exist
> @@ -552,6 +566,17 @@ static inline int media_device_register_entity(struct media_device *mdev,
>  static inline void media_device_unregister_entity(struct media_entity *entity)
>  {
>  }
> +static inline int media_device_register_entity_notify(
> +					struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +	return 0;
> +}
> +static inline void media_device_unregister_entity_notify(
> +					struct media_device *mdev,
> +					struct media_entity_notify *nptr)
> +{
> +}

Documentation is missing.

>  static inline struct media_device *media_device_get_devres(struct device *dev)
>  {
>  	return NULL;

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop()
@ 2016-02-04  9:18     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:18 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:38 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add non-locking __media_entity_pipeline_start/stop() interfaces
> to be called from code paths that hold the graph_mutex. For this
> change, the media_entity_pipeline_start() routine is renamed to
> __media_entity_pipeline_start() minus the graph_mutex lock and
> unlock. media_entity_pipeline_start() now calls the non-locking
> __media_entity_pipeline_start() holding the graph_lock. The stop
> interface, media_entity_pipeline_stop() routine is renamed to
> __media_entity_pipeline_stop() minus the graph_mutex lock and
> unlock. media_entity_pipeline_stop() now calls the non-locking
> __media_entity_pipeline_stop() holding the graph_lock.

Please write a better patch descriptions. The above could easily
be split into 3 or 4 paragraphs, with would make it easier to
read.

Also, too much details, written on a spaghetti style;)

It is obvious by anyone that looked at the patch that
"media_entity_pipeline_start() routine is renamed to 
__media_entity_pipeline_start() minus the graph_mutex lock and
unlock."

I read exactly the same thing at the C code, *and* at the
subject of the e-mail. Patch subject/description should tell
what, why and how (but you should not repeat what can easily
be inferred from looking at the diff).

I would describe it as:

   Currently, media pipeline graph traversal routines take
   the graph_mutex lock.

   While this works for the current code, we'll need 
   unlocked versions of them because
   (some explanation *why* you need it, with is the main
    thing that should be at the description).

   So, add non-locking media_entity_pipeline_start/stop()
   variations.

> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
>  include/media/media-entity.h | 12 ++++++++++++
>  2 files changed, 36 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 9b4d712..b78e4c2 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -365,8 +365,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
>   * Pipeline management
>   */
>  
> -__must_check int media_entity_pipeline_start(struct media_entity *entity,
> -					     struct media_pipeline *pipe)
> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
> +					       struct media_pipeline *pipe)
>  {
>  	struct media_device *mdev = entity->graph_obj.mdev;
>  	struct media_entity_graph *graph = &pipe->graph;
> @@ -374,8 +374,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  	struct media_link *link;
>  	int ret;
>  
> -	mutex_lock(&mdev->graph_mutex);
> -
>  	if (!pipe->streaming_count++) {
>  		ret = media_entity_graph_walk_init(&pipe->graph, mdev);
>  		if (ret)
> @@ -456,8 +454,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  		}
>  	}
>  
> -	mutex_unlock(&mdev->graph_mutex);
> -
>  	return 0;
>  
>  error:
> @@ -487,19 +483,28 @@ error_graph_walk_start:
>  	if (!--pipe->streaming_count)
>  		media_entity_graph_walk_cleanup(graph);
>  
> -	mutex_unlock(&mdev->graph_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_start);
>  
> +__must_check int media_entity_pipeline_start(struct media_entity *entity,
> +					     struct media_pipeline *pipe)
> +{
> +	struct media_device *mdev = entity->graph_obj.mdev;
> +	int ret;
> +
> +	mutex_lock(&mdev->graph_mutex);
> +	ret = __media_entity_pipeline_start(entity, pipe);
> +	mutex_unlock(&mdev->graph_mutex);
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
>  
> -void media_entity_pipeline_stop(struct media_entity *entity)
> +void __media_entity_pipeline_stop(struct media_entity *entity)
>  {
> -	struct media_device *mdev = entity->graph_obj.mdev;
>  	struct media_entity_graph *graph = &entity->pipe->graph;
>  	struct media_pipeline *pipe = entity->pipe;
>  
> -	mutex_lock(&mdev->graph_mutex);
>  
>  	WARN_ON(!pipe->streaming_count);
>  	media_entity_graph_walk_start(graph, entity);
> @@ -516,6 +521,15 @@ void media_entity_pipeline_stop(struct media_entity *entity)
>  	if (!--pipe->streaming_count)
>  		media_entity_graph_walk_cleanup(graph);
>  
> +}
> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop);
> +
> +void media_entity_pipeline_stop(struct media_entity *entity)
> +{
> +	struct media_device *mdev = entity->graph_obj.mdev;
> +
> +	mutex_lock(&mdev->graph_mutex);
> +	__media_entity_pipeline_stop(entity);
>  	mutex_unlock(&mdev->graph_mutex);
>  }
>  EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index fe485d3..c7583db 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -832,6 +832,12 @@ media_entity_graph_walk_next(struct media_entity_graph *graph);
>   */
>  __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  					     struct media_pipeline *pipe);
> +/**
> + * non-locking __media_entity_pipeline_start() can be called from
> + * code paths that hold the graph_mutex
> + */
> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
> +					       struct media_pipeline *pipe);
>  
>  /**
>   * media_entity_pipeline_stop - Mark a pipeline as not streaming
> @@ -848,6 +854,12 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  void media_entity_pipeline_stop(struct media_entity *entity);
>  
>  /**
> + * non-locking __media_entity_pipeline_stop() can be called from
> + * code paths that hold the graph_mutex
> + */
> +void __media_entity_pipeline_stop(struct media_entity *entity);
> +
> +/**
>   * media_devnode_create() - creates and initializes a device node interface
>   *
>   * @mdev:	pointer to struct &media_device

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop()
@ 2016-02-04  9:18     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:18 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai-IBi9RG/b67k, clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs

Em Wed, 03 Feb 2016 21:03:38 -0700
Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> escreveu:

> Add non-locking __media_entity_pipeline_start/stop() interfaces
> to be called from code paths that hold the graph_mutex. For this
> change, the media_entity_pipeline_start() routine is renamed to
> __media_entity_pipeline_start() minus the graph_mutex lock and
> unlock. media_entity_pipeline_start() now calls the non-locking
> __media_entity_pipeline_start() holding the graph_lock. The stop
> interface, media_entity_pipeline_stop() routine is renamed to
> __media_entity_pipeline_stop() minus the graph_mutex lock and
> unlock. media_entity_pipeline_stop() now calls the non-locking
> __media_entity_pipeline_stop() holding the graph_lock.

Please write a better patch descriptions. The above could easily
be split into 3 or 4 paragraphs, with would make it easier to
read.

Also, too much details, written on a spaghetti style;)

It is obvious by anyone that looked at the patch that
"media_entity_pipeline_start() routine is renamed to 
__media_entity_pipeline_start() minus the graph_mutex lock and
unlock."

I read exactly the same thing at the C code, *and* at the
subject of the e-mail. Patch subject/description should tell
what, why and how (but you should not repeat what can easily
be inferred from looking at the diff).

I would describe it as:

   Currently, media pipeline graph traversal routines take
   the graph_mutex lock.

   While this works for the current code, we'll need 
   unlocked versions of them because
   (some explanation *why* you need it, with is the main
    thing that should be at the description).

   So, add non-locking media_entity_pipeline_start/stop()
   variations.

> 
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
>  drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
>  include/media/media-entity.h | 12 ++++++++++++
>  2 files changed, 36 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 9b4d712..b78e4c2 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -365,8 +365,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
>   * Pipeline management
>   */
>  
> -__must_check int media_entity_pipeline_start(struct media_entity *entity,
> -					     struct media_pipeline *pipe)
> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
> +					       struct media_pipeline *pipe)
>  {
>  	struct media_device *mdev = entity->graph_obj.mdev;
>  	struct media_entity_graph *graph = &pipe->graph;
> @@ -374,8 +374,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  	struct media_link *link;
>  	int ret;
>  
> -	mutex_lock(&mdev->graph_mutex);
> -
>  	if (!pipe->streaming_count++) {
>  		ret = media_entity_graph_walk_init(&pipe->graph, mdev);
>  		if (ret)
> @@ -456,8 +454,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  		}
>  	}
>  
> -	mutex_unlock(&mdev->graph_mutex);
> -
>  	return 0;
>  
>  error:
> @@ -487,19 +483,28 @@ error_graph_walk_start:
>  	if (!--pipe->streaming_count)
>  		media_entity_graph_walk_cleanup(graph);
>  
> -	mutex_unlock(&mdev->graph_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_start);
>  
> +__must_check int media_entity_pipeline_start(struct media_entity *entity,
> +					     struct media_pipeline *pipe)
> +{
> +	struct media_device *mdev = entity->graph_obj.mdev;
> +	int ret;
> +
> +	mutex_lock(&mdev->graph_mutex);
> +	ret = __media_entity_pipeline_start(entity, pipe);
> +	mutex_unlock(&mdev->graph_mutex);
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
>  
> -void media_entity_pipeline_stop(struct media_entity *entity)
> +void __media_entity_pipeline_stop(struct media_entity *entity)
>  {
> -	struct media_device *mdev = entity->graph_obj.mdev;
>  	struct media_entity_graph *graph = &entity->pipe->graph;
>  	struct media_pipeline *pipe = entity->pipe;
>  
> -	mutex_lock(&mdev->graph_mutex);
>  
>  	WARN_ON(!pipe->streaming_count);
>  	media_entity_graph_walk_start(graph, entity);
> @@ -516,6 +521,15 @@ void media_entity_pipeline_stop(struct media_entity *entity)
>  	if (!--pipe->streaming_count)
>  		media_entity_graph_walk_cleanup(graph);
>  
> +}
> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop);
> +
> +void media_entity_pipeline_stop(struct media_entity *entity)
> +{
> +	struct media_device *mdev = entity->graph_obj.mdev;
> +
> +	mutex_lock(&mdev->graph_mutex);
> +	__media_entity_pipeline_stop(entity);
>  	mutex_unlock(&mdev->graph_mutex);
>  }
>  EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index fe485d3..c7583db 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -832,6 +832,12 @@ media_entity_graph_walk_next(struct media_entity_graph *graph);
>   */
>  __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  					     struct media_pipeline *pipe);
> +/**
> + * non-locking __media_entity_pipeline_start() can be called from
> + * code paths that hold the graph_mutex
> + */
> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
> +					       struct media_pipeline *pipe);
>  
>  /**
>   * media_entity_pipeline_stop - Mark a pipeline as not streaming
> @@ -848,6 +854,12 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>  void media_entity_pipeline_stop(struct media_entity *entity);
>  
>  /**
> + * non-locking __media_entity_pipeline_stop() can be called from
> + * code paths that hold the graph_mutex
> + */
> +void __media_entity_pipeline_stop(struct media_entity *entity);
> +
> +/**
>   * media_devnode_create() - creates and initializes a device node interface
>   *
>   * @mdev:	pointer to struct &media_device

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces
@ 2016-02-04  9:25     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:25 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:39 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add a new interfaces to be used by v4l-core to invoke enable
> source and disable_source handlers in the media_device. The
> enable_source helper function invokes the enable_source handler
> to find media source entity connected to the entity and check
> is it is available or busy. If source is available, link is
> activated and pipeline is started. The disable_source helper
> function invokes the disable_source handler to deactivate and
> stop the pipeline.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/v4l2-core/Makefile  |  2 +-
>  drivers/media/v4l2-core/v4l2-mc.c | 60 +++++++++++++++++++++++++++++++++++++++
>  include/media/v4l2-dev.h          |  1 +
>  include/media/v4l2-mc.h           | 52 +++++++++++++++++++++++++++++++++
>  4 files changed, 114 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/media/v4l2-core/v4l2-mc.c
> 
> diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> index 1dc8bba..c6acc01 100644
> --- a/drivers/media/v4l2-core/Makefile
> +++ b/drivers/media/v4l2-core/Makefile
> @@ -6,7 +6,7 @@ tuner-objs	:=	tuner-core.o
>  
>  videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
>  			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \
> -			v4l2-async.o
> +			v4l2-async.o v4l2-mc.o
>  ifeq ($(CONFIG_COMPAT),y)
>    videodev-objs += v4l2-compat-ioctl32.o
>  endif
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> new file mode 100644
> index 0000000..87416df
> --- /dev/null
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -0,0 +1,60 @@
> +/*
> + * v4l2-mc.c - Media Controller V4L2 Common Interfaces
> + *
> + * Copyright (C) 2016 Shuah Khan <shuahkh@osg.samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <media/v4l2-mc.h>
> +#include <media/media-device.h>
> +#include <media/videobuf2-core.h>
> +#include <media/v4l2-fh.h>
> +
> +int v4l_enable_media_source(struct video_device *vdev)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct media_device *mdev = vdev->entity.graph_obj.mdev;
> +	int ret;
> +
> +	if (!mdev || !mdev->enable_source)
> +		return 0;
> +	ret = mdev->enable_source(&vdev->entity, &vdev->pipe);
> +	if (ret)
> +		return -EBUSY;
> +	return 0;
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l_enable_media_source);
> +
> +void v4l_disable_media_source(struct video_device *vdev)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct media_device *mdev = vdev->entity.graph_obj.mdev;
> +
> +	if (mdev && mdev->disable_source)
> +		mdev->disable_source(&vdev->entity);
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +}
> +EXPORT_SYMBOL_GPL(v4l_disable_media_source);
> +
> +int v4l_vb2q_enable_media_source(struct vb2_queue *q)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct v4l2_fh *fh = q->owner;
> +
> +	return v4l_enable_media_source(fh->vdev);
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
> +

The code itself is ok. However, the above code would work better if you
declare them as static inline at the header file (v4l2-mc.h). That would
allow the compiler to optimize them with the caller codr (where the
declared structs like mdev, fh are likely already stored on some registers), 
and even removing the function completely if compiled without the media
controller.

> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
> index eeabf20..76056ab 100644
> --- a/include/media/v4l2-dev.h
> +++ b/include/media/v4l2-dev.h
> @@ -87,6 +87,7 @@ struct video_device
>  #if defined(CONFIG_MEDIA_CONTROLLER)
>  	struct media_entity entity;
>  	struct media_intf_devnode *intf_devnode;
> +	struct media_pipeline pipe;
>  #endif
>  	/* device ops */
>  	const struct v4l2_file_operations *fops;
> diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
> index df11519..df1a98f 100644
> --- a/include/media/v4l2-mc.h
> +++ b/include/media/v4l2-mc.h
> @@ -14,6 +14,11 @@
>   * GNU General Public License for more details.
>   */
>  
> +#ifndef _V4L2_MC_H
> +#define _V4L2_MC_H
> +
> +#include <media/v4l2-dev.h>
> +
>  /**
>   * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER
>   *
> @@ -89,3 +94,50 @@ enum demod_pad_index {
>  	DEMOD_PAD_VBI_OUT,
>  	DEMOD_NUM_PADS
>  };
> +
> +/**
> + * v4l_enable_media_source() -	Hold media source for exclusive use
> + *				if free
> + *
> + * @vdev - poniter to struct video_device
> + *
> + * This interface calls enable_source handler to determine if
> + * media source is free for use. The enable_source handler is
> + * responsible for checking is the media source is free and
> + * start a pipeline between the media source and the media
> + * entity associated with the video device. This interface
> + * should be called from v4l2-core and dvb-core interfaces
> + * that change the source configuration.
> + *
> + * Return: returns zero on success or a negative error code.
> + */
> +int v4l_enable_media_source(struct video_device *vdev);
> +
> +/**
> + * v4l_disable_media_source() -	Release media source
> + *
> + * @vdev - poniter to struct video_device
> + *
> + * This interface calls disable_source handler to release
> + * the media source. The disable_source handler stops the
> + * active media pipeline between the media source and the
> + * media entity associated with the video device.
> + *
> + * Return: returns zero on success or a negative error code.
> + */
> +void v4l_disable_media_source(struct video_device *vdev);
> +/*
> + * v4l_vb2q_enable_media_tuner -  Hold media source for exclusive use
> + *				  if free.
> + * @q - pointer to struct vb2_queue
> + *
> + * Wrapper for v4l_enable_media_source(). This function should
> + * be called from v4l2-core to enable the media source with
> + * pointer to struct vb2_queue as the input argument. Some
> + * v4l2-core interfaces don't have access to video device and
> + * this interface finds the struct video_device for the q and
> + * calls v4l_enable_media_source().
> + */
> +int v4l_vb2q_enable_media_source(struct vb2_queue *q);
> +
> +#endif /* _V4L2_MC_H */

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces
@ 2016-02-04  9:25     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:25 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai-IBi9RG/b67k, clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs

Em Wed, 03 Feb 2016 21:03:39 -0700
Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> escreveu:

> Add a new interfaces to be used by v4l-core to invoke enable
> source and disable_source handlers in the media_device. The
> enable_source helper function invokes the enable_source handler
> to find media source entity connected to the entity and check
> is it is available or busy. If source is available, link is
> activated and pipeline is started. The disable_source helper
> function invokes the disable_source handler to deactivate and
> stop the pipeline.
> 
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
>  drivers/media/v4l2-core/Makefile  |  2 +-
>  drivers/media/v4l2-core/v4l2-mc.c | 60 +++++++++++++++++++++++++++++++++++++++
>  include/media/v4l2-dev.h          |  1 +
>  include/media/v4l2-mc.h           | 52 +++++++++++++++++++++++++++++++++
>  4 files changed, 114 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/media/v4l2-core/v4l2-mc.c
> 
> diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> index 1dc8bba..c6acc01 100644
> --- a/drivers/media/v4l2-core/Makefile
> +++ b/drivers/media/v4l2-core/Makefile
> @@ -6,7 +6,7 @@ tuner-objs	:=	tuner-core.o
>  
>  videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
>  			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \
> -			v4l2-async.o
> +			v4l2-async.o v4l2-mc.o
>  ifeq ($(CONFIG_COMPAT),y)
>    videodev-objs += v4l2-compat-ioctl32.o
>  endif
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> new file mode 100644
> index 0000000..87416df
> --- /dev/null
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -0,0 +1,60 @@
> +/*
> + * v4l2-mc.c - Media Controller V4L2 Common Interfaces
> + *
> + * Copyright (C) 2016 Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <media/v4l2-mc.h>
> +#include <media/media-device.h>
> +#include <media/videobuf2-core.h>
> +#include <media/v4l2-fh.h>
> +
> +int v4l_enable_media_source(struct video_device *vdev)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct media_device *mdev = vdev->entity.graph_obj.mdev;
> +	int ret;
> +
> +	if (!mdev || !mdev->enable_source)
> +		return 0;
> +	ret = mdev->enable_source(&vdev->entity, &vdev->pipe);
> +	if (ret)
> +		return -EBUSY;
> +	return 0;
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l_enable_media_source);
> +
> +void v4l_disable_media_source(struct video_device *vdev)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct media_device *mdev = vdev->entity.graph_obj.mdev;
> +
> +	if (mdev && mdev->disable_source)
> +		mdev->disable_source(&vdev->entity);
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +}
> +EXPORT_SYMBOL_GPL(v4l_disable_media_source);
> +
> +int v4l_vb2q_enable_media_source(struct vb2_queue *q)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct v4l2_fh *fh = q->owner;
> +
> +	return v4l_enable_media_source(fh->vdev);
> +#endif /* CONFIG_MEDIA_CONTROLLER */
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
> +

The code itself is ok. However, the above code would work better if you
declare them as static inline at the header file (v4l2-mc.h). That would
allow the compiler to optimize them with the caller codr (where the
declared structs like mdev, fh are likely already stored on some registers), 
and even removing the function completely if compiled without the media
controller.

> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
> index eeabf20..76056ab 100644
> --- a/include/media/v4l2-dev.h
> +++ b/include/media/v4l2-dev.h
> @@ -87,6 +87,7 @@ struct video_device
>  #if defined(CONFIG_MEDIA_CONTROLLER)
>  	struct media_entity entity;
>  	struct media_intf_devnode *intf_devnode;
> +	struct media_pipeline pipe;
>  #endif
>  	/* device ops */
>  	const struct v4l2_file_operations *fops;
> diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
> index df11519..df1a98f 100644
> --- a/include/media/v4l2-mc.h
> +++ b/include/media/v4l2-mc.h
> @@ -14,6 +14,11 @@
>   * GNU General Public License for more details.
>   */
>  
> +#ifndef _V4L2_MC_H
> +#define _V4L2_MC_H
> +
> +#include <media/v4l2-dev.h>
> +
>  /**
>   * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER
>   *
> @@ -89,3 +94,50 @@ enum demod_pad_index {
>  	DEMOD_PAD_VBI_OUT,
>  	DEMOD_NUM_PADS
>  };
> +
> +/**
> + * v4l_enable_media_source() -	Hold media source for exclusive use
> + *				if free
> + *
> + * @vdev - poniter to struct video_device
> + *
> + * This interface calls enable_source handler to determine if
> + * media source is free for use. The enable_source handler is
> + * responsible for checking is the media source is free and
> + * start a pipeline between the media source and the media
> + * entity associated with the video device. This interface
> + * should be called from v4l2-core and dvb-core interfaces
> + * that change the source configuration.
> + *
> + * Return: returns zero on success or a negative error code.
> + */
> +int v4l_enable_media_source(struct video_device *vdev);
> +
> +/**
> + * v4l_disable_media_source() -	Release media source
> + *
> + * @vdev - poniter to struct video_device
> + *
> + * This interface calls disable_source handler to release
> + * the media source. The disable_source handler stops the
> + * active media pipeline between the media source and the
> + * media entity associated with the video device.
> + *
> + * Return: returns zero on success or a negative error code.
> + */
> +void v4l_disable_media_source(struct video_device *vdev);
> +/*
> + * v4l_vb2q_enable_media_tuner -  Hold media source for exclusive use
> + *				  if free.
> + * @q - pointer to struct vb2_queue
> + *
> + * Wrapper for v4l_enable_media_source(). This function should
> + * be called from v4l2-core to enable the media source with
> + * pointer to struct vb2_queue as the input argument. Some
> + * v4l2-core interfaces don't have access to video device and
> + * this interface finds the struct video_device for the q and
> + * calls v4l_enable_media_source().
> + */
> +int v4l_vb2q_enable_media_source(struct vb2_queue *q);
> +
> +#endif /* _V4L2_MC_H */

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers
@ 2016-02-04  9:35     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:35 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:43 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Change dvb frontend to check if tuner is free when
> device opened in RW mode. Call to enable_source
> handler either returns with an active pipeline to
> tuner or error if tuner is busy. Tuner is released
> when frontend is released calling the disable_source
> handler.

This patch seems too early in the series, as I'm not seeing any patch
providing a replacement for the removed code yet.

> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
>  drivers/media/dvb-core/dvb_frontend.h |   3 +
>  2 files changed, 24 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
> index 03cc508..2b17e8b 100644
> --- a/drivers/media/dvb-core/dvb_frontend.c
> +++ b/drivers/media/dvb-core/dvb_frontend.c
> @@ -131,11 +131,6 @@ struct dvb_frontend_private {
>  	int quality;
>  	unsigned int check_wrapped;
>  	enum dvbfe_search algo_status;
> -
> -#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
> -	struct media_pipeline pipe;
> -	struct media_entity *pipe_start_entity;
> -#endif
>  };
>  
>  static void dvb_frontend_wakeup(struct dvb_frontend *fe);
> @@ -596,104 +591,12 @@ 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.
> - */
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -static int dvb_enable_media_tuner(struct dvb_frontend *fe)
> -{
> -	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 ret, n_links = 0, active_links = 0;
> -
> -	fepriv->pipe_start_entity = NULL;
> -
> -	if (!mdev)
> -		return 0;
> -
> -	entity = fepriv->dvbdev->entity;
> -	fepriv->pipe_start_entity = entity;
> -
> -	list_for_each_entry(link, &entity->links, list) {
> -		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;
> -	fepriv->pipe_start_entity = source;
> -	list_for_each_entry(link, &source->links, list) {
> -		struct media_entity *sink;
> -		int flags = 0;
> -
> -		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");
> -	}
> -	return 0;
> -}
> -#endif
> -
>  static int dvb_frontend_thread(void *data)
>  {
>  	struct dvb_frontend *fe = data;
>  	struct dvb_frontend_private *fepriv = fe->frontend_priv;
>  	enum fe_status s;
>  	enum dvbfe_algo algo;
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -	int ret;
> -#endif
> -
>  	bool re_tune = false;
>  	bool semheld = false;
>  
> @@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)
>  	fepriv->wakeup = 0;
>  	fepriv->reinitialise = 0;
>  
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -	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");
> -	} else if (fepriv->pipe_start_entity) {
> -		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
> -						  &fepriv->pipe);
> -		if (ret)
> -			return ret;
> -	}
> -#endif
> -
>  	dvb_frontend_init(fe);
>  
>  	set_freezable();
> @@ -829,12 +718,6 @@ restart:
>  		}
>  	}
>  
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -	if (fepriv->pipe_start_entity)
> -		media_entity_pipeline_stop(fepriv->pipe_start_entity);
> -	fepriv->pipe_start_entity = NULL;
> -#endif
> -
>  	if (dvb_powerdown_on_sleep) {
>  		if (fe->ops.set_voltage)
>  			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
> @@ -2612,9 +2495,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>  		fepriv->tone = -1;
>  		fepriv->voltage = -1;
>  
> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> +		if (fe->dvb->mdev && fe->dvb->mdev->enable_source) {
> +			ret = fe->dvb->mdev->enable_source(dvbdev->entity,
> +							   &fe->pipe);
> +			if (ret) {
> +				dev_err(fe->dvb->device,
> +					"Tuner is busy. Error %d\n", ret);
> +				goto err2;
> +			}
> +		}
> +#endif
>  		ret = dvb_frontend_start (fe);
>  		if (ret)
> -			goto err2;
> +			goto err3;
>  
>  		/*  empty event queue */
>  		fepriv->events.eventr = fepriv->events.eventw = 0;
> @@ -2624,7 +2518,12 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>  		mutex_unlock (&adapter->mfe_lock);
>  	return ret;
>  
> +err3:
> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> +	if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
> +		fe->dvb->mdev->disable_source(dvbdev->entity);
>  err2:
> +#endif
>  	dvb_generic_release(inode, file);
>  err1:
>  	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
> @@ -2653,6 +2552,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
>  
>  	if (dvbdev->users == -1) {
>  		wake_up(&fepriv->wait_queue);
> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> +		if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
> +			fe->dvb->mdev->disable_source(dvbdev->entity);
> +#endif
>  		if (fe->exit != DVB_FE_NO_EXIT)
>  			wake_up(&dvbdev->wait_queue);
>  		if (fe->ops.ts_bus_ctrl)
> diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
> index 458bcce..9466906 100644
> --- a/drivers/media/dvb-core/dvb_frontend.h
> +++ b/drivers/media/dvb-core/dvb_frontend.h
> @@ -686,6 +686,9 @@ struct dvb_frontend {
>  	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
>  	int id;
>  	unsigned int exit;
> +#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
> +	struct media_pipeline pipe;
> +#endif

Why moving this to the non-private part of the data?

>  };
>  
>  /**

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers
@ 2016-02-04  9:35     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:35 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai-IBi9RG/b67k, clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs

Em Wed, 03 Feb 2016 21:03:43 -0700
Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> escreveu:

> Change dvb frontend to check if tuner is free when
> device opened in RW mode. Call to enable_source
> handler either returns with an active pipeline to
> tuner or error if tuner is busy. Tuner is released
> when frontend is released calling the disable_source
> handler.

This patch seems too early in the series, as I'm not seeing any patch
providing a replacement for the removed code yet.

> 
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
>  drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
>  drivers/media/dvb-core/dvb_frontend.h |   3 +
>  2 files changed, 24 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
> index 03cc508..2b17e8b 100644
> --- a/drivers/media/dvb-core/dvb_frontend.c
> +++ b/drivers/media/dvb-core/dvb_frontend.c
> @@ -131,11 +131,6 @@ struct dvb_frontend_private {
>  	int quality;
>  	unsigned int check_wrapped;
>  	enum dvbfe_search algo_status;
> -
> -#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
> -	struct media_pipeline pipe;
> -	struct media_entity *pipe_start_entity;
> -#endif
>  };
>  
>  static void dvb_frontend_wakeup(struct dvb_frontend *fe);
> @@ -596,104 +591,12 @@ 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.
> - */
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -static int dvb_enable_media_tuner(struct dvb_frontend *fe)
> -{
> -	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 ret, n_links = 0, active_links = 0;
> -
> -	fepriv->pipe_start_entity = NULL;
> -
> -	if (!mdev)
> -		return 0;
> -
> -	entity = fepriv->dvbdev->entity;
> -	fepriv->pipe_start_entity = entity;
> -
> -	list_for_each_entry(link, &entity->links, list) {
> -		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;
> -	fepriv->pipe_start_entity = source;
> -	list_for_each_entry(link, &source->links, list) {
> -		struct media_entity *sink;
> -		int flags = 0;
> -
> -		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");
> -	}
> -	return 0;
> -}
> -#endif
> -
>  static int dvb_frontend_thread(void *data)
>  {
>  	struct dvb_frontend *fe = data;
>  	struct dvb_frontend_private *fepriv = fe->frontend_priv;
>  	enum fe_status s;
>  	enum dvbfe_algo algo;
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -	int ret;
> -#endif
> -
>  	bool re_tune = false;
>  	bool semheld = false;
>  
> @@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)
>  	fepriv->wakeup = 0;
>  	fepriv->reinitialise = 0;
>  
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -	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");
> -	} else if (fepriv->pipe_start_entity) {
> -		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
> -						  &fepriv->pipe);
> -		if (ret)
> -			return ret;
> -	}
> -#endif
> -
>  	dvb_frontend_init(fe);
>  
>  	set_freezable();
> @@ -829,12 +718,6 @@ restart:
>  		}
>  	}
>  
> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> -	if (fepriv->pipe_start_entity)
> -		media_entity_pipeline_stop(fepriv->pipe_start_entity);
> -	fepriv->pipe_start_entity = NULL;
> -#endif
> -
>  	if (dvb_powerdown_on_sleep) {
>  		if (fe->ops.set_voltage)
>  			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
> @@ -2612,9 +2495,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>  		fepriv->tone = -1;
>  		fepriv->voltage = -1;
>  
> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> +		if (fe->dvb->mdev && fe->dvb->mdev->enable_source) {
> +			ret = fe->dvb->mdev->enable_source(dvbdev->entity,
> +							   &fe->pipe);
> +			if (ret) {
> +				dev_err(fe->dvb->device,
> +					"Tuner is busy. Error %d\n", ret);
> +				goto err2;
> +			}
> +		}
> +#endif
>  		ret = dvb_frontend_start (fe);
>  		if (ret)
> -			goto err2;
> +			goto err3;
>  
>  		/*  empty event queue */
>  		fepriv->events.eventr = fepriv->events.eventw = 0;
> @@ -2624,7 +2518,12 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>  		mutex_unlock (&adapter->mfe_lock);
>  	return ret;
>  
> +err3:
> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> +	if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
> +		fe->dvb->mdev->disable_source(dvbdev->entity);
>  err2:
> +#endif
>  	dvb_generic_release(inode, file);
>  err1:
>  	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
> @@ -2653,6 +2552,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
>  
>  	if (dvbdev->users == -1) {
>  		wake_up(&fepriv->wait_queue);
> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
> +		if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
> +			fe->dvb->mdev->disable_source(dvbdev->entity);
> +#endif
>  		if (fe->exit != DVB_FE_NO_EXIT)
>  			wake_up(&dvbdev->wait_queue);
>  		if (fe->ops.ts_bus_ctrl)
> diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
> index 458bcce..9466906 100644
> --- a/drivers/media/dvb-core/dvb_frontend.h
> +++ b/drivers/media/dvb-core/dvb_frontend.h
> @@ -686,6 +686,9 @@ struct dvb_frontend {
>  	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
>  	int id;
>  	unsigned int exit;
> +#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
> +	struct media_pipeline pipe;
> +#endif

Why moving this to the non-private part of the data?

>  };
>  
>  /**

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner()
@ 2016-02-04  9:37     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:37 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:44 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Remove au0828_enable_analog_tuner() as it is
> no longer needed because v4l2-core implements
> common interfaces to check for media source
> availability.

I didn't see such code at v4l2-core yet. Missing patch?

> 
> In addition, queue_setup() no longer needs the
> tuner availability check since v4l2-core does it.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
>  1 file changed, 61 deletions(-)
> 
> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
> index 8c54fd2..81952c8 100644
> --- a/drivers/media/usb/au0828/au0828-video.c
> +++ b/drivers/media/usb/au0828/au0828-video.c
> @@ -638,64 +638,6 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
>  	return rc;
>  }
>  
> -static int au0828_enable_analog_tuner(struct au0828_dev *dev)
> -{
> -#ifdef CONFIG_MEDIA_CONTROLLER
> -	struct media_device *mdev = dev->media_dev;
> -	struct media_entity *source;
> -	struct media_link *link, *found_link = NULL;
> -	int ret, active_links = 0;
> -
> -	if (!mdev || !dev->decoder)
> -		return 0;
> -
> -	/*
> -	 * This will find the tuner that is connected into the decoder.
> -	 * Technically, this is not 100% correct, as the device may be
> -	 * using an analog input instead of the tuner. However, as we can't
> -	 * do DVB streaming while the DMA engine is being used for V4L2,
> -	 * this should be enough for the actual needs.
> -	 */
> -	list_for_each_entry(link, &dev->decoder->links, list) {
> -		if (link->sink->entity == dev->decoder) {
> -			found_link = link;
> -			if (link->flags & MEDIA_LNK_FL_ENABLED)
> -				active_links++;
> -			break;
> -		}
> -	}
> -
> -	if (active_links == 1 || !found_link)
> -		return 0;
> -
> -	source = found_link->source->entity;
> -	list_for_each_entry(link, &source->links, list) {
> -		struct media_entity *sink;
> -		int flags = 0;
> -
> -		sink = link->sink->entity;
> -
> -		if (sink == dev->decoder)
> -			flags = MEDIA_LNK_FL_ENABLED;
> -
> -		ret = media_entity_setup_link(link, flags);
> -		if (ret) {
> -			pr_err(
> -				"Couldn't change link %s->%s to %s. Error %d\n",
> -				source->name, sink->name,
> -				flags ? "enabled" : "disabled",
> -				ret);
> -			return ret;
> -		} else
> -			au0828_isocdbg(
> -				"link %s->%s was %s\n",
> -				source->name, sink->name,
> -				flags ? "ENABLED" : "disabled");
> -	}
> -#endif
> -	return 0;
> -}
> -
>  static int queue_setup(struct vb2_queue *vq,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
> @@ -707,9 +649,6 @@ static int queue_setup(struct vb2_queue *vq,
>  		return sizes[0] < size ? -EINVAL : 0;
>  	*nplanes = 1;
>  	sizes[0] = size;
> -
> -	au0828_enable_analog_tuner(dev);
> -
>  	return 0;
>  }
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner()
@ 2016-02-04  9:37     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04  9:37 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai-IBi9RG/b67k, clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs

Em Wed, 03 Feb 2016 21:03:44 -0700
Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> escreveu:

> Remove au0828_enable_analog_tuner() as it is
> no longer needed because v4l2-core implements
> common interfaces to check for media source
> availability.

I didn't see such code at v4l2-core yet. Missing patch?

> 
> In addition, queue_setup() no longer needs the
> tuner availability check since v4l2-core does it.
> 
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
>  drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
>  1 file changed, 61 deletions(-)
> 
> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
> index 8c54fd2..81952c8 100644
> --- a/drivers/media/usb/au0828/au0828-video.c
> +++ b/drivers/media/usb/au0828/au0828-video.c
> @@ -638,64 +638,6 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
>  	return rc;
>  }
>  
> -static int au0828_enable_analog_tuner(struct au0828_dev *dev)
> -{
> -#ifdef CONFIG_MEDIA_CONTROLLER
> -	struct media_device *mdev = dev->media_dev;
> -	struct media_entity *source;
> -	struct media_link *link, *found_link = NULL;
> -	int ret, active_links = 0;
> -
> -	if (!mdev || !dev->decoder)
> -		return 0;
> -
> -	/*
> -	 * This will find the tuner that is connected into the decoder.
> -	 * Technically, this is not 100% correct, as the device may be
> -	 * using an analog input instead of the tuner. However, as we can't
> -	 * do DVB streaming while the DMA engine is being used for V4L2,
> -	 * this should be enough for the actual needs.
> -	 */
> -	list_for_each_entry(link, &dev->decoder->links, list) {
> -		if (link->sink->entity == dev->decoder) {
> -			found_link = link;
> -			if (link->flags & MEDIA_LNK_FL_ENABLED)
> -				active_links++;
> -			break;
> -		}
> -	}
> -
> -	if (active_links == 1 || !found_link)
> -		return 0;
> -
> -	source = found_link->source->entity;
> -	list_for_each_entry(link, &source->links, list) {
> -		struct media_entity *sink;
> -		int flags = 0;
> -
> -		sink = link->sink->entity;
> -
> -		if (sink == dev->decoder)
> -			flags = MEDIA_LNK_FL_ENABLED;
> -
> -		ret = media_entity_setup_link(link, flags);
> -		if (ret) {
> -			pr_err(
> -				"Couldn't change link %s->%s to %s. Error %d\n",
> -				source->name, sink->name,
> -				flags ? "enabled" : "disabled",
> -				ret);
> -			return ret;
> -		} else
> -			au0828_isocdbg(
> -				"link %s->%s was %s\n",
> -				source->name, sink->name,
> -				flags ? "ENABLED" : "disabled");
> -	}
> -#endif
> -	return 0;
> -}
> -
>  static int queue_setup(struct vb2_queue *vq,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
> @@ -707,9 +649,6 @@ static int queue_setup(struct vb2_queue *vq,
>  		return sizes[0] < size ? -EINVAL : 0;
>  	*nplanes = 1;
>  	sizes[0] = size;
> -
> -	au0828_enable_analog_tuner(dev);
> -
>  	return 0;
>  }
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 13/22] media: au0828 video change to use v4l_enable_media_source()
@ 2016-02-04 10:00     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:00 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:45 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Change au0828 to check if tuner is free or not
> before changing tuner configuration.
> 
> vidioc_g_tuner(), and au0828_v4l2_close() now call
> v4l-core interface v4l_enable_media_source() before
> changing tuner configuration.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/usb/au0828/au0828-video.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
> index 81952c8..8087215 100644
> --- a/drivers/media/usb/au0828/au0828-video.c
> +++ b/drivers/media/usb/au0828/au0828-video.c
> @@ -1006,8 +1006,12 @@ static int au0828_v4l2_close(struct file *filp)
>  		goto end;
>  
>  	if (dev->users == 1) {
> -		/* Save some power by putting tuner to sleep */
> -		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
> +		/* Save some power by putting tuner to sleep, if it is free */
> +		/* What happens when radio is using tuner?? */
> +		ret = v4l_enable_media_source(vdev);
> +		if (ret == 0)
> +			v4l2_device_call_all(&dev->v4l2_dev, 0, core,
> +					     s_power, 0);

Actually, for most USB devices (and this is the case of au0828), the
tuner can safely be disabled here if ALSA is not streaming, as, except
for some very old USB tuner models (like em28xx-based WinTV USB2) have
a separate audio output jack.

Btw, those devices that have a separate audio output jack have
analog tuners, like Philips FM1236. Those devices are always on, so
the s_power callback are silently ignored.

So, the best logic here would be to disable the tuner if:
	- ALSA is not streaming;
	- the last V4L2 file handler is closed.

Additionally, media source can be disabled if the above conditions
are met and if the device doesn't have a separate audio out plug
(or doesn't use a silicon tuner like xc2028/3028/4000/5000).

Of course, as ALSA may stream anytime, a callback would be needed to
enable the media source and power on the tuner, for radio to work.

I understand that the above would require some other non-trivial
changes, with would be best addressed on a separate patch series.

So, for now, I would add a FIXME there explaining the above.

>  		dev->std_set_in_tuner_core = 0;
>  
>  		/* When close the device, set the usb intf0 into alt0 to free
> @@ -1408,10 +1412,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
>  static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
>  {
>  	struct au0828_dev *dev = video_drvdata(file);
> +	struct video_device *vfd = video_devdata(file);
> +	int ret;
>  
>  	if (t->index != 0)
>  		return -EINVAL;
>  
> +	ret = v4l_enable_media_source(vfd);
> +	if (ret)
> +		return ret;
> +
>  	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
>  		dev->std_set_in_tuner_core, dev->dev_state);
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 13/22] media: au0828 video change to use v4l_enable_media_source()
@ 2016-02-04 10:00     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:00 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai-IBi9RG/b67k, clemens-P6GI/4k7KOmELgA04lAiVw,
	hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, pawel-FA/gS7QP4orQT0dZR+AlfA,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, perex-/Fr2/VpizcU,
	arnd-r2nGTMty4D4, dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA,
	tvboxspy-Re5JQEeQqe8AvxtiuMwx3w, crope-X3B1VOXEql0,
	ruchandani.tina-Re5JQEeQqe8AvxtiuMwx3w, corbet-T1hC0tSOHrs,
	chehabrafael-Re5JQEeQqe8AvxtiuMwx3w,
	k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ,
	stefanr-MtYdepGKPcBMYopoZt5u/LNAH6kLmebB,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ,
	jh1009.sung-Sze3O3UU22JBDgjK7y7TUQ,
	elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w,
	sw0312.kim-Sze3O3UU22JBDgjK7y7TUQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	ricardo.ribalda-Re5JQEeQqe8AvxtiuMwx3w,
	labbott-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy,
	pierre-louis.bossart-VuQAYsv1563Yd54FQh9/CA,
	ricard.wanderlof-VrBV9hrLPhE, julian-SZMMDGyaqes,
	takamichiho-Re5JQEeQqe8AvxtiuMwx3w, dominic.sacre-Mmb7MZpHnFY,
	misterpib-Re5JQEeQqe8AvxtiuMwx3w, daniel-cYrQPVfZoowdnm+yROfE0A,
	gtmkramer-qWit8jRvyhVmR6Xm/wNWPw, normalperson-rMlxZR9MS24,
	joe-amhYAVlgbXj10XsdtD+oqA, linuxbugs

Em Wed, 03 Feb 2016 21:03:45 -0700
Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> escreveu:

> Change au0828 to check if tuner is free or not
> before changing tuner configuration.
> 
> vidioc_g_tuner(), and au0828_v4l2_close() now call
> v4l-core interface v4l_enable_media_source() before
> changing tuner configuration.
> 
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
>  drivers/media/usb/au0828/au0828-video.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
> index 81952c8..8087215 100644
> --- a/drivers/media/usb/au0828/au0828-video.c
> +++ b/drivers/media/usb/au0828/au0828-video.c
> @@ -1006,8 +1006,12 @@ static int au0828_v4l2_close(struct file *filp)
>  		goto end;
>  
>  	if (dev->users == 1) {
> -		/* Save some power by putting tuner to sleep */
> -		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
> +		/* Save some power by putting tuner to sleep, if it is free */
> +		/* What happens when radio is using tuner?? */
> +		ret = v4l_enable_media_source(vdev);
> +		if (ret == 0)
> +			v4l2_device_call_all(&dev->v4l2_dev, 0, core,
> +					     s_power, 0);

Actually, for most USB devices (and this is the case of au0828), the
tuner can safely be disabled here if ALSA is not streaming, as, except
for some very old USB tuner models (like em28xx-based WinTV USB2) have
a separate audio output jack.

Btw, those devices that have a separate audio output jack have
analog tuners, like Philips FM1236. Those devices are always on, so
the s_power callback are silently ignored.

So, the best logic here would be to disable the tuner if:
	- ALSA is not streaming;
	- the last V4L2 file handler is closed.

Additionally, media source can be disabled if the above conditions
are met and if the device doesn't have a separate audio out plug
(or doesn't use a silicon tuner like xc2028/3028/4000/5000).

Of course, as ALSA may stream anytime, a callback would be needed to
enable the media source and power on the tuner, for radio to work.

I understand that the above would require some other non-trivial
changes, with would be best addressed on a separate patch series.

So, for now, I would add a FIXME there explaining the above.

>  		dev->std_set_in_tuner_core = 0;
>  
>  		/* When close the device, set the usb intf0 into alt0 to free
> @@ -1408,10 +1412,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
>  static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
>  {
>  	struct au0828_dev *dev = video_drvdata(file);
> +	struct video_device *vfd = video_devdata(file);
> +	int ret;
>  
>  	if (t->index != 0)
>  		return -EINVAL;
>  
> +	ret = v4l_enable_media_source(vfd);
> +	if (ret)
> +		return ret;
> +
>  	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
>  		dev->std_set_in_tuner_core, dev->dev_state);
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04 10:05     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:05 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:46 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Change au0828 to use Managed Media Controller API to
> share media device and coordinate creating/deleting
> the shared media device with the snd-usb-audio driver.
> The shared media device is created as device resource
> of the parent usb device of the two drivers.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/usb/au0828/au0828-core.c | 29 +++++++++++++++--------------
>  1 file changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index df2bc3f..b8c4bdd 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -134,10 +134,10 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
>  {
>  
>  #ifdef CONFIG_MEDIA_CONTROLLER
> -	if (dev->media_dev) {
> +	if (dev->media_dev &&
> +		media_devnode_is_registered(&dev->media_dev->devnode)) {
>  		media_device_unregister(dev->media_dev);
>  		media_device_cleanup(dev->media_dev);
> -		kfree(dev->media_dev);
>  		dev->media_dev = NULL;
>  	}
>  #endif
> @@ -223,23 +223,24 @@ static int au0828_media_device_init(struct au0828_dev *dev,
>  #ifdef CONFIG_MEDIA_CONTROLLER
>  	struct media_device *mdev;
>  
> -	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
> +	mdev = media_device_get_devres(&udev->dev);
>  	if (!mdev)
>  		return -ENOMEM;
>  
> -	mdev->dev = &udev->dev;
> +	if (!media_devnode_is_registered(&mdev->devnode)) {
> +		mdev->dev = &udev->dev;
>  
> -	if (!dev->board.name)
> -		strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model));
> -	else
> -		strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
> -	if (udev->serial)
> -		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
> -	strcpy(mdev->bus_info, udev->devpath);
> -	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
> -	mdev->driver_version = LINUX_VERSION_CODE;
> +		if (udev->product)
> +			strlcpy(mdev->model, udev->product,
> +				sizeof(mdev->model));

Why did you change that? On some boards, udev->product doesn't reflect
the brand name, but have just some random generic data.

Also, as the other logs associated with the device uses dev->board.name,
we want the media controller to use the same name here. Ok, if this
is null, we could use udev->product as a replacement.

> +		if (udev->serial)
> +			strlcpy(mdev->serial, udev->serial,
> +				sizeof(mdev->serial));
> +		strcpy(mdev->bus_info, udev->devpath);
> +		mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
>  
> -	media_device_init(mdev);
> +		media_device_init(mdev);
> +	}
>  
>  	dev->media_dev = mdev;
>  #endif

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API
@ 2016-02-04 10:05     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:05 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:46 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Change au0828 to use Managed Media Controller API to
> share media device and coordinate creating/deleting
> the shared media device with the snd-usb-audio driver.
> The shared media device is created as device resource
> of the parent usb device of the two drivers.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/usb/au0828/au0828-core.c | 29 +++++++++++++++--------------
>  1 file changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index df2bc3f..b8c4bdd 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -134,10 +134,10 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
>  {
>  
>  #ifdef CONFIG_MEDIA_CONTROLLER
> -	if (dev->media_dev) {
> +	if (dev->media_dev &&
> +		media_devnode_is_registered(&dev->media_dev->devnode)) {
>  		media_device_unregister(dev->media_dev);
>  		media_device_cleanup(dev->media_dev);
> -		kfree(dev->media_dev);
>  		dev->media_dev = NULL;
>  	}
>  #endif
> @@ -223,23 +223,24 @@ static int au0828_media_device_init(struct au0828_dev *dev,
>  #ifdef CONFIG_MEDIA_CONTROLLER
>  	struct media_device *mdev;
>  
> -	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
> +	mdev = media_device_get_devres(&udev->dev);
>  	if (!mdev)
>  		return -ENOMEM;
>  
> -	mdev->dev = &udev->dev;
> +	if (!media_devnode_is_registered(&mdev->devnode)) {
> +		mdev->dev = &udev->dev;
>  
> -	if (!dev->board.name)
> -		strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model));
> -	else
> -		strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
> -	if (udev->serial)
> -		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
> -	strcpy(mdev->bus_info, udev->devpath);
> -	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
> -	mdev->driver_version = LINUX_VERSION_CODE;
> +		if (udev->product)
> +			strlcpy(mdev->model, udev->product,
> +				sizeof(mdev->model));

Why did you change that? On some boards, udev->product doesn't reflect
the brand name, but have just some random generic data.

Also, as the other logs associated with the device uses dev->board.name,
we want the media controller to use the same name here. Ok, if this
is null, we could use udev->product as a replacement.

> +		if (udev->serial)
> +			strlcpy(mdev->serial, udev->serial,
> +				sizeof(mdev->serial));
> +		strcpy(mdev->bus_info, udev->devpath);
> +		mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
>  
> -	media_device_init(mdev);
> +		media_device_init(mdev);
> +	}
>  
>  	dev->media_dev = mdev;
>  #endif

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API
  2016-02-04 10:05     ` Mauro Carvalho Chehab
@ 2016-02-04 10:08       ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:08 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Thu, 4 Feb 2016 08:05:00 -0200
Mauro Carvalho Chehab <mchehab@osg.samsung.com> escreveu:

> Em Wed, 03 Feb 2016 21:03:46 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
> > Change au0828 to use Managed Media Controller API to
> > share media device and coordinate creating/deleting
> > the shared media device with the snd-usb-audio driver.
> > The shared media device is created as device resource
> > of the parent usb device of the two drivers.
> > 
> > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > ---
> >  drivers/media/usb/au0828/au0828-core.c | 29 +++++++++++++++--------------
> >  1 file changed, 15 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> > index df2bc3f..b8c4bdd 100644
> > --- a/drivers/media/usb/au0828/au0828-core.c
> > +++ b/drivers/media/usb/au0828/au0828-core.c
> > @@ -134,10 +134,10 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
> >  {
> >  
> >  #ifdef CONFIG_MEDIA_CONTROLLER
> > -	if (dev->media_dev) {
> > +	if (dev->media_dev &&
> > +		media_devnode_is_registered(&dev->media_dev->devnode)) {
> >  		media_device_unregister(dev->media_dev);
> >  		media_device_cleanup(dev->media_dev);
> > -		kfree(dev->media_dev);
> >  		dev->media_dev = NULL;
> >  	}
> >  #endif
> > @@ -223,23 +223,24 @@ static int au0828_media_device_init(struct au0828_dev *dev,
> >  #ifdef CONFIG_MEDIA_CONTROLLER
> >  	struct media_device *mdev;
> >  
> > -	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
> > +	mdev = media_device_get_devres(&udev->dev);
> >  	if (!mdev)
> >  		return -ENOMEM;
> >  
> > -	mdev->dev = &udev->dev;
> > +	if (!media_devnode_is_registered(&mdev->devnode)) {
> > +		mdev->dev = &udev->dev;
> >  
> > -	if (!dev->board.name)
> > -		strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model));
> > -	else
> > -		strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
> > -	if (udev->serial)
> > -		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
> > -	strcpy(mdev->bus_info, udev->devpath);
> > -	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
> > -	mdev->driver_version = LINUX_VERSION_CODE;
> > +		if (udev->product)
> > +			strlcpy(mdev->model, udev->product,
> > +				sizeof(mdev->model));
> 
> Why did you change that? On some boards, udev->product doesn't reflect
> the brand name, but have just some random generic data.
> 
> Also, as the other logs associated with the device uses dev->board.name,
> we want the media controller to use the same name here. Ok, if this
> is null, we could use udev->product as a replacement.

Ah, looking at patch 15/22, I understood why you wanted the above
change: if the device is registered first by ALSA, it won't have a
dev->board.name.

It looks OK to change from dev->board.name to udev->product then,
but please document the reason for it at the patch description.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API
@ 2016-02-04 10:08       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:08 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Thu, 4 Feb 2016 08:05:00 -0200
Mauro Carvalho Chehab <mchehab@osg.samsung.com> escreveu:

> Em Wed, 03 Feb 2016 21:03:46 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
> > Change au0828 to use Managed Media Controller API to
> > share media device and coordinate creating/deleting
> > the shared media device with the snd-usb-audio driver.
> > The shared media device is created as device resource
> > of the parent usb device of the two drivers.
> > 
> > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > ---
> >  drivers/media/usb/au0828/au0828-core.c | 29 +++++++++++++++--------------
> >  1 file changed, 15 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> > index df2bc3f..b8c4bdd 100644
> > --- a/drivers/media/usb/au0828/au0828-core.c
> > +++ b/drivers/media/usb/au0828/au0828-core.c
> > @@ -134,10 +134,10 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
> >  {
> >  
> >  #ifdef CONFIG_MEDIA_CONTROLLER
> > -	if (dev->media_dev) {
> > +	if (dev->media_dev &&
> > +		media_devnode_is_registered(&dev->media_dev->devnode)) {
> >  		media_device_unregister(dev->media_dev);
> >  		media_device_cleanup(dev->media_dev);
> > -		kfree(dev->media_dev);
> >  		dev->media_dev = NULL;
> >  	}
> >  #endif
> > @@ -223,23 +223,24 @@ static int au0828_media_device_init(struct au0828_dev *dev,
> >  #ifdef CONFIG_MEDIA_CONTROLLER
> >  	struct media_device *mdev;
> >  
> > -	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
> > +	mdev = media_device_get_devres(&udev->dev);
> >  	if (!mdev)
> >  		return -ENOMEM;
> >  
> > -	mdev->dev = &udev->dev;
> > +	if (!media_devnode_is_registered(&mdev->devnode)) {
> > +		mdev->dev = &udev->dev;
> >  
> > -	if (!dev->board.name)
> > -		strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model));
> > -	else
> > -		strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
> > -	if (udev->serial)
> > -		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
> > -	strcpy(mdev->bus_info, udev->devpath);
> > -	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
> > -	mdev->driver_version = LINUX_VERSION_CODE;
> > +		if (udev->product)
> > +			strlcpy(mdev->model, udev->product,
> > +				sizeof(mdev->model));
> 
> Why did you change that? On some boards, udev->product doesn't reflect
> the brand name, but have just some random generic data.
> 
> Also, as the other logs associated with the device uses dev->board.name,
> we want the media controller to use the same name here. Ok, if this
> is null, we could use udev->product as a replacement.

Ah, looking at patch 15/22, I understood why you wanted the above
change: if the device is registered first by ALSA, it won't have a
dev->board.name.

It looks OK to change from dev->board.name to udev->product then,
but please document the reason for it at the patch description.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04 10:26     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:26 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:52 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add enable_source and disable_source handlers.
> The enable source handler is called from
> v4l2-core, dvb-core, and ALSA drivers to check
> if the shared media source is free. The disable
> source handler is called to release the shared
> media source.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
>  drivers/media/usb/au0828/au0828.h      |   3 +
>  2 files changed, 152 insertions(+)
> 
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 4c90f28..fd2265c 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
>  		return -EINVAL;
>  
>  	if (tuner) {
> +		dev->tuner = tuner;
>  		/* create tuner to decoder link in deactivated state */
>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  					    decoder, 0, 0);
> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
>  #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 ret = 0;
> +	struct media_device *mdev = entity->graph_obj.mdev;
> +	struct au0828_dev *dev;
> +
> +	if (!mdev)
> +		return -ENODEV;
> +
> +	/* for Audio 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;
> +	}

This is wrong. There are devices without tuner (capture devices) and
without analog decoder (pure DVB devices).

In the case of pure DVB devices (e. g. no dev->decoder), it should
just enable the DVB path.

In the case of devices without tuner, it should use the same logic
needed to handle the S-Video/Composite connector inputs.

Btw, I'm not seeing how this logic would do the right thing if the user
selects either S-Video or Composite connectors.

> +
> +	/*
> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
> +		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;
> +		}
> +	}
> +
> +	list_for_each_entry(link, &sink->links, list) {
> +		/* Check sink, and source */
> +		if (link->sink->entity == sink &&
> +		    link->source->entity == dev->tuner) {
> +			found_link = link;
> +			break;
> +		}
> +	}
> +
> +	if (!found_link) {
> +		ret = -ENODEV;
> +		goto end;
> +	}
> +
> +	/* activate link between source and sink and start pipeline */
> +	source = found_link->source->entity;
> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
> +	if (ret) {
> +		pr_err(
> +			"Activate tuner link %s->%s. Error %d\n",
> +			source->name, sink->name, ret);
> +		goto end;
> +	}
> +
> +	ret = __media_entity_pipeline_start(entity, pipe);
> +	if (ret) {
> +		pr_err("Start Pipeline: %s->%s Error %d\n",
> +			source->name, entity->name, ret);
> +		ret = __media_entity_setup_link(found_link, 0);
> +		pr_err("Deactive link Error %d\n", ret);
> +		goto end;
> +	}

Hmm... isn't it to early to activate the pipeline here? My original
guess is that, on the analog side, this should happen only at the stream
on code. Wouldn't this break apps like mythTV?

> +	/*
> +	 * save active link and active link owner to avoid audio
> +	 * deactivating video owned link from disable_source and
> +	 * vice versa
> +	*/
> +	dev->active_link = found_link;
> +	dev->active_link_owner = entity;
> +end:
> +	mutex_unlock(&mdev->graph_mutex);
> +	pr_debug("au0828_enable_source() end %s %d %d\n",
> +		entity->name, entity->function, ret);
> +	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->graph_obj.mdev;
> +	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;
> +	}

Same note as before.

> +
> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
> +		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);
> +		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;
> +	}

Most code here looks like the one at au0828_enable_source(). Wouldn't
be simpler to merge those code and add a "bool enable" to the function
parameters?

> +
> +end:
> +	mutex_unlock(&mdev->graph_mutex);
> +#endif
> +}
> +
>  static int au0828_media_device_register(struct au0828_dev *dev,
>  					struct usb_device *udev)
>  {
> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
>  			ret);
>  		return ret;
>  	}
> +	/* set enable_source */
> +	dev->media_dev->source_priv = (void *) dev;
> +	dev->media_dev->enable_source = au0828_enable_source;
> +	dev->media_dev->disable_source = au0828_disable_source;
>  #endif
>  	return 0;
>  }
> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
> index 54379ec..a7c88a1 100644
> --- a/drivers/media/usb/au0828/au0828.h
> +++ b/drivers/media/usb/au0828/au0828.h
> @@ -284,6 +284,9 @@ struct au0828_dev {
>  	struct media_entity input_ent[AU0828_MAX_INPUT];
>  	struct media_pad input_pad[AU0828_MAX_INPUT];
>  	struct media_entity_notify entity_notify;
> +	struct media_entity *tuner;
> +	struct media_link *active_link;
> +	struct media_entity *active_link_owner;
>  #endif
>  };
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
@ 2016-02-04 10:26     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:26 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:52 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add enable_source and disable_source handlers.
> The enable source handler is called from
> v4l2-core, dvb-core, and ALSA drivers to check
> if the shared media source is free. The disable
> source handler is called to release the shared
> media source.
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
>  drivers/media/usb/au0828/au0828.h      |   3 +
>  2 files changed, 152 insertions(+)
> 
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 4c90f28..fd2265c 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
>  		return -EINVAL;
>  
>  	if (tuner) {
> +		dev->tuner = tuner;
>  		/* create tuner to decoder link in deactivated state */
>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  					    decoder, 0, 0);
> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
>  #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 ret = 0;
> +	struct media_device *mdev = entity->graph_obj.mdev;
> +	struct au0828_dev *dev;
> +
> +	if (!mdev)
> +		return -ENODEV;
> +
> +	/* for Audio 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;
> +	}

This is wrong. There are devices without tuner (capture devices) and
without analog decoder (pure DVB devices).

In the case of pure DVB devices (e. g. no dev->decoder), it should
just enable the DVB path.

In the case of devices without tuner, it should use the same logic
needed to handle the S-Video/Composite connector inputs.

Btw, I'm not seeing how this logic would do the right thing if the user
selects either S-Video or Composite connectors.

> +
> +	/*
> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
> +		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;
> +		}
> +	}
> +
> +	list_for_each_entry(link, &sink->links, list) {
> +		/* Check sink, and source */
> +		if (link->sink->entity == sink &&
> +		    link->source->entity == dev->tuner) {
> +			found_link = link;
> +			break;
> +		}
> +	}
> +
> +	if (!found_link) {
> +		ret = -ENODEV;
> +		goto end;
> +	}
> +
> +	/* activate link between source and sink and start pipeline */
> +	source = found_link->source->entity;
> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
> +	if (ret) {
> +		pr_err(
> +			"Activate tuner link %s->%s. Error %d\n",
> +			source->name, sink->name, ret);
> +		goto end;
> +	}
> +
> +	ret = __media_entity_pipeline_start(entity, pipe);
> +	if (ret) {
> +		pr_err("Start Pipeline: %s->%s Error %d\n",
> +			source->name, entity->name, ret);
> +		ret = __media_entity_setup_link(found_link, 0);
> +		pr_err("Deactive link Error %d\n", ret);
> +		goto end;
> +	}

Hmm... isn't it to early to activate the pipeline here? My original
guess is that, on the analog side, this should happen only at the stream
on code. Wouldn't this break apps like mythTV?

> +	/*
> +	 * save active link and active link owner to avoid audio
> +	 * deactivating video owned link from disable_source and
> +	 * vice versa
> +	*/
> +	dev->active_link = found_link;
> +	dev->active_link_owner = entity;
> +end:
> +	mutex_unlock(&mdev->graph_mutex);
> +	pr_debug("au0828_enable_source() end %s %d %d\n",
> +		entity->name, entity->function, ret);
> +	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->graph_obj.mdev;
> +	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;
> +	}

Same note as before.

> +
> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
> +		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);
> +		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;
> +	}

Most code here looks like the one at au0828_enable_source(). Wouldn't
be simpler to merge those code and add a "bool enable" to the function
parameters?

> +
> +end:
> +	mutex_unlock(&mdev->graph_mutex);
> +#endif
> +}
> +
>  static int au0828_media_device_register(struct au0828_dev *dev,
>  					struct usb_device *udev)
>  {
> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
>  			ret);
>  		return ret;
>  	}
> +	/* set enable_source */
> +	dev->media_dev->source_priv = (void *) dev;
> +	dev->media_dev->enable_source = au0828_enable_source;
> +	dev->media_dev->disable_source = au0828_disable_source;
>  #endif
>  	return 0;
>  }
> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
> index 54379ec..a7c88a1 100644
> --- a/drivers/media/usb/au0828/au0828.h
> +++ b/drivers/media/usb/au0828/au0828.h
> @@ -284,6 +284,9 @@ struct au0828_dev {
>  	struct media_entity input_ent[AU0828_MAX_INPUT];
>  	struct media_pad input_pad[AU0828_MAX_INPUT];
>  	struct media_entity_notify entity_notify;
> +	struct media_entity *tuner;
> +	struct media_link *active_link;
> +	struct media_entity *active_link_owner;
>  #endif
>  };
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04 10:36     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:36 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:53 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Change ALSA driver to use Media Controller API to
> share media resources with DVB and V4L2 drivers
> on a AU0828 media device. Media Controller specific
> initialization is done after sound card is registered.
> ALSA creates Media interface and entity function graph
> nodes for Control, Mixer, PCM Playback, and PCM Capture
> devices.
> 
> snd_usb_hw_params() will call Media Controller enable
> source handler interface to request the media resource.
> If resource request is granted, it will release it from
> snd_usb_hw_free(). If resource is busy, -EBUSY is returned.
> 
> Media specific cleanup is done in usb_audio_disconnect().
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  sound/usb/Kconfig        |   4 +
>  sound/usb/Makefile       |   2 +
>  sound/usb/card.c         |  14 +++
>  sound/usb/card.h         |   1 +
>  sound/usb/media.c        | 319 +++++++++++++++++++++++++++++++++++++++++++++++
>  sound/usb/media.h        |  72 +++++++++++
>  sound/usb/mixer.h        |   1 +
>  sound/usb/pcm.c          |  28 ++++-
>  sound/usb/quirks-table.h |   1 +
>  sound/usb/stream.c       |   2 +
>  sound/usb/usbaudio.h     |   3 +
>  11 files changed, 442 insertions(+), 5 deletions(-)
>  create mode 100644 sound/usb/media.c
>  create mode 100644 sound/usb/media.h
> 
> diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
> index a452ad7..1a71d93 100644
> --- a/sound/usb/Kconfig
> +++ b/sound/usb/Kconfig
> @@ -15,6 +15,7 @@ config SND_USB_AUDIO
>  	select SND_RAWMIDI
>  	select SND_PCM
>  	select BITREVERSE
> +	select SND_USB_AUDIO_USE_MEDIA_CONTROLLER	if MEDIA_CONTROLLER
>  	help
>  	  Say Y here to include support for USB audio and USB MIDI
>  	  devices.
> @@ -22,6 +23,9 @@ config SND_USB_AUDIO
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called snd-usb-audio.
>  
> +config SND_USB_AUDIO_USE_MEDIA_CONTROLLER
> +	bool
> +
>  config SND_USB_UA101
>  	tristate "Edirol UA-101/UA-1000 driver"
>  	select SND_PCM
> diff --git a/sound/usb/Makefile b/sound/usb/Makefile
> index 2d2d122..8dca3c4 100644
> --- a/sound/usb/Makefile
> +++ b/sound/usb/Makefile
> @@ -15,6 +15,8 @@ snd-usb-audio-objs := 	card.o \
>  			quirks.o \
>  			stream.o
>  
> +snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o
> +
>  snd-usbmidi-lib-objs := midi.o
>  
>  # Toplevel Module Dependency
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 1f09d95..35fe256 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -66,6 +66,7 @@
>  #include "format.h"
>  #include "power.h"
>  #include "stream.h"
> +#include "media.h"
>  
>  MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
>  MODULE_DESCRIPTION("USB Audio");
> @@ -561,6 +562,11 @@ static int usb_audio_probe(struct usb_interface *intf,
>  	if (err < 0)
>  		goto __error;
>  
> +	if (quirk->media_device) {
> +		/* don't want to fail when media_device_create() fails */
> +		media_device_create(chip, intf);
> +	}
> +
>  	usb_chip[chip->index] = chip;
>  	chip->num_interfaces++;
>  	usb_set_intfdata(intf, chip);
> @@ -617,6 +623,14 @@ static void usb_audio_disconnect(struct usb_interface *intf)
>  		list_for_each(p, &chip->midi_list) {
>  			snd_usbmidi_disconnect(p);
>  		}
> +		/*
> +		 * Nice to check quirk && quirk->media_device
> +		 * need some special handlings. Doesn't look like
> +		 * we have access to quirk here
> +		 * Acceses mixer_list
> +		*/
> +		media_device_delete(chip);
> +
>  		/* release mixer resources */
>  		list_for_each_entry(mixer, &chip->mixer_list, list) {
>  			snd_usb_mixer_disconnect(mixer);
> diff --git a/sound/usb/card.h b/sound/usb/card.h
> index 71778ca..c15a03c 100644
> --- a/sound/usb/card.h
> +++ b/sound/usb/card.h
> @@ -156,6 +156,7 @@ struct snd_usb_substream {
>  	} dsd_dop;
>  
>  	bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
> +	void *media_ctl;
>  };

This is Takashi's call, but I would prefer to avoid using a void *
here. Fortunately, GCC is smart enough to handle struct pointers
even if the header doesn't have a full declaration of the struct.

So, I would change the above to:

struct media_device;

struct snd_usb_substream {
...
	struct media_device *media_ctl;
};

This way, we ensure strong typecast checks when compiling the code under
sound/usb/media.c, while not needing to include media_device.h header here.

>  
>  struct snd_usb_stream {
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> new file mode 100644
> index 0000000..8fef48e
> --- /dev/null
> +++ b/sound/usb/media.c
> @@ -0,0 +1,319 @@
> +/*
> + * media.c - Media Controller specific ALSA driver code
> + *
> + * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
> + * Copyright (c) 2015 Samsung Electronics Co., Ltd.
> + *
> + * This file is released under the GPLv2.
> + */
> +
> +/*
> + * This file adds Media Controller support to ALSA driver
> + * to use the Media Controller API to share tuner with DVB
> + * and V4L2 drivers that control media device. Media device
> + * is created based on existing quirks framework. Using this
> + * approach, the media controller API usage can be added for
> + * a specific device.
> +*/
> +
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/usb.h>
> +
> +#include <sound/pcm.h>
> +#include <sound/core.h>
> +
> +#include "usbaudio.h"
> +#include "card.h"
> +#include "mixer.h"
> +#include "media.h"
> +
> +static int media_enable_source(struct media_ctl *mctl)
> +{
> +	if (mctl && mctl->media_dev->enable_source)
> +		return mctl->media_dev->enable_source(&mctl->media_entity,
> +						      &mctl->media_pipe);
> +	return 0;
> +}
> +
> +static void media_disable_source(struct media_ctl *mctl)
> +{
> +	if (mctl && mctl->media_dev->disable_source)
> +		mctl->media_dev->disable_source(&mctl->media_entity);
> +}
> +
> +int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
> +			int stream)
> +{
> +	struct media_device *mdev;
> +	struct media_ctl *mctl;
> +	struct device *pcm_dev = &pcm->streams[stream].dev;
> +	u32 intf_type;
> +	int ret = 0;
> +	u16 mixer_pad;
> +	struct media_entity *entity;
> +
> +	mdev = subs->stream->chip->media_dev;
> +	if (!mdev)
> +		return -ENODEV;
> +
> +	if (subs->media_ctl)
> +		return 0;
> +
> +	/* allocate media_ctl */
> +	mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
> +	if (!mctl)
> +		return -ENOMEM;
> +
> +	mctl->media_dev = mdev;
> +	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK;
> +		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK;
> +		mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE;
> +		mixer_pad = 1;
> +	} else {
> +		intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
> +		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
> +		mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
> +		mixer_pad = 2;
> +	}
> +	mctl->media_entity.name = pcm->name;
> +	media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
> +	ret =  media_device_register_entity(mctl->media_dev,
> +					    &mctl->media_entity);
> +	if (ret)
> +		goto err1;
> +
> +	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
> +						  MAJOR(pcm_dev->devt),
> +						  MINOR(pcm_dev->devt));
> +	if (!mctl->intf_devnode) {
> +		ret = -ENOMEM;
> +		goto err2;
> +	}
> +	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
> +						 &mctl->intf_devnode->intf,
> +						 MEDIA_LNK_FL_ENABLED);
> +	if (!mctl->intf_link) {
> +		ret = -ENOMEM;
> +		goto err3;
> +	}
> +
> +	/* create link between mixer and audio */
> +	media_device_for_each_entity(entity, mdev) {
> +		switch (entity->function) {
> +		case MEDIA_ENT_F_AUDIO_MIXER:
> +			ret = media_create_pad_link(entity, mixer_pad,
> +						    &mctl->media_entity, 0,
> +						    MEDIA_LNK_FL_ENABLED);
> +			if (ret)
> +				goto err4;
> +			break;
> +		}
> +	}
> +
> +	subs->media_ctl = mctl;
> +	return 0;
> +
> +err4:
> +	media_remove_intf_link(mctl->intf_link);
> +err3:
> +	media_devnode_remove(mctl->intf_devnode);
> +err2:
> +	media_device_unregister_entity(&mctl->media_entity);
> +err1:
> +	kfree(mctl);
> +	return ret;
> +}
> +
> +void media_stream_delete(struct snd_usb_substream *subs)
> +{
> +	struct media_ctl *mctl = subs->media_ctl;
> +
> +	if (mctl && mctl->media_dev) {
> +		struct media_device *mdev;
> +
> +		mdev = subs->stream->chip->media_dev;
> +		if (mdev && media_devnode_is_registered(&mdev->devnode)) {
> +			media_devnode_remove(mctl->intf_devnode);
> +			media_device_unregister_entity(&mctl->media_entity);
> +			media_entity_cleanup(&mctl->media_entity);
> +		}
> +		kfree(mctl);
> +		subs->media_ctl = NULL;
> +	}
> +}
> +
> +int media_start_pipeline(struct snd_usb_substream *subs)
> +{
> +	struct media_ctl *mctl = subs->media_ctl;
> +
> +	if (mctl)
> +		return media_enable_source(mctl);
> +	return 0;
> +}
> +
> +void media_stop_pipeline(struct snd_usb_substream *subs)
> +{
> +	struct media_ctl *mctl = subs->media_ctl;
> +
> +	if (mctl)
> +		media_disable_source(mctl);
> +}
> +
> +int media_mixer_init(struct snd_usb_audio *chip)
> +{
> +	struct device *ctl_dev = &chip->card->ctl_dev;
> +	struct media_intf_devnode *ctl_intf;
> +	struct usb_mixer_interface *mixer;
> +	struct media_device *mdev = chip->media_dev;
> +	struct media_mixer_ctl *mctl;
> +	u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
> +	int ret;
> +
> +	if (!mdev)
> +		return -ENODEV;
> +
> +	ctl_intf = chip->ctl_intf_media_devnode;
> +	if (!ctl_intf) {
> +		ctl_intf = (void *) media_devnode_create(mdev,
> +							 intf_type, 0,
> +							 MAJOR(ctl_dev->devt),
> +							 MINOR(ctl_dev->devt));
> +		if (!ctl_intf)
> +			return -ENOMEM;
> +		chip->ctl_intf_media_devnode = ctl_intf;
> +	}
> +
> +	list_for_each_entry(mixer, &chip->mixer_list, list) {
> +
> +		if (mixer->media_mixer_ctl)
> +			continue;
> +
> +		/* allocate media_mixer_ctl */
> +		mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
> +		if (!mctl)
> +			return -ENOMEM;
> +
> +		mctl->media_dev = mdev;
> +		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
> +		mctl->media_entity.name = chip->card->mixername;
> +		mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
> +		mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
> +		mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
> +		media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
> +				  mctl->media_pad);
> +		ret =  media_device_register_entity(mctl->media_dev,
> +						    &mctl->media_entity);
> +		if (ret) {
> +			kfree(mctl);
> +			return ret;
> +		}
> +
> +		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
> +							 &ctl_intf->intf,
> +							 MEDIA_LNK_FL_ENABLED);
> +		if (!mctl->intf_link) {
> +			media_device_unregister_entity(&mctl->media_entity);
> +			media_entity_cleanup(&mctl->media_entity);
> +			kfree(mctl);
> +			return -ENOMEM;
> +		}
> +		mctl->intf_devnode = ctl_intf;
> +		mixer->media_mixer_ctl = mctl;
> +	}
> +	return 0;
> +}
> +
> +static void media_mixer_delete(struct snd_usb_audio *chip)
> +{
> +	struct usb_mixer_interface *mixer;
> +	struct media_device *mdev = chip->media_dev;
> +
> +	if (!mdev)
> +		return;
> +
> +	list_for_each_entry(mixer, &chip->mixer_list, list) {
> +		struct media_mixer_ctl *mctl;
> +
> +		mctl = mixer->media_mixer_ctl;
> +		if (!mixer->media_mixer_ctl)
> +			continue;
> +
> +		if (media_devnode_is_registered(&mdev->devnode)) {
> +			media_device_unregister_entity(&mctl->media_entity);
> +			media_entity_cleanup(&mctl->media_entity);
> +		}
> +		kfree(mctl);
> +		mixer->media_mixer_ctl = NULL;
> +	}
> +	if (media_devnode_is_registered(&mdev->devnode))
> +		media_devnode_remove(chip->ctl_intf_media_devnode);
> +	chip->ctl_intf_media_devnode = NULL;
> +}
> +
> +int media_device_create(struct snd_usb_audio *chip,
> +			struct usb_interface *iface)
> +{
> +	struct media_device *mdev;
> +	struct usb_device *usbdev = interface_to_usbdev(iface);
> +	int ret;
> +
> +	mdev = media_device_get_devres(&usbdev->dev);
> +	if (!mdev)
> +		return -ENOMEM;
> +	if (!mdev->dev) {
> +		/* register media device */
> +		mdev->dev = &usbdev->dev;
> +		if (usbdev->product)
> +			strlcpy(mdev->model, usbdev->product,
> +				sizeof(mdev->model));
> +		if (usbdev->serial)
> +			strlcpy(mdev->serial, usbdev->serial,
> +				sizeof(mdev->serial));
> +		strcpy(mdev->bus_info, usbdev->devpath);
> +		mdev->hw_revision = le16_to_cpu(usbdev->descriptor.bcdDevice);
> +		media_device_init(mdev);
> +	}
> +	if (!media_devnode_is_registered(&mdev->devnode)) {
> +		ret = media_device_register(mdev);
> +		if (ret) {
> +			dev_err(&usbdev->dev,
> +				"Couldn't register media device. Error: %d\n",
> +				ret);
> +			return ret;
> +		}
> +	}
> +
> +	/* save media device - avoid lookups */
> +	chip->media_dev = mdev;
> +
> +	/* Create media entities for mixer and control dev */
> +	ret = media_mixer_init(chip);
> +	if (ret) {
> +		dev_err(&usbdev->dev,
> +			"Couldn't create media mixer entities. Error: %d\n",
> +			ret);
> +
> +		/* clear saved media_dev */
> +		chip->media_dev = NULL;
> +
> +		return ret;
> +	}
> +	return 0;
> +}
> +
> +void media_device_delete(struct snd_usb_audio *chip)
> +{
> +	struct media_device *mdev = chip->media_dev;
> +
> +	media_mixer_delete(chip);
> +
> +	if (mdev) {
> +		if (media_devnode_is_registered(&mdev->devnode))
> +			media_device_unregister(mdev);
> +		chip->media_dev = NULL;
> +	}
> +}
> diff --git a/sound/usb/media.h b/sound/usb/media.h
> new file mode 100644
> index 0000000..b5f451a
> --- /dev/null
> +++ b/sound/usb/media.h
> @@ -0,0 +1,72 @@
> +/*
> + * media.h - Media Controller specific ALSA driver code
> + *
> + * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
> + * Copyright (c) 2015 Samsung Electronics Co., Ltd.
> + *
> + * This file is released under the GPLv2.
> + */
> +
> +/*
> + * This file adds Media Controller support to ALSA driver
> + * to use the Media Controller API to share tuner with DVB
> + * and V4L2 drivers that control media device. Media device
> + * is created based on existing quirks framework. Using this
> + * approach, the media controller API usage can be added for
> + * a specific device.
> +*/
> +#ifndef __MEDIA_H
> +
> +#ifdef CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER
> +
> +#include <media/media-device.h>
> +#include <media/media-entity.h>
> +#include <sound/asound.h>
> +
> +struct media_ctl {
> +	struct media_device *media_dev;
> +	struct media_entity media_entity;
> +	struct media_intf_devnode *intf_devnode;
> +	struct media_link *intf_link;
> +	struct media_pad media_pad;
> +	struct media_pipeline media_pipe;
> +};
> +
> +/*
> + * One source pad each for SNDRV_PCM_STREAM_CAPTURE and
> + * SNDRV_PCM_STREAM_PLAYBACK. One for sink pad to link
> + * to AUDIO Source
> +*/
> +#define MEDIA_MIXER_PAD_MAX    (SNDRV_PCM_STREAM_LAST + 2)
> +
> +struct media_mixer_ctl {
> +	struct media_device *media_dev;
> +	struct media_entity media_entity;
> +	struct media_intf_devnode *intf_devnode;
> +	struct media_link *intf_link;
> +	struct media_pad media_pad[MEDIA_MIXER_PAD_MAX];
> +	struct media_pipeline media_pipe;
> +};
> +
> +int media_device_create(struct snd_usb_audio *chip,
> +			struct usb_interface *iface);
> +void media_device_delete(struct snd_usb_audio *chip);
> +int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
> +			int stream);
> +void media_stream_delete(struct snd_usb_substream *subs);
> +int media_start_pipeline(struct snd_usb_substream *subs);
> +void media_stop_pipeline(struct snd_usb_substream *subs);
> +#else
> +static inline int media_device_create(struct snd_usb_audio *chip,
> +				      struct usb_interface *iface)
> +						{ return 0; }
> +static inline void media_device_delete(struct snd_usb_audio *chip) { }
> +static inline int media_stream_init(struct snd_usb_substream *subs,
> +					struct snd_pcm *pcm, int stream)
> +						{ return 0; }
> +static inline void media_stream_delete(struct snd_usb_substream *subs) { }
> +static inline int media_start_pipeline(struct snd_usb_substream *subs)
> +					{ return 0; }
> +static inline void media_stop_pipeline(struct snd_usb_substream *subs) { }
> +#endif
> +#endif /* __MEDIA_H */
> diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
> index 3417ef3..787b352 100644
> --- a/sound/usb/mixer.h
> +++ b/sound/usb/mixer.h
> @@ -22,6 +22,7 @@ struct usb_mixer_interface {
>  	struct urb *rc_urb;
>  	struct usb_ctrlrequest *rc_setup_packet;
>  	u8 rc_buffer[6];
> +	void *media_mixer_ctl;
>  };
>  
>  #define MAX_CHANNELS	16	/* max logical channels */
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index 9245f52..c3b8486 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -35,6 +35,7 @@
>  #include "pcm.h"
>  #include "clock.h"
>  #include "power.h"
> +#include "media.h"
>  
>  #define SUBSTREAM_FLAG_DATA_EP_STARTED	0
>  #define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
> @@ -715,10 +716,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
>  	struct audioformat *fmt;
>  	int ret;
>  
> +	ret = media_start_pipeline(subs);
> +	if (ret)
> +		return ret;
> +
>  	ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
>  					       params_buffer_bytes(hw_params));
>  	if (ret < 0)
> -		return ret;
> +		goto err_ret;
>  
>  	subs->pcm_format = params_format(hw_params);
>  	subs->period_bytes = params_period_bytes(hw_params);
> @@ -732,22 +737,27 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
>  		dev_dbg(&subs->dev->dev,
>  			"cannot set format: format = %#x, rate = %d, channels = %d\n",
>  			   subs->pcm_format, subs->cur_rate, subs->channels);
> -		return -EINVAL;
> +		ret = -EINVAL;
> +		goto err_ret;
>  	}
>  
>  	ret = snd_usb_lock_shutdown(subs->stream->chip);
>  	if (ret < 0)
> -		return ret;
> +		goto err_ret;
>  	ret = set_format(subs, fmt);
>  	snd_usb_unlock_shutdown(subs->stream->chip);
>  	if (ret < 0)
> -		return ret;
> +		goto err_ret;
>  
>  	subs->interface = fmt->iface;
>  	subs->altset_idx = fmt->altset_idx;
>  	subs->need_setup_ep = true;
>  
>  	return 0;
> +
> +err_ret:
> +	media_stop_pipeline(subs);
> +	return ret;
>  }
>  
>  /*
> @@ -759,6 +769,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
>  {
>  	struct snd_usb_substream *subs = substream->runtime->private_data;
>  
> +	media_stop_pipeline(subs);
>  	subs->cur_audiofmt = NULL;
>  	subs->cur_rate = 0;
>  	subs->period_bytes = 0;
> @@ -1219,6 +1230,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
>  	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
>  	struct snd_pcm_runtime *runtime = substream->runtime;
>  	struct snd_usb_substream *subs = &as->substream[direction];
> +	int ret;
>  
>  	subs->interface = -1;
>  	subs->altset_idx = 0;
> @@ -1232,7 +1244,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
>  	subs->dsd_dop.channel = 0;
>  	subs->dsd_dop.marker = 1;
>  
> -	return setup_hw_info(runtime, subs);
> +	ret = setup_hw_info(runtime, subs);
> +	if (ret == 0)
> +		ret = media_stream_init(subs, as->pcm, direction);
> +	if (ret)
> +		snd_usb_autosuspend(subs->stream->chip);
> +	return ret;
>  }
>  
>  static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
> @@ -1241,6 +1258,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
>  	struct snd_usb_substream *subs = &as->substream[direction];
>  
>  	stop_endpoints(subs, true);
> +	media_stop_pipeline(subs);
>  
>  	if (subs->interface >= 0 &&
>  	    !snd_usb_lock_shutdown(subs->stream->chip)) {
> diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
> index c60a776..9d087b1 100644
> --- a/sound/usb/quirks-table.h
> +++ b/sound/usb/quirks-table.h
> @@ -2886,6 +2886,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
>  		.product_name = pname, \
>  		.ifnum = QUIRK_ANY_INTERFACE, \
>  		.type = QUIRK_AUDIO_ALIGN_TRANSFER, \
> +		.media_device = 1, \
>  	} \
>  }
>  
> diff --git a/sound/usb/stream.c b/sound/usb/stream.c
> index c4dc577..6c7f5c1 100644
> --- a/sound/usb/stream.c
> +++ b/sound/usb/stream.c
> @@ -36,6 +36,7 @@
>  #include "format.h"
>  #include "clock.h"
>  #include "stream.h"
> +#include "media.h"
>  
>  /*
>   * free a substream
> @@ -52,6 +53,7 @@ static void free_substream(struct snd_usb_substream *subs)
>  		kfree(fp);
>  	}
>  	kfree(subs->rate_list.list);
> +	media_stream_delete(subs);
>  }
>  
>  
> diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
> index b665d85..0c0a86c 100644
> --- a/sound/usb/usbaudio.h
> +++ b/sound/usb/usbaudio.h
> @@ -60,6 +60,8 @@ struct snd_usb_audio {
>  	bool autoclock;			/* from the 'autoclock' module param */
>  
>  	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
> +	void *media_dev;
> +	void *ctl_intf_media_devnode;
>  };
>  
>  #define usb_audio_err(chip, fmt, args...) \
> @@ -110,6 +112,7 @@ struct snd_usb_audio_quirk {
>  	const char *product_name;
>  	int16_t ifnum;
>  	uint16_t type;
> +	bool media_device;
>  	const void *data;
>  };
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
@ 2016-02-04 10:36     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:36 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:53 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Change ALSA driver to use Media Controller API to
> share media resources with DVB and V4L2 drivers
> on a AU0828 media device. Media Controller specific
> initialization is done after sound card is registered.
> ALSA creates Media interface and entity function graph
> nodes for Control, Mixer, PCM Playback, and PCM Capture
> devices.
> 
> snd_usb_hw_params() will call Media Controller enable
> source handler interface to request the media resource.
> If resource request is granted, it will release it from
> snd_usb_hw_free(). If resource is busy, -EBUSY is returned.
> 
> Media specific cleanup is done in usb_audio_disconnect().
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  sound/usb/Kconfig        |   4 +
>  sound/usb/Makefile       |   2 +
>  sound/usb/card.c         |  14 +++
>  sound/usb/card.h         |   1 +
>  sound/usb/media.c        | 319 +++++++++++++++++++++++++++++++++++++++++++++++
>  sound/usb/media.h        |  72 +++++++++++
>  sound/usb/mixer.h        |   1 +
>  sound/usb/pcm.c          |  28 ++++-
>  sound/usb/quirks-table.h |   1 +
>  sound/usb/stream.c       |   2 +
>  sound/usb/usbaudio.h     |   3 +
>  11 files changed, 442 insertions(+), 5 deletions(-)
>  create mode 100644 sound/usb/media.c
>  create mode 100644 sound/usb/media.h
> 
> diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
> index a452ad7..1a71d93 100644
> --- a/sound/usb/Kconfig
> +++ b/sound/usb/Kconfig
> @@ -15,6 +15,7 @@ config SND_USB_AUDIO
>  	select SND_RAWMIDI
>  	select SND_PCM
>  	select BITREVERSE
> +	select SND_USB_AUDIO_USE_MEDIA_CONTROLLER	if MEDIA_CONTROLLER
>  	help
>  	  Say Y here to include support for USB audio and USB MIDI
>  	  devices.
> @@ -22,6 +23,9 @@ config SND_USB_AUDIO
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called snd-usb-audio.
>  
> +config SND_USB_AUDIO_USE_MEDIA_CONTROLLER
> +	bool
> +
>  config SND_USB_UA101
>  	tristate "Edirol UA-101/UA-1000 driver"
>  	select SND_PCM
> diff --git a/sound/usb/Makefile b/sound/usb/Makefile
> index 2d2d122..8dca3c4 100644
> --- a/sound/usb/Makefile
> +++ b/sound/usb/Makefile
> @@ -15,6 +15,8 @@ snd-usb-audio-objs := 	card.o \
>  			quirks.o \
>  			stream.o
>  
> +snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o
> +
>  snd-usbmidi-lib-objs := midi.o
>  
>  # Toplevel Module Dependency
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 1f09d95..35fe256 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -66,6 +66,7 @@
>  #include "format.h"
>  #include "power.h"
>  #include "stream.h"
> +#include "media.h"
>  
>  MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
>  MODULE_DESCRIPTION("USB Audio");
> @@ -561,6 +562,11 @@ static int usb_audio_probe(struct usb_interface *intf,
>  	if (err < 0)
>  		goto __error;
>  
> +	if (quirk->media_device) {
> +		/* don't want to fail when media_device_create() fails */
> +		media_device_create(chip, intf);
> +	}
> +
>  	usb_chip[chip->index] = chip;
>  	chip->num_interfaces++;
>  	usb_set_intfdata(intf, chip);
> @@ -617,6 +623,14 @@ static void usb_audio_disconnect(struct usb_interface *intf)
>  		list_for_each(p, &chip->midi_list) {
>  			snd_usbmidi_disconnect(p);
>  		}
> +		/*
> +		 * Nice to check quirk && quirk->media_device
> +		 * need some special handlings. Doesn't look like
> +		 * we have access to quirk here
> +		 * Acceses mixer_list
> +		*/
> +		media_device_delete(chip);
> +
>  		/* release mixer resources */
>  		list_for_each_entry(mixer, &chip->mixer_list, list) {
>  			snd_usb_mixer_disconnect(mixer);
> diff --git a/sound/usb/card.h b/sound/usb/card.h
> index 71778ca..c15a03c 100644
> --- a/sound/usb/card.h
> +++ b/sound/usb/card.h
> @@ -156,6 +156,7 @@ struct snd_usb_substream {
>  	} dsd_dop;
>  
>  	bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
> +	void *media_ctl;
>  };

This is Takashi's call, but I would prefer to avoid using a void *
here. Fortunately, GCC is smart enough to handle struct pointers
even if the header doesn't have a full declaration of the struct.

So, I would change the above to:

struct media_device;

struct snd_usb_substream {
...
	struct media_device *media_ctl;
};

This way, we ensure strong typecast checks when compiling the code under
sound/usb/media.c, while not needing to include media_device.h header here.

>  
>  struct snd_usb_stream {
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> new file mode 100644
> index 0000000..8fef48e
> --- /dev/null
> +++ b/sound/usb/media.c
> @@ -0,0 +1,319 @@
> +/*
> + * media.c - Media Controller specific ALSA driver code
> + *
> + * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
> + * Copyright (c) 2015 Samsung Electronics Co., Ltd.
> + *
> + * This file is released under the GPLv2.
> + */
> +
> +/*
> + * This file adds Media Controller support to ALSA driver
> + * to use the Media Controller API to share tuner with DVB
> + * and V4L2 drivers that control media device. Media device
> + * is created based on existing quirks framework. Using this
> + * approach, the media controller API usage can be added for
> + * a specific device.
> +*/
> +
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/usb.h>
> +
> +#include <sound/pcm.h>
> +#include <sound/core.h>
> +
> +#include "usbaudio.h"
> +#include "card.h"
> +#include "mixer.h"
> +#include "media.h"
> +
> +static int media_enable_source(struct media_ctl *mctl)
> +{
> +	if (mctl && mctl->media_dev->enable_source)
> +		return mctl->media_dev->enable_source(&mctl->media_entity,
> +						      &mctl->media_pipe);
> +	return 0;
> +}
> +
> +static void media_disable_source(struct media_ctl *mctl)
> +{
> +	if (mctl && mctl->media_dev->disable_source)
> +		mctl->media_dev->disable_source(&mctl->media_entity);
> +}
> +
> +int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
> +			int stream)
> +{
> +	struct media_device *mdev;
> +	struct media_ctl *mctl;
> +	struct device *pcm_dev = &pcm->streams[stream].dev;
> +	u32 intf_type;
> +	int ret = 0;
> +	u16 mixer_pad;
> +	struct media_entity *entity;
> +
> +	mdev = subs->stream->chip->media_dev;
> +	if (!mdev)
> +		return -ENODEV;
> +
> +	if (subs->media_ctl)
> +		return 0;
> +
> +	/* allocate media_ctl */
> +	mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
> +	if (!mctl)
> +		return -ENOMEM;
> +
> +	mctl->media_dev = mdev;
> +	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK;
> +		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK;
> +		mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE;
> +		mixer_pad = 1;
> +	} else {
> +		intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
> +		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
> +		mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
> +		mixer_pad = 2;
> +	}
> +	mctl->media_entity.name = pcm->name;
> +	media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
> +	ret =  media_device_register_entity(mctl->media_dev,
> +					    &mctl->media_entity);
> +	if (ret)
> +		goto err1;
> +
> +	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
> +						  MAJOR(pcm_dev->devt),
> +						  MINOR(pcm_dev->devt));
> +	if (!mctl->intf_devnode) {
> +		ret = -ENOMEM;
> +		goto err2;
> +	}
> +	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
> +						 &mctl->intf_devnode->intf,
> +						 MEDIA_LNK_FL_ENABLED);
> +	if (!mctl->intf_link) {
> +		ret = -ENOMEM;
> +		goto err3;
> +	}
> +
> +	/* create link between mixer and audio */
> +	media_device_for_each_entity(entity, mdev) {
> +		switch (entity->function) {
> +		case MEDIA_ENT_F_AUDIO_MIXER:
> +			ret = media_create_pad_link(entity, mixer_pad,
> +						    &mctl->media_entity, 0,
> +						    MEDIA_LNK_FL_ENABLED);
> +			if (ret)
> +				goto err4;
> +			break;
> +		}
> +	}
> +
> +	subs->media_ctl = mctl;
> +	return 0;
> +
> +err4:
> +	media_remove_intf_link(mctl->intf_link);
> +err3:
> +	media_devnode_remove(mctl->intf_devnode);
> +err2:
> +	media_device_unregister_entity(&mctl->media_entity);
> +err1:
> +	kfree(mctl);
> +	return ret;
> +}
> +
> +void media_stream_delete(struct snd_usb_substream *subs)
> +{
> +	struct media_ctl *mctl = subs->media_ctl;
> +
> +	if (mctl && mctl->media_dev) {
> +		struct media_device *mdev;
> +
> +		mdev = subs->stream->chip->media_dev;
> +		if (mdev && media_devnode_is_registered(&mdev->devnode)) {
> +			media_devnode_remove(mctl->intf_devnode);
> +			media_device_unregister_entity(&mctl->media_entity);
> +			media_entity_cleanup(&mctl->media_entity);
> +		}
> +		kfree(mctl);
> +		subs->media_ctl = NULL;
> +	}
> +}
> +
> +int media_start_pipeline(struct snd_usb_substream *subs)
> +{
> +	struct media_ctl *mctl = subs->media_ctl;
> +
> +	if (mctl)
> +		return media_enable_source(mctl);
> +	return 0;
> +}
> +
> +void media_stop_pipeline(struct snd_usb_substream *subs)
> +{
> +	struct media_ctl *mctl = subs->media_ctl;
> +
> +	if (mctl)
> +		media_disable_source(mctl);
> +}
> +
> +int media_mixer_init(struct snd_usb_audio *chip)
> +{
> +	struct device *ctl_dev = &chip->card->ctl_dev;
> +	struct media_intf_devnode *ctl_intf;
> +	struct usb_mixer_interface *mixer;
> +	struct media_device *mdev = chip->media_dev;
> +	struct media_mixer_ctl *mctl;
> +	u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
> +	int ret;
> +
> +	if (!mdev)
> +		return -ENODEV;
> +
> +	ctl_intf = chip->ctl_intf_media_devnode;
> +	if (!ctl_intf) {
> +		ctl_intf = (void *) media_devnode_create(mdev,
> +							 intf_type, 0,
> +							 MAJOR(ctl_dev->devt),
> +							 MINOR(ctl_dev->devt));
> +		if (!ctl_intf)
> +			return -ENOMEM;
> +		chip->ctl_intf_media_devnode = ctl_intf;
> +	}
> +
> +	list_for_each_entry(mixer, &chip->mixer_list, list) {
> +
> +		if (mixer->media_mixer_ctl)
> +			continue;
> +
> +		/* allocate media_mixer_ctl */
> +		mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
> +		if (!mctl)
> +			return -ENOMEM;
> +
> +		mctl->media_dev = mdev;
> +		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
> +		mctl->media_entity.name = chip->card->mixername;
> +		mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
> +		mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
> +		mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
> +		media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
> +				  mctl->media_pad);
> +		ret =  media_device_register_entity(mctl->media_dev,
> +						    &mctl->media_entity);
> +		if (ret) {
> +			kfree(mctl);
> +			return ret;
> +		}
> +
> +		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
> +							 &ctl_intf->intf,
> +							 MEDIA_LNK_FL_ENABLED);
> +		if (!mctl->intf_link) {
> +			media_device_unregister_entity(&mctl->media_entity);
> +			media_entity_cleanup(&mctl->media_entity);
> +			kfree(mctl);
> +			return -ENOMEM;
> +		}
> +		mctl->intf_devnode = ctl_intf;
> +		mixer->media_mixer_ctl = mctl;
> +	}
> +	return 0;
> +}
> +
> +static void media_mixer_delete(struct snd_usb_audio *chip)
> +{
> +	struct usb_mixer_interface *mixer;
> +	struct media_device *mdev = chip->media_dev;
> +
> +	if (!mdev)
> +		return;
> +
> +	list_for_each_entry(mixer, &chip->mixer_list, list) {
> +		struct media_mixer_ctl *mctl;
> +
> +		mctl = mixer->media_mixer_ctl;
> +		if (!mixer->media_mixer_ctl)
> +			continue;
> +
> +		if (media_devnode_is_registered(&mdev->devnode)) {
> +			media_device_unregister_entity(&mctl->media_entity);
> +			media_entity_cleanup(&mctl->media_entity);
> +		}
> +		kfree(mctl);
> +		mixer->media_mixer_ctl = NULL;
> +	}
> +	if (media_devnode_is_registered(&mdev->devnode))
> +		media_devnode_remove(chip->ctl_intf_media_devnode);
> +	chip->ctl_intf_media_devnode = NULL;
> +}
> +
> +int media_device_create(struct snd_usb_audio *chip,
> +			struct usb_interface *iface)
> +{
> +	struct media_device *mdev;
> +	struct usb_device *usbdev = interface_to_usbdev(iface);
> +	int ret;
> +
> +	mdev = media_device_get_devres(&usbdev->dev);
> +	if (!mdev)
> +		return -ENOMEM;
> +	if (!mdev->dev) {
> +		/* register media device */
> +		mdev->dev = &usbdev->dev;
> +		if (usbdev->product)
> +			strlcpy(mdev->model, usbdev->product,
> +				sizeof(mdev->model));
> +		if (usbdev->serial)
> +			strlcpy(mdev->serial, usbdev->serial,
> +				sizeof(mdev->serial));
> +		strcpy(mdev->bus_info, usbdev->devpath);
> +		mdev->hw_revision = le16_to_cpu(usbdev->descriptor.bcdDevice);
> +		media_device_init(mdev);
> +	}
> +	if (!media_devnode_is_registered(&mdev->devnode)) {
> +		ret = media_device_register(mdev);
> +		if (ret) {
> +			dev_err(&usbdev->dev,
> +				"Couldn't register media device. Error: %d\n",
> +				ret);
> +			return ret;
> +		}
> +	}
> +
> +	/* save media device - avoid lookups */
> +	chip->media_dev = mdev;
> +
> +	/* Create media entities for mixer and control dev */
> +	ret = media_mixer_init(chip);
> +	if (ret) {
> +		dev_err(&usbdev->dev,
> +			"Couldn't create media mixer entities. Error: %d\n",
> +			ret);
> +
> +		/* clear saved media_dev */
> +		chip->media_dev = NULL;
> +
> +		return ret;
> +	}
> +	return 0;
> +}
> +
> +void media_device_delete(struct snd_usb_audio *chip)
> +{
> +	struct media_device *mdev = chip->media_dev;
> +
> +	media_mixer_delete(chip);
> +
> +	if (mdev) {
> +		if (media_devnode_is_registered(&mdev->devnode))
> +			media_device_unregister(mdev);
> +		chip->media_dev = NULL;
> +	}
> +}
> diff --git a/sound/usb/media.h b/sound/usb/media.h
> new file mode 100644
> index 0000000..b5f451a
> --- /dev/null
> +++ b/sound/usb/media.h
> @@ -0,0 +1,72 @@
> +/*
> + * media.h - Media Controller specific ALSA driver code
> + *
> + * Copyright (c) 2015 Shuah Khan <shuahkh@osg.samsung.com>
> + * Copyright (c) 2015 Samsung Electronics Co., Ltd.
> + *
> + * This file is released under the GPLv2.
> + */
> +
> +/*
> + * This file adds Media Controller support to ALSA driver
> + * to use the Media Controller API to share tuner with DVB
> + * and V4L2 drivers that control media device. Media device
> + * is created based on existing quirks framework. Using this
> + * approach, the media controller API usage can be added for
> + * a specific device.
> +*/
> +#ifndef __MEDIA_H
> +
> +#ifdef CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER
> +
> +#include <media/media-device.h>
> +#include <media/media-entity.h>
> +#include <sound/asound.h>
> +
> +struct media_ctl {
> +	struct media_device *media_dev;
> +	struct media_entity media_entity;
> +	struct media_intf_devnode *intf_devnode;
> +	struct media_link *intf_link;
> +	struct media_pad media_pad;
> +	struct media_pipeline media_pipe;
> +};
> +
> +/*
> + * One source pad each for SNDRV_PCM_STREAM_CAPTURE and
> + * SNDRV_PCM_STREAM_PLAYBACK. One for sink pad to link
> + * to AUDIO Source
> +*/
> +#define MEDIA_MIXER_PAD_MAX    (SNDRV_PCM_STREAM_LAST + 2)
> +
> +struct media_mixer_ctl {
> +	struct media_device *media_dev;
> +	struct media_entity media_entity;
> +	struct media_intf_devnode *intf_devnode;
> +	struct media_link *intf_link;
> +	struct media_pad media_pad[MEDIA_MIXER_PAD_MAX];
> +	struct media_pipeline media_pipe;
> +};
> +
> +int media_device_create(struct snd_usb_audio *chip,
> +			struct usb_interface *iface);
> +void media_device_delete(struct snd_usb_audio *chip);
> +int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
> +			int stream);
> +void media_stream_delete(struct snd_usb_substream *subs);
> +int media_start_pipeline(struct snd_usb_substream *subs);
> +void media_stop_pipeline(struct snd_usb_substream *subs);
> +#else
> +static inline int media_device_create(struct snd_usb_audio *chip,
> +				      struct usb_interface *iface)
> +						{ return 0; }
> +static inline void media_device_delete(struct snd_usb_audio *chip) { }
> +static inline int media_stream_init(struct snd_usb_substream *subs,
> +					struct snd_pcm *pcm, int stream)
> +						{ return 0; }
> +static inline void media_stream_delete(struct snd_usb_substream *subs) { }
> +static inline int media_start_pipeline(struct snd_usb_substream *subs)
> +					{ return 0; }
> +static inline void media_stop_pipeline(struct snd_usb_substream *subs) { }
> +#endif
> +#endif /* __MEDIA_H */
> diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
> index 3417ef3..787b352 100644
> --- a/sound/usb/mixer.h
> +++ b/sound/usb/mixer.h
> @@ -22,6 +22,7 @@ struct usb_mixer_interface {
>  	struct urb *rc_urb;
>  	struct usb_ctrlrequest *rc_setup_packet;
>  	u8 rc_buffer[6];
> +	void *media_mixer_ctl;
>  };
>  
>  #define MAX_CHANNELS	16	/* max logical channels */
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index 9245f52..c3b8486 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -35,6 +35,7 @@
>  #include "pcm.h"
>  #include "clock.h"
>  #include "power.h"
> +#include "media.h"
>  
>  #define SUBSTREAM_FLAG_DATA_EP_STARTED	0
>  #define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
> @@ -715,10 +716,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
>  	struct audioformat *fmt;
>  	int ret;
>  
> +	ret = media_start_pipeline(subs);
> +	if (ret)
> +		return ret;
> +
>  	ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
>  					       params_buffer_bytes(hw_params));
>  	if (ret < 0)
> -		return ret;
> +		goto err_ret;
>  
>  	subs->pcm_format = params_format(hw_params);
>  	subs->period_bytes = params_period_bytes(hw_params);
> @@ -732,22 +737,27 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
>  		dev_dbg(&subs->dev->dev,
>  			"cannot set format: format = %#x, rate = %d, channels = %d\n",
>  			   subs->pcm_format, subs->cur_rate, subs->channels);
> -		return -EINVAL;
> +		ret = -EINVAL;
> +		goto err_ret;
>  	}
>  
>  	ret = snd_usb_lock_shutdown(subs->stream->chip);
>  	if (ret < 0)
> -		return ret;
> +		goto err_ret;
>  	ret = set_format(subs, fmt);
>  	snd_usb_unlock_shutdown(subs->stream->chip);
>  	if (ret < 0)
> -		return ret;
> +		goto err_ret;
>  
>  	subs->interface = fmt->iface;
>  	subs->altset_idx = fmt->altset_idx;
>  	subs->need_setup_ep = true;
>  
>  	return 0;
> +
> +err_ret:
> +	media_stop_pipeline(subs);
> +	return ret;
>  }
>  
>  /*
> @@ -759,6 +769,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
>  {
>  	struct snd_usb_substream *subs = substream->runtime->private_data;
>  
> +	media_stop_pipeline(subs);
>  	subs->cur_audiofmt = NULL;
>  	subs->cur_rate = 0;
>  	subs->period_bytes = 0;
> @@ -1219,6 +1230,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
>  	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
>  	struct snd_pcm_runtime *runtime = substream->runtime;
>  	struct snd_usb_substream *subs = &as->substream[direction];
> +	int ret;
>  
>  	subs->interface = -1;
>  	subs->altset_idx = 0;
> @@ -1232,7 +1244,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
>  	subs->dsd_dop.channel = 0;
>  	subs->dsd_dop.marker = 1;
>  
> -	return setup_hw_info(runtime, subs);
> +	ret = setup_hw_info(runtime, subs);
> +	if (ret == 0)
> +		ret = media_stream_init(subs, as->pcm, direction);
> +	if (ret)
> +		snd_usb_autosuspend(subs->stream->chip);
> +	return ret;
>  }
>  
>  static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
> @@ -1241,6 +1258,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
>  	struct snd_usb_substream *subs = &as->substream[direction];
>  
>  	stop_endpoints(subs, true);
> +	media_stop_pipeline(subs);
>  
>  	if (subs->interface >= 0 &&
>  	    !snd_usb_lock_shutdown(subs->stream->chip)) {
> diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
> index c60a776..9d087b1 100644
> --- a/sound/usb/quirks-table.h
> +++ b/sound/usb/quirks-table.h
> @@ -2886,6 +2886,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
>  		.product_name = pname, \
>  		.ifnum = QUIRK_ANY_INTERFACE, \
>  		.type = QUIRK_AUDIO_ALIGN_TRANSFER, \
> +		.media_device = 1, \
>  	} \
>  }
>  
> diff --git a/sound/usb/stream.c b/sound/usb/stream.c
> index c4dc577..6c7f5c1 100644
> --- a/sound/usb/stream.c
> +++ b/sound/usb/stream.c
> @@ -36,6 +36,7 @@
>  #include "format.h"
>  #include "clock.h"
>  #include "stream.h"
> +#include "media.h"
>  
>  /*
>   * free a substream
> @@ -52,6 +53,7 @@ static void free_substream(struct snd_usb_substream *subs)
>  		kfree(fp);
>  	}
>  	kfree(subs->rate_list.list);
> +	media_stream_delete(subs);
>  }
>  
>  
> diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
> index b665d85..0c0a86c 100644
> --- a/sound/usb/usbaudio.h
> +++ b/sound/usb/usbaudio.h
> @@ -60,6 +60,8 @@ struct snd_usb_audio {
>  	bool autoclock;			/* from the 'autoclock' module param */
>  
>  	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
> +	void *media_dev;
> +	void *ctl_intf_media_devnode;
>  };
>  
>  #define usb_audio_err(chip, fmt, args...) \
> @@ -110,6 +112,7 @@ struct snd_usb_audio_quirk {
>  	const char *product_name;
>  	int16_t ifnum;
>  	uint16_t type;
> +	bool media_device;
>  	const void *data;
>  };
>  

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 22/22] media: Ensure media device unregister is done only once
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-04 10:40     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:40 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:54 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> media_device_unregister() checks if the media device
> is registered or not as the first step. However, the
> MEDIA_FLAG_REGISTERED bit doesn't get cleared until
> the end leaving a large window for two drivers to
> attempt media device unregister.
> 
> The above leads to general protection faults when
> device is removed.
> 
> Fix the problem with two phase media device unregister.
> Add a new interface media_devnode_start_unregister()
> to clear the MEDIA_FLAG_REGISTERED bit. Change
> media_device_unregister() call this interface to mark
> the start of unregister. This will ensure that media
> device unregister is done only once.

Hmm... it sounds simpler to use a kref at device register
and when other drivers need instantiate media_dev. We can
then do a kref_put() at unregister, and run the actual
unregister code and media_ctl kfree only when kref is
decremented on all drivers.

Regards,
Mauro
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-device.c  | 12 ++++++------
>  drivers/media/media-devnode.c | 15 ++++++++++-----
>  include/media/media-devnode.h | 17 +++++++++++++++++
>  3 files changed, 33 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> index 1f5d67e..584d46e 100644
> --- a/drivers/media/media-device.c
> +++ b/drivers/media/media-device.c
> @@ -747,17 +747,17 @@ void media_device_unregister(struct media_device *mdev)
>  	struct media_entity *next;
>  	struct media_interface *intf, *tmp_intf;
>  	struct media_entity_notify *notify, *nextp;
> +	int ret;
>  
>  	if (mdev == NULL)
>  		return;
>  
> -	spin_lock(&mdev->lock);
> -
> -	/* Check if mdev was ever registered at all */
> -	if (!media_devnode_is_registered(&mdev->devnode)) {
> -		spin_unlock(&mdev->lock);
> +	/* Start unregister - continue if necessary */
> +	ret = media_devnode_start_unregister(&mdev->devnode);
> +	if (ret)
>  		return;
> -	}
> +
> +	spin_lock(&mdev->lock);
>  
>  	/* Remove all entities from the media device */
>  	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
> diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
> index 29409f4..c27f9e7 100644
> --- a/drivers/media/media-devnode.c
> +++ b/drivers/media/media-devnode.c
> @@ -272,15 +272,20 @@ error:
>  	return ret;
>  }
>  
> -void media_devnode_unregister(struct media_devnode *mdev)
> +int __must_check media_devnode_start_unregister(struct media_devnode *mdev)
>  {
> -	/* Check if mdev was ever registered at all */
> -	if (!media_devnode_is_registered(mdev))
> -		return;
> -
>  	mutex_lock(&media_devnode_lock);
> +	if (!media_devnode_is_registered(mdev)) {
> +		mutex_unlock(&media_devnode_lock);
> +		return -EINVAL;
> +	}
>  	clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
>  	mutex_unlock(&media_devnode_lock);
> +	return 0;
> +}
> +
> +void media_devnode_unregister(struct media_devnode *mdev)
> +{
>  	device_unregister(&mdev->dev);
>  }
>  
> diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
> index fe42f08..6f08677 100644
> --- a/include/media/media-devnode.h
> +++ b/include/media/media-devnode.h
> @@ -120,6 +120,23 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
>  					struct module *owner);
>  
>  /**
> + * media_devnode_start_unregister - start unregister on a media device node
> + * @mdev: the device node to start unregister
> + *
> + * This clears the MEDIA_FLAG_REGISTERED bit to indicate that unregister
> + * is in progress.
> + *
> + * This function can safely be called if the device node has never been
> + * registered or has already been unregistered.
> + *
> + * Zero is returned on success.
> + *
> + * -EINVAL is returned if the device node has never been
> + * registered or has already been unregistered.
> + */
> +int __must_check media_devnode_start_unregister(struct media_devnode *mdev);
> +
> +/**
>   * media_devnode_unregister - unregister a media device node
>   * @mdev: the device node to unregister
>   *

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 22/22] media: Ensure media device unregister is done only once
@ 2016-02-04 10:40     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:40 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:54 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> media_device_unregister() checks if the media device
> is registered or not as the first step. However, the
> MEDIA_FLAG_REGISTERED bit doesn't get cleared until
> the end leaving a large window for two drivers to
> attempt media device unregister.
> 
> The above leads to general protection faults when
> device is removed.
> 
> Fix the problem with two phase media device unregister.
> Add a new interface media_devnode_start_unregister()
> to clear the MEDIA_FLAG_REGISTERED bit. Change
> media_device_unregister() call this interface to mark
> the start of unregister. This will ensure that media
> device unregister is done only once.

Hmm... it sounds simpler to use a kref at device register
and when other drivers need instantiate media_dev. We can
then do a kref_put() at unregister, and run the actual
unregister code and media_ctl kfree only when kref is
decremented on all drivers.

Regards,
Mauro
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
>  drivers/media/media-device.c  | 12 ++++++------
>  drivers/media/media-devnode.c | 15 ++++++++++-----
>  include/media/media-devnode.h | 17 +++++++++++++++++
>  3 files changed, 33 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> index 1f5d67e..584d46e 100644
> --- a/drivers/media/media-device.c
> +++ b/drivers/media/media-device.c
> @@ -747,17 +747,17 @@ void media_device_unregister(struct media_device *mdev)
>  	struct media_entity *next;
>  	struct media_interface *intf, *tmp_intf;
>  	struct media_entity_notify *notify, *nextp;
> +	int ret;
>  
>  	if (mdev == NULL)
>  		return;
>  
> -	spin_lock(&mdev->lock);
> -
> -	/* Check if mdev was ever registered at all */
> -	if (!media_devnode_is_registered(&mdev->devnode)) {
> -		spin_unlock(&mdev->lock);
> +	/* Start unregister - continue if necessary */
> +	ret = media_devnode_start_unregister(&mdev->devnode);
> +	if (ret)
>  		return;
> -	}
> +
> +	spin_lock(&mdev->lock);
>  
>  	/* Remove all entities from the media device */
>  	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
> diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
> index 29409f4..c27f9e7 100644
> --- a/drivers/media/media-devnode.c
> +++ b/drivers/media/media-devnode.c
> @@ -272,15 +272,20 @@ error:
>  	return ret;
>  }
>  
> -void media_devnode_unregister(struct media_devnode *mdev)
> +int __must_check media_devnode_start_unregister(struct media_devnode *mdev)
>  {
> -	/* Check if mdev was ever registered at all */
> -	if (!media_devnode_is_registered(mdev))
> -		return;
> -
>  	mutex_lock(&media_devnode_lock);
> +	if (!media_devnode_is_registered(mdev)) {
> +		mutex_unlock(&media_devnode_lock);
> +		return -EINVAL;
> +	}
>  	clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
>  	mutex_unlock(&media_devnode_lock);
> +	return 0;
> +}
> +
> +void media_devnode_unregister(struct media_devnode *mdev)
> +{
>  	device_unregister(&mdev->dev);
>  }
>  
> diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
> index fe42f08..6f08677 100644
> --- a/include/media/media-devnode.h
> +++ b/include/media/media-devnode.h
> @@ -120,6 +120,23 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
>  					struct module *owner);
>  
>  /**
> + * media_devnode_start_unregister - start unregister on a media device node
> + * @mdev: the device node to start unregister
> + *
> + * This clears the MEDIA_FLAG_REGISTERED bit to indicate that unregister
> + * is in progress.
> + *
> + * This function can safely be called if the device node has never been
> + * registered or has already been unregistered.
> + *
> + * Zero is returned on success.
> + *
> + * -EINVAL is returned if the device node has never been
> + * registered or has already been unregistered.
> + */
> +int __must_check media_devnode_start_unregister(struct media_devnode *mdev);
> +
> +/**
>   * media_devnode_unregister - unregister a media device node
>   * @mdev: the device node to unregister
>   *

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
  2016-02-04 10:36     ` Mauro Carvalho Chehab
@ 2016-02-04 10:46       ` Takashi Iwai
  -1 siblings, 0 replies; 94+ messages in thread
From: Takashi Iwai @ 2016-02-04 10:46 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Shuah Khan, geliangtang, alsa-devel, arnd, ricard.wanderlof,
	hans.verkuil, labbott, chehabrafael, klock.android, misterpib,
	prabhakar.csengg, ricardo.ribalda, ruchandani.tina, takamichiho,
	tvboxspy, dominic.sacre, laurent.pinchart, crope, julian,
	clemens, pierre-louis.bossart, sakari.ailus, corbet, joe, johan,
	dan.carpenter, pawel, javier, p.zabel, perex, stefanr, inki.dae,
	j.anaszewski, jh1009.sung, k.kozlowski, kyungmin.park,
	m.szyprowski, nenggun.kim, sw0312.kim, elfring, linux-api,
	linux-kernel, linux-media, linuxbugs, gtmkramer, normalperson,
	daniel

On Thu, 04 Feb 2016 11:36:00 +0100,
Mauro Carvalho Chehab wrote:
> 
> > diff --git a/sound/usb/card.h b/sound/usb/card.h
> > index 71778ca..c15a03c 100644
> > --- a/sound/usb/card.h
> > +++ b/sound/usb/card.h
> > @@ -156,6 +156,7 @@ struct snd_usb_substream {
> >  	} dsd_dop;
> >  
> >  	bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
> > +	void *media_ctl;
> >  };
> 
> This is Takashi's call, but I would prefer to avoid using a void *
> here. Fortunately, GCC is smart enough to handle struct pointers
> even if the header doesn't have a full declaration of the struct.
> 
> So, I would change the above to:
> 
> struct media_device;
> 
> struct snd_usb_substream {
> ...
> 	struct media_device *media_ctl;
> };
> 
> This way, we ensure strong typecast checks when compiling the code under
> sound/usb/media.c, while not needing to include media_device.h header here.

Agreed, this is no big merit to make it a void pointer.


Takashi

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
@ 2016-02-04 10:46       ` Takashi Iwai
  0 siblings, 0 replies; 94+ messages in thread
From: Takashi Iwai @ 2016-02-04 10:46 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Shuah Khan, geliangtang, alsa-devel, arnd, ricard.wanderlof,
	hans.verkuil, labbott, chehabrafael, klock.android, misterpib,
	prabhakar.csengg, ricardo.ribalda, ruchandani.tina, takamichiho,
	tvboxspy, dominic.sacre, laurent.pinchart, crope, julian,
	clemens, pierre-louis.bossart, sakari.ailus, corbet, joe, johan,
	dan.carpenter, pawel, javier, p.zabel, perex, stefanr, inki.dae,
	j.anaszewski, jh1009.sung

On Thu, 04 Feb 2016 11:36:00 +0100,
Mauro Carvalho Chehab wrote:
> 
> > diff --git a/sound/usb/card.h b/sound/usb/card.h
> > index 71778ca..c15a03c 100644
> > --- a/sound/usb/card.h
> > +++ b/sound/usb/card.h
> > @@ -156,6 +156,7 @@ struct snd_usb_substream {
> >  	} dsd_dop;
> >  
> >  	bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
> > +	void *media_ctl;
> >  };
> 
> This is Takashi's call, but I would prefer to avoid using a void *
> here. Fortunately, GCC is smart enough to handle struct pointers
> even if the header doesn't have a full declaration of the struct.
> 
> So, I would change the above to:
> 
> struct media_device;
> 
> struct snd_usb_substream {
> ...
> 	struct media_device *media_ctl;
> };
> 
> This way, we ensure strong typecast checks when compiling the code under
> sound/usb/media.c, while not needing to include media_device.h header here.

Agreed, this is no big merit to make it a void pointer.


Takashi

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 00/22] Sharing media resources across ALSA and au0828 drivers
  2016-02-04  4:03 ` Shuah Khan
@ 2016-02-04 10:54   ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:54 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, linux-api,
	alsa-devel

Em Wed, 03 Feb 2016 21:03:32 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> This patch series updates ALSA driver, and au0828 core
> driver to use Managed Media controller API and Media
> Controller API to share media resource (tuner).

Please see my comments to patch 20. I guess this series break support
for the digital-only boards below (where .has_analog is not set):

	[AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
		.name	= "Hauppauge HVR950Q rev xxF8",
		.tuner_type = TUNER_XC5000,
		.tuner_addr = 0x61,
		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
	},
	[AU0828_BOARD_DVICO_FUSIONHDTV7] = {
		.name	= "DViCO FusionHDTV USB",
		.tuner_type = TUNER_XC5000,
		.tuner_addr = 0x61,
		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
	},
	[AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
		.name = "Hauppauge Woodbury",
		.tuner_type = TUNER_NXP_TDA18271,
		.tuner_addr = 0x60,
		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
	},

None of this boards have V4L2. So, only the DVB part of the driver
should be enabled. Well, the DVB core won't be creating a tuner
subdev. So, calling au0828_enable_source() (and disable source) would
return -ENODEV, causing the driver to fail.

> 
> This Patch v2 series is based on linux_media master.
> This work addresses Mauro and Takashi's comments.

It is in a way better shape, but there are still several things I
noticed :)

Please see my per-patch review.

> 
> Composite or S-Video connector is the input case
> is still under discussion and isn't addressed in
> this series.

You need at least address pure DVB boards at patch 20 and
add there a FIXME for the composite/svideo connector pending 
issue.

> 
> Patches 3 and 4 need documentation updates and will
> be sent later this week.

Please send documentation at the same series. Nobody wants to see the
documentation warnings when checking at the main media development
branch or at -next. Also, it helps to better understand the changes.

Regards,
Mauro

> 
> Shuah Khan (22):
>   uapi/media.h: Declare interface types for ALSA
>   media: Add ALSA Media Controller function entities
>   media: Media Controller register/unregister entity_notify API
>   media: Media Controller enable/disable source handler API
>   media: Media Controller export non locking __media_entity_setup_link()
>   media: Media Controller non-locking
>     __media_entity_pipeline_start/stop()
>   media: v4l-core add enable/disable source common interfaces
>   media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
>   media: au8522 change to create MC pad for ALSA Audio Out
>   media: Change v4l-core to check if source is free
>   media: dvb-frontend invoke enable/disable_source handlers
>   media: au0828 video remove au0828_enable_analog_tuner()
>   media: au0828 video change to use v4l_enable_media_source()
>   media: au0828 change to use Managed Media Controller API
>   media: au0828 handle media_init and media_register window
>   media: au0828 create tuner to decoder link in disabled state
>   media: au0828 disable tuner to demod link
>   media: au0828 Use au8522_media_pads enum for pad defines
>   media: au0828-core register entity_notify hook
>   media: au0828 add enable, disable source handlers
>   sound/usb: Use Media Controller API to share media resources
>   media: Ensure media device unregister is done only once
> 
>  drivers/media/dvb-core/dvb_frontend.c        | 139 ++----------
>  drivers/media/dvb-core/dvb_frontend.h        |   3 +
>  drivers/media/dvb-frontends/au8522.h         |   8 +
>  drivers/media/dvb-frontends/au8522_decoder.c |   1 +
>  drivers/media/dvb-frontends/au8522_priv.h    |   8 -
>  drivers/media/media-device.c                 |  73 +++++-
>  drivers/media/media-devnode.c                |  15 +-
>  drivers/media/media-entity.c                 |  51 ++++-
>  drivers/media/usb/au0828/au0828-core.c       | 272 +++++++++++++++++++++--
>  drivers/media/usb/au0828/au0828-video.c      |  75 +------
>  drivers/media/usb/au0828/au0828.h            |   4 +
>  drivers/media/v4l2-core/Makefile             |   2 +-
>  drivers/media/v4l2-core/v4l2-fh.c            |   2 +
>  drivers/media/v4l2-core/v4l2-ioctl.c         |  30 +++
>  drivers/media/v4l2-core/v4l2-mc.c            |  60 +++++
>  drivers/media/v4l2-core/videobuf2-core.c     |   4 +
>  include/media/media-device.h                 |  44 ++++
>  include/media/media-devnode.h                |  17 ++
>  include/media/media-entity.h                 |  12 +
>  include/media/v4l2-dev.h                     |   1 +
>  include/media/v4l2-mc.h                      |  52 +++++
>  include/uapi/linux/media.h                   |  33 +++
>  sound/usb/Kconfig                            |   4 +
>  sound/usb/Makefile                           |   2 +
>  sound/usb/card.c                             |  14 ++
>  sound/usb/card.h                             |   1 +
>  sound/usb/media.c                            | 319 +++++++++++++++++++++++++++
>  sound/usb/media.h                            |  72 ++++++
>  sound/usb/mixer.h                            |   1 +
>  sound/usb/pcm.c                              |  28 ++-
>  sound/usb/quirks-table.h                     |   1 +
>  sound/usb/stream.c                           |   2 +
>  sound/usb/usbaudio.h                         |   3 +
>  33 files changed, 1117 insertions(+), 236 deletions(-)
>  create mode 100644 drivers/media/v4l2-core/v4l2-mc.c
>  create mode 100644 sound/usb/media.c
>  create mode 100644 sound/usb/media.h
> 

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 00/22] Sharing media resources across ALSA and au0828 drivers
@ 2016-02-04 10:54   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-04 10:54 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Wed, 03 Feb 2016 21:03:32 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> This patch series updates ALSA driver, and au0828 core
> driver to use Managed Media controller API and Media
> Controller API to share media resource (tuner).

Please see my comments to patch 20. I guess this series break support
for the digital-only boards below (where .has_analog is not set):

	[AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
		.name	= "Hauppauge HVR950Q rev xxF8",
		.tuner_type = TUNER_XC5000,
		.tuner_addr = 0x61,
		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
	},
	[AU0828_BOARD_DVICO_FUSIONHDTV7] = {
		.name	= "DViCO FusionHDTV USB",
		.tuner_type = TUNER_XC5000,
		.tuner_addr = 0x61,
		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
	},
	[AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
		.name = "Hauppauge Woodbury",
		.tuner_type = TUNER_NXP_TDA18271,
		.tuner_addr = 0x60,
		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
	},

None of this boards have V4L2. So, only the DVB part of the driver
should be enabled. Well, the DVB core won't be creating a tuner
subdev. So, calling au0828_enable_source() (and disable source) would
return -ENODEV, causing the driver to fail.

> 
> This Patch v2 series is based on linux_media master.
> This work addresses Mauro and Takashi's comments.

It is in a way better shape, but there are still several things I
noticed :)

Please see my per-patch review.

> 
> Composite or S-Video connector is the input case
> is still under discussion and isn't addressed in
> this series.

You need at least address pure DVB boards at patch 20 and
add there a FIXME for the composite/svideo connector pending 
issue.

> 
> Patches 3 and 4 need documentation updates and will
> be sent later this week.

Please send documentation at the same series. Nobody wants to see the
documentation warnings when checking at the main media development
branch or at -next. Also, it helps to better understand the changes.

Regards,
Mauro

> 
> Shuah Khan (22):
>   uapi/media.h: Declare interface types for ALSA
>   media: Add ALSA Media Controller function entities
>   media: Media Controller register/unregister entity_notify API
>   media: Media Controller enable/disable source handler API
>   media: Media Controller export non locking __media_entity_setup_link()
>   media: Media Controller non-locking
>     __media_entity_pipeline_start/stop()
>   media: v4l-core add enable/disable source common interfaces
>   media: Move au8522_media_pads enum to au8522.h from au8522_priv.h
>   media: au8522 change to create MC pad for ALSA Audio Out
>   media: Change v4l-core to check if source is free
>   media: dvb-frontend invoke enable/disable_source handlers
>   media: au0828 video remove au0828_enable_analog_tuner()
>   media: au0828 video change to use v4l_enable_media_source()
>   media: au0828 change to use Managed Media Controller API
>   media: au0828 handle media_init and media_register window
>   media: au0828 create tuner to decoder link in disabled state
>   media: au0828 disable tuner to demod link
>   media: au0828 Use au8522_media_pads enum for pad defines
>   media: au0828-core register entity_notify hook
>   media: au0828 add enable, disable source handlers
>   sound/usb: Use Media Controller API to share media resources
>   media: Ensure media device unregister is done only once
> 
>  drivers/media/dvb-core/dvb_frontend.c        | 139 ++----------
>  drivers/media/dvb-core/dvb_frontend.h        |   3 +
>  drivers/media/dvb-frontends/au8522.h         |   8 +
>  drivers/media/dvb-frontends/au8522_decoder.c |   1 +
>  drivers/media/dvb-frontends/au8522_priv.h    |   8 -
>  drivers/media/media-device.c                 |  73 +++++-
>  drivers/media/media-devnode.c                |  15 +-
>  drivers/media/media-entity.c                 |  51 ++++-
>  drivers/media/usb/au0828/au0828-core.c       | 272 +++++++++++++++++++++--
>  drivers/media/usb/au0828/au0828-video.c      |  75 +------
>  drivers/media/usb/au0828/au0828.h            |   4 +
>  drivers/media/v4l2-core/Makefile             |   2 +-
>  drivers/media/v4l2-core/v4l2-fh.c            |   2 +
>  drivers/media/v4l2-core/v4l2-ioctl.c         |  30 +++
>  drivers/media/v4l2-core/v4l2-mc.c            |  60 +++++
>  drivers/media/v4l2-core/videobuf2-core.c     |   4 +
>  include/media/media-device.h                 |  44 ++++
>  include/media/media-devnode.h                |  17 ++
>  include/media/media-entity.h                 |  12 +
>  include/media/v4l2-dev.h                     |   1 +
>  include/media/v4l2-mc.h                      |  52 +++++
>  include/uapi/linux/media.h                   |  33 +++
>  sound/usb/Kconfig                            |   4 +
>  sound/usb/Makefile                           |   2 +
>  sound/usb/card.c                             |  14 ++
>  sound/usb/card.h                             |   1 +
>  sound/usb/media.c                            | 319 +++++++++++++++++++++++++++
>  sound/usb/media.h                            |  72 ++++++
>  sound/usb/mixer.h                            |   1 +
>  sound/usb/pcm.c                              |  28 ++-
>  sound/usb/quirks-table.h                     |   1 +
>  sound/usb/stream.c                           |   2 +
>  sound/usb/usbaudio.h                         |   3 +
>  33 files changed, 1117 insertions(+), 236 deletions(-)
>  create mode 100644 drivers/media/v4l2-core/v4l2-mc.c
>  create mode 100644 sound/usb/media.c
>  create mode 100644 sound/usb/media.h
> 

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner()
  2016-02-04  9:37     ` Mauro Carvalho Chehab
@ 2016-02-04 14:49       ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04 14:49 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel,
	Shuah Khan

On 02/04/2016 02:37 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:44 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Remove au0828_enable_analog_tuner() as it is
>> no longer needed because v4l2-core implements
>> common interfaces to check for media source
>> availability.
> 
> I didn't see such code at v4l2-core yet. Missing patch?

Removed linux-api from cc:

Please see Patch 10/22 for v4l2-core changes.
[PATCH v2 10/22] media: Change v4l-core to check if source is free

thanks,
-- Shuah

> 
>>
>> In addition, queue_setup() no longer needs the
>> tuner availability check since v4l2-core does it.
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
>>  1 file changed, 61 deletions(-)
>>
>> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
>> index 8c54fd2..81952c8 100644
>> --- a/drivers/media/usb/au0828/au0828-video.c
>> +++ b/drivers/media/usb/au0828/au0828-video.c
>> @@ -638,64 +638,6 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
>>  	return rc;
>>  }
>>  
>> -static int au0828_enable_analog_tuner(struct au0828_dev *dev)
>> -{
>> -#ifdef CONFIG_MEDIA_CONTROLLER
>> -	struct media_device *mdev = dev->media_dev;
>> -	struct media_entity *source;
>> -	struct media_link *link, *found_link = NULL;
>> -	int ret, active_links = 0;
>> -
>> -	if (!mdev || !dev->decoder)
>> -		return 0;
>> -
>> -	/*
>> -	 * This will find the tuner that is connected into the decoder.
>> -	 * Technically, this is not 100% correct, as the device may be
>> -	 * using an analog input instead of the tuner. However, as we can't
>> -	 * do DVB streaming while the DMA engine is being used for V4L2,
>> -	 * this should be enough for the actual needs.
>> -	 */
>> -	list_for_each_entry(link, &dev->decoder->links, list) {
>> -		if (link->sink->entity == dev->decoder) {
>> -			found_link = link;
>> -			if (link->flags & MEDIA_LNK_FL_ENABLED)
>> -				active_links++;
>> -			break;
>> -		}
>> -	}
>> -
>> -	if (active_links == 1 || !found_link)
>> -		return 0;
>> -
>> -	source = found_link->source->entity;
>> -	list_for_each_entry(link, &source->links, list) {
>> -		struct media_entity *sink;
>> -		int flags = 0;
>> -
>> -		sink = link->sink->entity;
>> -
>> -		if (sink == dev->decoder)
>> -			flags = MEDIA_LNK_FL_ENABLED;
>> -
>> -		ret = media_entity_setup_link(link, flags);
>> -		if (ret) {
>> -			pr_err(
>> -				"Couldn't change link %s->%s to %s. Error %d\n",
>> -				source->name, sink->name,
>> -				flags ? "enabled" : "disabled",
>> -				ret);
>> -			return ret;
>> -		} else
>> -			au0828_isocdbg(
>> -				"link %s->%s was %s\n",
>> -				source->name, sink->name,
>> -				flags ? "ENABLED" : "disabled");
>> -	}
>> -#endif
>> -	return 0;
>> -}
>> -
>>  static int queue_setup(struct vb2_queue *vq,
>>  		       unsigned int *nbuffers, unsigned int *nplanes,
>>  		       unsigned int sizes[], void *alloc_ctxs[])
>> @@ -707,9 +649,6 @@ static int queue_setup(struct vb2_queue *vq,
>>  		return sizes[0] < size ? -EINVAL : 0;
>>  	*nplanes = 1;
>>  	sizes[0] = size;
>> -
>> -	au0828_enable_analog_tuner(dev);
>> -
>>  	return 0;
>>  }
>>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner()
@ 2016-02-04 14:49       ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04 14:49 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

On 02/04/2016 02:37 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:44 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Remove au0828_enable_analog_tuner() as it is
>> no longer needed because v4l2-core implements
>> common interfaces to check for media source
>> availability.
> 
> I didn't see such code at v4l2-core yet. Missing patch?

Removed linux-api from cc:

Please see Patch 10/22 for v4l2-core changes.
[PATCH v2 10/22] media: Change v4l-core to check if source is free

thanks,
-- Shuah

> 
>>
>> In addition, queue_setup() no longer needs the
>> tuner availability check since v4l2-core does it.
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/usb/au0828/au0828-video.c | 61 ---------------------------------
>>  1 file changed, 61 deletions(-)
>>
>> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
>> index 8c54fd2..81952c8 100644
>> --- a/drivers/media/usb/au0828/au0828-video.c
>> +++ b/drivers/media/usb/au0828/au0828-video.c
>> @@ -638,64 +638,6 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
>>  	return rc;
>>  }
>>  
>> -static int au0828_enable_analog_tuner(struct au0828_dev *dev)
>> -{
>> -#ifdef CONFIG_MEDIA_CONTROLLER
>> -	struct media_device *mdev = dev->media_dev;
>> -	struct media_entity *source;
>> -	struct media_link *link, *found_link = NULL;
>> -	int ret, active_links = 0;
>> -
>> -	if (!mdev || !dev->decoder)
>> -		return 0;
>> -
>> -	/*
>> -	 * This will find the tuner that is connected into the decoder.
>> -	 * Technically, this is not 100% correct, as the device may be
>> -	 * using an analog input instead of the tuner. However, as we can't
>> -	 * do DVB streaming while the DMA engine is being used for V4L2,
>> -	 * this should be enough for the actual needs.
>> -	 */
>> -	list_for_each_entry(link, &dev->decoder->links, list) {
>> -		if (link->sink->entity == dev->decoder) {
>> -			found_link = link;
>> -			if (link->flags & MEDIA_LNK_FL_ENABLED)
>> -				active_links++;
>> -			break;
>> -		}
>> -	}
>> -
>> -	if (active_links == 1 || !found_link)
>> -		return 0;
>> -
>> -	source = found_link->source->entity;
>> -	list_for_each_entry(link, &source->links, list) {
>> -		struct media_entity *sink;
>> -		int flags = 0;
>> -
>> -		sink = link->sink->entity;
>> -
>> -		if (sink == dev->decoder)
>> -			flags = MEDIA_LNK_FL_ENABLED;
>> -
>> -		ret = media_entity_setup_link(link, flags);
>> -		if (ret) {
>> -			pr_err(
>> -				"Couldn't change link %s->%s to %s. Error %d\n",
>> -				source->name, sink->name,
>> -				flags ? "enabled" : "disabled",
>> -				ret);
>> -			return ret;
>> -		} else
>> -			au0828_isocdbg(
>> -				"link %s->%s was %s\n",
>> -				source->name, sink->name,
>> -				flags ? "ENABLED" : "disabled");
>> -	}
>> -#endif
>> -	return 0;
>> -}
>> -
>>  static int queue_setup(struct vb2_queue *vq,
>>  		       unsigned int *nbuffers, unsigned int *nplanes,
>>  		       unsigned int sizes[], void *alloc_ctxs[])
>> @@ -707,9 +649,6 @@ static int queue_setup(struct vb2_queue *vq,
>>  		return sizes[0] < size ? -EINVAL : 0;
>>  	*nplanes = 1;
>>  	sizes[0] = size;
>> -
>> -	au0828_enable_analog_tuner(dev);
>> -
>>  	return 0;
>>  }
>>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers
  2016-02-04  9:35     ` Mauro Carvalho Chehab
@ 2016-02-04 14:58       ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04 14:58 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel,
	Shuah Khan

On 02/04/2016 02:35 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:43 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Change dvb frontend to check if tuner is free when
>> device opened in RW mode. Call to enable_source
>> handler either returns with an active pipeline to
>> tuner or error if tuner is busy. Tuner is released
>> when frontend is released calling the disable_source
>> handler.
> 
> This patch seems too early in the series, as I'm not seeing any patch
> providing a replacement for the removed code yet.

Removed linux-api from cc:

Yes you are right - I will move this after au0828 patch
that adds the handler.

> 
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
>>  drivers/media/dvb-core/dvb_frontend.h |   3 +
>>  2 files changed, 24 insertions(+), 118 deletions(-)
>>
>> diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
>> index 03cc508..2b17e8b 100644
>> --- a/drivers/media/dvb-core/dvb_frontend.c
>> +++ b/drivers/media/dvb-core/dvb_frontend.c
>> @@ -131,11 +131,6 @@ struct dvb_frontend_private {
>>  	int quality;
>>  	unsigned int check_wrapped;
>>  	enum dvbfe_search algo_status;
>> -
>> -#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
>> -	struct media_pipeline pipe;
>> -	struct media_entity *pipe_start_entity;
>> -#endif
>>  };
>>  
>>  static void dvb_frontend_wakeup(struct dvb_frontend *fe);
>> @@ -596,104 +591,12 @@ 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.
>> - */
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -static int dvb_enable_media_tuner(struct dvb_frontend *fe)
>> -{
>> -	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 ret, n_links = 0, active_links = 0;
>> -
>> -	fepriv->pipe_start_entity = NULL;
>> -
>> -	if (!mdev)
>> -		return 0;
>> -
>> -	entity = fepriv->dvbdev->entity;
>> -	fepriv->pipe_start_entity = entity;
>> -
>> -	list_for_each_entry(link, &entity->links, list) {
>> -		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;
>> -	fepriv->pipe_start_entity = source;
>> -	list_for_each_entry(link, &source->links, list) {
>> -		struct media_entity *sink;
>> -		int flags = 0;
>> -
>> -		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");
>> -	}
>> -	return 0;
>> -}
>> -#endif
>> -
>>  static int dvb_frontend_thread(void *data)
>>  {
>>  	struct dvb_frontend *fe = data;
>>  	struct dvb_frontend_private *fepriv = fe->frontend_priv;
>>  	enum fe_status s;
>>  	enum dvbfe_algo algo;
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -	int ret;
>> -#endif
>> -
>>  	bool re_tune = false;
>>  	bool semheld = false;
>>  
>> @@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)
>>  	fepriv->wakeup = 0;
>>  	fepriv->reinitialise = 0;
>>  
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -	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");
>> -	} else if (fepriv->pipe_start_entity) {
>> -		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
>> -						  &fepriv->pipe);
>> -		if (ret)
>> -			return ret;
>> -	}
>> -#endif
>> -
>>  	dvb_frontend_init(fe);
>>  
>>  	set_freezable();
>> @@ -829,12 +718,6 @@ restart:
>>  		}
>>  	}
>>  
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -	if (fepriv->pipe_start_entity)
>> -		media_entity_pipeline_stop(fepriv->pipe_start_entity);
>> -	fepriv->pipe_start_entity = NULL;
>> -#endif
>> -
>>  	if (dvb_powerdown_on_sleep) {
>>  		if (fe->ops.set_voltage)
>>  			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
>> @@ -2612,9 +2495,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>>  		fepriv->tone = -1;
>>  		fepriv->voltage = -1;
>>  
>> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> +		if (fe->dvb->mdev && fe->dvb->mdev->enable_source) {
>> +			ret = fe->dvb->mdev->enable_source(dvbdev->entity,
>> +							   &fe->pipe);
>> +			if (ret) {
>> +				dev_err(fe->dvb->device,
>> +					"Tuner is busy. Error %d\n", ret);
>> +				goto err2;
>> +			}
>> +		}
>> +#endif
>>  		ret = dvb_frontend_start (fe);
>>  		if (ret)
>> -			goto err2;
>> +			goto err3;
>>  
>>  		/*  empty event queue */
>>  		fepriv->events.eventr = fepriv->events.eventw = 0;
>> @@ -2624,7 +2518,12 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>>  		mutex_unlock (&adapter->mfe_lock);
>>  	return ret;
>>  
>> +err3:
>> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> +	if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
>> +		fe->dvb->mdev->disable_source(dvbdev->entity);
>>  err2:
>> +#endif
>>  	dvb_generic_release(inode, file);
>>  err1:
>>  	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
>> @@ -2653,6 +2552,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
>>  
>>  	if (dvbdev->users == -1) {
>>  		wake_up(&fepriv->wait_queue);
>> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> +		if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
>> +			fe->dvb->mdev->disable_source(dvbdev->entity);
>> +#endif
>>  		if (fe->exit != DVB_FE_NO_EXIT)
>>  			wake_up(&dvbdev->wait_queue);
>>  		if (fe->ops.ts_bus_ctrl)
>> diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
>> index 458bcce..9466906 100644
>> --- a/drivers/media/dvb-core/dvb_frontend.h
>> +++ b/drivers/media/dvb-core/dvb_frontend.h
>> @@ -686,6 +686,9 @@ struct dvb_frontend {
>>  	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
>>  	int id;
>>  	unsigned int exit;
>> +#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
>> +	struct media_pipeline pipe;
>> +#endif
> 
> Why moving this to the non-private part of the data?
> 

There was a reason for this move and I don't recall
at the moment. It has been several months since I
had to rework. I will make sure this change is
necessary and include it in the changelog.

thanks,
-- Shuah


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers
@ 2016-02-04 14:58       ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04 14:58 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

On 02/04/2016 02:35 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:43 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Change dvb frontend to check if tuner is free when
>> device opened in RW mode. Call to enable_source
>> handler either returns with an active pipeline to
>> tuner or error if tuner is busy. Tuner is released
>> when frontend is released calling the disable_source
>> handler.
> 
> This patch seems too early in the series, as I'm not seeing any patch
> providing a replacement for the removed code yet.

Removed linux-api from cc:

Yes you are right - I will move this after au0828 patch
that adds the handler.

> 
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/dvb-core/dvb_frontend.c | 139 +++++-----------------------------
>>  drivers/media/dvb-core/dvb_frontend.h |   3 +
>>  2 files changed, 24 insertions(+), 118 deletions(-)
>>
>> diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
>> index 03cc508..2b17e8b 100644
>> --- a/drivers/media/dvb-core/dvb_frontend.c
>> +++ b/drivers/media/dvb-core/dvb_frontend.c
>> @@ -131,11 +131,6 @@ struct dvb_frontend_private {
>>  	int quality;
>>  	unsigned int check_wrapped;
>>  	enum dvbfe_search algo_status;
>> -
>> -#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
>> -	struct media_pipeline pipe;
>> -	struct media_entity *pipe_start_entity;
>> -#endif
>>  };
>>  
>>  static void dvb_frontend_wakeup(struct dvb_frontend *fe);
>> @@ -596,104 +591,12 @@ 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.
>> - */
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -static int dvb_enable_media_tuner(struct dvb_frontend *fe)
>> -{
>> -	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 ret, n_links = 0, active_links = 0;
>> -
>> -	fepriv->pipe_start_entity = NULL;
>> -
>> -	if (!mdev)
>> -		return 0;
>> -
>> -	entity = fepriv->dvbdev->entity;
>> -	fepriv->pipe_start_entity = entity;
>> -
>> -	list_for_each_entry(link, &entity->links, list) {
>> -		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;
>> -	fepriv->pipe_start_entity = source;
>> -	list_for_each_entry(link, &source->links, list) {
>> -		struct media_entity *sink;
>> -		int flags = 0;
>> -
>> -		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");
>> -	}
>> -	return 0;
>> -}
>> -#endif
>> -
>>  static int dvb_frontend_thread(void *data)
>>  {
>>  	struct dvb_frontend *fe = data;
>>  	struct dvb_frontend_private *fepriv = fe->frontend_priv;
>>  	enum fe_status s;
>>  	enum dvbfe_algo algo;
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -	int ret;
>> -#endif
>> -
>>  	bool re_tune = false;
>>  	bool semheld = false;
>>  
>> @@ -706,20 +609,6 @@ static int dvb_frontend_thread(void *data)
>>  	fepriv->wakeup = 0;
>>  	fepriv->reinitialise = 0;
>>  
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -	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");
>> -	} else if (fepriv->pipe_start_entity) {
>> -		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
>> -						  &fepriv->pipe);
>> -		if (ret)
>> -			return ret;
>> -	}
>> -#endif
>> -
>>  	dvb_frontend_init(fe);
>>  
>>  	set_freezable();
>> @@ -829,12 +718,6 @@ restart:
>>  		}
>>  	}
>>  
>> -#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> -	if (fepriv->pipe_start_entity)
>> -		media_entity_pipeline_stop(fepriv->pipe_start_entity);
>> -	fepriv->pipe_start_entity = NULL;
>> -#endif
>> -
>>  	if (dvb_powerdown_on_sleep) {
>>  		if (fe->ops.set_voltage)
>>  			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
>> @@ -2612,9 +2495,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>>  		fepriv->tone = -1;
>>  		fepriv->voltage = -1;
>>  
>> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> +		if (fe->dvb->mdev && fe->dvb->mdev->enable_source) {
>> +			ret = fe->dvb->mdev->enable_source(dvbdev->entity,
>> +							   &fe->pipe);
>> +			if (ret) {
>> +				dev_err(fe->dvb->device,
>> +					"Tuner is busy. Error %d\n", ret);
>> +				goto err2;
>> +			}
>> +		}
>> +#endif
>>  		ret = dvb_frontend_start (fe);
>>  		if (ret)
>> -			goto err2;
>> +			goto err3;
>>  
>>  		/*  empty event queue */
>>  		fepriv->events.eventr = fepriv->events.eventw = 0;
>> @@ -2624,7 +2518,12 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
>>  		mutex_unlock (&adapter->mfe_lock);
>>  	return ret;
>>  
>> +err3:
>> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> +	if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
>> +		fe->dvb->mdev->disable_source(dvbdev->entity);
>>  err2:
>> +#endif
>>  	dvb_generic_release(inode, file);
>>  err1:
>>  	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
>> @@ -2653,6 +2552,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
>>  
>>  	if (dvbdev->users == -1) {
>>  		wake_up(&fepriv->wait_queue);
>> +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
>> +		if (fe->dvb->mdev && fe->dvb->mdev->disable_source)
>> +			fe->dvb->mdev->disable_source(dvbdev->entity);
>> +#endif
>>  		if (fe->exit != DVB_FE_NO_EXIT)
>>  			wake_up(&dvbdev->wait_queue);
>>  		if (fe->ops.ts_bus_ctrl)
>> diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
>> index 458bcce..9466906 100644
>> --- a/drivers/media/dvb-core/dvb_frontend.h
>> +++ b/drivers/media/dvb-core/dvb_frontend.h
>> @@ -686,6 +686,9 @@ struct dvb_frontend {
>>  	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
>>  	int id;
>>  	unsigned int exit;
>> +#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
>> +	struct media_pipeline pipe;
>> +#endif
> 
> Why moving this to the non-private part of the data?
> 

There was a reason for this move and I don't recall
at the moment. It has been several months since I
had to rework. I will make sure this change is
necessary and include it in the changelog.

thanks,
-- Shuah


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop()
  2016-02-04  9:18     ` Mauro Carvalho Chehab
@ 2016-02-04 15:00       ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04 15:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel,
	Shuah Khan

On 02/04/2016 02:18 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:38 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Add non-locking __media_entity_pipeline_start/stop() interfaces
>> to be called from code paths that hold the graph_mutex. For this
>> change, the media_entity_pipeline_start() routine is renamed to
>> __media_entity_pipeline_start() minus the graph_mutex lock and
>> unlock. media_entity_pipeline_start() now calls the non-locking
>> __media_entity_pipeline_start() holding the graph_lock. The stop
>> interface, media_entity_pipeline_stop() routine is renamed to
>> __media_entity_pipeline_stop() minus the graph_mutex lock and
>> unlock. media_entity_pipeline_stop() now calls the non-locking
>> __media_entity_pipeline_stop() holding the graph_lock.
> 
> Please write a better patch descriptions. The above could easily
> be split into 3 or 4 paragraphs, with would make it easier to
> read.
> 

Removed linux-api from cc list


ok - I updated several changelogs based on your earlier
comments and this one slipped by.

-- Shuah
> Also, too much details, written on a spaghetti style;)
> 
> It is obvious by anyone that looked at the patch that
> "media_entity_pipeline_start() routine is renamed to 
> __media_entity_pipeline_start() minus the graph_mutex lock and
> unlock."
> 
> I read exactly the same thing at the C code, *and* at the
> subject of the e-mail. Patch subject/description should tell
> what, why and how (but you should not repeat what can easily
> be inferred from looking at the diff).
> 
> I would describe it as:
> 
>    Currently, media pipeline graph traversal routines take
>    the graph_mutex lock.
> 
>    While this works for the current code, we'll need 
>    unlocked versions of them because
>    (some explanation *why* you need it, with is the main
>     thing that should be at the description).
> 
>    So, add non-locking media_entity_pipeline_start/stop()
>    variations.
> 
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
>>  include/media/media-entity.h | 12 ++++++++++++
>>  2 files changed, 36 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
>> index 9b4d712..b78e4c2 100644
>> --- a/drivers/media/media-entity.c
>> +++ b/drivers/media/media-entity.c
>> @@ -365,8 +365,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
>>   * Pipeline management
>>   */
>>  
>> -__must_check int media_entity_pipeline_start(struct media_entity *entity,
>> -					     struct media_pipeline *pipe)
>> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
>> +					       struct media_pipeline *pipe)
>>  {
>>  	struct media_device *mdev = entity->graph_obj.mdev;
>>  	struct media_entity_graph *graph = &pipe->graph;
>> @@ -374,8 +374,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  	struct media_link *link;
>>  	int ret;
>>  
>> -	mutex_lock(&mdev->graph_mutex);
>> -
>>  	if (!pipe->streaming_count++) {
>>  		ret = media_entity_graph_walk_init(&pipe->graph, mdev);
>>  		if (ret)
>> @@ -456,8 +454,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  		}
>>  	}
>>  
>> -	mutex_unlock(&mdev->graph_mutex);
>> -
>>  	return 0;
>>  
>>  error:
>> @@ -487,19 +483,28 @@ error_graph_walk_start:
>>  	if (!--pipe->streaming_count)
>>  		media_entity_graph_walk_cleanup(graph);
>>  
>> -	mutex_unlock(&mdev->graph_mutex);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_start);
>>  
>> +__must_check int media_entity_pipeline_start(struct media_entity *entity,
>> +					     struct media_pipeline *pipe)
>> +{
>> +	struct media_device *mdev = entity->graph_obj.mdev;
>> +	int ret;
>> +
>> +	mutex_lock(&mdev->graph_mutex);
>> +	ret = __media_entity_pipeline_start(entity, pipe);
>> +	mutex_unlock(&mdev->graph_mutex);
>>  	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
>>  
>> -void media_entity_pipeline_stop(struct media_entity *entity)
>> +void __media_entity_pipeline_stop(struct media_entity *entity)
>>  {
>> -	struct media_device *mdev = entity->graph_obj.mdev;
>>  	struct media_entity_graph *graph = &entity->pipe->graph;
>>  	struct media_pipeline *pipe = entity->pipe;
>>  
>> -	mutex_lock(&mdev->graph_mutex);
>>  
>>  	WARN_ON(!pipe->streaming_count);
>>  	media_entity_graph_walk_start(graph, entity);
>> @@ -516,6 +521,15 @@ void media_entity_pipeline_stop(struct media_entity *entity)
>>  	if (!--pipe->streaming_count)
>>  		media_entity_graph_walk_cleanup(graph);
>>  
>> +}
>> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop);
>> +
>> +void media_entity_pipeline_stop(struct media_entity *entity)
>> +{
>> +	struct media_device *mdev = entity->graph_obj.mdev;
>> +
>> +	mutex_lock(&mdev->graph_mutex);
>> +	__media_entity_pipeline_stop(entity);
>>  	mutex_unlock(&mdev->graph_mutex);
>>  }
>>  EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
>> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
>> index fe485d3..c7583db 100644
>> --- a/include/media/media-entity.h
>> +++ b/include/media/media-entity.h
>> @@ -832,6 +832,12 @@ media_entity_graph_walk_next(struct media_entity_graph *graph);
>>   */
>>  __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  					     struct media_pipeline *pipe);
>> +/**
>> + * non-locking __media_entity_pipeline_start() can be called from
>> + * code paths that hold the graph_mutex
>> + */
>> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
>> +					       struct media_pipeline *pipe);
>>  
>>  /**
>>   * media_entity_pipeline_stop - Mark a pipeline as not streaming
>> @@ -848,6 +854,12 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  void media_entity_pipeline_stop(struct media_entity *entity);
>>  
>>  /**
>> + * non-locking __media_entity_pipeline_stop() can be called from
>> + * code paths that hold the graph_mutex
>> + */
>> +void __media_entity_pipeline_stop(struct media_entity *entity);
>> +
>> +/**
>>   * media_devnode_create() - creates and initializes a device node interface
>>   *
>>   * @mdev:	pointer to struct &media_device


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop()
@ 2016-02-04 15:00       ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-04 15:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

On 02/04/2016 02:18 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:38 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Add non-locking __media_entity_pipeline_start/stop() interfaces
>> to be called from code paths that hold the graph_mutex. For this
>> change, the media_entity_pipeline_start() routine is renamed to
>> __media_entity_pipeline_start() minus the graph_mutex lock and
>> unlock. media_entity_pipeline_start() now calls the non-locking
>> __media_entity_pipeline_start() holding the graph_lock. The stop
>> interface, media_entity_pipeline_stop() routine is renamed to
>> __media_entity_pipeline_stop() minus the graph_mutex lock and
>> unlock. media_entity_pipeline_stop() now calls the non-locking
>> __media_entity_pipeline_stop() holding the graph_lock.
> 
> Please write a better patch descriptions. The above could easily
> be split into 3 or 4 paragraphs, with would make it easier to
> read.
> 

Removed linux-api from cc list


ok - I updated several changelogs based on your earlier
comments and this one slipped by.

-- Shuah
> Also, too much details, written on a spaghetti style;)
> 
> It is obvious by anyone that looked at the patch that
> "media_entity_pipeline_start() routine is renamed to 
> __media_entity_pipeline_start() minus the graph_mutex lock and
> unlock."
> 
> I read exactly the same thing at the C code, *and* at the
> subject of the e-mail. Patch subject/description should tell
> what, why and how (but you should not repeat what can easily
> be inferred from looking at the diff).
> 
> I would describe it as:
> 
>    Currently, media pipeline graph traversal routines take
>    the graph_mutex lock.
> 
>    While this works for the current code, we'll need 
>    unlocked versions of them because
>    (some explanation *why* you need it, with is the main
>     thing that should be at the description).
> 
>    So, add non-locking media_entity_pipeline_start/stop()
>    variations.
> 
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/media-entity.c | 34 ++++++++++++++++++++++++----------
>>  include/media/media-entity.h | 12 ++++++++++++
>>  2 files changed, 36 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
>> index 9b4d712..b78e4c2 100644
>> --- a/drivers/media/media-entity.c
>> +++ b/drivers/media/media-entity.c
>> @@ -365,8 +365,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
>>   * Pipeline management
>>   */
>>  
>> -__must_check int media_entity_pipeline_start(struct media_entity *entity,
>> -					     struct media_pipeline *pipe)
>> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
>> +					       struct media_pipeline *pipe)
>>  {
>>  	struct media_device *mdev = entity->graph_obj.mdev;
>>  	struct media_entity_graph *graph = &pipe->graph;
>> @@ -374,8 +374,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  	struct media_link *link;
>>  	int ret;
>>  
>> -	mutex_lock(&mdev->graph_mutex);
>> -
>>  	if (!pipe->streaming_count++) {
>>  		ret = media_entity_graph_walk_init(&pipe->graph, mdev);
>>  		if (ret)
>> @@ -456,8 +454,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  		}
>>  	}
>>  
>> -	mutex_unlock(&mdev->graph_mutex);
>> -
>>  	return 0;
>>  
>>  error:
>> @@ -487,19 +483,28 @@ error_graph_walk_start:
>>  	if (!--pipe->streaming_count)
>>  		media_entity_graph_walk_cleanup(graph);
>>  
>> -	mutex_unlock(&mdev->graph_mutex);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_start);
>>  
>> +__must_check int media_entity_pipeline_start(struct media_entity *entity,
>> +					     struct media_pipeline *pipe)
>> +{
>> +	struct media_device *mdev = entity->graph_obj.mdev;
>> +	int ret;
>> +
>> +	mutex_lock(&mdev->graph_mutex);
>> +	ret = __media_entity_pipeline_start(entity, pipe);
>> +	mutex_unlock(&mdev->graph_mutex);
>>  	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
>>  
>> -void media_entity_pipeline_stop(struct media_entity *entity)
>> +void __media_entity_pipeline_stop(struct media_entity *entity)
>>  {
>> -	struct media_device *mdev = entity->graph_obj.mdev;
>>  	struct media_entity_graph *graph = &entity->pipe->graph;
>>  	struct media_pipeline *pipe = entity->pipe;
>>  
>> -	mutex_lock(&mdev->graph_mutex);
>>  
>>  	WARN_ON(!pipe->streaming_count);
>>  	media_entity_graph_walk_start(graph, entity);
>> @@ -516,6 +521,15 @@ void media_entity_pipeline_stop(struct media_entity *entity)
>>  	if (!--pipe->streaming_count)
>>  		media_entity_graph_walk_cleanup(graph);
>>  
>> +}
>> +EXPORT_SYMBOL_GPL(__media_entity_pipeline_stop);
>> +
>> +void media_entity_pipeline_stop(struct media_entity *entity)
>> +{
>> +	struct media_device *mdev = entity->graph_obj.mdev;
>> +
>> +	mutex_lock(&mdev->graph_mutex);
>> +	__media_entity_pipeline_stop(entity);
>>  	mutex_unlock(&mdev->graph_mutex);
>>  }
>>  EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
>> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
>> index fe485d3..c7583db 100644
>> --- a/include/media/media-entity.h
>> +++ b/include/media/media-entity.h
>> @@ -832,6 +832,12 @@ media_entity_graph_walk_next(struct media_entity_graph *graph);
>>   */
>>  __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  					     struct media_pipeline *pipe);
>> +/**
>> + * non-locking __media_entity_pipeline_start() can be called from
>> + * code paths that hold the graph_mutex
>> + */
>> +__must_check int __media_entity_pipeline_start(struct media_entity *entity,
>> +					       struct media_pipeline *pipe);
>>  
>>  /**
>>   * media_entity_pipeline_stop - Mark a pipeline as not streaming
>> @@ -848,6 +854,12 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
>>  void media_entity_pipeline_stop(struct media_entity *entity);
>>  
>>  /**
>> + * non-locking __media_entity_pipeline_stop() can be called from
>> + * code paths that hold the graph_mutex
>> + */
>> +void __media_entity_pipeline_stop(struct media_entity *entity);
>> +
>> +/**
>>   * media_devnode_create() - creates and initializes a device node interface
>>   *
>>   * @mdev:	pointer to struct &media_device


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
  2016-02-04  4:03   ` Shuah Khan
@ 2016-02-07 11:25     ` kbuild test robot
  -1 siblings, 0 replies; 94+ messages in thread
From: kbuild test robot @ 2016-02-07 11:25 UTC (permalink / raw)
  To: Shuah Khan
  Cc: kbuild-all, mchehab, tiwai, clemens, hans.verkuil,
	laurent.pinchart, sakari.ailus, javier, Shuah Khan, pawel,
	m.szyprowski, kyungmin.park, perex, arnd, dan.carpenter,
	tvboxspy, crope, ruchandani.tina, corbet, chehabrafael,
	k.kozlowski, stefanr, inki.dae, jh1009.sung, elfring,
	prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda, labbott,
	pierre-louis.bossart, ricard.wanderlof, julian, takamichiho,
	dominic.sacre, misterpib, daniel, gtmkramer, normalperson, joe,
	linuxbugs, johan, klock.android, nenggun.kim, j.anaszewski,
	geliangtang, linux-kernel, linux-media, linux-api, alsa-devel

[-- Attachment #1: Type: text/plain, Size: 3362 bytes --]

Hi Shuah,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on next-20160205]
[cannot apply to v4.5-rc2]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Shuah-Khan/Sharing-media-resources-across-ALSA-and-au0828-drivers/20160204-121414
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-b0-02071259 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a043): undefined reference to `media_entity_pads_init'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a04d): undefined reference to `media_device_register_entity'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a080): undefined reference to `media_devnode_create'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a09c): undefined reference to `media_create_intf_link'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a0f4): undefined reference to `media_create_pad_link'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a105): undefined reference to `media_remove_intf_link'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a113): undefined reference to `media_devnode_remove'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a121): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_stream_delete':
   (.text+0x3a1f4): undefined reference to `media_devnode_remove'
   sound/built-in.o: In function `media_stream_delete':
   (.text+0x3a1fc): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a347): undefined reference to `media_entity_pads_init'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a351): undefined reference to `media_device_register_entity'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a369): undefined reference to `media_create_intf_link'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a39e): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a3da): undefined reference to `media_devnode_create'
   sound/built-in.o: In function `media_device_create':
>> (.text+0x3a424): undefined reference to `media_device_get_devres'
   sound/built-in.o: In function `media_device_create':
>> (.text+0x3a475): undefined reference to `__media_device_register'
   sound/built-in.o: In function `media_device_create':
>> (.text+0x3a526): undefined reference to `media_device_init'
   sound/built-in.o: In function `media_device_delete':
   (.text+0x3a5b1): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_device_delete':
   (.text+0x3a5f7): undefined reference to `media_devnode_remove'
   sound/built-in.o: In function `media_device_delete':
>> (.text+0x3a603): undefined reference to `media_device_unregister'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 28965 bytes --]

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources
@ 2016-02-07 11:25     ` kbuild test robot
  0 siblings, 0 replies; 94+ messages in thread
From: kbuild test robot @ 2016-02-07 11:25 UTC (permalink / raw)
  Cc: kbuild-all, mchehab, tiwai, clemens, hans.verkuil,
	laurent.pinchart, sakari.ailus, javier, Shuah Khan, pawel,
	m.szyprowski, kyungmin.park, perex, arnd, dan.carpenter,
	tvboxspy, crope, ruchandani.tina, corbet, chehabrafael,
	k.kozlowski, stefanr, inki.dae, jh1009.sung, elfring,
	prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda, labbott,
	pierre-louis.bossart, ricard.wanderlof, julian, takamichiho,
	dominic.sacre, misterpib, daniel

[-- Attachment #1: Type: text/plain, Size: 3362 bytes --]

Hi Shuah,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on next-20160205]
[cannot apply to v4.5-rc2]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Shuah-Khan/Sharing-media-resources-across-ALSA-and-au0828-drivers/20160204-121414
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-b0-02071259 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a043): undefined reference to `media_entity_pads_init'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a04d): undefined reference to `media_device_register_entity'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a080): undefined reference to `media_devnode_create'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a09c): undefined reference to `media_create_intf_link'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a0f4): undefined reference to `media_create_pad_link'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a105): undefined reference to `media_remove_intf_link'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a113): undefined reference to `media_devnode_remove'
   sound/built-in.o: In function `media_stream_init':
>> (.text+0x3a121): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_stream_delete':
   (.text+0x3a1f4): undefined reference to `media_devnode_remove'
   sound/built-in.o: In function `media_stream_delete':
   (.text+0x3a1fc): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a347): undefined reference to `media_entity_pads_init'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a351): undefined reference to `media_device_register_entity'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a369): undefined reference to `media_create_intf_link'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a39e): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_mixer_init':
   (.text+0x3a3da): undefined reference to `media_devnode_create'
   sound/built-in.o: In function `media_device_create':
>> (.text+0x3a424): undefined reference to `media_device_get_devres'
   sound/built-in.o: In function `media_device_create':
>> (.text+0x3a475): undefined reference to `__media_device_register'
   sound/built-in.o: In function `media_device_create':
>> (.text+0x3a526): undefined reference to `media_device_init'
   sound/built-in.o: In function `media_device_delete':
   (.text+0x3a5b1): undefined reference to `media_device_unregister_entity'
   sound/built-in.o: In function `media_device_delete':
   (.text+0x3a5f7): undefined reference to `media_devnode_remove'
   sound/built-in.o: In function `media_device_delete':
>> (.text+0x3a603): undefined reference to `media_device_unregister'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 28965 bytes --]

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
  2016-02-04 10:26     ` Mauro Carvalho Chehab
@ 2016-02-08 22:42       ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-08 22:42 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel,
	Shuah Khan

On 02/04/2016 03:26 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:52 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Add enable_source and disable_source handlers.
>> The enable source handler is called from
>> v4l2-core, dvb-core, and ALSA drivers to check
>> if the shared media source is free. The disable
>> source handler is called to release the shared
>> media source.
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
>>  drivers/media/usb/au0828/au0828.h      |   3 +
>>  2 files changed, 152 insertions(+)
>>
>> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
>> index 4c90f28..fd2265c 100644
>> --- a/drivers/media/usb/au0828/au0828-core.c
>> +++ b/drivers/media/usb/au0828/au0828-core.c
>> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
>>  		return -EINVAL;
>>  
>>  	if (tuner) {
>> +		dev->tuner = tuner;
>>  		/* create tuner to decoder link in deactivated state */
>>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>>  					    decoder, 0, 0);
>> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
>>  #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 ret = 0;
>> +	struct media_device *mdev = entity->graph_obj.mdev;
>> +	struct au0828_dev *dev;
>> +
>> +	if (!mdev)
>> +		return -ENODEV;
>> +
>> +	/* for Audio 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;
>> +	}
> 
> This is wrong. There are devices without tuner (capture devices) and
> without analog decoder (pure DVB devices).

Removed linux-api from the list.

Yes this logic is making an assumption that both
decoder and tuner are present. Based on your comment
here, is the following check for decoder in 
au0828_create_media_graph() incorrect? When decoder
is null, au0828_usb_probe() bails out. Please see
au0828_create_media_graph() return handling in
au0828_usb_probe()?


       /* Something bad happened! */
        if (!decoder)
                return -EINVAL;

> 
> In the case of pure DVB devices (e. g. no dev->decoder), it should
> just enable the DVB path.
> 
> In the case of devices without tuner, it should use the same logic
> needed to handle the S-Video/Composite connector inputs.
> 
> Btw, I'm not seeing how this logic would do the right thing if the user
> selects either S-Video or Composite connectors.
> 
>> +
>> +	/*
>> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
>> +		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;
>> +		}
>> +	}
>> +
>> +	list_for_each_entry(link, &sink->links, list) {
>> +		/* Check sink, and source */
>> +		if (link->sink->entity == sink &&
>> +		    link->source->entity == dev->tuner) {
>> +			found_link = link;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (!found_link) {
>> +		ret = -ENODEV;
>> +		goto end;
>> +	}
>> +
>> +	/* activate link between source and sink and start pipeline */
>> +	source = found_link->source->entity;
>> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
>> +	if (ret) {
>> +		pr_err(
>> +			"Activate tuner link %s->%s. Error %d\n",
>> +			source->name, sink->name, ret);
>> +		goto end;
>> +	}
>> +
>> +	ret = __media_entity_pipeline_start(entity, pipe);
>> +	if (ret) {
>> +		pr_err("Start Pipeline: %s->%s Error %d\n",
>> +			source->name, entity->name, ret);
>> +		ret = __media_entity_setup_link(found_link, 0);
>> +		pr_err("Deactive link Error %d\n", ret);
>> +		goto end;
>> +	}
> 
> Hmm... isn't it to early to activate the pipeline here? My original
> guess is that, on the analog side, this should happen only at the stream
> on code. Wouldn't this break apps like mythTV?
> 
>> +	/*
>> +	 * save active link and active link owner to avoid audio
>> +	 * deactivating video owned link from disable_source and
>> +	 * vice versa
>> +	*/
>> +	dev->active_link = found_link;
>> +	dev->active_link_owner = entity;
>> +end:
>> +	mutex_unlock(&mdev->graph_mutex);
>> +	pr_debug("au0828_enable_source() end %s %d %d\n",
>> +		entity->name, entity->function, ret);
>> +	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->graph_obj.mdev;
>> +	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;
>> +	}
> 
> Same note as before.

Same comment as before here about au0828_create_media_graph()
and au0828_usb_probe() handling.

> 
>> +
>> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
>> +		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);
>> +		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;
>> +	}
> 
> Most code here looks like the one at au0828_enable_source(). Wouldn't
> be simpler to merge those code and add a "bool enable" to the function
> parameters?

I would rather keep these separate. A very short
section is common really.

thanks,
-- Shuah

> 
>> +
>> +end:
>> +	mutex_unlock(&mdev->graph_mutex);
>> +#endif
>> +}
>> +
>>  static int au0828_media_device_register(struct au0828_dev *dev,
>>  					struct usb_device *udev)
>>  {
>> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
>>  			ret);
>>  		return ret;
>>  	}
>> +	/* set enable_source */
>> +	dev->media_dev->source_priv = (void *) dev;
>> +	dev->media_dev->enable_source = au0828_enable_source;
>> +	dev->media_dev->disable_source = au0828_disable_source;
>>  #endif
>>  	return 0;
>>  }
>> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
>> index 54379ec..a7c88a1 100644
>> --- a/drivers/media/usb/au0828/au0828.h
>> +++ b/drivers/media/usb/au0828/au0828.h
>> @@ -284,6 +284,9 @@ struct au0828_dev {
>>  	struct media_entity input_ent[AU0828_MAX_INPUT];
>>  	struct media_pad input_pad[AU0828_MAX_INPUT];
>>  	struct media_entity_notify entity_notify;
>> +	struct media_entity *tuner;
>> +	struct media_link *active_link;
>> +	struct media_entity *active_link_owner;
>>  #endif
>>  };
>>  


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
@ 2016-02-08 22:42       ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-08 22:42 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

On 02/04/2016 03:26 AM, Mauro Carvalho Chehab wrote:
> Em Wed, 03 Feb 2016 21:03:52 -0700
> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> 
>> Add enable_source and disable_source handlers.
>> The enable source handler is called from
>> v4l2-core, dvb-core, and ALSA drivers to check
>> if the shared media source is free. The disable
>> source handler is called to release the shared
>> media source.
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
>>  drivers/media/usb/au0828/au0828.h      |   3 +
>>  2 files changed, 152 insertions(+)
>>
>> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
>> index 4c90f28..fd2265c 100644
>> --- a/drivers/media/usb/au0828/au0828-core.c
>> +++ b/drivers/media/usb/au0828/au0828-core.c
>> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
>>  		return -EINVAL;
>>  
>>  	if (tuner) {
>> +		dev->tuner = tuner;
>>  		/* create tuner to decoder link in deactivated state */
>>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>>  					    decoder, 0, 0);
>> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
>>  #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 ret = 0;
>> +	struct media_device *mdev = entity->graph_obj.mdev;
>> +	struct au0828_dev *dev;
>> +
>> +	if (!mdev)
>> +		return -ENODEV;
>> +
>> +	/* for Audio 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;
>> +	}
> 
> This is wrong. There are devices without tuner (capture devices) and
> without analog decoder (pure DVB devices).

Removed linux-api from the list.

Yes this logic is making an assumption that both
decoder and tuner are present. Based on your comment
here, is the following check for decoder in 
au0828_create_media_graph() incorrect? When decoder
is null, au0828_usb_probe() bails out. Please see
au0828_create_media_graph() return handling in
au0828_usb_probe()?


       /* Something bad happened! */
        if (!decoder)
                return -EINVAL;

> 
> In the case of pure DVB devices (e. g. no dev->decoder), it should
> just enable the DVB path.
> 
> In the case of devices without tuner, it should use the same logic
> needed to handle the S-Video/Composite connector inputs.
> 
> Btw, I'm not seeing how this logic would do the right thing if the user
> selects either S-Video or Composite connectors.
> 
>> +
>> +	/*
>> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
>> +		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;
>> +		}
>> +	}
>> +
>> +	list_for_each_entry(link, &sink->links, list) {
>> +		/* Check sink, and source */
>> +		if (link->sink->entity == sink &&
>> +		    link->source->entity == dev->tuner) {
>> +			found_link = link;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (!found_link) {
>> +		ret = -ENODEV;
>> +		goto end;
>> +	}
>> +
>> +	/* activate link between source and sink and start pipeline */
>> +	source = found_link->source->entity;
>> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
>> +	if (ret) {
>> +		pr_err(
>> +			"Activate tuner link %s->%s. Error %d\n",
>> +			source->name, sink->name, ret);
>> +		goto end;
>> +	}
>> +
>> +	ret = __media_entity_pipeline_start(entity, pipe);
>> +	if (ret) {
>> +		pr_err("Start Pipeline: %s->%s Error %d\n",
>> +			source->name, entity->name, ret);
>> +		ret = __media_entity_setup_link(found_link, 0);
>> +		pr_err("Deactive link Error %d\n", ret);
>> +		goto end;
>> +	}
> 
> Hmm... isn't it to early to activate the pipeline here? My original
> guess is that, on the analog side, this should happen only at the stream
> on code. Wouldn't this break apps like mythTV?
> 
>> +	/*
>> +	 * save active link and active link owner to avoid audio
>> +	 * deactivating video owned link from disable_source and
>> +	 * vice versa
>> +	*/
>> +	dev->active_link = found_link;
>> +	dev->active_link_owner = entity;
>> +end:
>> +	mutex_unlock(&mdev->graph_mutex);
>> +	pr_debug("au0828_enable_source() end %s %d %d\n",
>> +		entity->name, entity->function, ret);
>> +	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->graph_obj.mdev;
>> +	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;
>> +	}
> 
> Same note as before.

Same comment as before here about au0828_create_media_graph()
and au0828_usb_probe() handling.

> 
>> +
>> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
>> +		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);
>> +		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;
>> +	}
> 
> Most code here looks like the one at au0828_enable_source(). Wouldn't
> be simpler to merge those code and add a "bool enable" to the function
> parameters?

I would rather keep these separate. A very short
section is common really.

thanks,
-- Shuah

> 
>> +
>> +end:
>> +	mutex_unlock(&mdev->graph_mutex);
>> +#endif
>> +}
>> +
>>  static int au0828_media_device_register(struct au0828_dev *dev,
>>  					struct usb_device *udev)
>>  {
>> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
>>  			ret);
>>  		return ret;
>>  	}
>> +	/* set enable_source */
>> +	dev->media_dev->source_priv = (void *) dev;
>> +	dev->media_dev->enable_source = au0828_enable_source;
>> +	dev->media_dev->disable_source = au0828_disable_source;
>>  #endif
>>  	return 0;
>>  }
>> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
>> index 54379ec..a7c88a1 100644
>> --- a/drivers/media/usb/au0828/au0828.h
>> +++ b/drivers/media/usb/au0828/au0828.h
>> @@ -284,6 +284,9 @@ struct au0828_dev {
>>  	struct media_entity input_ent[AU0828_MAX_INPUT];
>>  	struct media_pad input_pad[AU0828_MAX_INPUT];
>>  	struct media_entity_notify entity_notify;
>> +	struct media_entity *tuner;
>> +	struct media_link *active_link;
>> +	struct media_entity *active_link_owner;
>>  #endif
>>  };
>>  


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
  2016-02-08 22:42       ` Shuah Khan
@ 2016-02-08 23:00         ` Shuah Khan
  -1 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-08 23:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel,
	Shuah Khan

On 02/08/2016 03:42 PM, Shuah Khan wrote:
> On 02/04/2016 03:26 AM, Mauro Carvalho Chehab wrote:
>> Em Wed, 03 Feb 2016 21:03:52 -0700
>> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
>>
>>> Add enable_source and disable_source handlers.
>>> The enable source handler is called from
>>> v4l2-core, dvb-core, and ALSA drivers to check
>>> if the shared media source is free. The disable
>>> source handler is called to release the shared
>>> media source.
>>>
>>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>>> ---
>>>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
>>>  drivers/media/usb/au0828/au0828.h      |   3 +
>>>  2 files changed, 152 insertions(+)
>>>
>>> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
>>> index 4c90f28..fd2265c 100644
>>> --- a/drivers/media/usb/au0828/au0828-core.c
>>> +++ b/drivers/media/usb/au0828/au0828-core.c
>>> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
>>>  		return -EINVAL;
>>>  
>>>  	if (tuner) {
>>> +		dev->tuner = tuner;
>>>  		/* create tuner to decoder link in deactivated state */
>>>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>>>  					    decoder, 0, 0);
>>> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
>>>  #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 ret = 0;
>>> +	struct media_device *mdev = entity->graph_obj.mdev;
>>> +	struct au0828_dev *dev;
>>> +
>>> +	if (!mdev)
>>> +		return -ENODEV;
>>> +
>>> +	/* for Audio 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;
>>> +	}
>>
>> This is wrong. There are devices without tuner (capture devices) and
>> without analog decoder (pure DVB devices).
> 
> Removed linux-api from the list.
> 
> Yes this logic is making an assumption that both
> decoder and tuner are present. Based on your comment
> here, is the following check for decoder in 
> au0828_create_media_graph() incorrect? When decoder
> is null, au0828_usb_probe() bails out. Please see
> au0828_create_media_graph() return handling in
> au0828_usb_probe()?
> 
> 
>        /* Something bad happened! */
>         if (!decoder)
>                 return -EINVAL;
> 
>>
>> In the case of pure DVB devices (e. g. no dev->decoder), it should
>> just enable the DVB path.
>>
>> In the case of devices without tuner, it should use the same logic
>> needed to handle the S-Video/Composite connector inputs.
>>
>> Btw, I'm not seeing how this logic would do the right thing if the user
>> selects either S-Video or Composite connectors.
>>
>>> +
>>> +	/*
>>> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
>>> +		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;
>>> +		}
>>> +	}
>>> +
>>> +	list_for_each_entry(link, &sink->links, list) {
>>> +		/* Check sink, and source */
>>> +		if (link->sink->entity == sink &&
>>> +		    link->source->entity == dev->tuner) {
>>> +			found_link = link;
>>> +			break;
>>> +		}
>>> +	}
>>> +
>>> +	if (!found_link) {
>>> +		ret = -ENODEV;
>>> +		goto end;
>>> +	}
>>> +
>>> +	/* activate link between source and sink and start pipeline */
>>> +	source = found_link->source->entity;
>>> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
>>> +	if (ret) {
>>> +		pr_err(
>>> +			"Activate tuner link %s->%s. Error %d\n",
>>> +			source->name, sink->name, ret);
>>> +		goto end;
>>> +	}
>>> +
>>> +	ret = __media_entity_pipeline_start(entity, pipe);
>>> +	if (ret) {
>>> +		pr_err("Start Pipeline: %s->%s Error %d\n",
>>> +			source->name, entity->name, ret);
>>> +		ret = __media_entity_setup_link(found_link, 0);
>>> +		pr_err("Deactive link Error %d\n", ret);
>>> +		goto end;
>>> +	}
>>
>> Hmm... isn't it to early to activate the pipeline here? My original
>> guess is that, on the analog side, this should happen only at the stream
>> on code. Wouldn't this break apps like mythTV?

On analog side, there are a few ioctls that
change the configuration on the tuner way
before stream on step. Is there a reason to
separate the setup_link() and pipeline_start()
steps? I can separate these two steps, but I
am not really seeing the reason for that.

>>
>>> +	/*
>>> +	 * save active link and active link owner to avoid audio
>>> +	 * deactivating video owned link from disable_source and
>>> +	 * vice versa
>>> +	*/
>>> +	dev->active_link = found_link;
>>> +	dev->active_link_owner = entity;
>>> +end:
>>> +	mutex_unlock(&mdev->graph_mutex);
>>> +	pr_debug("au0828_enable_source() end %s %d %d\n",
>>> +		entity->name, entity->function, ret);
>>> +	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->graph_obj.mdev;
>>> +	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;
>>> +	}
>>
>> Same note as before.
> 
> Same comment as before here about au0828_create_media_graph()
> and au0828_usb_probe() handling.
> 
>>
>>> +
>>> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
>>> +		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);
>>> +		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;
>>> +	}
>>
>> Most code here looks like the one at au0828_enable_source(). Wouldn't
>> be simpler to merge those code and add a "bool enable" to the function
>> parameters?
> 
> I would rather keep these separate. A very short
> section is common really.
> 
> thanks,
> -- Shuah
> 
>>
>>> +
>>> +end:
>>> +	mutex_unlock(&mdev->graph_mutex);
>>> +#endif
>>> +}
>>> +
>>>  static int au0828_media_device_register(struct au0828_dev *dev,
>>>  					struct usb_device *udev)
>>>  {
>>> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
>>>  			ret);
>>>  		return ret;
>>>  	}
>>> +	/* set enable_source */
>>> +	dev->media_dev->source_priv = (void *) dev;
>>> +	dev->media_dev->enable_source = au0828_enable_source;
>>> +	dev->media_dev->disable_source = au0828_disable_source;
>>>  #endif
>>>  	return 0;
>>>  }
>>> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
>>> index 54379ec..a7c88a1 100644
>>> --- a/drivers/media/usb/au0828/au0828.h
>>> +++ b/drivers/media/usb/au0828/au0828.h
>>> @@ -284,6 +284,9 @@ struct au0828_dev {
>>>  	struct media_entity input_ent[AU0828_MAX_INPUT];
>>>  	struct media_pad input_pad[AU0828_MAX_INPUT];
>>>  	struct media_entity_notify entity_notify;
>>> +	struct media_entity *tuner;
>>> +	struct media_link *active_link;
>>> +	struct media_entity *active_link_owner;
>>>  #endif
>>>  };
>>>  
> 
> 


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
@ 2016-02-08 23:00         ` Shuah Khan
  0 siblings, 0 replies; 94+ messages in thread
From: Shuah Khan @ 2016-02-08 23:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

On 02/08/2016 03:42 PM, Shuah Khan wrote:
> On 02/04/2016 03:26 AM, Mauro Carvalho Chehab wrote:
>> Em Wed, 03 Feb 2016 21:03:52 -0700
>> Shuah Khan <shuahkh@osg.samsung.com> escreveu:
>>
>>> Add enable_source and disable_source handlers.
>>> The enable source handler is called from
>>> v4l2-core, dvb-core, and ALSA drivers to check
>>> if the shared media source is free. The disable
>>> source handler is called to release the shared
>>> media source.
>>>
>>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>>> ---
>>>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
>>>  drivers/media/usb/au0828/au0828.h      |   3 +
>>>  2 files changed, 152 insertions(+)
>>>
>>> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
>>> index 4c90f28..fd2265c 100644
>>> --- a/drivers/media/usb/au0828/au0828-core.c
>>> +++ b/drivers/media/usb/au0828/au0828-core.c
>>> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
>>>  		return -EINVAL;
>>>  
>>>  	if (tuner) {
>>> +		dev->tuner = tuner;
>>>  		/* create tuner to decoder link in deactivated state */
>>>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>>>  					    decoder, 0, 0);
>>> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
>>>  #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 ret = 0;
>>> +	struct media_device *mdev = entity->graph_obj.mdev;
>>> +	struct au0828_dev *dev;
>>> +
>>> +	if (!mdev)
>>> +		return -ENODEV;
>>> +
>>> +	/* for Audio 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;
>>> +	}
>>
>> This is wrong. There are devices without tuner (capture devices) and
>> without analog decoder (pure DVB devices).
> 
> Removed linux-api from the list.
> 
> Yes this logic is making an assumption that both
> decoder and tuner are present. Based on your comment
> here, is the following check for decoder in 
> au0828_create_media_graph() incorrect? When decoder
> is null, au0828_usb_probe() bails out. Please see
> au0828_create_media_graph() return handling in
> au0828_usb_probe()?
> 
> 
>        /* Something bad happened! */
>         if (!decoder)
>                 return -EINVAL;
> 
>>
>> In the case of pure DVB devices (e. g. no dev->decoder), it should
>> just enable the DVB path.
>>
>> In the case of devices without tuner, it should use the same logic
>> needed to handle the S-Video/Composite connector inputs.
>>
>> Btw, I'm not seeing how this logic would do the right thing if the user
>> selects either S-Video or Composite connectors.
>>
>>> +
>>> +	/*
>>> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
>>> +		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;
>>> +		}
>>> +	}
>>> +
>>> +	list_for_each_entry(link, &sink->links, list) {
>>> +		/* Check sink, and source */
>>> +		if (link->sink->entity == sink &&
>>> +		    link->source->entity == dev->tuner) {
>>> +			found_link = link;
>>> +			break;
>>> +		}
>>> +	}
>>> +
>>> +	if (!found_link) {
>>> +		ret = -ENODEV;
>>> +		goto end;
>>> +	}
>>> +
>>> +	/* activate link between source and sink and start pipeline */
>>> +	source = found_link->source->entity;
>>> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
>>> +	if (ret) {
>>> +		pr_err(
>>> +			"Activate tuner link %s->%s. Error %d\n",
>>> +			source->name, sink->name, ret);
>>> +		goto end;
>>> +	}
>>> +
>>> +	ret = __media_entity_pipeline_start(entity, pipe);
>>> +	if (ret) {
>>> +		pr_err("Start Pipeline: %s->%s Error %d\n",
>>> +			source->name, entity->name, ret);
>>> +		ret = __media_entity_setup_link(found_link, 0);
>>> +		pr_err("Deactive link Error %d\n", ret);
>>> +		goto end;
>>> +	}
>>
>> Hmm... isn't it to early to activate the pipeline here? My original
>> guess is that, on the analog side, this should happen only at the stream
>> on code. Wouldn't this break apps like mythTV?

On analog side, there are a few ioctls that
change the configuration on the tuner way
before stream on step. Is there a reason to
separate the setup_link() and pipeline_start()
steps? I can separate these two steps, but I
am not really seeing the reason for that.

>>
>>> +	/*
>>> +	 * save active link and active link owner to avoid audio
>>> +	 * deactivating video owned link from disable_source and
>>> +	 * vice versa
>>> +	*/
>>> +	dev->active_link = found_link;
>>> +	dev->active_link_owner = entity;
>>> +end:
>>> +	mutex_unlock(&mdev->graph_mutex);
>>> +	pr_debug("au0828_enable_source() end %s %d %d\n",
>>> +		entity->name, entity->function, ret);
>>> +	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->graph_obj.mdev;
>>> +	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;
>>> +	}
>>
>> Same note as before.
> 
> Same comment as before here about au0828_create_media_graph()
> and au0828_usb_probe() handling.
> 
>>
>>> +
>>> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
>>> +		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);
>>> +		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;
>>> +	}
>>
>> Most code here looks like the one at au0828_enable_source(). Wouldn't
>> be simpler to merge those code and add a "bool enable" to the function
>> parameters?
> 
> I would rather keep these separate. A very short
> section is common really.
> 
> thanks,
> -- Shuah
> 
>>
>>> +
>>> +end:
>>> +	mutex_unlock(&mdev->graph_mutex);
>>> +#endif
>>> +}
>>> +
>>>  static int au0828_media_device_register(struct au0828_dev *dev,
>>>  					struct usb_device *udev)
>>>  {
>>> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
>>>  			ret);
>>>  		return ret;
>>>  	}
>>> +	/* set enable_source */
>>> +	dev->media_dev->source_priv = (void *) dev;
>>> +	dev->media_dev->enable_source = au0828_enable_source;
>>> +	dev->media_dev->disable_source = au0828_disable_source;
>>>  #endif
>>>  	return 0;
>>>  }
>>> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
>>> index 54379ec..a7c88a1 100644
>>> --- a/drivers/media/usb/au0828/au0828.h
>>> +++ b/drivers/media/usb/au0828/au0828.h
>>> @@ -284,6 +284,9 @@ struct au0828_dev {
>>>  	struct media_entity input_ent[AU0828_MAX_INPUT];
>>>  	struct media_pad input_pad[AU0828_MAX_INPUT];
>>>  	struct media_entity_notify entity_notify;
>>> +	struct media_entity *tuner;
>>> +	struct media_link *active_link;
>>> +	struct media_entity *active_link_owner;
>>>  #endif
>>>  };
>>>  
> 
> 


-- 
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
  2016-02-08 22:42       ` Shuah Khan
@ 2016-02-09 10:51         ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-09 10:51 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel

Em Mon, 08 Feb 2016 15:42:15 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> On 02/04/2016 03:26 AM, Mauro Carvalho Chehab wrote:
> > Em Wed, 03 Feb 2016 21:03:52 -0700
> > Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> >   
> >> Add enable_source and disable_source handlers.
> >> The enable source handler is called from
> >> v4l2-core, dvb-core, and ALSA drivers to check
> >> if the shared media source is free. The disable
> >> source handler is called to release the shared
> >> media source.
> >>
> >> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> >> ---
> >>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
> >>  drivers/media/usb/au0828/au0828.h      |   3 +
> >>  2 files changed, 152 insertions(+)
> >>
> >> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> >> index 4c90f28..fd2265c 100644
> >> --- a/drivers/media/usb/au0828/au0828-core.c
> >> +++ b/drivers/media/usb/au0828/au0828-core.c
> >> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
> >>  		return -EINVAL;
> >>  
> >>  	if (tuner) {
> >> +		dev->tuner = tuner;
> >>  		/* create tuner to decoder link in deactivated state */
> >>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
> >>  					    decoder, 0, 0);
> >> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
> >>  #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 ret = 0;
> >> +	struct media_device *mdev = entity->graph_obj.mdev;
> >> +	struct au0828_dev *dev;
> >> +
> >> +	if (!mdev)
> >> +		return -ENODEV;
> >> +
> >> +	/* for Audio 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;
> >> +	}  
> > 
> > This is wrong. There are devices without tuner (capture devices) and
> > without analog decoder (pure DVB devices).  
> 
> Removed linux-api from the list.
> 
> Yes this logic is making an assumption that both
> decoder and tuner are present. Based on your comment
> here, is the following check for decoder in 
> au0828_create_media_graph() incorrect? When decoder
> is null, au0828_usb_probe() bails out. Please see
> au0828_create_media_graph() return handling in
> au0828_usb_probe()?

It seems so. at its current state, au0828 always register a V4L2
node, except if !CONFIG_VIDEO_AU0828_V4L2. So, it is missing a

#ifdef CONFIG_VIDEO_AU0828_V4L2

inside it. I'll write such fixup.


> 
> 
>        /* Something bad happened! */
>         if (!decoder)
>                 return -EINVAL;
> 
> > 
> > In the case of pure DVB devices (e. g. no dev->decoder), it should
> > just enable the DVB path.
> > 
> > In the case of devices without tuner, it should use the same logic
> > needed to handle the S-Video/Composite connector inputs.
> > 
> > Btw, I'm not seeing how this logic would do the right thing if the user
> > selects either S-Video or Composite connectors.
> >   
> >> +
> >> +	/*
> >> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
> >> +		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;
> >> +		}
> >> +	}
> >> +
> >> +	list_for_each_entry(link, &sink->links, list) {
> >> +		/* Check sink, and source */
> >> +		if (link->sink->entity == sink &&
> >> +		    link->source->entity == dev->tuner) {
> >> +			found_link = link;
> >> +			break;
> >> +		}
> >> +	}
> >> +
> >> +	if (!found_link) {
> >> +		ret = -ENODEV;
> >> +		goto end;
> >> +	}
> >> +
> >> +	/* activate link between source and sink and start pipeline */
> >> +	source = found_link->source->entity;
> >> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
> >> +	if (ret) {
> >> +		pr_err(
> >> +			"Activate tuner link %s->%s. Error %d\n",
> >> +			source->name, sink->name, ret);
> >> +		goto end;
> >> +	}
> >> +
> >> +	ret = __media_entity_pipeline_start(entity, pipe);
> >> +	if (ret) {
> >> +		pr_err("Start Pipeline: %s->%s Error %d\n",
> >> +			source->name, entity->name, ret);
> >> +		ret = __media_entity_setup_link(found_link, 0);
> >> +		pr_err("Deactive link Error %d\n", ret);
> >> +		goto end;
> >> +	}  
> > 
> > Hmm... isn't it to early to activate the pipeline here? My original
> > guess is that, on the analog side, this should happen only at the stream
> > on code. Wouldn't this break apps like mythTV?
> >   
> >> +	/*
> >> +	 * save active link and active link owner to avoid audio
> >> +	 * deactivating video owned link from disable_source and
> >> +	 * vice versa
> >> +	*/
> >> +	dev->active_link = found_link;
> >> +	dev->active_link_owner = entity;
> >> +end:
> >> +	mutex_unlock(&mdev->graph_mutex);
> >> +	pr_debug("au0828_enable_source() end %s %d %d\n",
> >> +		entity->name, entity->function, ret);
> >> +	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->graph_obj.mdev;
> >> +	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;
> >> +	}  
> > 
> > Same note as before.  
> 
> Same comment as before here about au0828_create_media_graph()
> and au0828_usb_probe() handling.
> 
> >   
> >> +
> >> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
> >> +		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);
> >> +		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;
> >> +	}  
> > 
> > Most code here looks like the one at au0828_enable_source(). Wouldn't
> > be simpler to merge those code and add a "bool enable" to the function
> > parameters?  
> 
> I would rather keep these separate. A very short
> section is common really.
> 
> thanks,
> -- Shuah
> 
> >   
> >> +
> >> +end:
> >> +	mutex_unlock(&mdev->graph_mutex);
> >> +#endif
> >> +}
> >> +
> >>  static int au0828_media_device_register(struct au0828_dev *dev,
> >>  					struct usb_device *udev)
> >>  {
> >> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
> >>  			ret);
> >>  		return ret;
> >>  	}
> >> +	/* set enable_source */
> >> +	dev->media_dev->source_priv = (void *) dev;
> >> +	dev->media_dev->enable_source = au0828_enable_source;
> >> +	dev->media_dev->disable_source = au0828_disable_source;
> >>  #endif
> >>  	return 0;
> >>  }
> >> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
> >> index 54379ec..a7c88a1 100644
> >> --- a/drivers/media/usb/au0828/au0828.h
> >> +++ b/drivers/media/usb/au0828/au0828.h
> >> @@ -284,6 +284,9 @@ struct au0828_dev {
> >>  	struct media_entity input_ent[AU0828_MAX_INPUT];
> >>  	struct media_pad input_pad[AU0828_MAX_INPUT];
> >>  	struct media_entity_notify entity_notify;
> >> +	struct media_entity *tuner;
> >> +	struct media_link *active_link;
> >> +	struct media_entity *active_link_owner;
> >>  #endif
> >>  };
> >>    
> 
> 

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
@ 2016-02-09 10:51         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-09 10:51 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Mon, 08 Feb 2016 15:42:15 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> On 02/04/2016 03:26 AM, Mauro Carvalho Chehab wrote:
> > Em Wed, 03 Feb 2016 21:03:52 -0700
> > Shuah Khan <shuahkh@osg.samsung.com> escreveu:
> >   
> >> Add enable_source and disable_source handlers.
> >> The enable source handler is called from
> >> v4l2-core, dvb-core, and ALSA drivers to check
> >> if the shared media source is free. The disable
> >> source handler is called to release the shared
> >> media source.
> >>
> >> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> >> ---
> >>  drivers/media/usb/au0828/au0828-core.c | 149 +++++++++++++++++++++++++++++++++
> >>  drivers/media/usb/au0828/au0828.h      |   3 +
> >>  2 files changed, 152 insertions(+)
> >>
> >> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> >> index 4c90f28..fd2265c 100644
> >> --- a/drivers/media/usb/au0828/au0828-core.c
> >> +++ b/drivers/media/usb/au0828/au0828-core.c
> >> @@ -282,6 +282,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
> >>  		return -EINVAL;
> >>  
> >>  	if (tuner) {
> >> +		dev->tuner = tuner;
> >>  		/* create tuner to decoder link in deactivated state */
> >>  		ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
> >>  					    decoder, 0, 0);
> >> @@ -373,6 +374,150 @@ void au0828_media_graph_notify(struct media_entity *new, void *notify_data)
> >>  #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 ret = 0;
> >> +	struct media_device *mdev = entity->graph_obj.mdev;
> >> +	struct au0828_dev *dev;
> >> +
> >> +	if (!mdev)
> >> +		return -ENODEV;
> >> +
> >> +	/* for Audio 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;
> >> +	}  
> > 
> > This is wrong. There are devices without tuner (capture devices) and
> > without analog decoder (pure DVB devices).  
> 
> Removed linux-api from the list.
> 
> Yes this logic is making an assumption that both
> decoder and tuner are present. Based on your comment
> here, is the following check for decoder in 
> au0828_create_media_graph() incorrect? When decoder
> is null, au0828_usb_probe() bails out. Please see
> au0828_create_media_graph() return handling in
> au0828_usb_probe()?

It seems so. at its current state, au0828 always register a V4L2
node, except if !CONFIG_VIDEO_AU0828_V4L2. So, it is missing a

#ifdef CONFIG_VIDEO_AU0828_V4L2

inside it. I'll write such fixup.


> 
> 
>        /* Something bad happened! */
>         if (!decoder)
>                 return -EINVAL;
> 
> > 
> > In the case of pure DVB devices (e. g. no dev->decoder), it should
> > just enable the DVB path.
> > 
> > In the case of devices without tuner, it should use the same logic
> > needed to handle the S-Video/Composite connector inputs.
> > 
> > Btw, I'm not seeing how this logic would do the right thing if the user
> > selects either S-Video or Composite connectors.
> >   
> >> +
> >> +	/*
> >> +	 * For Audio 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->function != MEDIA_ENT_F_DTV_DEMOD)
> >> +		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;
> >> +		}
> >> +	}
> >> +
> >> +	list_for_each_entry(link, &sink->links, list) {
> >> +		/* Check sink, and source */
> >> +		if (link->sink->entity == sink &&
> >> +		    link->source->entity == dev->tuner) {
> >> +			found_link = link;
> >> +			break;
> >> +		}
> >> +	}
> >> +
> >> +	if (!found_link) {
> >> +		ret = -ENODEV;
> >> +		goto end;
> >> +	}
> >> +
> >> +	/* activate link between source and sink and start pipeline */
> >> +	source = found_link->source->entity;
> >> +	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
> >> +	if (ret) {
> >> +		pr_err(
> >> +			"Activate tuner link %s->%s. Error %d\n",
> >> +			source->name, sink->name, ret);
> >> +		goto end;
> >> +	}
> >> +
> >> +	ret = __media_entity_pipeline_start(entity, pipe);
> >> +	if (ret) {
> >> +		pr_err("Start Pipeline: %s->%s Error %d\n",
> >> +			source->name, entity->name, ret);
> >> +		ret = __media_entity_setup_link(found_link, 0);
> >> +		pr_err("Deactive link Error %d\n", ret);
> >> +		goto end;
> >> +	}  
> > 
> > Hmm... isn't it to early to activate the pipeline here? My original
> > guess is that, on the analog side, this should happen only at the stream
> > on code. Wouldn't this break apps like mythTV?
> >   
> >> +	/*
> >> +	 * save active link and active link owner to avoid audio
> >> +	 * deactivating video owned link from disable_source and
> >> +	 * vice versa
> >> +	*/
> >> +	dev->active_link = found_link;
> >> +	dev->active_link_owner = entity;
> >> +end:
> >> +	mutex_unlock(&mdev->graph_mutex);
> >> +	pr_debug("au0828_enable_source() end %s %d %d\n",
> >> +		entity->name, entity->function, ret);
> >> +	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->graph_obj.mdev;
> >> +	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;
> >> +	}  
> > 
> > Same note as before.  
> 
> Same comment as before here about au0828_create_media_graph()
> and au0828_usb_probe() handling.
> 
> >   
> >> +
> >> +	if (entity->function != MEDIA_ENT_F_DTV_DEMOD)
> >> +		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);
> >> +		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;
> >> +	}  
> > 
> > Most code here looks like the one at au0828_enable_source(). Wouldn't
> > be simpler to merge those code and add a "bool enable" to the function
> > parameters?  
> 
> I would rather keep these separate. A very short
> section is common really.
> 
> thanks,
> -- Shuah
> 
> >   
> >> +
> >> +end:
> >> +	mutex_unlock(&mdev->graph_mutex);
> >> +#endif
> >> +}
> >> +
> >>  static int au0828_media_device_register(struct au0828_dev *dev,
> >>  					struct usb_device *udev)
> >>  {
> >> @@ -403,6 +548,10 @@ static int au0828_media_device_register(struct au0828_dev *dev,
> >>  			ret);
> >>  		return ret;
> >>  	}
> >> +	/* set enable_source */
> >> +	dev->media_dev->source_priv = (void *) dev;
> >> +	dev->media_dev->enable_source = au0828_enable_source;
> >> +	dev->media_dev->disable_source = au0828_disable_source;
> >>  #endif
> >>  	return 0;
> >>  }
> >> diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
> >> index 54379ec..a7c88a1 100644
> >> --- a/drivers/media/usb/au0828/au0828.h
> >> +++ b/drivers/media/usb/au0828/au0828.h
> >> @@ -284,6 +284,9 @@ struct au0828_dev {
> >>  	struct media_entity input_ent[AU0828_MAX_INPUT];
> >>  	struct media_pad input_pad[AU0828_MAX_INPUT];
> >>  	struct media_entity_notify entity_notify;
> >> +	struct media_entity *tuner;
> >> +	struct media_link *active_link;
> >> +	struct media_entity *active_link_owner;
> >>  #endif
> >>  };
> >>    
> 
> 

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
  2016-02-08 23:00         ` Shuah Khan
@ 2016-02-09 13:42           ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-09 13:42 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs, johan, klock.android, nenggun.kim,
	j.anaszewski, geliangtang, linux-kernel, linux-media, alsa-devel

Em Mon, 08 Feb 2016 16:00:26 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> >>> +	ret = __media_entity_pipeline_start(entity, pipe);
> >>> +	if (ret) {
> >>> +		pr_err("Start Pipeline: %s->%s Error %d\n",
> >>> +			source->name, entity->name, ret);
> >>> +		ret = __media_entity_setup_link(found_link, 0);
> >>> +		pr_err("Deactive link Error %d\n", ret);
> >>> +		goto end;
> >>> +	}  
> >>
> >> Hmm... isn't it to early to activate the pipeline here? My original
> >> guess is that, on the analog side, this should happen only at the stream
> >> on code. Wouldn't this break apps like mythTV?  
> 
> On analog side, there are a few ioctls that
> change the configuration on the tuner way
> before stream on step. Is there a reason to
> separate the setup_link() and pipeline_start()
> steps? I can separate these two steps, but I
> am not really seeing the reason for that.

I'm actually ok with that, provided that it won't break existing
apps. Did you test it with MythTV?

Regards,
Mauro

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 20/22] media: au0828 add enable, disable source handlers
@ 2016-02-09 13:42           ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 94+ messages in thread
From: Mauro Carvalho Chehab @ 2016-02-09 13:42 UTC (permalink / raw)
  To: Shuah Khan
  Cc: tiwai, clemens, hans.verkuil, laurent.pinchart, sakari.ailus,
	javier, pawel, m.szyprowski, kyungmin.park, perex, arnd,
	dan.carpenter, tvboxspy, crope, ruchandani.tina, corbet,
	chehabrafael, k.kozlowski, stefanr, inki.dae, jh1009.sung,
	elfring, prabhakar.csengg, sw0312.kim, p.zabel, ricardo.ribalda,
	labbott, pierre-louis.bossart, ricard.wanderlof, julian,
	takamichiho, dominic.sacre, misterpib, daniel, gtmkramer,
	normalperson, joe, linuxbugs

Em Mon, 08 Feb 2016 16:00:26 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> >>> +	ret = __media_entity_pipeline_start(entity, pipe);
> >>> +	if (ret) {
> >>> +		pr_err("Start Pipeline: %s->%s Error %d\n",
> >>> +			source->name, entity->name, ret);
> >>> +		ret = __media_entity_setup_link(found_link, 0);
> >>> +		pr_err("Deactive link Error %d\n", ret);
> >>> +		goto end;
> >>> +	}  
> >>
> >> Hmm... isn't it to early to activate the pipeline here? My original
> >> guess is that, on the analog side, this should happen only at the stream
> >> on code. Wouldn't this break apps like mythTV?  
> 
> On analog side, there are a few ioctls that
> change the configuration on the tuner way
> before stream on step. Is there a reason to
> separate the setup_link() and pipeline_start()
> steps? I can separate these two steps, but I
> am not really seeing the reason for that.

I'm actually ok with that, provided that it won't break existing
apps. Did you test it with MythTV?

Regards,
Mauro

^ permalink raw reply	[flat|nested] 94+ messages in thread

end of thread, other threads:[~2016-02-09 13:42 UTC | newest]

Thread overview: 94+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-04  4:03 [PATCH v2 00/22] Sharing media resources across ALSA and au0828 drivers Shuah Khan
2016-02-04  4:03 ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 01/22] uapi/media.h: Declare interface types for ALSA Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  8:38   ` Mauro Carvalho Chehab
2016-02-04  8:38     ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 02/22] media: Add ALSA Media Controller function entities Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  8:40   ` Mauro Carvalho Chehab
2016-02-04  8:40     ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 03/22] media: Media Controller register/unregister entity_notify API Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  9:03   ` Mauro Carvalho Chehab
2016-02-04  9:03     ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 04/22] media: Media Controller enable/disable source handler API Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 05/22] media: Media Controller export non locking __media_entity_setup_link() Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 06/22] media: Media Controller non-locking __media_entity_pipeline_start/stop() Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  9:18   ` Mauro Carvalho Chehab
2016-02-04  9:18     ` Mauro Carvalho Chehab
2016-02-04 15:00     ` Shuah Khan
2016-02-04 15:00       ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 07/22] media: v4l-core add enable/disable source common interfaces Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  6:29   ` kbuild test robot
2016-02-04  6:29     ` kbuild test robot
2016-02-04  9:25   ` Mauro Carvalho Chehab
2016-02-04  9:25     ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 08/22] media: Move au8522_media_pads enum to au8522.h from au8522_priv.h Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 09/22] media: au8522 change to create MC pad for ALSA Audio Out Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 10/22] media: Change v4l-core to check if source is free Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 11/22] media: dvb-frontend invoke enable/disable_source handlers Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  9:35   ` Mauro Carvalho Chehab
2016-02-04  9:35     ` Mauro Carvalho Chehab
2016-02-04 14:58     ` Shuah Khan
2016-02-04 14:58       ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 12/22] media: au0828 video remove au0828_enable_analog_tuner() Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  9:37   ` Mauro Carvalho Chehab
2016-02-04  9:37     ` Mauro Carvalho Chehab
2016-02-04 14:49     ` Shuah Khan
2016-02-04 14:49       ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 13/22] media: au0828 video change to use v4l_enable_media_source() Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04 10:00   ` Mauro Carvalho Chehab
2016-02-04 10:00     ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 14/22] media: au0828 change to use Managed Media Controller API Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04 10:05   ` Mauro Carvalho Chehab
2016-02-04 10:05     ` Mauro Carvalho Chehab
2016-02-04 10:08     ` Mauro Carvalho Chehab
2016-02-04 10:08       ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 15/22] media: au0828 handle media_init and media_register window Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 16/22] media: au0828 create tuner to decoder link in disabled state Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 17/22] media: au0828 disable tuner to demod link Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 18/22] media: au0828 Use au8522_media_pads enum for pad defines Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 19/22] media: au0828-core register entity_notify hook Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04  4:03 ` [PATCH v2 20/22] media: au0828 add enable, disable source handlers Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04 10:26   ` Mauro Carvalho Chehab
2016-02-04 10:26     ` Mauro Carvalho Chehab
2016-02-08 22:42     ` Shuah Khan
2016-02-08 22:42       ` Shuah Khan
2016-02-08 23:00       ` Shuah Khan
2016-02-08 23:00         ` Shuah Khan
2016-02-09 13:42         ` Mauro Carvalho Chehab
2016-02-09 13:42           ` Mauro Carvalho Chehab
2016-02-09 10:51       ` Mauro Carvalho Chehab
2016-02-09 10:51         ` Mauro Carvalho Chehab
2016-02-04  4:03 ` [PATCH v2 21/22] sound/usb: Use Media Controller API to share media resources Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04 10:36   ` Mauro Carvalho Chehab
2016-02-04 10:36     ` Mauro Carvalho Chehab
2016-02-04 10:46     ` Takashi Iwai
2016-02-04 10:46       ` Takashi Iwai
2016-02-07 11:25   ` kbuild test robot
2016-02-07 11:25     ` kbuild test robot
2016-02-04  4:03 ` [PATCH v2 22/22] media: Ensure media device unregister is done only once Shuah Khan
2016-02-04  4:03   ` Shuah Khan
2016-02-04 10:40   ` Mauro Carvalho Chehab
2016-02-04 10:40     ` Mauro Carvalho Chehab
2016-02-04 10:54 ` [PATCH v2 00/22] Sharing media resources across ALSA and au0828 drivers Mauro Carvalho Chehab
2016-02-04 10:54   ` Mauro Carvalho Chehab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.