Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1303063 > unrolled thread

[PATCH 00/31] Sharing media resources across ALSA and au0828 drivers

Started byShuah Khan <shuahkh@osg.samsung.com>
First post2016-01-06 21:40 +0100
Last post2016-01-06 22:10 +0100
Articles 14 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 00/31] Sharing media resources across ALSA and au0828 drivers  Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 21:40 +0100
    [PATCH 05/31] media: Media Controller fix to not let stream_count go negative Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 21:40 +0100
    [PATCH 01/31] uapi/media.h: Declare interface types for ALSA Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 21:40 +0100
    [PATCH 30/31] sound/usb: Check media device unregister progress state Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:00 +0100
    [PATCH 28/31] media: au0828 create link between ALSA Mixer and decoder Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:00 +0100
    [PATCH 04/31] media: Media Controller enable/disable source handler API Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:00 +0100
    [PATCH 31/31] media: au0828 change to check media device unregister progress state Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:00 +0100
    [PATCH 11/31] media: au8522 change to create MC pad for ALSA Audio Out Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:00 +0100
    [PATCH 29/31] media: track media device unregister in progress Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:00 +0100
    [PATCH 25/31] media: au0828 fix to not call media_device_unregister_entity_notify() Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:10 +0100
    [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:10 +0100
      Re: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API Takashi Iwai <tiwai@suse.de> - 2016-01-07 16:50 +0100
        Re: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media  Controller API Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-07 21:30 +0100
    [PATCH 27/31] sound/usb: Create media mixer function and control interface entities Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-06 22:10 +0100

#1303063 — [PATCH 00/31] Sharing media resources across ALSA and au0828 drivers

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 21:40 +0100
Subject[PATCH 00/31] Sharing media resources across ALSA and au0828 drivers
Message-ID<qO329-63K-3@gated-at.bofh.it>
This patch series updates ALSA driver, and au0828 core
driver to use Managed Media controller API and Media
Controller API to share tuner.

Media Controller Next Generation API has been enhanced
to add two new interfaces to register and unregister
entity_notify hooks to allow drivers to take appropriate
actions when as new entities get added to the shared media
device.

Mauro and Takashi: I am hoping you can both coordinate
and decide on ALSA patches once the reviews are done
and the patches look good.

Design Highlights:
1. ALSA to check for resources and hold in snd_usb_hw_params(),
   and release from snd_usb_hw_free(). This change fixed the
   lockdep warnings seen when resources were held in
   TRIGGER_START and released from TRIGGER_STOP which could
   run in IRQ context. I acknowledge Clemens Ladisch for
   suggesting the correct places to hold/free resources to
   avoid IRQ path complications.
2. The Bridge driver (au0828) owns and drives the graph creation
   as well as enabling and disabling tuner. It also keeps state
   information to avoid graph walks in enable_source and
   disable_source handler. I acknowledge Hans Verkuil for his
   suggestions and ideas for this change.

Tested exclusion between digital, analog, and audio to ensure
when tuner has an active link to DVB FE, analog, and audio will
detect and honor the tuner busy conditions and vice versa.

Please find the graphs generated using mc_nextgen_test tool at
various points during testing at:
https://drive.google.com/folderview?id=0B0NIL0BQg-AlRndaaXViSXdPeTA&usp=sharing

This patch series is a rebase and update to the latest Media
Controller Next Gen API of the Media Controller Next Generation
API port.

Rebase highlights:
1. Changes to videobuf2 framework required additional
   v4l2 helper function to enable the tuner from
   vb2_core_streamon(). Patch 9 has this work.
2. Media device initialization and registration steps
   are now split in the latest Media Controller Next Gen
   API. This required changes to au0828 and ALSA to coordinate
   initialization and registration of the Managed Media Device
   they share. Patch 19 shows au0828 changes. ALSA changes
   for this are folded into the main ALSA patch 26.
3. Media device unregistration does more cleanup now. As a
   result, au0828 and ALSA need to coordinate so media device
   is done only once. These changes are in patches: 29, 30,
   and 31.
4. In addition, media device resources cleanup gets done
   before snd_card_disconnect(). This work is in patch 30.

Media Controller Next Generation API port from Media Controller API:
The patch series below was a port of the Patch v3 - Media Controller API
to Next Gen API and Mixer patch update to address comments and bug fixes:
https://www.mail-archive.com/linux-media@vger.kernel.org/msg93086.html
https://www.mail-archive.com/linux-media@vger.kernel.org/msg93417.html

Patch v3 - Media Controller API:
https://www.mail-archive.com/linux-media@vger.kernel.org/msg92572.html

Mauro Carvalho Chehab (1):
  uapi/media.h: Declare interface types for ALSA

Shuah Khan (30):
  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 fix to not let stream_count go negative
  media: Media Controller export non locking __media_entity_setup_link()
  media: Media Controller non-locking
    __media_entity_pipeline_start/stop()
  media: v4l-core add v4l_enable/disable_media_tuner() helper functions
  media: v4l2-core add v4l_vb2q_enable_media_tuner() helper
  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: au0828 Use au8522_media_pads enum for pad defines
  media: au0828 fix au0828_create_media_graph() entity checks
  media: Change v4l-core to check for tuner availability
  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_tuner()
  media: au0828 change to use Managed Media Controller API
  media: au0828 handle media_init and media_register window
  media: au0828 change to register/unregister entity_notify hook
  media: au0828 create tuner to decoder link in deactivated state
  media: dvb-core create tuner to demod pad link in disabled state
  media: au0828 implement enable_source and disable_source handlers
  media: au0828 fix null pointer reference in
    au0828_create_media_graph()
  media: au0828 fix to not call media_device_unregister_entity_notify()
  sound/usb: Update ALSA driver to use Managed Media Controller API
  sound/usb: Create media mixer function and control interface entities
  media: au0828 create link between ALSA Mixer and decoder
  media: track media device unregister in progress
  sound/usb: Check media device unregister progress state
  media: au0828 change to check media device unregister progress state

 drivers/media/dvb-core/dvb_frontend.c        | 139 ++---------
 drivers/media/dvb-core/dvb_frontend.h        |   3 +
 drivers/media/dvb-core/dvbdev.c              |   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                 |  66 ++++-
 drivers/media/media-entity.c                 |  65 +++--
 drivers/media/usb/au0828/au0828-core.c       | 355 ++++++++++++++++++++++-----
 drivers/media/usb/au0828/au0828-video.c      |  75 +-----
 drivers/media/usb/au0828/au0828.h            |   9 +
 drivers/media/v4l2-core/v4l2-dev.c           |  48 ++++
 drivers/media/v4l2-core/v4l2-fh.c            |   1 +
 drivers/media/v4l2-core/v4l2-ioctl.c         |  29 +++
 drivers/media/v4l2-core/videobuf2-core.c     |   4 +
 include/media/media-device.h                 |  61 +++++
 include/media/media-entity.h                 |  12 +
 include/media/v4l2-dev.h                     |   5 +
 include/uapi/linux/media.h                   |  17 +-
 sound/usb/Makefile                           |  15 +-
 sound/usb/card.c                             |  16 ++
 sound/usb/card.h                             |   1 +
 sound/usb/media.c                            | 325 ++++++++++++++++++++++++
 sound/usb/media.h                            |  75 ++++++
 sound/usb/mixer.h                            |   1 +
 sound/usb/pcm.c                              |  26 +-
 sound/usb/quirks-table.h                     |   1 +
 sound/usb/quirks.c                           |   9 +-
 sound/usb/stream.c                           |   1 +
 sound/usb/usbaudio.h                         |   2 +
 30 files changed, 1111 insertions(+), 270 deletions(-)
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1303064 — [PATCH 05/31] media: Media Controller fix to not let stream_count go negative

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 21:40 +0100
Subject[PATCH 05/31] media: Media Controller fix to not let stream_count go negative
Message-ID<qO32c-63K-57@gated-at.bofh.it>
In reply to#1303063
Add a range check to not let the stream_count become negative.
Wthout this check, calls to stop pipeline when there is no active
pipeline will result in stream_count < 0 condition and lock and
preventing link state (activate/deactivate) changes. This will
happen from error leg in start pipeline interface.

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

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 6e02d19..78486a9 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -464,9 +464,12 @@ error:
 	media_entity_graph_walk_start(graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(graph))) {
-		entity_err->stream_count--;
-		if (entity_err->stream_count == 0)
-			entity_err->pipe = NULL;
+		/* don't let the stream_count go negative */
+		if (entity->stream_count > 0) {
+			entity_err->stream_count--;
+			if (entity_err->stream_count == 0)
+				entity_err->pipe = NULL;
+		}
 
 		/*
 		 * We haven't increased stream_count further than this
@@ -498,9 +501,12 @@ void media_entity_pipeline_stop(struct media_entity *entity)
 	media_entity_graph_walk_start(graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(graph))) {
-		entity->stream_count--;
-		if (entity->stream_count == 0)
-			entity->pipe = NULL;
+		/* don't let the stream_count go negative */
+		if (entity->stream_count > 0) {
+			entity->stream_count--;
+			if (entity->stream_count == 0)
+				entity->pipe = NULL;
+		}
 	}
 
 	if (!--pipe->streaming_count)
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303065 — [PATCH 01/31] uapi/media.h: Declare interface types for ALSA

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 21:40 +0100
Subject[PATCH 01/31] uapi/media.h: Declare interface types for ALSA
Message-ID<qO32c-63K-59@gated-at.bofh.it>
In reply to#1303063
From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

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

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
---
 drivers/media/media-entity.c | 12 ++++++++++++
 include/uapi/linux/media.h   |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index eb38bc3..6e02d19 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -65,6 +65,18 @@ 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";
 	default:
 		return "unknown-intf";
 	}
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index cacfceb..75cbe92 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -252,6 +252,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 */
 
