On Wed, 21 Oct 2015 01:25:15 +0200,
Shuah Khan wrote:
> 
> 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 <shua...@osg.samsung.com>
> ---
>  sound/usb/card.c     |  5 +++
>  sound/usb/media.c    | 89 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  sound/usb/media.h    | 20 ++++++++++++
>  sound/usb/mixer.h    |  1 +
>  sound/usb/usbaudio.h |  1 +
>  5 files changed, 116 insertions(+)
> 
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 469d2bf..d004cb4 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -560,6 +560,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++;
>       chip->probing = 0;
> @@ -616,6 +619,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 0cbfee6..a26ea8b 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -199,4 +199,93 @@ 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 = (struct media_intf_devnode *) chip->ctl_intf_media_devnode;

Why do we need cast?  Can't chip->ctl_intf_media_devnode itself be
struct media_intf_devndoe pointer?


> +     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;
> +     }

Is chip->ctl_intf_media_devnode assigned anywhere at all?

Not directly related with this patchset: the above uses
media_devnode_create(), which I assume it's a device-file
(major:minor) specific.  What if sound hardware with multiple codecs
and so on in general?


> +
> +     list_for_each_entry(mixer, &chip->mixer_list, list) {
> +
> +             if (mixer->media_mixer_ctl)
> +                     continue;
> +
> +             /* allocate media_ctl */
> +             mctl = kzalloc(sizeof(struct media_ctl), GFP_KERNEL);
> +             if (!mctl)
> +                     return -ENOMEM;
> +
> +             mixer->media_mixer_ctl = (void *) mctl;
> +             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_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
> +                               mctl->media_pad);
> +             ret =  media_device_register_entity(mctl->media_dev,
> +                                                 &mctl->media_entity);
> +             if (ret)
> +                     return ret;

Will the last (unfinished) mctl be freed properly in the error path?

> +             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);
> +                     return -ENOMEM;

Ditto.

> +             }
> +             mctl->intf_devnode = ctl_intf;
> +     }
> +     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_entity_remove_links(&mctl->media_entity);
> +             media_device_unregister_entity(&mctl->media_entity);
> +             media_entity_cleanup(&mctl->media_entity);
> +             mctl->media_dev = NULL;
> +             mctl->intf_devnode = NULL;
> +             kfree(mctl);

The previous two NULL are superfluous as we'll free them immediately.


thanks,

Takashi


> +             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 cdcfb80..8268e52 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,21 @@ 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_init(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,
> @@ -37,6 +53,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_init(struct snd_usb_audio *chip,
>                                       struct usb_interface *iface)
> @@ -49,5 +67,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 d3268f0..9d62a9e 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 c2dbf1d..b2be7c3 100644
> --- a/sound/usb/usbaudio.h
> +++ b/sound/usb/usbaudio.h
> @@ -59,6 +59,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.1.4
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to