@@ -267,6 +268,13 @@ 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)
 
+#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)
+
 /*
  * MC next gen API definitions
  *
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303068 — [PATCH 30/31] sound/usb: Check media device unregister progress state

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:00 +0100
Subject[PATCH 30/31] sound/usb: Check media device unregister progress state
Message-ID<qO3lv-6bl-3@gated-at.bofh.it>
In reply to#1303063
Change to release media resources for pcm streams
and mixer before snd_card_disconnect() is done from
usb_audio_disconnect(). The stream and mixer resource
release interfaces access managed media resources
(device resources) created on the usb device parent.
These interfaces should be called before the last
put_device() which releases all the device resources.
In addition, changed the stream and mixer resource
release interfaces to check if media device unregister
is in progress and avoid calling Media Controller API
to unregister entities and remove devnodes. Media device
unregister takes care of all of this. This fixes the
the general protection faults while snd-usb-audio was
cleaning up media resources for pcm streams and mixers.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 sound/usb/card.c   |  8 ++++++--
 sound/usb/media.c  | 41 +++++++++++++++++++++++++++++++----------
 sound/usb/media.h  |  4 ++--
 sound/usb/stream.c |  1 -
 4 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index e965982..8959ccb 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -608,6 +608,12 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		 */
 		wait_event(chip->shutdown_wait,
 			   !atomic_read(&chip->usage_count));
+
+		/* release media pcm stream resources */
+		media_stream_delete(chip);
+		/* delete mixer media resources */
+		media_mixer_delete(chip);
+
 		snd_card_disconnect(card);
 		/* release the pcm resources */
 		list_for_each_entry(as, &chip->pcm_list, list) {
@@ -621,8 +627,6 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		list_for_each(p, &chip->midi_list) {
 			snd_usbmidi_disconnect(p);
 		}
-		/* delete mixer media resources */
-		media_mixer_delete(chip);
 		/* release mixer resources */
 		list_for_each_entry(mixer, &chip->mixer_list, list) {
 			snd_usb_mixer_disconnect(mixer);
diff --git a/sound/usb/media.c b/sound/usb/media.c
index 4f99086..9d29e1d 100644
--- a/sound/usb/media.c
+++ b/sound/usb/media.c
@@ -98,8 +98,11 @@ void media_device_delete(struct usb_interface *iface)
 	struct usb_device *usbdev = interface_to_usbdev(iface);
 
 	mdev = media_device_find_devres(&usbdev->dev);
-	if (mdev && media_devnode_is_registered(&mdev->devnode))
-		media_device_unregister(mdev);
+	if (mdev) {
+		if (media_devnode_is_registered(&mdev->devnode) &&
+		    !media_device_is_unregister_in_progress(mdev))
+			media_device_unregister(mdev);
+	}
 }
 
 static int media_enable_source(struct media_ctl *mctl)
@@ -177,7 +180,7 @@ int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 	return 0;
 }
 
-void media_stream_delete(struct snd_usb_substream *subs)
+static void __media_stream_delete(struct snd_usb_substream *subs)
 {
 	struct media_ctl *mctl = (struct media_ctl *) subs->media_ctl;
 
@@ -185,7 +188,7 @@ void media_stream_delete(struct snd_usb_substream *subs)
 		struct media_device *mdev;
 
 		mdev = media_device_find_devres(&subs->dev->dev);
-		if (mdev) {
+		if (mdev && !media_device_is_unregister_in_progress(mdev)) {
 			media_devnode_remove(mctl->intf_devnode);
 			media_device_unregister_entity(&mctl->media_entity);
 			media_entity_cleanup(&mctl->media_entity);
@@ -195,6 +198,21 @@ void media_stream_delete(struct snd_usb_substream *subs)
 	}
 }
 
+void media_stream_delete(struct snd_usb_audio *chip)
+{
+	struct snd_usb_stream *as;
+
+	list_for_each_entry(as, &chip->pcm_list, list) {
+		struct snd_usb_substream *subs;
+		int idx;
+
+		for (idx = 0; idx < 2; idx++) {
+			subs = &as->substream[idx];
+			__media_stream_delete(subs);
+		}
+	}
+}
+
 int media_start_pipeline(struct snd_usb_substream *subs)
 {
 	struct media_ctl *mctl = (struct media_ctl *) subs->media_ctl;
@@ -283,22 +301,25 @@ void media_mixer_delete(struct snd_usb_audio *chip)
 	struct media_device *mdev;
 
 	mdev = media_device_find_devres(&chip->dev->dev);
-	if (!mdev)
-		return;
 
+	if (chip->ctl_intf_media_devnode) {
+		if (mdev && !media_device_is_unregister_in_progress(mdev))
+			media_devnode_remove(chip->ctl_intf_media_devnode);
+		chip->ctl_intf_media_devnode = NULL;
+	}
 	list_for_each_entry(mixer, &chip->mixer_list, list) {
 		struct media_mixer_ctl *mctl;
 
 		mctl = (struct media_mixer_ctl *) mixer->media_mixer_ctl;
 		if (!mixer->media_mixer_ctl)
 			continue;
-
-		media_device_unregister_entity(&mctl->media_entity);
-		media_entity_cleanup(&mctl->media_entity);
+		if (mdev && !media_device_is_unregister_in_progress(mdev)) {
+			media_device_unregister_entity(&mctl->media_entity);
+			media_entity_cleanup(&mctl->media_entity);
+		}
 		kfree(mctl);
 		mixer->media_mixer_ctl = NULL;
 	}
-	media_devnode_remove(chip->ctl_intf_media_devnode);
 }
 
 #endif
diff --git a/sound/usb/media.h b/sound/usb/media.h
index 00884b5..bd1b1ec 100644
--- a/sound/usb/media.h
+++ b/sound/usb/media.h
@@ -52,7 +52,7 @@ int media_device_create(struct snd_usb_audio *chip,
 void media_device_delete(struct usb_interface *iface);
 int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 			int stream);
-void media_stream_delete(struct snd_usb_substream *subs);
+void media_stream_delete(struct snd_usb_audio *chip);
 int media_start_pipeline(struct snd_usb_substream *subs);
 void media_stop_pipeline(struct snd_usb_substream *subs);
 int media_mixer_init(struct snd_usb_audio *chip);
@@ -65,7 +65,7 @@ static inline void media_device_delete(struct usb_interface *iface) { }
 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 void media_stream_delete(struct snd_usb_audio *chip) { }
 static inline int media_start_pipeline(struct snd_usb_substream *subs)
 					{ return 0; }
 static inline void media_stop_pipeline(struct snd_usb_substream *subs) { }
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 789e515..f96f539 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -53,7 +53,6 @@ static void free_substream(struct snd_usb_substream *subs)
 		kfree(fp);
 	}
 	kfree(subs->rate_list.list);
-	media_stream_delete(subs);
 }
 
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303069 — [PATCH 28/31] media: au0828 create link between ALSA Mixer and decoder

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:00 +0100
Subject[PATCH 28/31] media: au0828 create link between ALSA Mixer and decoder
Message-ID<qO3lw-6bl-11@gated-at.bofh.it>
In reply to#1303063
Change au0828_create_media_graph() to create pad link
between MEDIA_ENT_F_AUDIO_MIXER entity and decoder's
AU8522_PAD_AUDIO_OUT. With mixer entity now linked to
decoder, change to link MEDIA_ENT_F_AUDIO_CAPTURE to
mixer's source pad.

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

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 722e073..886fb28 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -264,6 +264,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 	struct media_entity *entity;
 	struct media_entity *tuner = NULL, *decoder = NULL;
 	struct media_entity *audio_capture = NULL;
+	struct media_entity *mixer = NULL;
 	int i, ret;
 
 	if (!mdev)
@@ -284,6 +285,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 		case MEDIA_ENT_F_AUDIO_CAPTURE:
 			audio_capture = entity;
 			break;
+		case MEDIA_ENT_F_AUDIO_MIXER:
+			mixer = entity;
+			break;
 		}
 	}
 
@@ -356,14 +360,21 @@ static int au0828_create_media_graph(struct au0828_dev *dev)
 			}
 		}
 	}
-	if (audio_capture && !dev->audio_capture_linked) {
-		ret = media_create_pad_link(decoder, AU8522_PAD_AUDIO_OUT,
-					    audio_capture, 0,
+	if (mixer && audio_capture && !dev->audio_capture_linked) {
+		ret = media_create_pad_link(mixer, 1, audio_capture, 0,
 					    MEDIA_LNK_FL_ENABLED);
 		if (ret)
 			return ret;
 		dev->audio_capture_linked = 1;
 	}
+	if (mixer && !dev->mixer_linked) {
+		ret = media_create_pad_link(decoder, AU8522_PAD_AUDIO_OUT,
+					    mixer, 0,
+					    MEDIA_LNK_FL_ENABLED);
+		if (ret)
+			return ret;
+		dev->mixer_linked = 1;
+	}
 #endif
 	return 0;
 }
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 3707664..b9aa74f 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -289,6 +289,7 @@ struct au0828_dev {
 	bool vdev_linked;
 	bool vbi_linked;
 	bool audio_capture_linked;
+	bool mixer_linked;
 	struct media_link *active_link;
 	struct media_entity *active_link_owner;
 #endif
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303070 — [PATCH 04/31] media: Media Controller enable/disable source handler API

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:00 +0100
Subject[PATCH 04/31] media: Media Controller enable/disable source handler API
Message-ID<qO3lw-6bl-7@gated-at.bofh.it>
In reply to#1303063
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 need to run these handlers. The enable_source handler
finds source entity for the passed in entity and check if it is
available, and activate the link using __media_entity_setup_link()
interface. Bridge driver is expected to implement and set these
handlers and private data when media_device is registered or when
bridge driver finds the media_device during probe. This is to enable
the use-case to find tuner entity connected to the decoder entity and
check if it is available, and activate it and start pipeline between
the source and the entity. The disable_source handler deactivates the
link and stops the pipeline. This handler can be invoked from the
media core (v4l-core, dvb-core) as well as other drivers such as ALSA
that control the media device.

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 6520d1c..04b6c2e 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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303071 — [PATCH 31/31] media: au0828 change to check media device unregister progress state

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:00 +0100
Subject[PATCH 31/31] media: au0828 change to check media device unregister progress state
Message-ID<qO3lw-6bl-17@gated-at.bofh.it>
In reply to#1303063
Change au0828_unregister_media_device() to check media
device media device unregister is in progress and avoid
calling media_device_unregister() and other cleanup done
in au0828_unregister_media_device().

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

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 886fb28..de357a2 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -136,7 +136,9 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 	if (dev->media_dev &&
-		media_devnode_is_registered(&dev->media_dev->devnode)) {
+		media_devnode_is_registered(&dev->media_dev->devnode) &&
+		!media_device_is_unregister_in_progress(dev->media_dev)) {
+
 		media_device_unregister(dev->media_dev);
 		media_device_cleanup(dev->media_dev);
 		dev->media_dev = NULL;
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303072 — [PATCH 11/31] media: au8522 change to create MC pad for ALSA Audio Out

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:00 +0100
Subject[PATCH 11/31] media: au8522 change to create MC pad for ALSA Audio Out
Message-ID<qO3lw-6bl-29@gated-at.bofh.it>
In reply to#1303063
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 9674cef..2c53b61 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -775,6 +775,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303073 — [PATCH 29/31] media: track media device unregister in progress

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:00 +0100
Subject[PATCH 29/31] media: track media device unregister in progress
Message-ID<qO3lw-6bl-27@gated-at.bofh.it>
In reply to#1303063
Add support to track media device unregister in progress
state to prevent more than one driver entering unregister.
This enables fixing the general protection faults while
snd-usb-audio was cleaning up media resources for pcm
streams and mixers. In this patch a new interface is added
to return the unregister in progress state. Subsequent
patches to snd-usb-audio and au0828-core use this interface
to avoid entering unregister and attempting to unregister
entities and remove devnodes while unregister is in progress.
Media device unregister removes entities and interface nodes.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 drivers/media/media-device.c |  5 ++++-
 include/media/media-device.h | 17 +++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 20c85a9..1bb9a5f 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -749,10 +749,13 @@ void media_device_unregister(struct media_device *mdev)
 	spin_lock(&mdev->lock);
 
 	/* Check if mdev was ever registered at all */
-	if (!media_devnode_is_registered(&mdev->devnode)) {
+	/* check if unregister is in progress */
+	if (!media_devnode_is_registered(&mdev->devnode) ||
+	    mdev->unregister_in_progress) {
 		spin_unlock(&mdev->lock);
 		return;
 	}
+	mdev->unregister_in_progress = true;
 
 	/* Remove all entities from the media device */
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
diff --git a/include/media/media-device.h b/include/media/media-device.h
index 04b6c2e..0807292 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -332,6 +332,10 @@ struct media_device {
 	spinlock_t lock;
 	/* Serializes graph operations. */
 	struct mutex graph_mutex;
+	/* Tracks unregister in progress state to prevent
+	 * more than one driver entering unregister
+	*/
+	bool unregister_in_progress;
 
 	/* Handlers to find source entity for the sink entity and
 	 * check if it is available, and activate the link using
@@ -365,6 +369,7 @@ struct media_device {
 /* media_devnode to media_device */
 #define to_media_device(node) container_of(node, struct media_device, devnode)
 
+
 /**
  * media_entity_enum_init - Initialise an entity enumeration
  *
@@ -553,6 +558,12 @@ struct media_device *media_device_get_devres(struct device *dev);
  * @dev: pointer to struct &device.
  */
 struct media_device *media_device_find_devres(struct device *dev);
+/* return unregister in progress state */
+static inline bool media_device_is_unregister_in_progress(
+					struct media_device *mdev)
+{
+	return mdev->unregister_in_progress;
+}
 
 /* Iterate over all entities. */
 #define media_device_for_each_entity(entity, mdev)			\
@@ -569,6 +580,7 @@ struct media_device *media_device_find_devres(struct device *dev);
 /* Iterate over all links. */
 #define media_device_for_each_link(link, mdev)			\
 	list_for_each_entry(link, &(mdev)->links, graph_obj.list)
+
 #else
 static inline int media_device_register(struct media_device *mdev)
 {
@@ -604,5 +616,10 @@ static inline struct media_device *media_device_find_devres(struct device *dev)
 {
 	return NULL;
 }
+static inline bool media_device_is_unregister_in_progress(
+					struct media_device *mdev)
+{
+	return false;
+}
 #endif /* CONFIG_MEDIA_CONTROLLER */
 #endif
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303077 — [PATCH 25/31] media: au0828 fix to not call media_device_unregister_entity_notify()

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:10 +0100
Subject[PATCH 25/31] media: au0828 fix to not call media_device_unregister_entity_notify()
Message-ID<qO3vc-6u0-3@gated-at.bofh.it>
In reply to#1303063
entity_notify handlers are removed from media_device_unregister().
There is no need to call media_device_unregister_entity_notify()
to do that right before calling media_device_unregister().

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

diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 9497ad1..722e073 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -137,8 +137,6 @@ static void au0828_unregister_media_device(struct au0828_dev *dev)
 #ifdef CONFIG_MEDIA_CONTROLLER
 	if (dev->media_dev &&
 		media_devnode_is_registered(&dev->media_dev->devnode)) {
-		media_device_unregister_entity_notify(dev->media_dev,
-						      &dev->entity_notify);
 		media_device_unregister(dev->media_dev);
 		media_device_cleanup(dev->media_dev);
 		dev->media_dev = NULL;
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303084 — [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:10 +0100
Subject[PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API
Message-ID<qO3ve-6u0-29@gated-at.bofh.it>
In reply to#1303063
Change ALSA driver to use Managed Media Managed Controller
API to share tuner with DVB and V4L2 drivers that control
AU0828 media device.  Media device is created based on a
newly added field value in the struct snd_usb_audio_quirk.
Using this approach, the media controller API usage can be
added for a specific device. In this patch, Media Controller
API is enabled for AU0828 hw. snd_usb_create_quirk() will
check this new field, if set will create a media device using
media_device_get_devres() interface.

media_device_get_devres() will allocate a new media device
devres or return an existing one, if it finds one.

During probe, media usb driver could have created the media
device devres. It will then initialze (if necessary) and
register the media device if it isn't already initialized
and registered. Media device unregister is done from
usb_audio_disconnect().

During probe, media usb driver could have created the
media device devres. It will then register the media
device if it isn't already registered. Media device
unregister is done from usb_audio_disconnect().

New structure media_ctl is added to group the new
fields to support media entity and links. This new
structure is added to struct snd_usb_substream.

A new entity_notify hook and a new ALSA capture media
entity are registered from snd_usb_pcm_open() after
setting up hardware information for the PCM device.

When a new entity is registered, Media Controller API
interface media_device_register_entity() invokes all
registered entity_notify hooks for the media device.
ALSA entity_notify hook parses all the entity list to
find a link from decoder it ALSA entity. This indicates
that the bridge driver created a link from decoder to
ALSA capture entity.

ALSA will attempt to enable the tuner to link the tuner
to the decoder calling enable_source handler if one is
provided by the bridge driver prior to starting Media
pipeline from snd_usb_hw_params(). If enable_source returns
with tuner busy condition, then snd_usb_hw_params() will fail
with -EBUSY. Media pipeline is stopped from snd_usb_hw_free().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 sound/usb/Makefile       |  15 +++-
 sound/usb/card.c         |   7 ++
 sound/usb/card.h         |   1 +
 sound/usb/media.c        | 214 +++++++++++++++++++++++++++++++++++++++++++++++
 sound/usb/media.h        |  54 ++++++++++++
 sound/usb/pcm.c          |  26 ++++--
 sound/usb/quirks-table.h |   1 +
 sound/usb/quirks.c       |   9 +-
 sound/usb/stream.c       |   2 +
 sound/usb/usbaudio.h     |   1 +
 10 files changed, 323 insertions(+), 7 deletions(-)
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 2d2d122..665fdd9 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -2,6 +2,18 @@
 # Makefile for ALSA
 #
 
+# Media Controller
+ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
+  ifeq ($(CONFIG_MEDIA_SUPPORT),y)
+        KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
+  endif
+  ifeq ($(CONFIG_MEDIA_SUPPORT_MODULE),y)
+    ifeq ($(MODULE),y)
+          KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
+    endif
+  endif
+endif
+
 snd-usb-audio-objs := 	card.o \
 			clock.o \
 			endpoint.o \
@@ -13,7 +25,8 @@ snd-usb-audio-objs := 	card.o \
 			pcm.o \
 			proc.o \
 			quirks.o \
-			stream.o
+			stream.o \
+			media.o
 
 snd-usbmidi-lib-objs := midi.o
 
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 18f5664..1a63851 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");
@@ -621,6 +622,12 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		list_for_each_entry(mixer, &chip->mixer_list, list) {
 			snd_usb_mixer_disconnect(mixer);
 		}
+		/*
+		 * Nice to check quirk && quirk->media_device
+		 * need some special handlings. Doesn't look like
+		 * we have access to quirk here
+		*/
+		media_device_delete(intf);
 	}
 
 	chip->num_interfaces--;
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..747a66a
--- /dev/null
+++ b/sound/usb/media.c
@@ -0,0 +1,214 @@
+/*
+ * 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/slab.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/usb.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+#include <linux/module.h>
+
+#include <sound/control.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "midi.h"
+#include "mixer.h"
+#include "proc.h"
+#include "quirks.h"
+#include "endpoint.h"
+#include "helper.h"
+#include "debug.h"
+#include "pcm.h"
+#include "format.h"
+#include "power.h"
+#include "stream.h"
+#include "media.h"
+
+#ifdef USE_MEDIA_CONTROLLER
+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);
+		ret = media_device_init(mdev);
+		if (ret) {
+			dev_err(&usbdev->dev,
+				"Couldn't create a media device. Error: %d\n",
+				ret);
+			return ret;
+		}
+	}
+	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;
+		}
+	}
+	return 0;
+}
+
+void media_device_delete(struct usb_interface *iface)
+{
+	struct media_device *mdev;
+	struct usb_device *usbdev = interface_to_usbdev(iface);
+
+	mdev = media_device_find_devres(&usbdev->dev);
+	if (mdev && media_devnode_is_registered(&mdev->devnode))
+		media_device_unregister(mdev);
+}
+
+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;
+
+	mdev = media_device_find_devres(&subs->dev->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;
+	} else {
+		intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
+		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
+	}
+	mctl->media_entity.name = pcm->name;
+	mctl->media_entity.info.dev.major = MAJOR(pcm_dev->devt);
+	mctl->media_entity.info.dev.minor = MINOR(pcm_dev->devt);
+	mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
+	media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
+	ret =  media_device_register_entity(mctl->media_dev,
+					    &mctl->media_entity);
+	if (ret) {
+		kfree(mctl);
+		return ret;
+	}
+	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
+						  MAJOR(pcm_dev->devt),
+						  MINOR(pcm_dev->devt));
+	if (!mctl->intf_devnode) {
+		media_device_unregister_entity(&mctl->media_entity);
+		kfree(mctl);
+		return -ENOMEM;
+	}
+	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
+						 &mctl->intf_devnode->intf,
+						 MEDIA_LNK_FL_ENABLED);
+	if (!mctl->intf_link) {
+		media_devnode_remove(mctl->intf_devnode);
+		media_device_unregister_entity(&mctl->media_entity);
+		kfree(mctl);
+		return -ENOMEM;
+	}
+	subs->media_ctl = (void *) mctl;
+	return 0;
+}
+
+void media_stream_delete(struct snd_usb_substream *subs)
+{
+	struct media_ctl *mctl = (struct media_ctl *) subs->media_ctl;
+
+	if (mctl && mctl->media_dev) {
+		struct media_device *mdev;
+
+		mdev = media_device_find_devres(&subs->dev->dev);
+		if (mdev) {
+			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 = (struct media_ctl *) 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 = (struct media_ctl *) subs->media_ctl;
+
+	if (mctl)
+		media_disable_source(mctl);
+}
+#endif
diff --git a/sound/usb/media.h b/sound/usb/media.h
new file mode 100644
index 0000000..4a93dbd
--- /dev/null
+++ b/sound/usb/media.h
@@ -0,0 +1,54 @@
+/*
+ * 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 USE_MEDIA_CONTROLLER
+#include <media/media-device.h>
+#include <media/media-entity.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;
+};
+
+int media_device_create(struct snd_usb_audio *chip,
+			struct usb_interface *iface);
+void media_device_delete(struct usb_interface *iface);
+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 usb_interface *iface) { }
+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/pcm.c b/sound/usb/pcm.c
index 9245f52..30bc183 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,10 @@ 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);
+	return ret;
 }
 
 static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
@@ -1241,6 +1256,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 1a1e2e4..8f7b71b 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2875,6 +2875,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/quirks.c b/sound/usb/quirks.c
index 5ca80e7..dc6878c 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -36,6 +36,7 @@
 #include "pcm.h"
 #include "clock.h"
 #include "stream.h"
+#include "media.h"
 
 /*
  * handle the quirks for the contained interfaces
@@ -544,13 +545,19 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
 		[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
 	};
+	int ret;
 
+	if (quirk->media_device) {
+		/* don't want to fail when media_device_create() fails */
+		media_device_create(chip, iface);
+	}
 	if (quirk->type < QUIRK_TYPE_COUNT) {
-		return quirk_funcs[quirk->type](chip, iface, driver, quirk);
+		ret = quirk_funcs[quirk->type](chip, iface, driver, quirk);
 	} else {
 		usb_audio_err(chip, "invalid quirk type %d\n", quirk->type);
 		return -ENXIO;
 	}
+	return ret;
 }
 
 /*
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 8ee14f2..789e515 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 15a1271..e3fac29 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -109,6 +109,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303678 — Re: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API

FromTakashi Iwai <tiwai@suse.de>
Date2016-01-07 16:50 +0100
SubjectRe: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API
Message-ID<qOkZ4-1DY-23@gated-at.bofh.it>
In reply to#1303084
On Wed, 06 Jan 2016 22:05:35 +0100,
Shuah Khan wrote:
> 
> diff --git a/sound/usb/Makefile b/sound/usb/Makefile
> index 2d2d122..665fdd9 100644
> --- a/sound/usb/Makefile
> +++ b/sound/usb/Makefile
> @@ -2,6 +2,18 @@
>  # Makefile for ALSA
>  #
>  
> +# Media Controller
> +ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
> +  ifeq ($(CONFIG_MEDIA_SUPPORT),y)
> +        KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
> +  endif
> +  ifeq ($(CONFIG_MEDIA_SUPPORT_MODULE),y)
> +    ifeq ($(MODULE),y)
> +          KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
> +    endif
> +  endif
> +endif

Can't we define this rather via Kconfig?
Doing this in Makefile is way too tricky, and it's unclear to users
whether MC is actually enabled or not.


> diff --git a/sound/usb/media.c b/sound/usb/media.c
> new file mode 100644
> index 0000000..747a66a
> --- /dev/null
> +++ b/sound/usb/media.c
> @@ -0,0 +1,214 @@
> +/*
> + * 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/slab.h>
> +#include <linux/string.h>
> +#include <linux/ctype.h>
> +#include <linux/usb.h>
> +#include <linux/moduleparam.h>
> +#include <linux/mutex.h>
> +#include <linux/usb/audio.h>
> +#include <linux/usb/audio-v2.h>
> +#include <linux/module.h>
> +
> +#include <sound/control.h>
> +#include <sound/core.h>
> +#include <sound/info.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/initval.h>
> +
> +#include "usbaudio.h"
> +#include "card.h"
> +#include "midi.h"
> +#include "mixer.h"
> +#include "proc.h"
> +#include "quirks.h"
> +#include "endpoint.h"
> +#include "helper.h"
> +#include "debug.h"
> +#include "pcm.h"
> +#include "format.h"
> +#include "power.h"
> +#include "stream.h"
> +#include "media.h"

I believe we can get rid of many include files just for MC support...


> +#ifdef USE_MEDIA_CONTROLLER

This ifdef can be removed once if we build this object file
conditionally in Makefile.


> @@ -1232,7 +1244,10 @@ 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);

Need to call snd_usb_autosuspend() in the error path.


> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -544,13 +545,19 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
>  		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
>  		[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
>  	};
> +	int ret;
>  
> +	if (quirk->media_device) {
> +		/* don't want to fail when media_device_create() fails */
> +		media_device_create(chip, iface);
> +	}

So far, so good...

>  	if (quirk->type < QUIRK_TYPE_COUNT) {
> -		return quirk_funcs[quirk->type](chip, iface, driver, quirk);
> +		ret = quirk_funcs[quirk->type](chip, iface, driver, quirk);
>  	} else {
>  		usb_audio_err(chip, "invalid quirk type %d\n", quirk->type);
>  		return -ENXIO;
>  	}
> +	return ret;

Any reason to change this?


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1303870 — Re: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-07 21:30 +0100
SubjectRe: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API
Message-ID<qOpm3-4Jn-11@gated-at.bofh.it>
In reply to#1303678
On 01/07/2016 08:44 AM, Takashi Iwai wrote:
> On Wed, 06 Jan 2016 22:05:35 +0100,
> Shuah Khan wrote:
>>
>> diff --git a/sound/usb/Makefile b/sound/usb/Makefile
>> index 2d2d122..665fdd9 100644
>> --- a/sound/usb/Makefile
>> +++ b/sound/usb/Makefile
>> @@ -2,6 +2,18 @@
>>  # Makefile for ALSA
>>  #
>>  
>> +# Media Controller
>> +ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
>> +  ifeq ($(CONFIG_MEDIA_SUPPORT),y)
>> +        KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
>> +  endif
>> +  ifeq ($(CONFIG_MEDIA_SUPPORT_MODULE),y)
>> +    ifeq ($(MODULE),y)
>> +          KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
>> +    endif
>> +  endif
>> +endif
> 
> Can't we define this rather via Kconfig?
> Doing this in Makefile is way too tricky, and it's unclear to users
> whether MC is actually enabled or not.
> 

Yeah doing this in Makefile is a bit tricky
and can lead to confusion.

I can't think of any specific reason why I added
this check to the Makefile instead of Kconfig.
Looks like I added this in my second version
of the patch series several months ago and didn't
revisit. I will add this to Kconfig.
> 
>> diff --git a/sound/usb/media.c b/sound/usb/media.c
>> new file mode 100644
>> index 0000000..747a66a
>> --- /dev/null
>> +++ b/sound/usb/media.c
>> @@ -0,0 +1,214 @@
>> +/*
>> + * 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/slab.h>
>> +#include <linux/string.h>
>> +#include <linux/ctype.h>
>> +#include <linux/usb.h>
>> +#include <linux/moduleparam.h>
>> +#include <linux/mutex.h>
>> +#include <linux/usb/audio.h>
>> +#include <linux/usb/audio-v2.h>
>> +#include <linux/module.h>
>> +
>> +#include <sound/control.h>
>> +#include <sound/core.h>
>> +#include <sound/info.h>
>> +#include <sound/pcm.h>
>> +#include <sound/pcm_params.h>
>> +#include <sound/initval.h>
>> +
>> +#include "usbaudio.h"
>> +#include "card.h"
>> +#include "midi.h"
>> +#include "mixer.h"
>> +#include "proc.h"
>> +#include "quirks.h"
>> +#include "endpoint.h"
>> +#include "helper.h"
>> +#include "debug.h"
>> +#include "pcm.h"
>> +#include "format.h"
>> +#include "power.h"
>> +#include "stream.h"
>> +#include "media.h"
> 
> I believe we can get rid of many include files just for MC support...
> 
> 
>> +#ifdef USE_MEDIA_CONTROLLER
> 
> This ifdef can be removed once if we build this object file
> conditionally in Makefile.

Right.

> 
> 
>> @@ -1232,7 +1244,10 @@ 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);
> 
> Need to call snd_usb_autosuspend() in the error path.

I will add it.

> 
> 
>> --- a/sound/usb/quirks.c
>> +++ b/sound/usb/quirks.c
>> @@ -544,13 +545,19 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
>>  		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
>>  		[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
>>  	};
>> +	int ret;
>>  
>> +	if (quirk->media_device) {
>> +		/* don't want to fail when media_device_create() fails */
>> +		media_device_create(chip, iface);
>> +	}
> 
> So far, so good...
> 
>>  	if (quirk->type < QUIRK_TYPE_COUNT) {
>> -		return quirk_funcs[quirk->type](chip, iface, driver, quirk);
>> +		ret = quirk_funcs[quirk->type](chip, iface, driver, quirk);
>>  	} else {
>>  		usb_audio_err(chip, "invalid quirk type %d\n", quirk->type);
>>  		return -ENXIO;
>>  	}
>> +	return ret;
> 
> Any reason to change this?

Thanks for catching this. I think I might have
added some debug code to print ret value and
missed it when I cleaned up the debug code.
I will fix it.

thanks,
-- Shuah

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

[toc] | [prev] | [next] | [standalone]


#1303086 — [PATCH 27/31] sound/usb: Create media mixer function and control interface entities

FromShuah Khan <shuahkh@osg.samsung.com>
Date2016-01-06 22:10 +0100
Subject[PATCH 27/31] sound/usb: Create media mixer function and control interface entities
Message-ID<qO3ve-6u0-33@gated-at.bofh.it>
In reply to#1303063
Add support for creating MEDIA_ENT_F_AUDIO_MIXER entity for
each mixer and a MEDIA_INTF_T_ALSA_CONTROL control interface
entity that links to mixer entities. MEDIA_INTF_T_ALSA_CONTROL
entity corresponds to the control device for the card.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
 sound/usb/card.c     |  5 +++
 sound/usb/media.c    | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 sound/usb/media.h    | 21 ++++++++++++
 sound/usb/mixer.h    |  1 +
 sound/usb/usbaudio.h |  1 +
 5 files changed, 118 insertions(+)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 1a63851..e965982 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -562,6 +562,9 @@ static int usb_audio_probe(struct usb_interface *intf,
 	if (err < 0)
 		goto __error;
 
+	/* Create media entities for mixer and control dev */
+	media_mixer_init(chip);
+
 	usb_chip[chip->index] = chip;
 	chip->num_interfaces++;
 	usb_set_intfdata(intf, chip);
@@ -618,6 +621,8 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		list_for_each(p, &chip->midi_list) {
 			snd_usbmidi_disconnect(p);
 		}
+		/* delete mixer media resources */
+		media_mixer_delete(chip);
 		/* release mixer resources */
 		list_for_each_entry(mixer, &chip->mixer_list, list) {
 			snd_usb_mixer_disconnect(mixer);
diff --git a/sound/usb/media.c b/sound/usb/media.c
index 747a66a..4f99086 100644
--- a/sound/usb/media.c
+++ b/sound/usb/media.c
@@ -211,4 +211,94 @@ void media_stop_pipeline(struct snd_usb_substream *subs)
 	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;
+	struct media_mixer_ctl *mctl;
+	u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
+	int ret;
+
+	mdev = media_device_find_devres(&chip->dev->dev);
+	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 = (void *) mctl;
+	}
+	return 0;
+}
+
+void media_mixer_delete(struct snd_usb_audio *chip)
+{
+	struct usb_mixer_interface *mixer;
+	struct media_device *mdev;
+
+	mdev = media_device_find_devres(&chip->dev->dev);
+	if (!mdev)
+		return;
+
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+		struct media_mixer_ctl *mctl;
+
+		mctl = (struct media_mixer_ctl *) mixer->media_mixer_ctl;
+		if (!mixer->media_mixer_ctl)
+			continue;
+
+		media_device_unregister_entity(&mctl->media_entity);
+		media_entity_cleanup(&mctl->media_entity);
+		kfree(mctl);
+		mixer->media_mixer_ctl = NULL;
+	}
+	media_devnode_remove(chip->ctl_intf_media_devnode);
+}
+
 #endif
diff --git a/sound/usb/media.h b/sound/usb/media.h
index 4a93dbd..00884b5 100644
--- a/sound/usb/media.h
+++ b/sound/usb/media.h
@@ -20,6 +20,7 @@
 #ifdef 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;
@@ -30,6 +31,22 @@ struct media_ctl {
 	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 usb_interface *iface);
@@ -38,6 +55,8 @@ int media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 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);
+int media_mixer_init(struct snd_usb_audio *chip);
+void media_mixer_delete(struct snd_usb_audio *chip);
 #else
 static inline int media_device_create(struct snd_usb_audio *chip,
 				      struct usb_interface *iface)
@@ -50,5 +69,7 @@ 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) { }
+static int media_mixer_init(struct snd_usb_audio *chip) { return 0; }
+static void media_mixer_delete(struct snd_usb_audio *chip) { }
 #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/usbaudio.h b/sound/usb/usbaudio.h
index e3fac29..490b16a 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -60,6 +60,7 @@ struct snd_usb_audio {
 	bool autoclock;			/* from the 'autoclock' module param */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
+	void *ctl_intf_media_devnode;
 };
 
 #define usb_audio_err(chip, fmt, args...) \
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web